Files
grafana/pkg/tsdb/jaeger/utils/client_utils_test.go
Jocelyn Collado-Kuri d0ea82633f Jaeger: Migrate API calls to gRPC endpoint (#113297)
* Jaeger: Migrate Services and Operations to the gRPC Jaeger endpoint (#112384)

* add grpc feature toggle

* move types into types.go

* creates grpc client functions for services and operations

* Call grpc services function when feature flag is enabled for health check

* remove unnecessary double encoding

* check for successful status code before decoding response and return nil in case of successful response

* remove duplicate code

* use variable

* fix error type in testsz

* Jaeger: Migrate search and Trace Search calls to use gRPC endpoint (#112610)

* move all types into types package except for JagerClient

* move all helper functions into utils package

* change return type of search function to be frames and add grpc search functionality

* fix tests

* fix types and the way we check error response from grpc

* change trace name and duration unit conversion

* fix types and add tests

* support queryAttributes

* quick limit implementation in post processing

* add todo for attributes / tags

* make trace functionality ready to support grpc flow

* add functions to process search response for a specific trace and create the Trace frame

* tests for helper funtions

* remove grpc querying for now!

* change logic to be able to process and support multiple resource spans

* remove logic for gRPC from grpc_client.go

* add equivalent fields for logs and references

* add tests for grpcTraceResponse function

* fix types after merge with main

* fix status code checks and return nil for error on successful responses

* enable reading through config flag for trace search

* create sigle key value type since they are similar for OTLP and non OTLP based formats

* reference right type

* convert events and links into references and logs

* add status code, status message and kind to data frame

* fix tests to accomodate new format

* remove unused function and add more tests

* remove edit flag for jsonc golden test files

* add clarifying comment

* fix tests and linting

* fix golden files for testing

* fix typo

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix typo

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix typo

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* add clarifying comment

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* remove unnecessary logging statement

* fix downstream errors

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* use downstreamerrorf where applicable and add missing downstream eror sources.

* tests

---------

Co-authored-by: ismail simsek <ismailsimsek09@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-31 11:19:16 -07:00

262 lines
7.4 KiB
Go

package utils
import (
"testing"
"github.com/grafana/grafana-plugin-sdk-go/experimental"
"github.com/grafana/grafana/pkg/tsdb/jaeger/types"
)
func TestTransformSearchResponse(t *testing.T) {
t.Run("empty_response", func(t *testing.T) {
frame := TransformSearchResponse([]types.TraceResponse{}, "test-uid", "test-name")
experimental.CheckGoldenJSONFrame(t, "../testdata", "search_empty_response.golden", frame, false)
})
t.Run("single_trace", func(t *testing.T) {
response := []types.TraceResponse{
{
TraceID: "test-trace-id",
Spans: []types.Span{
{
TraceID: "test-trace-id",
ProcessID: "p1",
OperationName: "test-operation",
StartTime: 1605873894680409,
Duration: 1000,
},
},
Processes: map[string]types.TraceProcess{
"p1": {
ServiceName: "test-service",
},
},
},
}
frame := TransformSearchResponse(response, "test-uid", "test-name")
experimental.CheckGoldenJSONFrame(t, "../testdata", "search_single_response.golden", frame, false)
})
t.Run("multiple_traces", func(t *testing.T) {
response := []types.TraceResponse{
{
TraceID: "trace-1",
Spans: []types.Span{
{
TraceID: "trace-1",
ProcessID: "p1",
OperationName: "op1",
StartTime: 1605873894680409,
Duration: 1000,
},
},
Processes: map[string]types.TraceProcess{
"p1": {
ServiceName: "service-1",
},
},
},
{
TraceID: "trace-2",
Spans: []types.Span{
{
TraceID: "trace-2",
ProcessID: "p2",
OperationName: "op2",
StartTime: 1605873894680409,
Duration: 2000,
},
},
Processes: map[string]types.TraceProcess{
"p2": {
ServiceName: "service-2",
},
},
},
}
frame := TransformSearchResponse(response, "test-uid", "test-name")
experimental.CheckGoldenJSONFrame(t, "../testdata", "search_multiple_response.golden", frame, false)
})
}
func TestTransformTraceResponse(t *testing.T) {
t.Run("simple_trace", func(t *testing.T) {
trace := types.TraceResponse{
TraceID: "3fa414edcef6ad90",
Spans: []types.Span{
{
TraceID: "3fa414edcef6ad90",
SpanID: "3fa414edcef6ad90",
OperationName: "HTTP GET - api_traces_traceid",
StartTime: 1605873894680409,
Duration: 1049141,
Tags: []types.KeyValueType{
{Key: "sampler.type", Type: "string", Value: "probabilistic"},
{Key: "sampler.param", Type: "float64", Value: 1},
},
Logs: []types.TraceLog{},
ProcessID: "p1",
Warnings: nil,
Flags: 0,
},
{
TraceID: "3fa414edcef6ad90",
SpanID: "0f5c1808567e4403",
OperationName: "/tempopb.Querier/FindTraceByID",
References: []types.TraceSpanReference{
{
RefType: "CHILD_OF",
TraceID: "3fa414edcef6ad90",
SpanID: "3fa414edcef6ad90",
},
},
StartTime: 1605873894680587,
Duration: 1847,
Tags: []types.KeyValueType{
{Key: "component", Type: "string", Value: "gRPC"},
{Key: "span.kind", Type: "string", Value: "client"},
},
Logs: []types.TraceLog{},
ProcessID: "p1",
Warnings: nil,
Flags: 0,
},
},
Processes: map[string]types.TraceProcess{
"p1": {
ServiceName: "tempo-querier",
Tags: []types.KeyValueType{
{Key: "cluster", Type: "string", Value: "ops-tools1"},
{Key: "container", Type: "string", Value: "tempo-query"},
},
},
},
Warnings: nil,
}
frame := TransformTraceResponse(trace, "test")
experimental.CheckGoldenJSONFrame(t, "../testdata", "simple_trace.golden", frame, false)
})
t.Run("complex_trace", func(t *testing.T) {
trace := types.TraceResponse{
TraceID: "3fa414edcef6ad90",
Spans: []types.Span{
{
TraceID: "3fa414edcef6ad90",
SpanID: "3fa414edcef6ad90",
OperationName: "HTTP GET - api_traces_traceid",
References: []types.TraceSpanReference{},
StartTime: 1605873894680409,
Duration: 1049141,
Tags: []types.KeyValueType{
{Key: "sampler.type", Type: "string", Value: "probabilistic"},
{Key: "sampler.param", Type: "float64", Value: 1},
{Key: "error", Type: "bool", Value: true},
{Key: "http.status_code", Type: "int", Value: 500},
},
Logs: []types.TraceLog{
{
Timestamp: 1605873894681000,
Fields: []types.KeyValueType{
{Key: "event", Type: "string", Value: "error"},
{Key: "message", Type: "string", Value: "Internal server error"},
},
},
},
ProcessID: "p1",
Warnings: []string{"High latency detected", "Error rate above threshold"},
Flags: 0,
},
{
TraceID: "3fa414edcef6ad90",
SpanID: "0f5c1808567e4403",
OperationName: "/tempopb.Querier/FindTraceByID",
References: []types.TraceSpanReference{
{
RefType: "CHILD_OF",
TraceID: "3fa414edcef6ad90",
SpanID: "3fa414edcef6ad90",
},
},
StartTime: 1605873894680587,
Duration: 1847,
Tags: []types.KeyValueType{
{Key: "component", Type: "string", Value: "gRPC"},
{Key: "span.kind", Type: "string", Value: "client"},
{Key: "error", Type: "bool", Value: true},
{Key: "grpc.status_code", Type: "int", Value: 13},
},
Logs: []types.TraceLog{
{
Timestamp: 1605873894680700,
Fields: []types.KeyValueType{
{Key: "event", Type: "string", Value: "error"},
{Key: "message", Type: "string", Value: "gRPC error: INTERNAL"},
},
},
},
ProcessID: "p1",
Warnings: []string{"gRPC call failed", "Retry attempt 3"},
Flags: 0,
},
{
TraceID: "3fa414edcef6ad90",
SpanID: "1a2b3c4d5e6f7g8h",
OperationName: "db.query",
References: []types.TraceSpanReference{
{
RefType: "CHILD_OF",
TraceID: "3fa414edcef6ad90",
SpanID: "0f5c1808567e4403",
},
},
StartTime: 1605873894680800,
Duration: 500,
Tags: []types.KeyValueType{
{Key: "db.type", Type: "string", Value: "postgresql"},
{Key: "db.statement", Type: "string", Value: "SELECT * FROM traces WHERE id = $1"},
{Key: "error", Type: "bool", Value: true},
},
Logs: []types.TraceLog{
{
Timestamp: 1605873894680850,
Fields: []types.KeyValueType{
{Key: "event", Type: "string", Value: "error"},
{Key: "message", Type: "string", Value: "Database connection timeout"},
},
},
},
ProcessID: "p2",
Warnings: []string{"Database connection slow", "Query timeout"},
Flags: 0,
},
},
Processes: map[string]types.TraceProcess{
"p1": {
ServiceName: "tempo-querier",
Tags: []types.KeyValueType{
{Key: "cluster", Type: "string", Value: "ops-tools1"},
{Key: "container", Type: "string", Value: "tempo-query"},
{Key: "version", Type: "string", Value: "1.2.3"},
},
},
"p2": {
ServiceName: "tempo-storage",
Tags: []types.KeyValueType{
{Key: "cluster", Type: "string", Value: "ops-tools1"},
{Key: "container", Type: "string", Value: "tempo-storage"},
{Key: "version", Type: "string", Value: "2.0.1"},
},
},
},
Warnings: []string{"Trace contains errors", "Multiple service failures"},
}
frame := TransformTraceResponse(trace, "test")
experimental.CheckGoldenJSONFrame(t, "../testdata", "complex_trace.golden", frame, false)
})
}