-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[storage] Add OTLP Scope metadata validation test (part of #7050) #7632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
SoumyaRaikwar
wants to merge
15
commits into
jaegertracing:main
Choose a base branch
from
SoumyaRaikwar:feature/upgrade-integration-tests-v2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+245
−8
Open
Changes from 12 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
f9cb3a5
[storage] Upgrade e2e storage tests to use v2 Storage API and OTLP
SoumyaRaikwar 1f5fabe
Merge branch 'main' into feature/upgrade-integration-tests-v2
SoumyaRaikwar aa25cf0
Change loadParseAndWriteExampleTrace() to NOT use new OTLP functions
SoumyaRaikwar 13dc0db
fixed formatting and testing coverage
SoumyaRaikwar 908ffb2
Merge branch 'main' into feature/upgrade-integration-tests-v2
SoumyaRaikwar d68c32f
test(integration): remove unused V1TraceFromOtelTrace function
SoumyaRaikwar 2f11e32
Merge branch 'main' into feature/upgrade-integration-tests-v2
SoumyaRaikwar 33554b9
test: add OTLP Scope preservation test
SoumyaRaikwar 6baab68
Merge branch 'main' into feature/upgrade-integration-tests-v2
SoumyaRaikwar d295d97
fix: resolve lint errors - remove unused receiver; use require.Positive
SoumyaRaikwar c81068e
Update internal/storage/integration/fixtures/traces/otlp_scope_attrib…
SoumyaRaikwar 5035896
fix: normalize OTLP fixture timestamps
SoumyaRaikwar 8e188b1
Update internal/storage/integration/fixtures/traces/otlp_scope_attrib…
SoumyaRaikwar 59d3253
Clean up comments in normalizeOTLPTimestamps function
SoumyaRaikwar 77165e9
Clean up integration.go by removing empty lines
SoumyaRaikwar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
53 changes: 53 additions & 0 deletions
53
internal/storage/integration/fixtures/traces/otlp_scope_attributes.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| { | ||
| "resourceSpans": [ | ||
| { | ||
| "resource": { | ||
| "attributes": [ | ||
| { | ||
| "key": "service.name", | ||
| "value": {"stringValue": "otlp-test-service"} | ||
| }, | ||
| { | ||
| "key": "service.version", | ||
| "value": {"stringValue": "1.0.0"} | ||
| }, | ||
| { | ||
| "key": "deployment.environment", | ||
| "value": {"stringValue": "test"} | ||
| } | ||
| ] | ||
| }, | ||
| "scopeSpans": [ | ||
| { | ||
| "scope": { | ||
| "name": "test-instrumentation-library", | ||
| "version": "2.1.0" | ||
| }, | ||
| "spans": [ | ||
| { | ||
| "traceId": "00000000000000000000000000000020", | ||
| "spanId": "0000000000000010", | ||
| "name": "otlp-scope-test-operation", | ||
| "kind": 2, | ||
| "startTimeUnixNano": "1485445591639875000", | ||
| "endTimeUnixNano": "1485445591739875000", | ||
| "attributes": [ | ||
| { | ||
| "key": "http.method", | ||
| "value": {"stringValue": "GET"} | ||
| }, | ||
| { | ||
| "key": "http.status_code", | ||
| "value": {"intValue": "200"} | ||
| } | ||
| ], | ||
| "status": { | ||
| "code": 0 | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
64 changes: 64 additions & 0 deletions
64
internal/storage/integration/fixtures/traces/otlp_span_links.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| { | ||
| "resourceSpans": [ | ||
| { | ||
| "resource": { | ||
| "attributes": [ | ||
| { | ||
| "key": "service.name", | ||
| "value": {"stringValue": "span-links-service"} | ||
| } | ||
| ] | ||
| }, | ||
| "scopeSpans": [ | ||
| { | ||
| "scope": { | ||
| "name": "span-links-test", | ||
| "version": "1.0.0", | ||
| "attributes": [ | ||
| { | ||
| "key": "otel.scope.test", | ||
| "value": {"stringValue": "true"} | ||
| } | ||
| ] | ||
| }, | ||
| "spans": [ | ||
| { | ||
| "traceId": "00000000000000000000000000000040", | ||
| "spanId": "0000000000000030", | ||
| "name": "parent-span-with-links", | ||
| "kind": 1, | ||
| "startTimeUnixNano": "1485445591639875000", | ||
| "endTimeUnixNano": "1485445591939875000", | ||
| "attributes": [], | ||
| "links": [ | ||
| { | ||
| "traceId": "00000000000000000000000000000050", | ||
| "spanId": "0000000000000040", | ||
| "attributes": [ | ||
| { | ||
| "key": "link.type", | ||
| "value": {"stringValue": "parent_link"} | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "traceId": "00000000000000000000000000000060", | ||
| "spanId": "0000000000000050", | ||
| "attributes": [ | ||
| { | ||
| "key": "link.type", | ||
| "value": {"stringValue": "sibling_link"} | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "status": { | ||
| "code": 0 | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ import ( | |
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| "go.opentelemetry.io/collector/pdata/pcommon" | ||
| "go.opentelemetry.io/collector/pdata/ptrace" | ||
|
|
||
| "github.com/jaegertracing/jaeger-idl/model/v1" | ||
| "github.com/jaegertracing/jaeger/internal/storage/v1/api/samplingstore" | ||
|
|
@@ -368,7 +369,9 @@ func (s *StorageIntegration) testFindTraces(t *testing.T) { | |
| trace, ok := allTraceFixtures[traceFixture] | ||
| if !ok { | ||
| trace = s.getTraceFixture(t, traceFixture) | ||
| s.writeTrace(t, trace) | ||
| otelTraces := v1adapter.V1TraceToOtelTrace(trace) | ||
| s.writeTrace(t, otelTraces) | ||
|
|
||
| allTraceFixtures[traceFixture] = trace | ||
| } | ||
| expected = append(expected, trace) | ||
|
|
@@ -409,20 +412,21 @@ func (s *StorageIntegration) findTracesByQuery(t *testing.T, query *tracestore.T | |
| return traces | ||
| } | ||
|
|
||
| func (s *StorageIntegration) writeTrace(t *testing.T, trace *model.Trace) { | ||
| t.Logf("%-23s Writing trace with %d spans", time.Now().Format("2006-01-02 15:04:05.999"), len(trace.Spans)) | ||
| func (s *StorageIntegration) writeTrace(t *testing.T, traces ptrace.Traces) { | ||
| spanCount := traces.SpanCount() | ||
| t.Logf("%-23s Writing trace with %d spans", time.Now().Format("2006-01-02 15:04:05.999"), spanCount) | ||
| ctx, cx := context.WithTimeout(context.Background(), 5*time.Minute) | ||
| defer cx() | ||
| otelTraces := v1adapter.V1TraceToOtelTrace(trace) | ||
| err := s.TraceWriter.WriteTraces(ctx, otelTraces) | ||
| err := s.TraceWriter.WriteTraces(ctx, traces) | ||
| require.NoError(t, err, "Not expecting error when writing trace to storage") | ||
|
|
||
| t.Logf("%-23s Finished writing trace with %d spans", time.Now().Format("2006-01-02 15:04:05.999"), len(trace.Spans)) | ||
| t.Logf("%-23s Finished writing trace with %d spans", time.Now().Format("2006-01-02 15:04:05.999"), spanCount) | ||
| } | ||
|
|
||
| func (s *StorageIntegration) loadParseAndWriteExampleTrace(t *testing.T) *model.Trace { | ||
| trace := s.getTraceFixture(t, "example_trace") | ||
| s.writeTrace(t, trace) | ||
| otelTraces := v1adapter.V1TraceToOtelTrace(trace) | ||
| s.writeTrace(t, otelTraces) | ||
| return trace | ||
| } | ||
|
|
||
|
|
@@ -446,7 +450,9 @@ func (s *StorageIntegration) writeLargeTraceWithDuplicateSpanIds( | |
| newSpan.StartTime = newSpan.StartTime.Add(time.Second * time.Duration(i+1)) | ||
| trace.Spans[i] = newSpan | ||
| } | ||
| s.writeTrace(t, trace) | ||
| // Convert to OTLP for writing | ||
| otelTraces := v1adapter.V1TraceToOtelTrace(trace) | ||
| s.writeTrace(t, otelTraces) | ||
| return trace | ||
| } | ||
|
|
||
|
|
@@ -627,6 +633,129 @@ func (s *StorageIntegration) insertThroughput(t *testing.T) { | |
| require.NoError(t, err) | ||
| } | ||
|
|
||
| // === OTLP v2 API Tests === | ||
|
|
||
| func (s *StorageIntegration) testOTLPScopePreservation(t *testing.T) { | ||
| s.skipIfNeeded(t) | ||
| defer s.cleanUp(t) | ||
|
|
||
| t.Log("Testing OTLP InstrumentationScope preservation through v2 API") | ||
|
|
||
| traces := loadOTLPFixture(t, "otlp_scope_attributes") | ||
|
|
||
| s.writeTrace(t, traces) | ||
|
|
||
| traceID := extractTraceID(t, traces) | ||
|
|
||
| var readTraces []*model.Trace | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why the new test has old |
||
| found := s.waitForCondition(t, func(t *testing.T) bool { | ||
| iterTraces := s.TraceReader.GetTraces(context.Background(), tracestore.GetTraceParams{TraceID: traceID}) | ||
| var err error | ||
| readTraces, err = v1adapter.V1TracesFromSeq2(iterTraces) | ||
| if err != nil { | ||
| t.Log(err) | ||
| return false | ||
| } | ||
| return len(readTraces) > 0 | ||
| }) | ||
|
|
||
| require.True(t, found, "Failed to retrieve written trace") | ||
| require.NotEmpty(t, readTraces, "Should retrieve written trace") | ||
|
|
||
| // Convert back to ptrace to validate Scope metadata | ||
| retrievedTrace := v1adapter.V1TraceToOtelTrace(readTraces[0]) | ||
| require.Positive(t, retrievedTrace.ResourceSpans().Len(), "Should have resource spans") | ||
|
|
||
| scopeSpans := retrievedTrace.ResourceSpans().At(0).ScopeSpans() | ||
| require.Positive(t, scopeSpans.Len(), "Should have scope spans") | ||
|
|
||
| scope := scopeSpans.At(0).Scope() | ||
| assert.Equal(t, "test-instrumentation-library", scope.Name(), "Scope name should be preserved") | ||
| assert.Equal(t, "2.1.0", scope.Version(), "Scope version should be preserved") | ||
|
|
||
| t.Log("OTLP InstrumentationScope metadata preserved successfully") | ||
| } | ||
|
|
||
| // loadOTLPFixture loads an OTLP trace fixture by name from the fixtures directory. | ||
| func loadOTLPFixture(t *testing.T, fixtureName string) ptrace.Traces { | ||
| fileName := fmt.Sprintf("fixtures/traces/%s.json", fixtureName) | ||
| data, err := fixtures.ReadFile(fileName) | ||
| require.NoError(t, err, "Failed to read OTLP fixture %s", fileName) | ||
|
|
||
| unmarshaler := &ptrace.JSONUnmarshaler{} | ||
| traces, err := unmarshaler.UnmarshalTraces(data) | ||
| require.NoError(t, err, "Failed to unmarshal OTLP fixture %s", fixtureName) | ||
|
|
||
| normalizeOTLPTimestamps(traces) | ||
|
|
||
| return traces | ||
| } | ||
|
|
||
| // normalizeOTLPTimestamps shifts all span timestamps so they fall within a recent | ||
| // time window (relative to time.Now). This keeps the test data inside the | ||
| // time range that storage backends query when resolving traces by ID. | ||
| func normalizeOTLPTimestamps(traces ptrace.Traces) { | ||
| // Find the first span to establish the original start time. | ||
| resourceSpans := traces.ResourceSpans() | ||
| if resourceSpans.Len() == 0 { | ||
| return | ||
| } | ||
|
|
||
| var ( | ||
| firstStart time.Time | ||
| found bool | ||
| ) | ||
|
|
||
| for i := 0; i < resourceSpans.Len() && !found; i++ { | ||
| rs := resourceSpans.At(i) | ||
| scopeSpans := rs.ScopeSpans() | ||
| for j := 0; j < scopeSpans.Len() && !found; j++ { | ||
| ss := scopeSpans.At(j) | ||
| spans := ss.Spans() | ||
| if spans.Len() == 0 { | ||
| continue | ||
| } | ||
| firstStart = spans.At(0).StartTimestamp().AsTime() | ||
| found = !firstStart.IsZero() | ||
| } | ||
| } | ||
|
|
||
| if !found { | ||
| return | ||
| } | ||
|
|
||
| // Target the recent past so indices and time-range queries include the data. | ||
| // Using "now - 1m" avoids clock skew issues but keeps the trace very recent. | ||
| targetStart := time.Now().Add(-time.Minute).UTC() | ||
| delta := targetStart.Sub(firstStart) | ||
|
|
||
| for i := 0; i < resourceSpans.Len(); i++ { | ||
| rs := resourceSpans.At(i) | ||
| scopeSpans := rs.ScopeSpans() | ||
| for j := 0; j < scopeSpans.Len(); j++ { | ||
| ss := scopeSpans.At(j) | ||
| spans := ss.Spans() | ||
| for k := 0; k < spans.Len(); k++ { | ||
| span := spans.At(k) | ||
| start := span.StartTimestamp().AsTime().Add(delta) | ||
| end := span.EndTimestamp().AsTime().Add(delta) | ||
| span.SetStartTimestamp(pcommon.NewTimestampFromTime(start)) | ||
| span.SetEndTimestamp(pcommon.NewTimestampFromTime(end)) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // extractTraceID extracts the first trace ID from ptrace.Traces for retrieval testing. | ||
| func extractTraceID(t *testing.T, traces ptrace.Traces) pcommon.TraceID { | ||
| require.Positive(t, traces.ResourceSpans().Len(), "Trace must have resource spans") | ||
| rs := traces.ResourceSpans().At(0) | ||
| require.Positive(t, rs.ScopeSpans().Len(), "Resource must have scope spans") | ||
| ss := rs.ScopeSpans().At(0) | ||
| require.Positive(t, ss.Spans().Len(), "Scope must have spans") | ||
| return ss.Spans().At(0).TraceID() | ||
| } | ||
|
|
||
| // RunAll runs all integration tests | ||
| func (s *StorageIntegration) RunAll(t *testing.T) { | ||
| s.RunSpanStoreTests(t) | ||
|
|
@@ -643,4 +772,5 @@ func (s *StorageIntegration) RunSpanStoreTests(t *testing.T) { | |
| t.Run("GetLargeTrace", s.testGetLargeTrace) | ||
| t.Run("GetTraceWithDuplicateSpans", s.testGetTraceWithDuplicates) | ||
| t.Run("FindTraces", s.testFindTraces) | ||
| t.Run("OTLPScopePreservation", s.testOTLPScopePreservation) | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.