newTraceIDV2Handler 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.GRPCCombiner[*tempopb.TraceByIDResponse], logger log.Logger, dataAccessController DataAccessController)
| 86 | |
| 87 | // newTraceIDV2Handler creates a http.handler for trace by id requests |
| 88 | func newTraceIDV2Handler(cfg Config, next pipeline.AsyncRoundTripper[combiner.PipelineResponse], o overrides.Interface, combinerFn func(int, api.MarshallingFormat, combiner.TraceRedactor) combiner.GRPCCombiner[*tempopb.TraceByIDResponse], logger log.Logger, dataAccessController DataAccessController) http.RoundTripper { |
| 89 | postSLOHook := traceByIDSLOPostHook(cfg.TraceByID.SLO) |
| 90 | |
| 91 | return RoundTripperFunc(func(req *http.Request) (*http.Response, error) { |
| 92 | tenant, errResp := extractTenant(req, logger) |
| 93 | if errResp != nil { |
| 94 | return errResp, nil |
| 95 | } |
| 96 | |
| 97 | // validate traceID |
| 98 | _, err := api.ParseTraceID(req) |
| 99 | if err != nil { |
| 100 | return httpInvalidRequest(err), nil |
| 101 | } |
| 102 | |
| 103 | // validate start and end parameter |
| 104 | _, _, _, _, _, reqErr := api.ValidateAndSanitizeRequest(req) |
| 105 | if reqErr != nil { |
| 106 | return httpInvalidRequest(reqErr), nil |
| 107 | } |
| 108 | |
| 109 | // check marshalling format |
| 110 | marshallingFormat := api.MarshalingFormatFromAcceptHeader(req.Header) |
| 111 | |
| 112 | // enforce all communication internal to Tempo to be in protobuf bytes |
| 113 | req.Header.Set(api.HeaderAccept, api.HeaderAcceptProtobuf) |
| 114 | |
| 115 | level.Info(logger).Log( |
| 116 | "msg", "trace id request", |
| 117 | "tenant", tenant, |
| 118 | "path", req.URL.Path) |
| 119 | |
| 120 | var traceRedactor combiner.TraceRedactor |
| 121 | if dataAccessController != nil { |
| 122 | traceRedactor, err = dataAccessController.HandleHTTPTraceByIDReq(req) |
| 123 | if err != nil { |
| 124 | level.Error(logger).Log("msg", "trace id v2: failed to get trace redactor", "err", err) |
| 125 | return httpInvalidRequest(err), nil |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | comb := combinerFn(o.MaxBytesPerTrace(tenant), marshallingFormat, traceRedactor) |
| 130 | rt := pipeline.NewHTTPCollector(next, cfg.ResponseConsumers, comb) |
| 131 | |
| 132 | start := time.Now() |
| 133 | resp, err := rt.RoundTrip(req) |
| 134 | elapsed := time.Since(start) |
| 135 | |
| 136 | var bytesProcessed uint64 |
| 137 | findResp, _ := comb.GRPCFinal() |
| 138 | if findResp != nil && findResp.Metrics != nil { |
| 139 | bytesProcessed = findResp.Metrics.InspectedBytes |
| 140 | } |
| 141 | |
| 142 | postSLOHook(resp, tenant, bytesProcessed, elapsed, err) |
| 143 | |
| 144 | traceID, _ := tracing.ExtractTraceID(req.Context()) |
| 145 | level.Info(logger).Log( |
no test coverage detected