mirror of
https://github.com/hanzoai/traces.git
synced 2026-10-30 18:20:41 +00:00
* First pass test harness Signed-off-by: Joe Elliott <[email protected]> * limits - passed Signed-off-by: Joe Elliott <[email protected]> * metrics generator - passed Signed-off-by: Joe Elliott <[email protected]> * harness cleanup/fix target info test Signed-off-by: Joe Elliott <[email protected]> * deployments - passed Signed-off-by: Joe Elliott <[email protected]> * receivers - passed Signed-off-by: Joe Elliott <[email protected]> * harness cleanup Signed-off-by: Joe Elliott <[email protected]> * storage - passed Signed-off-by: Joe Elliott <[email protected]> * api - passing Signed-off-by: Joe Elliott <[email protected]> * cleanup and CI Signed-off-by: Joe Elliott <[email protected]> * Additional tests Signed-off-by: Joe Elliott <[email protected]> * it's me and you linter. how many times are you going to do this to me? Signed-off-by: Joe Elliott <[email protected]> * lint and tests Signed-off-by: Joe Elliott <[email protected]> * restored live store partition tests Signed-off-by: Joe Elliott <[email protected]> * massive lint Signed-off-by: Joe Elliott <[email protected]> * cleanup Signed-off-by: Joe Elliott <[email protected]> * lint >.< Signed-off-by: Joe Elliott <[email protected]> * wups Signed-off-by: Joe Elliott <[email protected]> * cleanup and stabilizing Signed-off-by: Joe Elliott <[email protected]> * cleanup Signed-off-by: Joe Elliott <[email protected]> * omg Signed-off-by: Joe Elliott <[email protected]> * added config file. removed empty file. deleted some debug code Signed-off-by: Joe Elliott <[email protected]> * even more fixes Signed-off-by: Joe Elliott <[email protected]> * maybe this works? maybe it was all local networking issues Signed-off-by: Joe Elliott <[email protected]> * review Signed-off-by: Joe Elliott <[email protected]> * backed off huge write timeout. added missing config file Signed-off-by: Joe Elliott <[email protected]> * restore disable parallelism setting. restore beefy write timeout Signed-off-by: Joe Elliott <[email protected]> * apparently another test relied on the http receiver Signed-off-by: Joe Elliott <[email protected]> * livestore avail zone! Signed-off-by: Joe Elliott <[email protected]> * add support for v1 traces and tags endpoints Signed-off-by: Joe Elliott <[email protected]> * review Signed-off-by: Joe Elliott <[email protected]> * changed the location of the changelog entry to avoid conflicts Signed-off-by: Joe Elliott <[email protected]> --------- Signed-off-by: Joe Elliott <[email protected]>
160 lines
4.5 KiB
Go
160 lines
4.5 KiB
Go
package util
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"testing"
|
|
|
|
"github.com/grafana/dskit/user"
|
|
"github.com/grafana/tempo/pkg/httpclient"
|
|
"github.com/grafana/tempo/pkg/model/trace"
|
|
"github.com/grafana/tempo/pkg/tempopb"
|
|
tempoUtil "github.com/grafana/tempo/pkg/util"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
)
|
|
|
|
// BaseURL returns the base URL for the Tempo queryAPI. Some tests construct requests manually if
|
|
// they need to do something such as set custom headers or bad requests bodies. If you don't have
|
|
// a special need, use the client returned from APIClientHTTP or APIClientGRPC instead.
|
|
func (h *TempoHarness) BaseURL() string {
|
|
return "http://" + h.Services[ServiceQueryFrontend].Endpoint(3200)
|
|
}
|
|
|
|
func (h *TempoHarness) APIClientHTTP(tenant string) *httpclient.Client {
|
|
return httpclient.New(h.BaseURL(), tenant)
|
|
}
|
|
|
|
func (h *TempoHarness) APIClientGRPC(tenant string) (tempopb.StreamingQuerierClient, context.Context, error) {
|
|
endpoint := h.Services[ServiceQueryFrontend].Endpoint(3200)
|
|
|
|
ctx := context.Background()
|
|
|
|
if tenant != "" {
|
|
ctx = user.InjectOrgID(ctx, tenant)
|
|
var err error
|
|
ctx, err = user.InjectIntoGRPCRequest(ctx)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
}
|
|
|
|
client, err := NewSearchGRPCClient(endpoint, insecure.NewCredentials())
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return client, ctx, nil
|
|
}
|
|
|
|
func NewSearchGRPCClient(endpoint string, creds credentials.TransportCredentials) (tempopb.StreamingQuerierClient, error) {
|
|
clientConn, err := grpc.NewClient(endpoint, grpc.WithTransportCredentials(creds))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return tempopb.NewStreamingQuerierClient(clientConn), nil
|
|
}
|
|
|
|
func SearchTraceQLAndAssertTrace(t *testing.T, client *httpclient.Client, info *tempoUtil.TraceInfo) {
|
|
expected, err := info.ConstructTraceFromEpoch()
|
|
require.NoError(t, err)
|
|
|
|
attr := tempoUtil.RandomAttrFromTrace(expected)
|
|
query := fmt.Sprintf(`{ .%s = "%s"}`, attr.GetKey(), attr.GetValue().GetStringValue())
|
|
|
|
resp, err := client.SearchTraceQL(query)
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, traceIDInResults(t, info.HexID(), resp))
|
|
}
|
|
|
|
func SearchTraceQLAndAssertTraceWithRange(t *testing.T, client *httpclient.Client, info *tempoUtil.TraceInfo, start, end int64) {
|
|
expected, err := info.ConstructTraceFromEpoch()
|
|
require.NoError(t, err)
|
|
|
|
attr := tempoUtil.RandomAttrFromTrace(expected)
|
|
query := fmt.Sprintf(`{ .%s = "%s"}`, attr.GetKey(), attr.GetValue().GetStringValue())
|
|
|
|
resp, err := client.SearchTraceQLWithRange(query, start, end)
|
|
require.NoError(t, err)
|
|
|
|
require.True(t, traceIDInResults(t, info.HexID(), resp))
|
|
}
|
|
|
|
// SearchStreamAndAssertTrace will search and assert that the trace is present in the streamed results.
|
|
// nolint: revive
|
|
func SearchStreamAndAssertTrace(t *testing.T, ctx context.Context, client tempopb.StreamingQuerierClient, info *tempoUtil.TraceInfo, start, end int64) {
|
|
expected, err := info.ConstructTraceFromEpoch()
|
|
require.NoError(t, err)
|
|
|
|
attr := tempoUtil.RandomAttrFromTrace(expected)
|
|
query := fmt.Sprintf(`{ .%s = "%s"}`, attr.GetKey(), attr.GetValue().GetStringValue())
|
|
|
|
// -- assert search
|
|
resp, err := client.Search(ctx, &tempopb.SearchRequest{
|
|
Query: query,
|
|
Start: uint32(start),
|
|
End: uint32(end),
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
// drain the stream until everything is returned while watching for the trace in question
|
|
found := false
|
|
for {
|
|
resp, err := resp.Recv()
|
|
if resp != nil {
|
|
found = traceIDInResults(t, info.HexID(), resp)
|
|
if found {
|
|
break
|
|
}
|
|
}
|
|
if errors.Is(err, io.EOF) {
|
|
break
|
|
}
|
|
require.NoError(t, err)
|
|
}
|
|
require.True(t, found)
|
|
}
|
|
|
|
func traceIDInResults(t *testing.T, hexID string, resp *tempopb.SearchResponse) bool {
|
|
for _, s := range resp.Traces {
|
|
equal, err := tempoUtil.EqualHexStringTraceIDs(s.TraceID, hexID)
|
|
require.NoError(t, err)
|
|
if equal {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func QueryAndAssertTrace(t *testing.T, client *httpclient.Client, info *tempoUtil.TraceInfo) {
|
|
// v2
|
|
respV2, err := client.QueryTraceV2(info.HexID())
|
|
require.NoError(t, err)
|
|
|
|
expected, err := info.ConstructTraceFromEpoch()
|
|
require.NoError(t, err)
|
|
|
|
AssertEqualTrace(t, respV2.Trace, expected)
|
|
|
|
// v1
|
|
respV1, err := client.QueryTrace(info.HexID())
|
|
require.NoError(t, err)
|
|
|
|
AssertEqualTrace(t, respV1, expected)
|
|
}
|
|
|
|
func AssertEqualTrace(t *testing.T, a, b *tempopb.Trace) {
|
|
t.Helper()
|
|
trace.SortTraceAndAttributes(a)
|
|
trace.SortTraceAndAttributes(b)
|
|
|
|
assert.Equal(t, a, b)
|
|
}
|