Jaeger: forward request context on HTTP calls so auth headers are sent (#119573)

* forward request context on HTTP calls so auth headers are sent

* apply suggestions
This commit is contained in:
Gareth
2026-03-05 10:57:19 +00:00
committed by GitHub
parent 0d611c375b
commit 9d1119b71e
7 changed files with 51 additions and 32 deletions
+8 -6
View File
@@ -31,13 +31,14 @@ func (s *Service) withDatasourceHandlerFunc(getHandler func(d *datasourceInfo) h
func getServicesHandler(ds *datasourceInfo) http.HandlerFunc {
return func(rw http.ResponseWriter, r *http.Request) {
cfg := backend.GrafanaConfigFromContext(r.Context())
ctx := r.Context()
cfg := backend.GrafanaConfigFromContext(ctx)
var services []string
var err error
if cfg.FeatureToggles().IsEnabled("jaegerEnableGrpcEndpoint") {
services, err = ds.JaegerClient.GrpcServices()
services, err = ds.JaegerClient.GrpcServices(ctx)
} else {
services, err = ds.JaegerClient.Services()
services, err = ds.JaegerClient.Services(ctx)
}
writeResponse(services, err, rw, ds.JaegerClient.logger)
}
@@ -45,14 +46,15 @@ func getServicesHandler(ds *datasourceInfo) http.HandlerFunc {
func getOperationsHandler(ds *datasourceInfo) http.HandlerFunc {
return func(rw http.ResponseWriter, r *http.Request) {
cfg := backend.GrafanaConfigFromContext(r.Context())
ctx := r.Context()
cfg := backend.GrafanaConfigFromContext(ctx)
service := strings.TrimSpace(r.PathValue("service"))
var operations []string
var err error
if cfg.FeatureToggles().IsEnabled("jaegerEnableGrpcEndpoint") {
operations, err = ds.JaegerClient.GrpcOperations(service)
operations, err = ds.JaegerClient.GrpcOperations(ctx, service)
} else {
operations, err = ds.JaegerClient.Operations(service)
operations, err = ds.JaegerClient.Operations(ctx, service)
}
writeResponse(operations, err, rw, ds.JaegerClient.logger)
}
+26 -8
View File
@@ -33,7 +33,25 @@ func New(hc *http.Client, logger log.Logger, settings backend.DataSourceInstance
return client, nil
}
func (j *JaegerClient) Services() ([]string, error) {
// doGet performs a GET request with the given context so that contextual HTTP middleware
// (e.g. Forward OAuth Identity, x-grafana-id) can attach headers to the outgoing request.
func (j *JaegerClient) doGet(ctx context.Context, rawURL string) (*http.Response, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil)
if err != nil {
return nil, err
}
res, err := j.httpClient.Do(req)
if err != nil {
j.logger.Error("Jaeger request failed", "error", err)
return nil, err
}
if res != nil && res.StatusCode/100 != 2 {
j.logger.Warn("Jaeger request returned non-2xx status", "status", res.StatusCode, "statusText", res.Status)
}
return res, nil
}
func (j *JaegerClient) Services(ctx context.Context) ([]string, error) {
var response types.ServicesResponse
services := []string{}
@@ -42,7 +60,7 @@ func (j *JaegerClient) Services() ([]string, error) {
return services, backend.DownstreamErrorf("failed to join url: %w", err)
}
res, err := j.httpClient.Get(u)
res, err := j.doGet(ctx, u)
if err != nil {
return services, err
}
@@ -61,7 +79,7 @@ func (j *JaegerClient) Services() ([]string, error) {
return services, err
}
func (j *JaegerClient) Operations(s string) ([]string, error) {
func (j *JaegerClient) Operations(ctx context.Context, s string) ([]string, error) {
var response types.ServicesResponse
operations := []string{}
@@ -70,7 +88,7 @@ func (j *JaegerClient) Operations(s string) ([]string, error) {
return operations, backend.DownstreamErrorf("failed to join url: %w", err)
}
res, err := j.httpClient.Get(u)
res, err := j.doGet(ctx, u)
if err != nil {
return operations, err
}
@@ -89,7 +107,7 @@ func (j *JaegerClient) Operations(s string) ([]string, error) {
return operations, err
}
func (j *JaegerClient) Search(query *JaegerQuery, start, end int64) (*data.Frame, error) {
func (j *JaegerClient) Search(ctx context.Context, query *JaegerQuery, start, end int64) (*data.Frame, error) {
u, err := url.JoinPath(j.url, "/api/traces")
if err != nil {
return nil, backend.DownstreamErrorf("failed to join url path: %w", err)
@@ -147,7 +165,7 @@ func (j *JaegerClient) Search(query *JaegerQuery, start, end int64) (*data.Frame
}
jaegerURL.RawQuery = urlQuery.Encode()
resp, err := j.httpClient.Get(jaegerURL.String())
resp, err := j.doGet(ctx, jaegerURL.String())
if err != nil {
if backend.IsDownstreamHTTPError(err) {
return nil, backend.DownstreamError(err)
@@ -217,7 +235,7 @@ func (j *JaegerClient) Trace(ctx context.Context, traceID string, start, end int
}
}
res, err := j.httpClient.Get(traceUrl)
res, err := j.doGet(ctx, traceUrl)
if err != nil {
if backend.IsDownstreamHTTPError(err) {
return nil, backend.DownstreamError(err)
@@ -276,7 +294,7 @@ func (j *JaegerClient) Dependencies(ctx context.Context, start, end int64) (type
parsedURL.RawQuery = query.Encode()
u = parsedURL.String()
res, err := j.httpClient.Get(u)
res, err := j.doGet(ctx, u)
if err != nil {
if backend.IsDownstreamHTTPError(err) {
return dependencies, backend.DownstreamError(err)
+5 -6
View File
@@ -1,7 +1,6 @@
package jaeger
import (
"context"
"encoding/json"
"errors"
"fmt"
@@ -67,7 +66,7 @@ func TestJaegerClient_Services(t *testing.T) {
client, err := New(server.Client(), log.NewNullLogger(), settings)
assert.NoError(t, err)
services, err := client.Services()
services, err := client.Services(t.Context())
if tt.expectError {
assert.Error(t, err)
@@ -159,7 +158,7 @@ func TestJaegerClient_Operations(t *testing.T) {
client, err := New(server.Client(), log.NewNullLogger(), settings)
assert.NoError(t, err)
operations, err := client.Operations(tt.service)
operations, err := client.Operations(t.Context(), tt.service)
if tt.expectError {
assert.Error(t, err)
@@ -265,7 +264,7 @@ func TestJaegerClient_Search(t *testing.T) {
client, err := New(server.Client(), log.NewNullLogger(), settings)
assert.NoError(t, err)
traces, err := client.Search(tt.query, tt.start, tt.end)
traces, err := client.Search(t.Context(), tt.query, tt.start, tt.end)
if tt.expectError {
assert.Error(t, err)
@@ -379,7 +378,7 @@ func TestJaegerClient_Trace(t *testing.T) {
client, err := New(server.Client(), log.NewNullLogger(), settings)
assert.NoError(t, err)
trace, err := client.Trace(context.Background(), tt.traceId, tt.start, tt.end, "A")
trace, err := client.Trace(t.Context(), tt.traceId, tt.start, tt.end, "A")
if tt.expectError {
assert.Error(t, err)
@@ -491,7 +490,7 @@ func TestJaegerClient_Dependencies(t *testing.T) {
client, err := New(server.Client(), log.NewNullLogger(), settings)
assert.NoError(t, err)
dependencies, err := client.Dependencies(context.Background(), tt.start, tt.end)
dependencies, err := client.Dependencies(t.Context(), tt.start, tt.end)
if tt.expectError {
assert.Error(t, err)
+7 -7
View File
@@ -16,7 +16,7 @@ import (
"github.com/grafana/grafana/pkg/tsdb/jaeger/utils"
)
func (j *JaegerClient) GrpcServices() ([]string, error) {
func (j *JaegerClient) GrpcServices(ctx context.Context) ([]string, error) {
var response types.GrpcServicesResponse
services := []string{}
@@ -25,7 +25,7 @@ func (j *JaegerClient) GrpcServices() ([]string, error) {
return services, backend.DownstreamErrorf("failed to join url: %w", err)
}
res, err := j.httpClient.Get(u)
res, err := j.doGet(ctx, u)
if err != nil {
if backend.IsDownstreamHTTPError(err) {
return services, backend.DownstreamError(err)
@@ -55,7 +55,7 @@ func (j *JaegerClient) GrpcServices() ([]string, error) {
return services, nil
}
func (j *JaegerClient) GrpcOperations(s string) ([]string, error) {
func (j *JaegerClient) GrpcOperations(ctx context.Context, s string) ([]string, error) {
var response types.GrpcOperationsResponse
operations := []string{}
@@ -73,7 +73,7 @@ func (j *JaegerClient) GrpcOperations(s string) ([]string, error) {
urlQuery.Set("service", s)
jaegerURL.RawQuery = urlQuery.Encode()
res, err := j.httpClient.Get(jaegerURL.String())
res, err := j.doGet(ctx, jaegerURL.String())
if err != nil {
if backend.IsDownstreamHTTPError(err) {
return operations, backend.DownstreamError(err)
@@ -109,7 +109,7 @@ func (j *JaegerClient) GrpcOperations(s string) ([]string, error) {
// Note that this and all functionality around search is not yet being used. Once Jaeger adds support for attributes and limit parameters
// we will be able to start using this and routing traffic to the new API based on the feature flag.
func (j *JaegerClient) GrpcSearch(query *JaegerQuery, start, end time.Time) (*data.Frame, error) {
func (j *JaegerClient) GrpcSearch(ctx context.Context, query *JaegerQuery, start, end time.Time) (*data.Frame, error) {
u, err := url.JoinPath(j.url, "/api/v3/traces")
if err != nil {
return nil, backend.DownstreamErrorf("failed to join url path: %w", err)
@@ -159,7 +159,7 @@ func (j *JaegerClient) GrpcSearch(query *JaegerQuery, start, end time.Time) (*da
jaegerURL.RawQuery = urlQuery.Encode()
// jaeger will not be able to process the request if the time is encoded, all other parameters are encoded except for the start and end time
jaegerURL.RawQuery += fmt.Sprintf("&query.start_time_min=%s&query.start_time_max=%s", start.Format(time.RFC3339Nano), end.Format(time.RFC3339Nano))
resp, err := j.httpClient.Get(jaegerURL.String())
resp, err := j.doGet(ctx, jaegerURL.String())
if err != nil {
if backend.IsDownstreamHTTPError(err) {
return nil, backend.DownstreamError(err)
@@ -231,7 +231,7 @@ func (j *JaegerClient) GrpcTrace(ctx context.Context, traceID string, start, end
}
}
res, err := j.httpClient.Get(traceUrl)
res, err := j.doGet(ctx, traceUrl)
if err != nil {
if backend.IsDownstreamHTTPError(err) {
return nil, backend.DownstreamError(err)
+2 -2
View File
@@ -69,7 +69,7 @@ func TestJaegerGrpcClient_Services(t *testing.T) {
client, err := New(server.Client(), log.NewNullLogger(), settings)
assert.NoError(t, err)
services, err := client.GrpcServices()
services, err := client.GrpcServices(context.Background())
if tt.expectError {
assert.Error(t, err)
@@ -387,7 +387,7 @@ func TestJaegerGrpcClient_Operations(t *testing.T) {
client, err := New(server.Client(), log.NewNullLogger(), settings)
assert.NoError(t, err)
operations, err := client.GrpcOperations(tt.service)
operations, err := client.GrpcOperations(context.Background(), tt.service)
if tt.expectError {
assert.Error(t, err)
+2 -2
View File
@@ -93,9 +93,9 @@ func (s *Service) CheckHealth(ctx context.Context, req *backend.CheckHealthReque
var servicesErr error
if cfg.FeatureToggles().IsEnabled("jaegerEnableGrpcEndpoint") {
_, servicesErr = client.JaegerClient.GrpcServices()
_, servicesErr = client.JaegerClient.GrpcServices(ctx)
} else {
_, servicesErr = client.JaegerClient.Services()
_, servicesErr = client.JaegerClient.Services(ctx)
}
if servicesErr != nil {
+1 -1
View File
@@ -51,7 +51,7 @@ func queryData(ctx context.Context, dsInfo *datasourceInfo, req *backend.QueryDa
// Handle "Search" query type
if query.QueryType == "search" {
// TODO: enable routing to gRPC when ready, currently pending on: https://github.com/jaegertracing/jaeger/issues/7594
frames, err := dsInfo.JaegerClient.Search(&query, q.TimeRange.From.UnixMicro(), q.TimeRange.To.UnixMicro())
frames, err := dsInfo.JaegerClient.Search(ctx, &query, q.TimeRange.From.UnixMicro(), q.TimeRange.To.UnixMicro())
if err != nil {
response.Responses[q.RefID] = backend.ErrorResponseWithErrorSource(err)
continue