Jaeger: Run dependency graph queries through backend behind the feature toggle (#103768)
* Start with dependency graph * Update and add tests * Fix lint and ordering in test
This commit is contained in:
@@ -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}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user