Fix: correctly close trace span in Prometheus and Loki data sources (#57774)

* rename span for loki
This commit is contained in:
Yuriy Tseretyan
2022-10-28 10:17:56 -04:00
committed by GitHub
parent 6126f56ef0
commit fa043efb2c
2 changed files with 64 additions and 59 deletions

View File

@@ -122,72 +122,77 @@ func (b *Buffered) runQueries(ctx context.Context, queries []*PrometheusQuery) (
Responses: backend.Responses{},
}
for _, query := range queries {
ctx, endSpan := utils.StartTrace(ctx, b.tracer, "datasource.prometheus", []utils.Attribute{
{Key: "expr", Value: query.Expr, Kv: attribute.Key("expr").String(query.Expr)},
{Key: "start_unixnano", Value: query.Start, Kv: attribute.Key("start_unixnano").Int64(query.Start.UnixNano())},
{Key: "stop_unixnano", Value: query.End, Kv: attribute.Key("stop_unixnano").Int64(query.End.UnixNano())},
})
defer endSpan()
logger := b.log.FromContext(ctx) // read trace-id and other info from the context
logger.Debug("Sending query", "start", query.Start, "end", query.End, "step", query.Step, "query", query.Expr)
response := make(map[TimeSeriesQueryType]interface{})
timeRange := apiv1.Range{
Step: query.Step,
// Align query range to step. It rounds start and end down to a multiple of step.
Start: alignTimeRange(query.Start, query.Step, query.UtcOffsetSec),
End: alignTimeRange(query.End, query.Step, query.UtcOffsetSec),
}
if query.RangeQuery {
rangeResponse, _, err := b.client.QueryRange(ctx, query.Expr, timeRange)
if err != nil {
logger.Error("Range query failed", "query", query.Expr, "err", err)
result.Responses[query.RefId] = backend.DataResponse{Error: err}
continue
}
response[RangeQueryType] = rangeResponse
}
if query.InstantQuery {
instantResponse, _, err := b.client.Query(ctx, query.Expr, query.End)
if err != nil {
logger.Error("Instant query failed", "query", query.Expr, "err", err)
result.Responses[query.RefId] = backend.DataResponse{Error: err}
continue
}
response[InstantQueryType] = instantResponse
}
// This is a special case
// If exemplar query returns error, we want to only log it and continue with other results processing
if query.ExemplarQuery {
exemplarResponse, err := b.client.QueryExemplars(ctx, query.Expr, timeRange.Start, timeRange.End)
if err != nil {
logger.Error("Exemplar query failed", "query", query.Expr, "err", err)
} else {
response[ExemplarQueryType] = exemplarResponse
}
}
frames, err := parseTimeSeriesResponse(response, query)
response, err := b.runQuery(ctx, query)
if err != nil {
return &result, err
}
result.Responses[query.RefId] = response
}
return &result, nil
}
// The ExecutedQueryString can be viewed in QueryInspector in UI
for _, frame := range frames {
frame.Meta.ExecutedQueryString = "Expr: " + query.Expr + "\n" + "Step: " + query.Step.String()
func (b *Buffered) runQuery(ctx context.Context, query *PrometheusQuery) (backend.DataResponse, error) {
ctx, endSpan := utils.StartTrace(ctx, b.tracer, "datasource.prometheus", []utils.Attribute{
{Key: "expr", Value: query.Expr, Kv: attribute.Key("expr").String(query.Expr)},
{Key: "start_unixnano", Value: query.Start, Kv: attribute.Key("start_unixnano").Int64(query.Start.UnixNano())},
{Key: "stop_unixnano", Value: query.End, Kv: attribute.Key("stop_unixnano").Int64(query.End.UnixNano())},
})
defer endSpan()
logger := b.log.FromContext(ctx) // read trace-id and other info from the context
logger.Debug("Sending query", "start", query.Start, "end", query.End, "step", query.Step, "query", query.Expr)
response := make(map[TimeSeriesQueryType]interface{})
timeRange := apiv1.Range{
Step: query.Step,
// Align query range to step. It rounds start and end down to a multiple of step.
Start: alignTimeRange(query.Start, query.Step, query.UtcOffsetSec),
End: alignTimeRange(query.End, query.Step, query.UtcOffsetSec),
}
if query.RangeQuery {
rangeResponse, _, err := b.client.QueryRange(ctx, query.Expr, timeRange)
if err != nil {
logger.Error("Range query failed", "query", query.Expr, "err", err)
return backend.DataResponse{Error: err}, nil
}
response[RangeQueryType] = rangeResponse
}
result.Responses[query.RefId] = backend.DataResponse{
Frames: frames,
if query.InstantQuery {
instantResponse, _, err := b.client.Query(ctx, query.Expr, query.End)
if err != nil {
logger.Error("Instant query failed", "query", query.Expr, "err", err)
return backend.DataResponse{Error: err}, nil
}
response[InstantQueryType] = instantResponse
}
// This is a special case
// If exemplar query returns error, we want to only log it and continue with other results processing
if query.ExemplarQuery {
exemplarResponse, err := b.client.QueryExemplars(ctx, query.Expr, timeRange.Start, timeRange.End)
if err != nil {
logger.Error("Exemplar query failed", "query", query.Expr, "err", err)
} else {
response[ExemplarQueryType] = exemplarResponse
}
}
return &result, nil
frames, err := parseTimeSeriesResponse(response, query)
if err != nil {
return backend.DataResponse{}, err
}
// The ExecutedQueryString can be viewed in QueryInspector in UI
for _, frame := range frames {
frame.Meta.ExecutedQueryString = "Expr: " + query.Expr + "\n" + "Step: " + query.Step.String()
}
return backend.DataResponse{
Frames: frames,
}, nil
}
func formatLegend(metric model.Metric, query *PrometheusQuery) string {