Loki: Improve backend instrumentation of QueryData calls (#73807)
* improve loki `queryData` instrumentation * fix lint * use correct logger in "queryData" * capitalize log messages * distinguish between requests from alerting
This commit is contained in:
+19
-13
@@ -14,11 +14,13 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
ngalertmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/tsdb/loki/kinds/dataquery"
|
||||
)
|
||||
|
||||
@@ -122,7 +124,7 @@ func callResource(ctx context.Context, req *backend.CallResourceRequest, sender
|
||||
span.SetAttributes("url", lokiURL, attribute.Key("url").String(lokiURL))
|
||||
defer span.End()
|
||||
|
||||
api := newLokiAPI(dsInfo.HTTPClient, dsInfo.URL, plog)
|
||||
api := newLokiAPI(dsInfo.HTTPClient, dsInfo.URL, plog, tracer)
|
||||
rawLokiResponse, err := api.RawQuery(ctx, lokiURL)
|
||||
|
||||
if err != nil {
|
||||
@@ -144,7 +146,10 @@ func callResource(ctx context.Context, req *backend.CallResourceRequest, sender
|
||||
|
||||
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||
dsInfo, err := s.getDSInfo(ctx, req.PluginContext)
|
||||
_, fromAlert := req.Headers[ngalertmodels.FromAlertHeaderName]
|
||||
logger := logger.FromContext(ctx).New("api", "QueryData", "fromAlert", fromAlert)
|
||||
if err != nil {
|
||||
logger.Error("Failed to get data source info", "err", err)
|
||||
result := backend.NewQueryDataResponse()
|
||||
return result, err
|
||||
}
|
||||
@@ -154,21 +159,22 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
||||
logsDataplane: s.features.IsEnabled(featuremgmt.FlagLokiLogsDataplane),
|
||||
}
|
||||
|
||||
return queryData(ctx, req, dsInfo, responseOpts, s.tracer)
|
||||
return queryData(ctx, req, dsInfo, responseOpts, s.tracer, logger)
|
||||
}
|
||||
|
||||
func queryData(ctx context.Context, req *backend.QueryDataRequest, dsInfo *datasourceInfo, responseOpts ResponseOpts, tracer tracing.Tracer) (*backend.QueryDataResponse, error) {
|
||||
func queryData(ctx context.Context, req *backend.QueryDataRequest, dsInfo *datasourceInfo, responseOpts ResponseOpts, tracer tracing.Tracer, plog log.Logger) (*backend.QueryDataResponse, error) {
|
||||
result := backend.NewQueryDataResponse()
|
||||
|
||||
api := newLokiAPI(dsInfo.HTTPClient, dsInfo.URL, logger.FromContext(ctx))
|
||||
api := newLokiAPI(dsInfo.HTTPClient, dsInfo.URL, plog, tracer)
|
||||
|
||||
queries, err := parseQuery(req)
|
||||
if err != nil {
|
||||
plog.Error("Failed to parse queries", "err", err)
|
||||
return result, err
|
||||
}
|
||||
|
||||
for _, query := range queries {
|
||||
ctx, span := tracer.Start(ctx, "datasource.loki")
|
||||
ctx, span := tracer.Start(ctx, "datasource.loki.queryData.runQuery")
|
||||
span.SetAttributes("expr", query.Expr, attribute.Key("expr").String(query.Expr))
|
||||
span.SetAttributes("start_unixnano", query.Start, attribute.Key("start_unixnano").Int64(query.Start.UnixNano()))
|
||||
span.SetAttributes("stop_unixnano", query.End, attribute.Key("stop_unixnano").Int64(query.End.UnixNano()))
|
||||
@@ -177,21 +183,20 @@ func queryData(ctx context.Context, req *backend.QueryDataRequest, dsInfo *datas
|
||||
span.SetAttributes("query_group_id", req.GetHTTPHeader("X-Query-Group-Id"), attribute.Key("query_group_id").String(req.GetHTTPHeader("X-Query-Group-Id")))
|
||||
}
|
||||
|
||||
logger := logger.FromContext(ctx) // get logger with trace-id and other contextual info
|
||||
logger.Debug("Sending query", "start", query.Start, "end", query.End, "step", query.Step, "query", query.Expr)
|
||||
|
||||
frames, err := runQuery(ctx, api, query, responseOpts)
|
||||
|
||||
span.End()
|
||||
queryRes := backend.DataResponse{}
|
||||
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
queryRes.Error = err
|
||||
} else {
|
||||
queryRes.Frames = frames
|
||||
}
|
||||
|
||||
result.Responses[query.RefID] = queryRes
|
||||
span.End()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@@ -200,14 +205,15 @@ func queryData(ctx context.Context, req *backend.QueryDataRequest, dsInfo *datas
|
||||
func runQuery(ctx context.Context, api *LokiAPI, query *lokiQuery, responseOpts ResponseOpts) (data.Frames, error) {
|
||||
frames, err := api.DataQuery(ctx, *query, responseOpts)
|
||||
if err != nil {
|
||||
logger.Error("Error querying loki", "err", err)
|
||||
return data.Frames{}, err
|
||||
}
|
||||
|
||||
for _, frame := range frames {
|
||||
if err = adjustFrame(frame, query, !responseOpts.metricDataplane, responseOpts.logsDataplane); err != nil {
|
||||
return data.Frames{}, err
|
||||
}
|
||||
err = adjustFrame(frame, query, !responseOpts.metricDataplane, responseOpts.logsDataplane)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("Error adjusting frame", "err", err)
|
||||
return data.Frames{}, err
|
||||
}
|
||||
}
|
||||
@@ -223,7 +229,7 @@ func (s *Service) getDSInfo(ctx context.Context, pluginCtx backend.PluginContext
|
||||
|
||||
instance, ok := i.(*datasourceInfo)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to cast datsource info")
|
||||
return nil, fmt.Errorf("failed to cast data source info")
|
||||
}
|
||||
|
||||
return instance, nil
|
||||
|
||||
Reference in New Issue
Block a user