From 7189b52ee5b41f51597503ab26dbf9432f4f9c88 Mon Sep 17 00:00:00 2001 From: Mahad Zaryab <43658574+mahadzaryab1@users.noreply.github.com> Date: Thu, 16 Jan 2025 19:42:12 -0500 Subject: [PATCH] [v2][storage] Implement reverse adapter to translate v2 writer to v1 (#6555) ## Which problem is this PR solving? - Towards #6065 ## Description of the changes - This PR implements a reverse adapter (SpanWriter) that wraps a native v2 storage writer (tracestore.Writer) and downgrades it to implement the v1 writer (spanstore.Writer). - This will be used by https://github.com/jaegertracing/jaeger/pull/6519 to downgrade a native v2 writer so that it can be used by the v1 query service ## 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`: `npm run lint` and `npm run test` --------- Signed-off-by: Mahad Zaryab --- storage_v2/v1adapter/spanwriter.go | 33 +++++++++ storage_v2/v1adapter/spanwriter_test.go | 67 +++++++++++++++++++ .../v1adapter/{reader.go => tracereader.go} | 0 .../{reader_test.go => tracereader_test.go} | 0 .../v1adapter/{writer.go => tracewriter.go} | 0 .../{writer_test.go => tracewriter_test.go} | 0 6 files changed, 100 insertions(+) create mode 100644 storage_v2/v1adapter/spanwriter.go create mode 100644 storage_v2/v1adapter/spanwriter_test.go rename storage_v2/v1adapter/{reader.go => tracereader.go} (100%) rename storage_v2/v1adapter/{reader_test.go => tracereader_test.go} (100%) rename storage_v2/v1adapter/{writer.go => tracewriter.go} (100%) rename storage_v2/v1adapter/{writer_test.go => tracewriter_test.go} (100%) diff --git a/storage_v2/v1adapter/spanwriter.go b/storage_v2/v1adapter/spanwriter.go new file mode 100644 index 00000000000..fa649308a9e --- /dev/null +++ b/storage_v2/v1adapter/spanwriter.go @@ -0,0 +1,33 @@ +// Copyright (c) 2025 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package v1adapter + +import ( + "context" + + jaegerTranslator "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/jaeger" + + "github.com/jaegertracing/jaeger/model" + "github.com/jaegertracing/jaeger/storage/spanstore" + "github.com/jaegertracing/jaeger/storage_v2/tracestore" +) + +var _ spanstore.Writer = (*SpanWriter)(nil) + +// SpanReader wraps a tracestore.Writer so that it can be downgraded to implement +// the v1 spanstore.Writer interface. +type SpanWriter struct { + traceWriter tracestore.Writer +} + +func NewSpanWriter(traceWriter tracestore.Writer) *SpanWriter { + return &SpanWriter{ + traceWriter: traceWriter, + } +} + +func (sw *SpanWriter) WriteSpan(ctx context.Context, span *model.Span) error { + traces, _ := jaegerTranslator.ProtoToTraces([]*model.Batch{{Spans: []*model.Span{span}}}) + return sw.traceWriter.WriteTraces(ctx, traces) +} diff --git a/storage_v2/v1adapter/spanwriter_test.go b/storage_v2/v1adapter/spanwriter_test.go new file mode 100644 index 00000000000..ad63232d67b --- /dev/null +++ b/storage_v2/v1adapter/spanwriter_test.go @@ -0,0 +1,67 @@ +// Copyright (c) 2025 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package v1adapter + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/pdata/ptrace" + + "github.com/jaegertracing/jaeger/model" + tracestoremocks "github.com/jaegertracing/jaeger/storage_v2/tracestore/mocks" +) + +func TestSpanWriter_WriteSpan(t *testing.T) { + tests := []struct { + name string + mockReturnErr error + expectedErr error + }{ + { + name: "success", + mockReturnErr: nil, + expectedErr: nil, + }, + { + name: "error in translator", + mockReturnErr: assert.AnError, + expectedErr: assert.AnError, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + mockTraceWriter := &tracestoremocks.Writer{} + spanWriter := NewSpanWriter(mockTraceWriter) + + now := time.Now().UTC() + testSpan := &model.Span{ + TraceID: model.NewTraceID(0, 1), + SpanID: model.NewSpanID(1), + StartTime: now, + Duration: time.Second, + } + + traces := ptrace.NewTraces() + resources := traces.ResourceSpans().AppendEmpty() + scopes := resources.ScopeSpans().AppendEmpty() + span := scopes.Spans().AppendEmpty() + span.SetTraceID(pcommon.TraceID([16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})) + span.SetSpanID(pcommon.SpanID([8]byte{0, 0, 0, 0, 0, 0, 0, 1})) + span.SetStartTimestamp(pcommon.NewTimestampFromTime(now)) + span.SetEndTimestamp(pcommon.NewTimestampFromTime(now.Add(time.Second))) + + mockTraceWriter.On("WriteTraces", mock.Anything, traces).Return(test.mockReturnErr) + + err := spanWriter.WriteSpan(context.Background(), testSpan) + require.ErrorIs(t, err, test.expectedErr) + }) + } +} diff --git a/storage_v2/v1adapter/reader.go b/storage_v2/v1adapter/tracereader.go similarity index 100% rename from storage_v2/v1adapter/reader.go rename to storage_v2/v1adapter/tracereader.go diff --git a/storage_v2/v1adapter/reader_test.go b/storage_v2/v1adapter/tracereader_test.go similarity index 100% rename from storage_v2/v1adapter/reader_test.go rename to storage_v2/v1adapter/tracereader_test.go diff --git a/storage_v2/v1adapter/writer.go b/storage_v2/v1adapter/tracewriter.go similarity index 100% rename from storage_v2/v1adapter/writer.go rename to storage_v2/v1adapter/tracewriter.go diff --git a/storage_v2/v1adapter/writer_test.go b/storage_v2/v1adapter/tracewriter_test.go similarity index 100% rename from storage_v2/v1adapter/writer_test.go rename to storage_v2/v1adapter/tracewriter_test.go