New returns a new QueryFrontend
(cfg Config, next pipeline.RoundTripper, o overrides.Interface, reader tempodb.Reader, cacheProvider cache.Provider, apiPrefix string, authMiddleware middleware.Interface, dataAccessController DataAccessController, logger log.Logger, registerer prometheus.Registerer)
| 85 | |
| 86 | // New returns a new QueryFrontend |
| 87 | func New(cfg Config, next pipeline.RoundTripper, o overrides.Interface, reader tempodb.Reader, cacheProvider cache.Provider, apiPrefix string, authMiddleware middleware.Interface, dataAccessController DataAccessController, logger log.Logger, registerer prometheus.Registerer) (*QueryFrontend, error) { |
| 88 | level.Info(logger).Log("msg", "creating middleware in query frontend") |
| 89 | |
| 90 | if cfg.TraceByID.QueryShards < minQueryShards || cfg.TraceByID.QueryShards > maxQueryShards { |
| 91 | return nil, fmt.Errorf("frontend query shards should be between %d and %d (both inclusive)", minQueryShards, maxQueryShards) |
| 92 | } |
| 93 | |
| 94 | if cfg.Search.Sharder.ConcurrentRequests <= 0 { |
| 95 | return nil, fmt.Errorf("frontend search concurrent requests should be greater than 0") |
| 96 | } |
| 97 | |
| 98 | if cfg.Search.Sharder.TargetBytesPerRequest <= 0 { |
| 99 | return nil, fmt.Errorf("frontend search target bytes per request should be greater than 0") |
| 100 | } |
| 101 | |
| 102 | if cfg.Search.Sharder.MostRecentShards <= 0 { |
| 103 | return nil, fmt.Errorf("most recent shards must be greater than 0") |
| 104 | } |
| 105 | |
| 106 | if cfg.Metrics.Sharder.ConcurrentRequests <= 0 { |
| 107 | return nil, fmt.Errorf("frontend metrics concurrent requests should be greater than 0") |
| 108 | } |
| 109 | |
| 110 | if cfg.Metrics.Sharder.TargetBytesPerRequest <= 0 { |
| 111 | return nil, fmt.Errorf("frontend metrics target bytes per request should be greater than 0") |
| 112 | } |
| 113 | |
| 114 | if cfg.Metrics.Sharder.Interval <= 0 { |
| 115 | return nil, fmt.Errorf("frontend metrics interval should be greater than 0") |
| 116 | } |
| 117 | |
| 118 | if cfg.QueryEndCutoff > cfg.Search.Sharder.QueryBackendAfter { |
| 119 | return nil, fmt.Errorf("QueryBackendAfter (%v) must be greater than query end cutoff (%v)", cfg.Search.Sharder.QueryBackendAfter, cfg.QueryEndCutoff) |
| 120 | } |
| 121 | |
| 122 | jobsPerQuery := promauto.With(registerer).NewHistogramVec(prometheus.HistogramOpts{ |
| 123 | Name: "tempo_query_frontend_jobs_per_query", |
| 124 | Help: "Number of planned jobs per query in the query frontend.", |
| 125 | Buckets: prometheus.ExponentialBuckets(1, 10, 7), |
| 126 | NativeHistogramBucketFactor: 1.1, |
| 127 | NativeHistogramMaxBucketNumber: 100, |
| 128 | NativeHistogramMinResetDuration: 1 * time.Hour, |
| 129 | }, []string{"op"}) |
| 130 | |
| 131 | adjustEndWareSeconds := pipeline.NewAdjustStartEndWare(cfg.Search.Sharder.QueryBackendAfter, cfg.QueryEndCutoff, false) |
| 132 | adjustEndWareNanos := pipeline.NewAdjustStartEndWare(cfg.Metrics.Sharder.QueryBackendAfter, cfg.QueryEndCutoff, true) // metrics queries work in nanoseconds |
| 133 | retryWare := pipeline.NewRetryWare(cfg.MaxRetries, cfg.Weights.RetryWithWeights, registerer) |
| 134 | cacheWare := pipeline.NewCachingWare(cacheProvider, cache.RoleFrontendSearch, logger) |
| 135 | statusCodeWare := pipeline.NewStatusCodeAdjustWare() |
| 136 | traceIDStatusCodeWare := pipeline.NewStatusCodeAdjustWareWithAllowedCode(http.StatusNotFound) |
| 137 | urlDenyListWare := pipeline.NewURLDenyListWare(cfg.URLDenyList) |
| 138 | queryValidatorWare := pipeline.NewQueryValidatorWare(cfg.MaxQueryExpressionSizeBytes) |
| 139 | headerStripWare := pipeline.NewStripHeadersWare(cfg.AllowedHeaders) |
| 140 | tenantValidatorWare := pipeline.NewTenantValidatorMiddleware() |
| 141 | |
| 142 | tracePipeline := pipeline.Build( |
| 143 | []pipeline.AsyncMiddleware[combiner.PipelineResponse]{ |
| 144 | headerStripWare, |