From 1788f0320e6def0691f3f07c7d5cff6cd374fa83 Mon Sep 17 00:00:00 2001 From: Mahad Zaryab <43658574+mahadzaryab1@users.noreply.github.com> Date: Sun, 8 Dec 2024 09:14:48 -0500 Subject: [PATCH] [storage][v2] Implement `FindTraceIDs` in v2 factory adapter (#6326) ## Which problem is this PR solving? - Towards #5079 ## Description of the changes - This PR implements `FindTraceIDs` in the v2 factory adapter ## How was this change tested? - Added unit tests ## Checklist - [x] I have read https://github.com/jaegertracing/jaeger/blob/master/CONTRIBUTING_GUIDELINES.md - [x] I have signed all commits - [x] I have added unit tests for the new functionality - [x] I have run lint and test steps successfully - for `jaeger`: `make lint test` - for `jaeger-ui`: `yarn lint` and `yarn test` --------- Signed-off-by: Mahad Zaryab --- model/ids.go | 11 ++++ model/ids_test.go | 11 ++++ storage_v2/factoryadapter/reader.go | 28 +++++++-- storage_v2/factoryadapter/reader_test.go | 80 +++++++++++++++++++++--- 4 files changed, 118 insertions(+), 12 deletions(-) diff --git a/model/ids.go b/model/ids.go index 27c7d3846b0..f911a7beb0e 100644 --- a/model/ids.go +++ b/model/ids.go @@ -12,6 +12,7 @@ import ( "strconv" "github.com/gogo/protobuf/jsonpb" + "go.opentelemetry.io/collector/pdata/pcommon" ) const ( @@ -145,6 +146,16 @@ func (t *TraceID) UnmarshalJSON(data []byte) error { return t.Unmarshal(b) } +// ToOTELTraceID converts the TraceID to OTEL's representation of a trace identitfier. +// This was taken from +// https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/internal/coreinternal/idutils/big_endian_converter.go. +func (t *TraceID) ToOTELTraceID() pcommon.TraceID { + traceID := [16]byte{} + binary.BigEndian.PutUint64(traceID[:8], t.High) + binary.BigEndian.PutUint64(traceID[8:], t.Low) + return traceID +} + // ------- SpanID ------- // NewSpanID creates a new SpanID from a 64bit unsigned int. diff --git a/model/ids_test.go b/model/ids_test.go index ba490236bb6..6bab7614b96 100644 --- a/model/ids_test.go +++ b/model/ids_test.go @@ -12,6 +12,7 @@ import ( "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/pdata/pcommon" "github.com/jaegertracing/jaeger/model" "github.com/jaegertracing/jaeger/model/prototest" @@ -117,3 +118,13 @@ func TestTraceIDFromBytes(t *testing.T) { assert.Equal(t, test.expected, traceID) } } + +func TestToOTELTraceID(t *testing.T) { + modelTraceID := model.TraceID{ + Low: 3, + High: 2, + } + otelTraceID := modelTraceID.ToOTELTraceID() + expected := []byte{0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3} + require.Equal(t, pcommon.TraceID(expected), otelTraceID) +} diff --git a/storage_v2/factoryadapter/reader.go b/storage_v2/factoryadapter/reader.go index 4831b92538d..7345e84fe60 100644 --- a/storage_v2/factoryadapter/reader.go +++ b/storage_v2/factoryadapter/reader.go @@ -49,22 +49,42 @@ func (tr *TraceReader) GetOperations(ctx context.Context, query tracestore.Opera ServiceName: query.ServiceName, SpanKind: query.SpanKind, }) - var operations []tracestore.Operation + if err != nil || o == nil { + return nil, err + } + operations := []tracestore.Operation{} for _, operation := range o { operations = append(operations, tracestore.Operation{ Name: operation.Name, SpanKind: operation.SpanKind, }) } - return operations, err + return operations, nil } func (*TraceReader) FindTraces(_ context.Context, _ tracestore.TraceQueryParameters) ([]ptrace.Traces, error) { panic("not implemented") } -func (*TraceReader) FindTraceIDs(_ context.Context, _ tracestore.TraceQueryParameters) ([]pcommon.TraceID, error) { - panic("not implemented") +func (tr *TraceReader) FindTraceIDs(ctx context.Context, query tracestore.TraceQueryParameters) ([]pcommon.TraceID, error) { + t, err := tr.spanReader.FindTraceIDs(ctx, &spanstore.TraceQueryParameters{ + ServiceName: query.ServiceName, + OperationName: query.OperationName, + Tags: query.Tags, + StartTimeMin: query.StartTimeMin, + StartTimeMax: query.StartTimeMax, + DurationMin: query.DurationMin, + DurationMax: query.DurationMax, + NumTraces: query.NumTraces, + }) + if err != nil || t == nil { + return nil, err + } + traceIDs := []pcommon.TraceID{} + for _, traceID := range t { + traceIDs = append(traceIDs, traceID.ToOTELTraceID()) + } + return traceIDs, nil } type DependencyReader struct { diff --git a/storage_v2/factoryadapter/reader_test.go b/storage_v2/factoryadapter/reader_test.go index 20df60fa768..9d1891a547b 100644 --- a/storage_v2/factoryadapter/reader_test.go +++ b/storage_v2/factoryadapter/reader_test.go @@ -159,15 +159,79 @@ func TestTraceReader_FindTracesPanics(t *testing.T) { ) } -func TestTraceReader_FindTraceIDsPanics(t *testing.T) { - memstore := memory.NewStore() - traceReader := &TraceReader{ - spanReader: memstore, +func TestTraceReader_FindTraceIDsDelegatesResponse(t *testing.T) { + tests := []struct { + name string + modelTraceIDs []model.TraceID + expectedTraceIDs []pcommon.TraceID + err error + }{ + { + name: "successful response", + modelTraceIDs: []model.TraceID{ + {Low: 3, High: 2}, + {Low: 4, High: 3}, + }, + expectedTraceIDs: []pcommon.TraceID{ + pcommon.TraceID([]byte{0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3}), + pcommon.TraceID([]byte{0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4}), + }, + }, + { + name: "empty response", + modelTraceIDs: []model.TraceID{}, + expectedTraceIDs: []pcommon.TraceID{}, + }, + { + name: "nil response", + modelTraceIDs: nil, + expectedTraceIDs: nil, + }, + { + name: "error response", + modelTraceIDs: nil, + expectedTraceIDs: nil, + err: errors.New("test error"), + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + sr := new(spanStoreMocks.Reader) + now := time.Now() + sr.On( + "FindTraceIDs", + mock.Anything, + &spanstore.TraceQueryParameters{ + ServiceName: "service", + OperationName: "operation", + Tags: map[string]string{"tag-a": "val-a"}, + StartTimeMin: now, + StartTimeMax: now.Add(time.Minute), + DurationMin: time.Minute, + DurationMax: time.Hour, + NumTraces: 10, + }, + ).Return(test.modelTraceIDs, test.err) + traceReader := &TraceReader{ + spanReader: sr, + } + traceIDs, err := traceReader.FindTraceIDs( + context.Background(), + tracestore.TraceQueryParameters{ + ServiceName: "service", + OperationName: "operation", + Tags: map[string]string{"tag-a": "val-a"}, + StartTimeMin: now, + StartTimeMax: now.Add(time.Minute), + DurationMin: time.Minute, + DurationMax: time.Hour, + NumTraces: 10, + }, + ) + require.ErrorIs(t, err, test.err) + require.Equal(t, test.expectedTraceIDs, traceIDs) + }) } - require.Panics( - t, - func() { traceReader.FindTraceIDs(context.Background(), tracestore.TraceQueryParameters{}) }, - ) } func TestDependencyReader_GetDependencies(t *testing.T) {