newTraceIDHandler creates a http.handler for trace by id requests
(cfg Config, next pipeline.AsyncRoundTripper[combiner.PipelineResponse], o overrides.Interface, combinerFn func(int, api.MarshallingFormat, combiner.TraceRedactor) *combiner.TraceByIDCombiner, logger log.Logger, dataAccessController DataAccessController)
| 16 | |
| 17 | // newTraceIDHandler creates a http.handler for trace by id requests |
| 18 | func newTraceIDHandler(cfg Config, next pipeline.AsyncRoundTripper[combiner.PipelineResponse], o overrides.Interface, combinerFn func(int, api.MarshallingFormat, combiner.TraceRedactor) *combiner.TraceByIDCombiner, logger log.Logger, dataAccessController DataAccessController) http.RoundTripper { |
| 19 | postSLOHook := traceByIDSLOPostHook(cfg.TraceByID.SLO) |
| 20 | |
| 21 | return RoundTripperFunc(func(req *http.Request) (*http.Response, error) { |
| 22 | tenant, errResp := extractTenant(req, logger) |
| 23 | if errResp != nil { |
| 24 | return errResp, nil |
| 25 | } |
| 26 | |
| 27 | // validate traceID |
| 28 | _, err := api.ParseTraceID(req) |
| 29 | if err != nil { |
| 30 | return httpInvalidRequest(err), nil |
| 31 | } |
| 32 | |
| 33 | // validate start and end parameter |
| 34 | _, _, _, _, _, reqErr := api.ValidateAndSanitizeRequest(req) |
| 35 | if reqErr != nil { |
| 36 | return httpInvalidRequest(reqErr), nil |
| 37 | } |
| 38 | |
| 39 | // check marshalling format |
| 40 | marshallingFormat := api.MarshalingFormatFromAcceptHeader(req.Header) |
| 41 | |
| 42 | // enforce all communication internal to Tempo to be in protobuf bytes |
| 43 | req.Header.Set(api.HeaderAccept, api.HeaderAcceptProtobuf) |
| 44 | |
| 45 | level.Info(logger).Log( |
| 46 | "msg", "trace id request", |
| 47 | "tenant", tenant, |
| 48 | "path", req.URL.Path) |
| 49 | |
| 50 | var traceRedactor combiner.TraceRedactor |
| 51 | if dataAccessController != nil { |
| 52 | traceRedactor, err = dataAccessController.HandleHTTPTraceByIDReq(req) |
| 53 | if err != nil { |
| 54 | level.Error(logger).Log("msg", "trace id: failed to get trace redactor", "err", err) |
| 55 | return httpInvalidRequest(err), nil |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | comb := combinerFn(o.MaxBytesPerTrace(tenant), marshallingFormat, traceRedactor) |
| 60 | rt := pipeline.NewHTTPCollector(next, cfg.ResponseConsumers, comb) |
| 61 | |
| 62 | start := time.Now() |
| 63 | resp, err := rt.RoundTrip(req) |
| 64 | elapsed := time.Since(start) |
| 65 | |
| 66 | var inspectBytes uint64 |
| 67 | if comb.MetricsCombiner != nil && comb.MetricsCombiner.Metrics != nil { |
| 68 | inspectBytes = comb.MetricsCombiner.Metrics.InspectedBytes |
| 69 | } |
| 70 | postSLOHook(resp, tenant, inspectBytes, elapsed, err) |
| 71 | |
| 72 | traceID, _ := tracing.ExtractTraceID(req.Context()) |
| 73 | level.Info(logger).Log( |
| 74 | "msg", "trace id response", |
| 75 | "tenant", tenant, |
no test coverage detected