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>
This commit is contained in:
co-authored by
Copilot
ismail simsek
parent
64da716a2e
commit
d0ea82633f
@@ -3,294 +3,14 @@ package jaeger
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"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) {
|
||||
dsInfo := &datasourceInfo{
|
||||
JaegerClient: JaegerClient{
|
||||
settings: backend.DataSourceInstanceSettings{
|
||||
UID: "test-uid",
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
frame := transformSearchResponse([]TraceResponse{}, dsInfo)
|
||||
experimental.CheckGoldenJSONFrame(t, "./testdata", "search_empty_response.golden", frame, false)
|
||||
})
|
||||
|
||||
t.Run("single_trace", func(t *testing.T) {
|
||||
dsInfo := &datasourceInfo{
|
||||
JaegerClient: JaegerClient{
|
||||
settings: backend.DataSourceInstanceSettings{
|
||||
UID: "test-uid",
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
response := []TraceResponse{
|
||||
{
|
||||
TraceID: "test-trace-id",
|
||||
Spans: []Span{
|
||||
{
|
||||
TraceID: "test-trace-id",
|
||||
ProcessID: "p1",
|
||||
OperationName: "test-operation",
|
||||
StartTime: 1605873894680409,
|
||||
Duration: 1000,
|
||||
},
|
||||
},
|
||||
Processes: map[string]TraceProcess{
|
||||
"p1": {
|
||||
ServiceName: "test-service",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
frame := transformSearchResponse(response, dsInfo)
|
||||
experimental.CheckGoldenJSONFrame(t, "./testdata", "search_single_response.golden", frame, false)
|
||||
})
|
||||
|
||||
t.Run("multiple_traces", func(t *testing.T) {
|
||||
dsInfo := &datasourceInfo{
|
||||
JaegerClient: JaegerClient{
|
||||
settings: backend.DataSourceInstanceSettings{
|
||||
UID: "test-uid",
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
response := []TraceResponse{
|
||||
{
|
||||
TraceID: "trace-1",
|
||||
Spans: []Span{
|
||||
{
|
||||
TraceID: "trace-1",
|
||||
ProcessID: "p1",
|
||||
OperationName: "op1",
|
||||
StartTime: 1605873894680409,
|
||||
Duration: 1000,
|
||||
},
|
||||
},
|
||||
Processes: map[string]TraceProcess{
|
||||
"p1": {
|
||||
ServiceName: "service-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
TraceID: "trace-2",
|
||||
Spans: []Span{
|
||||
{
|
||||
TraceID: "trace-2",
|
||||
ProcessID: "p2",
|
||||
OperationName: "op2",
|
||||
StartTime: 1605873894680409,
|
||||
Duration: 2000,
|
||||
},
|
||||
},
|
||||
Processes: map[string]TraceProcess{
|
||||
"p2": {
|
||||
ServiceName: "service-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
frame := transformSearchResponse(response, dsInfo)
|
||||
experimental.CheckGoldenJSONFrame(t, "./testdata", "search_multiple_response.golden", frame, false)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTransformTraceResponse(t *testing.T) {
|
||||
t.Run("simple_trace", func(t *testing.T) {
|
||||
trace := TraceResponse{
|
||||
TraceID: "3fa414edcef6ad90",
|
||||
Spans: []Span{
|
||||
{
|
||||
TraceID: "3fa414edcef6ad90",
|
||||
SpanID: "3fa414edcef6ad90",
|
||||
OperationName: "HTTP GET - api_traces_traceid",
|
||||
StartTime: 1605873894680409,
|
||||
Duration: 1049141,
|
||||
Tags: []TraceKeyValuePair{
|
||||
{Key: "sampler.type", Type: "string", Value: "probabilistic"},
|
||||
{Key: "sampler.param", Type: "float64", Value: 1},
|
||||
},
|
||||
Logs: []TraceLog{},
|
||||
ProcessID: "p1",
|
||||
Warnings: nil,
|
||||
Flags: 0,
|
||||
},
|
||||
{
|
||||
TraceID: "3fa414edcef6ad90",
|
||||
SpanID: "0f5c1808567e4403",
|
||||
OperationName: "/tempopb.Querier/FindTraceByID",
|
||||
References: []TraceSpanReference{
|
||||
{
|
||||
RefType: "CHILD_OF",
|
||||
TraceID: "3fa414edcef6ad90",
|
||||
SpanID: "3fa414edcef6ad90",
|
||||
},
|
||||
},
|
||||
StartTime: 1605873894680587,
|
||||
Duration: 1847,
|
||||
Tags: []TraceKeyValuePair{
|
||||
{Key: "component", Type: "string", Value: "gRPC"},
|
||||
{Key: "span.kind", Type: "string", Value: "client"},
|
||||
},
|
||||
Logs: []TraceLog{},
|
||||
ProcessID: "p1",
|
||||
Warnings: nil,
|
||||
Flags: 0,
|
||||
},
|
||||
},
|
||||
Processes: map[string]TraceProcess{
|
||||
"p1": {
|
||||
ServiceName: "tempo-querier",
|
||||
Tags: []TraceKeyValuePair{
|
||||
{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 := TraceResponse{
|
||||
TraceID: "3fa414edcef6ad90",
|
||||
Spans: []Span{
|
||||
{
|
||||
TraceID: "3fa414edcef6ad90",
|
||||
SpanID: "3fa414edcef6ad90",
|
||||
OperationName: "HTTP GET - api_traces_traceid",
|
||||
References: []TraceSpanReference{},
|
||||
StartTime: 1605873894680409,
|
||||
Duration: 1049141,
|
||||
Tags: []TraceKeyValuePair{
|
||||
{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: []TraceLog{
|
||||
{
|
||||
Timestamp: 1605873894681000,
|
||||
Fields: []TraceKeyValuePair{
|
||||
{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: []TraceSpanReference{
|
||||
{
|
||||
RefType: "CHILD_OF",
|
||||
TraceID: "3fa414edcef6ad90",
|
||||
SpanID: "3fa414edcef6ad90",
|
||||
},
|
||||
},
|
||||
StartTime: 1605873894680587,
|
||||
Duration: 1847,
|
||||
Tags: []TraceKeyValuePair{
|
||||
{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: []TraceLog{
|
||||
{
|
||||
Timestamp: 1605873894680700,
|
||||
Fields: []TraceKeyValuePair{
|
||||
{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: []TraceSpanReference{
|
||||
{
|
||||
RefType: "CHILD_OF",
|
||||
TraceID: "3fa414edcef6ad90",
|
||||
SpanID: "0f5c1808567e4403",
|
||||
},
|
||||
},
|
||||
StartTime: 1605873894680800,
|
||||
Duration: 500,
|
||||
Tags: []TraceKeyValuePair{
|
||||
{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: []TraceLog{
|
||||
{
|
||||
Timestamp: 1605873894680850,
|
||||
Fields: []TraceKeyValuePair{
|
||||
{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]TraceProcess{
|
||||
"p1": {
|
||||
ServiceName: "tempo-querier",
|
||||
Tags: []TraceKeyValuePair{
|
||||
{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: []TraceKeyValuePair{
|
||||
{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)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTransformDependenciesResponse(t *testing.T) {
|
||||
t.Run("simple_dependencies", func(t *testing.T) {
|
||||
dependencies := DependenciesResponse{
|
||||
Data: []ServiceDependency{
|
||||
dependencies := types.DependenciesResponse{
|
||||
Data: []types.ServiceDependency{
|
||||
{
|
||||
Parent: "serviceA",
|
||||
Child: "serviceB",
|
||||
@@ -315,8 +35,8 @@ func TestTransformDependenciesResponse(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("empty_dependencies", func(t *testing.T) {
|
||||
dependencies := DependenciesResponse{
|
||||
Data: []ServiceDependency{},
|
||||
dependencies := types.DependenciesResponse{
|
||||
Data: []types.ServiceDependency{},
|
||||
}
|
||||
|
||||
frames := transformDependenciesResponse(dependencies, "test")
|
||||
@@ -325,8 +45,8 @@ func TestTransformDependenciesResponse(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("complex_dependencies", func(t *testing.T) {
|
||||
dependencies := DependenciesResponse{
|
||||
Data: []ServiceDependency{
|
||||
dependencies := types.DependenciesResponse{
|
||||
Data: []types.ServiceDependency{
|
||||
{
|
||||
Parent: "frontend",
|
||||
Child: "auth-service",
|
||||
|
||||
Reference in New Issue
Block a user