Files
traces/modules/frontend/traceid_sharder_test.go
c0e6528e7a [querier] Support external mode for traceID lookups (#6185)
* [querier] Support `external` mode for traceIDv2

This PR adds a new `external` mode to the querier. In this mode, an HTTP
request is sent to an external endpoint to fetch trace contents in
addition to the normal ingester + block storages.

The external API is expected to support an API matching Tempo's
TraceIDV2 API. `/api/v2/traces/{traceID}?start=<start>&end=<end>`. This
endpoint should respond with an OTLP proto encoded trace.

This can be used to augment tempo's internal traceID lookup with
additional data that may not be ingested to tempo directly.

* Update config docs

* Update CHANGELOG

* Update test

* Update manifest

* Add metrics and traces

* Update modules/querier/external/client.go

Co-authored-by: Suraj Nath <[email protected]>

* Address PR feedback

* make generate-manifest

---------

Co-authored-by: Suraj Nath <[email protected]>
2026-01-14 02:31:04 +05:30

64 lines
2.0 KiB
Go

package frontend
import (
"context"
"net/http/httptest"
"testing"
"github.com/grafana/dskit/user"
"github.com/stretchr/testify/require"
"github.com/grafana/tempo/modules/frontend/pipeline"
"github.com/grafana/tempo/pkg/blockboundary"
)
func TestBuildShardedRequests(t *testing.T) {
queryShards := 2
sharder := &asyncTraceSharder{
cfg: &TraceByIDConfig{
QueryShards: queryShards,
},
blockBoundaries: blockboundary.CreateBlockBoundaries(queryShards - 1),
}
ctx := user.InjectOrgID(context.Background(), "blerg")
req := httptest.NewRequest("GET", "/", nil).WithContext(ctx)
shardedReqs, err := sharder.buildShardedRequests(pipeline.NewHTTPRequest(req))
require.NoError(t, err)
require.Len(t, shardedReqs, queryShards)
require.Equal(t, "/querier?mode=ingesters", shardedReqs[0].HTTPRequest().RequestURI)
urisEqual(t, []string{"/querier?blockEnd=ffffffffffffffffffffffffffffffff&blockStart=00000000000000000000000000000000&mode=blocks"}, []string{shardedReqs[1].HTTPRequest().RequestURI})
}
func TestBuildShardedRequestsWithExternal(t *testing.T) {
queryShards := 4
sharder := &asyncTraceSharder{
cfg: &TraceByIDConfig{
QueryShards: queryShards,
ExternalEnabled: true,
},
blockBoundaries: blockboundary.CreateBlockBoundaries(queryShards - 2),
}
ctx := user.InjectOrgID(context.Background(), "blerg")
req := httptest.NewRequest("GET", "/", nil).WithContext(ctx)
shardedReqs, err := sharder.buildShardedRequests(pipeline.NewHTTPRequest(req))
require.NoError(t, err)
require.Len(t, shardedReqs, queryShards)
require.Equal(t, "/querier?mode=ingesters", shardedReqs[0].HTTPRequest().RequestURI)
require.Equal(t, "/querier?mode=external", shardedReqs[1].HTTPRequest().RequestURI)
// Verify block shard requests
for i := 2; i < queryShards; i++ {
require.Contains(t, shardedReqs[i].HTTPRequest().RequestURI, "mode=blocks")
require.Contains(t, shardedReqs[i].HTTPRequest().RequestURI, "blockStart")
require.Contains(t, shardedReqs[i].HTTPRequest().RequestURI, "blockEnd")
}
}