| 935 | } |
| 936 | |
| 937 | func (e *Engine) CompileMetricsQueryRangeNonRaw(req *tempopb.QueryRangeRequest, mode AggregateMode, opts ...CompileOption) (*MetricsFrontendEvaluator, error) { |
| 938 | if req.Exemplars > maxExemplars { |
| 939 | level.Warn(log.Logger).Log("msg", "capping exemplars to safety limit", "requested", req.Exemplars, "cap", maxExemplars) |
| 940 | req.Exemplars = maxExemplars |
| 941 | } |
| 942 | |
| 943 | if req.Start <= 0 { |
| 944 | return nil, fmt.Errorf("start required") |
| 945 | } |
| 946 | if req.End <= 0 { |
| 947 | return nil, fmt.Errorf("end required") |
| 948 | } |
| 949 | if req.End <= req.Start { |
| 950 | return nil, fmt.Errorf("end must be greater than start") |
| 951 | } |
| 952 | if req.Step <= 0 { |
| 953 | return nil, fmt.Errorf("step required") |
| 954 | } |
| 955 | |
| 956 | _, _, metricsPipeline, metricsSecondStage, _, err := Compile(req.Query, opts...) |
| 957 | if err != nil { |
| 958 | return nil, fmt.Errorf("compiling query: %w", err) |
| 959 | } |
| 960 | |
| 961 | // for metrics queries, we need a metrics pipeline |
| 962 | if metricsPipeline == nil { |
| 963 | return nil, fmt.Errorf("not a metrics query") |
| 964 | } |
| 965 | |
| 966 | metricsPipeline.init(req, mode) |
| 967 | mfe := &MetricsFrontendEvaluator{ |
| 968 | metricsPipeline: metricsPipeline, |
| 969 | } |
| 970 | |
| 971 | // only run metrics second stage if we have second stage and query mode = final, |
| 972 | // as we are not sharding them now in lower layers. |
| 973 | if metricsSecondStage != nil && mode == AggregateModeFinal { |
| 974 | metricsSecondStage.init(req) |
| 975 | mfe.metricsSecondStage = metricsSecondStage |
| 976 | } |
| 977 | |
| 978 | return mfe, nil |
| 979 | } |
| 980 | |
| 981 | // CompileMetricsQueryRange returns an evaluator that can be reused across multiple data sources. |
| 982 | func (e *Engine) CompileMetricsQueryRange(req *tempopb.QueryRangeRequest, opts ...CompileOption) (*MetricsEvaluator, error) { |