QueryRange returns metrics.
(ctx context.Context, req *tempopb.QueryRangeRequest)
| 696 | |
| 697 | // QueryRange returns metrics. |
| 698 | func (i *instance) QueryRange(ctx context.Context, req *tempopb.QueryRangeRequest) (*tempopb.QueryRangeResponse, error) { |
| 699 | ctx, cancel := context.WithCancel(ctx) |
| 700 | defer cancel() |
| 701 | |
| 702 | e := traceql.NewEngine() |
| 703 | |
| 704 | // Parse without optimizations to read hints; optimizations are applied by CompileMetricsQueryRange. |
| 705 | expr, err := traceql.ParseNoOptimizations(req.Query) |
| 706 | if err != nil { |
| 707 | return nil, fmt.Errorf("compiling query: %w", err) |
| 708 | } |
| 709 | |
| 710 | var compileOpts []traceql.CompileOption |
| 711 | |
| 712 | unsafe := i.overrides.UnsafeQueryHints(i.tenantID) |
| 713 | if unsafe { |
| 714 | compileOpts = append(compileOpts, traceql.WithUnsafeHints(true)) |
| 715 | } |
| 716 | for _, name := range req.SkipASTTransformations { |
| 717 | compileOpts = append(compileOpts, traceql.WithSkipOptimization(name)) |
| 718 | } |
| 719 | |
| 720 | if v, ok := expr.Hints.GetFloat(traceql.HintTimeOverlapCutoff, unsafe); ok && v >= 0 && v <= 1.0 { |
| 721 | compileOpts = append(compileOpts, traceql.WithTimeOverlapCutoff(v)) |
| 722 | } else { |
| 723 | compileOpts = append(compileOpts, traceql.WithTimeOverlapCutoff(i.Cfg.Metrics.TimeOverlapCutoff)) |
| 724 | } |
| 725 | |
| 726 | if p := i.overrides.MetricsSpanOnlyFetch(i.tenantID); p != nil { |
| 727 | compileOpts = append(compileOpts, traceql.WithSpanOnlyFetch(*p)) |
| 728 | } |
| 729 | |
| 730 | // Compile the raw version of the query for head and wal blocks |
| 731 | // These aren't cached and we put them all into the same evaluator |
| 732 | // for efficiency. |
| 733 | rawEval, err := e.CompileMetricsQueryRange(req, compileOpts...) |
| 734 | if err != nil { |
| 735 | return nil, err |
| 736 | } |
| 737 | |
| 738 | // This is a summation version of the query for complete blocks |
| 739 | // which can be cached. They are timeseries, so they need the job-level evaluator. |
| 740 | jobEval, err := traceql.NewEngine().CompileMetricsQueryRangeNonRaw(req, traceql.AggregateModeSum, compileOpts...) |
| 741 | if err != nil { |
| 742 | return nil, err |
| 743 | } |
| 744 | |
| 745 | cutoff := time.Now().Add(-i.Cfg.CompleteBlockTimeout).Add(-timeBuffer) |
| 746 | if req.Start < uint64(cutoff.UnixNano()) { |
| 747 | return nil, fmt.Errorf("time range must be within last %v", i.Cfg.CompleteBlockTimeout) |
| 748 | } |
| 749 | |
| 750 | maxSeries := int(req.MaxSeries) |
| 751 | maxSeriesReached := atomic.Bool{} |
| 752 | maxSeriesReached.Store(false) |
| 753 | |
| 754 | search := func(ctx context.Context, _ *backend.BlockMeta, b block) error { |
| 755 | if walBlock, ok := b.(common.WALBlock); ok { |
nothing calls this directly
no test coverage detected