diff --git a/pkg/tsdb/jaeger/client.go b/pkg/tsdb/jaeger/client.go index 3e5ca5f5daf..79bef83fac4 100644 --- a/pkg/tsdb/jaeger/client.go +++ b/pkg/tsdb/jaeger/client.go @@ -26,6 +26,20 @@ type ServicesResponse struct { Total int `json:"total"` } +type DependenciesResponse struct { + Data []ServiceDependency `json:"data"` + Errors []struct { + Code int `json:"code"` + Msg string `json:"msg"` + } `json:"errors"` +} + +type ServiceDependency struct { + Parent string `json:"parent"` + Child string `json:"child"` + CallCount int `json:"callCount"` +} + func New(url string, hc *http.Client, logger log.Logger, traceIdTimeEnabled bool) (JaegerClient, error) { client := JaegerClient{ logger: logger, @@ -158,3 +172,59 @@ func (j *JaegerClient) Trace(ctx context.Context, traceID string, start, end int trace = response.Data[0] return trace, err } + +func (j *JaegerClient) Dependencies(ctx context.Context, start, end int64) (DependenciesResponse, error) { + logger := j.logger.FromContext(ctx) + var dependencies DependenciesResponse + + u, err := url.JoinPath(j.url, "/api/dependencies") + if err != nil { + return dependencies, backend.DownstreamError(fmt.Errorf("failed to join url: %w", err)) + } + + // Add time parameters + parsedURL, err := url.Parse(u) + if err != nil { + return dependencies, backend.DownstreamError(fmt.Errorf("failed to parse url: %w", err)) + } + + query := parsedURL.Query() + if end > 0 { + query.Set("endTs", fmt.Sprintf("%d", end)) + } + if start > 0 { + lookback := end - start + query.Set("lookback", fmt.Sprintf("%d", lookback)) + } + + parsedURL.RawQuery = query.Encode() + u = parsedURL.String() + + res, err := j.httpClient.Get(u) + if err != nil { + if backend.IsDownstreamHTTPError(err) { + return dependencies, backend.DownstreamError(err) + } + return dependencies, err + } + + defer func() { + if err = res.Body.Close(); err != nil { + logger.Error("Failed to close response body", "error", err) + } + }() + + if res != nil && res.StatusCode/100 != 2 { + err := backend.DownstreamError(fmt.Errorf("request failed: %s", res.Status)) + if backend.ErrorSourceFromHTTPStatus(res.StatusCode) == backend.ErrorSourceDownstream { + return dependencies, backend.DownstreamError(err) + } + return dependencies, err + } + + if err := json.NewDecoder(res.Body).Decode(&dependencies); err != nil { + return dependencies, err + } + + return dependencies, nil +} diff --git a/pkg/tsdb/jaeger/client_test.go b/pkg/tsdb/jaeger/client_test.go index fc34fa61379..67a83d84668 100644 --- a/pkg/tsdb/jaeger/client_test.go +++ b/pkg/tsdb/jaeger/client_test.go @@ -276,3 +276,112 @@ func TestJaegerClient_Trace(t *testing.T) { }) } } + +func TestJaegerClient_Dependencies(t *testing.T) { + tests := []struct { + name string + start int64 + end int64 + mockResponse string + mockStatusCode int + mockStatus string + expectedURL string + expectError bool + expectedError error + }{ + { + name: "Successful response with time range", + start: 1000, + end: 2000, + mockResponse: `{"data":[{"parent":"serviceA","child":"serviceB","callCount":1}]}`, + mockStatusCode: http.StatusOK, + mockStatus: "OK", + expectedURL: "/api/dependencies?endTs=2000&lookback=1000", + expectError: false, + expectedError: nil, + }, + { + name: "Successful response without time range", + start: 0, + end: 0, + mockResponse: `{"data":[{"parent":"serviceA","child":"serviceB","callCount":1}]}`, + mockStatusCode: http.StatusOK, + mockStatus: "OK", + expectedURL: "/api/dependencies", + expectError: false, + expectedError: nil, + }, + { + name: "Non-200 response", + start: 1000, + end: 2000, + mockResponse: "", + mockStatusCode: http.StatusInternalServerError, + mockStatus: "Internal Server Error", + expectedURL: "/api/dependencies?endTs=2000&lookback=1000", + expectError: true, + expectedError: backend.PluginError(errors.New("Internal Server Error")), + }, + { + name: "Invalid JSON response", + start: 1000, + end: 2000, + mockResponse: `{invalid json`, + mockStatusCode: http.StatusOK, + mockStatus: "OK", + expectedURL: "/api/dependencies?endTs=2000&lookback=1000", + expectError: true, + expectedError: &json.SyntaxError{}, + }, + { + name: "Empty dependencies response and no errors", + start: 1000, + end: 2000, + mockResponse: `{"data":[]}`, + mockStatusCode: http.StatusOK, + mockStatus: "OK", + expectedURL: "/api/dependencies?endTs=2000&lookback=1000", + expectError: false, + expectedError: nil, + }, + { + name: "Response with errors", + start: 1000, + end: 2000, + mockResponse: `{"data":[],"errors":[{"code":500,"msg":"Internal error"}]}`, + mockStatusCode: http.StatusOK, + mockStatus: "OK", + expectedURL: "/api/dependencies?endTs=2000&lookback=1000", + expectError: false, + expectedError: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var actualURL string + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + actualURL = r.URL.String() + w.WriteHeader(tt.mockStatusCode) + _, _ = w.Write([]byte(tt.mockResponse)) + })) + defer server.Close() + + client, err := New(server.URL, server.Client(), log.NewNullLogger(), false) + assert.NoError(t, err) + + dependencies, err := client.Dependencies(context.Background(), tt.start, tt.end) + + if tt.expectError { + assert.Error(t, err) + if tt.expectedError != nil { + assert.IsType(t, tt.expectedError, err) + } + } else { + assert.NoError(t, err) + assert.NotNil(t, dependencies) + } + assert.Equal(t, tt.expectedURL, actualURL) + }) + } +} diff --git a/pkg/tsdb/jaeger/querydata.go b/pkg/tsdb/jaeger/querydata.go index 85aed936bff..1f2202d6cf0 100644 --- a/pkg/tsdb/jaeger/querydata.go +++ b/pkg/tsdb/jaeger/querydata.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "sort" "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/data" @@ -45,6 +46,23 @@ func queryData(ctx context.Context, dsInfo *datasourceInfo, req *backend.QueryDa Frames: []*data.Frame{frame}, } } + + if query.QueryType == "dependencyGraph" { + dependencies, err := dsInfo.JaegerClient.Dependencies(ctx, q.TimeRange.From.UnixMilli(), q.TimeRange.To.UnixMilli()) + if err != nil { + response.Responses[q.RefID] = backend.ErrorResponseWithErrorSource(err) + continue + } + + if len(dependencies.Errors) > 0 { + response.Responses[q.RefID] = backend.ErrorResponseWithErrorSource(backend.DownstreamError(fmt.Errorf("error while fetching dependencies, code: %v, message: %v", dependencies.Errors[0].Code, dependencies.Errors[0].Msg))) + continue + } + frames := transformDependenciesResponse(dependencies, q.RefID) + response.Responses[q.RefID] = backend.DataResponse{ + Frames: frames, + } + } } return response, nil @@ -215,3 +233,70 @@ type TracesResponse struct { Offset int `json:"offset"` Total int `json:"total"` } + +func transformDependenciesResponse(dependencies DependenciesResponse, refID string) []*data.Frame { + // Create nodes frame + nodesFrame := data.NewFrame(refID+"_nodes", + data.NewField("id", nil, []string{}), + data.NewField("title", nil, []string{}), + ) + nodesFrame.Meta = &data.FrameMeta{ + PreferredVisualization: "nodeGraph", + } + + // Create edges frame + mainStatField := data.NewField("mainstat", nil, []int64{}) + mainStatField.Config = &data.FieldConfig{ + DisplayName: "Call count", + } + edgesFrame := data.NewFrame(refID+"_edges", + data.NewField("id", nil, []string{}), + data.NewField("source", nil, []string{}), + data.NewField("target", nil, []string{}), + mainStatField, + ) + + edgesFrame.Meta = &data.FrameMeta{ + PreferredVisualization: "nodeGraph", + } + + // Return early if there are no dependencies + if len(dependencies.Data) == 0 { + return []*data.Frame{nodesFrame, edgesFrame} + } + + // Create a map to store unique service nodes + servicesByName := make(map[string]bool) + + // Process each dependency + for _, dependency := range dependencies.Data { + // Add services to the map to track unique services + servicesByName[dependency.Parent] = true + servicesByName[dependency.Child] = true + + // Add edge data + edgesFrame.AppendRow( + dependency.Parent+"--"+dependency.Child, + dependency.Parent, + dependency.Child, + int64(dependency.CallCount), + ) + } + + // Convert map keys to slice and sort them - this is to ensure the returned nodes are in a consistent order + services := make([]string, 0, len(servicesByName)) + for service := range servicesByName { + services = append(services, service) + } + sort.Strings(services) + + // Add node data in sorted order + for _, service := range services { + nodesFrame.AppendRow( + service, + service, + ) + } + + return []*data.Frame{nodesFrame, edgesFrame} +} diff --git a/pkg/tsdb/jaeger/querydata_test.go b/pkg/tsdb/jaeger/querydata_test.go index 8dc6dc3b0ad..7dbe86041ea 100644 --- a/pkg/tsdb/jaeger/querydata_test.go +++ b/pkg/tsdb/jaeger/querydata_test.go @@ -184,3 +184,97 @@ func TestTransformTraceResponse(t *testing.T) { 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{ + { + Parent: "serviceA", + Child: "serviceB", + CallCount: 1, + }, + { + Parent: "serviceA", + Child: "serviceC", + CallCount: 2, + }, + { + Parent: "serviceB", + Child: "serviceC", + CallCount: 3, + }, + }, + } + + frames := transformDependenciesResponse(dependencies, "test") + experimental.CheckGoldenJSONFrame(t, "./testdata", "simple_dependencies_nodes.golden", frames[0], false) + experimental.CheckGoldenJSONFrame(t, "./testdata", "simple_dependencies_edges.golden", frames[1], false) + }) + + t.Run("empty_dependencies", func(t *testing.T) { + dependencies := DependenciesResponse{ + Data: []ServiceDependency{}, + } + + frames := transformDependenciesResponse(dependencies, "test") + experimental.CheckGoldenJSONFrame(t, "./testdata", "empty_dependencies_nodes.golden", frames[0], false) + experimental.CheckGoldenJSONFrame(t, "./testdata", "empty_dependencies_edges.golden", frames[1], false) + }) + + t.Run("complex_dependencies", func(t *testing.T) { + dependencies := DependenciesResponse{ + Data: []ServiceDependency{ + { + Parent: "frontend", + Child: "auth-service", + CallCount: 150, + }, + { + Parent: "frontend", + Child: "api-gateway", + CallCount: 300, + }, + { + Parent: "api-gateway", + Child: "user-service", + CallCount: 200, + }, + { + Parent: "api-gateway", + Child: "order-service", + CallCount: 100, + }, + { + Parent: "order-service", + Child: "payment-service", + CallCount: 80, + }, + { + Parent: "order-service", + Child: "inventory-service", + CallCount: 90, + }, + { + Parent: "user-service", + Child: "database", + CallCount: 500, + }, + { + Parent: "payment-service", + Child: "database", + CallCount: 200, + }, + { + Parent: "inventory-service", + Child: "database", + CallCount: 300, + }, + }, + } + + frames := transformDependenciesResponse(dependencies, "test") + experimental.CheckGoldenJSONFrame(t, "./testdata", "complex_dependencies_nodes.golden", frames[0], false) + experimental.CheckGoldenJSONFrame(t, "./testdata", "complex_dependencies_edges.golden", frames[1], false) + }) +} diff --git a/pkg/tsdb/jaeger/testdata/complex_dependencies_edges.golden.jsonc b/pkg/tsdb/jaeger/testdata/complex_dependencies_edges.golden.jsonc new file mode 100644 index 00000000000..df3abb4f180 --- /dev/null +++ b/pkg/tsdb/jaeger/testdata/complex_dependencies_edges.golden.jsonc @@ -0,0 +1,127 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "preferredVisualisationType": "nodeGraph" +// } +// Name: test_edges +// Dimensions: 4 Fields by 9 Rows +// +----------------------------------+-------------------+-------------------+----------------+ +// | Name: id | Name: source | Name: target | Name: mainstat | +// | Labels: | Labels: | Labels: | Labels: | +// | Type: []string | Type: []string | Type: []string | Type: []int64 | +// +----------------------------------+-------------------+-------------------+----------------+ +// | frontend--auth-service | frontend | auth-service | 150 | +// | frontend--api-gateway | frontend | api-gateway | 300 | +// | api-gateway--user-service | api-gateway | user-service | 200 | +// | api-gateway--order-service | api-gateway | order-service | 100 | +// | order-service--payment-service | order-service | payment-service | 80 | +// | order-service--inventory-service | order-service | inventory-service | 90 | +// | user-service--database | user-service | database | 500 | +// | payment-service--database | payment-service | database | 200 | +// | inventory-service--database | inventory-service | database | 300 | +// +----------------------------------+-------------------+-------------------+----------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "name": "test_edges", + "meta": { + "typeVersion": [ + 0, + 0 + ], + "preferredVisualisationType": "nodeGraph" + }, + "fields": [ + { + "name": "id", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "source", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "target", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "mainstat", + "type": "number", + "typeInfo": { + "frame": "int64" + }, + "config": { + "displayName": "Call count" + } + } + ] + }, + "data": { + "values": [ + [ + "frontend--auth-service", + "frontend--api-gateway", + "api-gateway--user-service", + "api-gateway--order-service", + "order-service--payment-service", + "order-service--inventory-service", + "user-service--database", + "payment-service--database", + "inventory-service--database" + ], + [ + "frontend", + "frontend", + "api-gateway", + "api-gateway", + "order-service", + "order-service", + "user-service", + "payment-service", + "inventory-service" + ], + [ + "auth-service", + "api-gateway", + "user-service", + "order-service", + "payment-service", + "inventory-service", + "database", + "database", + "database" + ], + [ + 150, + 300, + 200, + 100, + 80, + 90, + 500, + 200, + 300 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/tsdb/jaeger/testdata/complex_dependencies_nodes.golden.jsonc b/pkg/tsdb/jaeger/testdata/complex_dependencies_nodes.golden.jsonc new file mode 100644 index 00000000000..f20e91ddba6 --- /dev/null +++ b/pkg/tsdb/jaeger/testdata/complex_dependencies_nodes.golden.jsonc @@ -0,0 +1,85 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "preferredVisualisationType": "nodeGraph" +// } +// Name: test_nodes +// Dimensions: 2 Fields by 8 Rows +// +-------------------+-------------------+ +// | Name: id | Name: title | +// | Labels: | Labels: | +// | Type: []string | Type: []string | +// +-------------------+-------------------+ +// | api-gateway | api-gateway | +// | auth-service | auth-service | +// | database | database | +// | frontend | frontend | +// | inventory-service | inventory-service | +// | order-service | order-service | +// | payment-service | payment-service | +// | user-service | user-service | +// +-------------------+-------------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "name": "test_nodes", + "meta": { + "typeVersion": [ + 0, + 0 + ], + "preferredVisualisationType": "nodeGraph" + }, + "fields": [ + { + "name": "id", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "title", + "type": "string", + "typeInfo": { + "frame": "string" + } + } + ] + }, + "data": { + "values": [ + [ + "api-gateway", + "auth-service", + "database", + "frontend", + "inventory-service", + "order-service", + "payment-service", + "user-service" + ], + [ + "api-gateway", + "auth-service", + "database", + "frontend", + "inventory-service", + "order-service", + "payment-service", + "user-service" + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/tsdb/jaeger/testdata/empty_dependencies_edges.golden.jsonc b/pkg/tsdb/jaeger/testdata/empty_dependencies_edges.golden.jsonc new file mode 100644 index 00000000000..cdfca484c20 --- /dev/null +++ b/pkg/tsdb/jaeger/testdata/empty_dependencies_edges.golden.jsonc @@ -0,0 +1,78 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "preferredVisualisationType": "nodeGraph" +// } +// Name: test_edges +// Dimensions: 4 Fields by 0 Rows +// +----------------+----------------+----------------+----------------+ +// | Name: id | Name: source | Name: target | Name: mainstat | +// | Labels: | Labels: | Labels: | Labels: | +// | Type: []string | Type: []string | Type: []string | Type: []int64 | +// +----------------+----------------+----------------+----------------+ +// +----------------+----------------+----------------+----------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "name": "test_edges", + "meta": { + "typeVersion": [ + 0, + 0 + ], + "preferredVisualisationType": "nodeGraph" + }, + "fields": [ + { + "name": "id", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "source", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "target", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "mainstat", + "type": "number", + "typeInfo": { + "frame": "int64" + }, + "config": { + "displayName": "Call count" + } + } + ] + }, + "data": { + "values": [ + [], + [], + [], + [] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/tsdb/jaeger/testdata/empty_dependencies_nodes.golden.jsonc b/pkg/tsdb/jaeger/testdata/empty_dependencies_nodes.golden.jsonc new file mode 100644 index 00000000000..ba5e5512620 --- /dev/null +++ b/pkg/tsdb/jaeger/testdata/empty_dependencies_nodes.golden.jsonc @@ -0,0 +1,59 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "preferredVisualisationType": "nodeGraph" +// } +// Name: test_nodes +// Dimensions: 2 Fields by 0 Rows +// +----------------+----------------+ +// | Name: id | Name: title | +// | Labels: | Labels: | +// | Type: []string | Type: []string | +// +----------------+----------------+ +// +----------------+----------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "name": "test_nodes", + "meta": { + "typeVersion": [ + 0, + 0 + ], + "preferredVisualisationType": "nodeGraph" + }, + "fields": [ + { + "name": "id", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "title", + "type": "string", + "typeInfo": { + "frame": "string" + } + } + ] + }, + "data": { + "values": [ + [], + [] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/tsdb/jaeger/testdata/simple_dependencies_edges.golden.jsonc b/pkg/tsdb/jaeger/testdata/simple_dependencies_edges.golden.jsonc new file mode 100644 index 00000000000..37a0845274f --- /dev/null +++ b/pkg/tsdb/jaeger/testdata/simple_dependencies_edges.golden.jsonc @@ -0,0 +1,97 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "preferredVisualisationType": "nodeGraph" +// } +// Name: test_edges +// Dimensions: 4 Fields by 3 Rows +// +--------------------+----------------+----------------+----------------+ +// | Name: id | Name: source | Name: target | Name: mainstat | +// | Labels: | Labels: | Labels: | Labels: | +// | Type: []string | Type: []string | Type: []string | Type: []int64 | +// +--------------------+----------------+----------------+----------------+ +// | serviceA--serviceB | serviceA | serviceB | 1 | +// | serviceA--serviceC | serviceA | serviceC | 2 | +// | serviceB--serviceC | serviceB | serviceC | 3 | +// +--------------------+----------------+----------------+----------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "name": "test_edges", + "meta": { + "typeVersion": [ + 0, + 0 + ], + "preferredVisualisationType": "nodeGraph" + }, + "fields": [ + { + "name": "id", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "source", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "target", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "mainstat", + "type": "number", + "typeInfo": { + "frame": "int64" + }, + "config": { + "displayName": "Call count" + } + } + ] + }, + "data": { + "values": [ + [ + "serviceA--serviceB", + "serviceA--serviceC", + "serviceB--serviceC" + ], + [ + "serviceA", + "serviceA", + "serviceB" + ], + [ + "serviceB", + "serviceC", + "serviceC" + ], + [ + 1, + 2, + 3 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/tsdb/jaeger/testdata/simple_dependencies_nodes.golden.jsonc b/pkg/tsdb/jaeger/testdata/simple_dependencies_nodes.golden.jsonc new file mode 100644 index 00000000000..56bb35cdd5d --- /dev/null +++ b/pkg/tsdb/jaeger/testdata/simple_dependencies_nodes.golden.jsonc @@ -0,0 +1,70 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] { +// "typeVersion": [ +// 0, +// 0 +// ], +// "preferredVisualisationType": "nodeGraph" +// } +// Name: test_nodes +// Dimensions: 2 Fields by 3 Rows +// +----------------+----------------+ +// | Name: id | Name: title | +// | Labels: | Labels: | +// | Type: []string | Type: []string | +// +----------------+----------------+ +// | serviceA | serviceA | +// | serviceB | serviceB | +// | serviceC | serviceC | +// +----------------+----------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "status": 200, + "frames": [ + { + "schema": { + "name": "test_nodes", + "meta": { + "typeVersion": [ + 0, + 0 + ], + "preferredVisualisationType": "nodeGraph" + }, + "fields": [ + { + "name": "id", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "title", + "type": "string", + "typeInfo": { + "frame": "string" + } + } + ] + }, + "data": { + "values": [ + [ + "serviceA", + "serviceB", + "serviceC" + ], + [ + "serviceA", + "serviceB", + "serviceC" + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/public/app/plugins/datasource/jaeger/datasource.ts b/public/app/plugins/datasource/jaeger/datasource.ts index 3c7b33c2109..c0cca5ad098 100644 --- a/public/app/plugins/datasource/jaeger/datasource.ts +++ b/public/app/plugins/datasource/jaeger/datasource.ts @@ -72,10 +72,15 @@ export class JaegerDatasource extends DataSourceWithBackend !target.queryType); + const allTargetsDependencyGraph = options.targets.every((target) => target.queryType === 'dependencyGraph'); // We have not migrated the node graph to the backend // If the node graph is disabled, we can use the backend migration const nodeGraphDisabled = !this.nodeGraph?.enabled; - if (config.featureToggles.jaegerBackendMigration && allTargetsTraceIdQuery && nodeGraphDisabled) { + if ( + config.featureToggles.jaegerBackendMigration && + (allTargetsTraceIdQuery || allTargetsDependencyGraph) && + nodeGraphDisabled + ) { return super.query(options); }