(ctx context.Context, b *LocalBlock, req tempopb.QueryRangeRequest, compileOpts []traceql.CompileOption)
| 825 | } |
| 826 | |
| 827 | func (i *instance) queryRangeCompleteBlock(ctx context.Context, b *LocalBlock, req tempopb.QueryRangeRequest, compileOpts []traceql.CompileOption) ([]*tempopb.TimeSeries, error) { |
| 828 | m := b.BlockMeta() |
| 829 | ctx, span := tracer.Start(ctx, "instance.QueryRange.CompleteBlock", oteltrace.WithAttributes( |
| 830 | attribute.String("block", m.BlockID.String()), |
| 831 | attribute.Int64("blockSize", int64(m.Size_)), |
| 832 | )) |
| 833 | defer span.End() |
| 834 | |
| 835 | // Trim and align the request for this block. I.e. if the request is "Last Hour" we don't want to |
| 836 | // cache the response for that, we want only the few minutes time range for this block. This has |
| 837 | // size savings but the main thing is that the response is reuseable for any overlapping query. |
| 838 | req.Start, req.End, req.Step = traceql.TrimToBlockOverlap(&req, m.StartTime, m.EndTime) |
| 839 | |
| 840 | if req.Start >= req.End { |
| 841 | // After alignment there is no overlap or something else isn't right |
| 842 | return nil, nil |
| 843 | } |
| 844 | |
| 845 | cached, name, err := i.queryRangeCacheGet(ctx, m, req) |
| 846 | if err != nil { |
| 847 | return nil, err |
| 848 | } |
| 849 | |
| 850 | span.SetAttributes(attribute.Bool("cached", cached != nil)) |
| 851 | |
| 852 | if cached != nil { |
| 853 | return cached.Series, nil |
| 854 | } |
| 855 | |
| 856 | // Not in cache or not cacheable, so execute |
| 857 | eval, err := traceql.NewEngine().CompileMetricsQueryRange(&req, compileOpts...) |
| 858 | if err != nil { |
| 859 | return nil, err |
| 860 | } |
| 861 | f := traceql.NewSpansetFetcherWrapperBoth( |
| 862 | func(ctx context.Context, req traceql.FetchSpansRequest) (traceql.FetchSpansResponse, error) { |
| 863 | return b.Fetch(ctx, req, common.DefaultSearchOptions()) |
| 864 | }, |
| 865 | func(ctx context.Context, req traceql.FetchSpansRequest) (traceql.FetchSpansOnlyResponse, error) { |
| 866 | return b.FetchSpans(ctx, req, common.DefaultSearchOptions()) |
| 867 | }, |
| 868 | ) |
| 869 | err = eval.Do(ctx, f, uint64(m.StartTime.UnixNano()), uint64(m.EndTime.UnixNano()), int(req.MaxSeries)) |
| 870 | if err != nil { |
| 871 | return nil, err |
| 872 | } |
| 873 | |
| 874 | results := eval.Results().ToProto(&req) |
| 875 | |
| 876 | if name != "" { |
| 877 | err = i.queryRangeCacheSet(ctx, m, name, &tempopb.QueryRangeResponse{ |
| 878 | Series: results, |
| 879 | }) |
| 880 | if err != nil { |
| 881 | return nil, fmt.Errorf("writing local query cache: %w", err) |
| 882 | } |
| 883 | } |
| 884 |
no test coverage detected