Skip to content

Commit 4bac647

Browse files
authored
[connector/spanmetrics] Add extra tests (#34765)
This PR adds tests which were previously added in #17350, but got removed in #30149.
1 parent b52e760 commit 4bac647

File tree

1 file changed

+187
-63
lines changed

1 file changed

+187
-63
lines changed

connector/servicegraphconnector/connector_test.go

Lines changed: 187 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"go.opentelemetry.io/collector/consumer"
2020
"go.opentelemetry.io/collector/consumer/consumertest"
2121
"go.opentelemetry.io/collector/exporter"
22+
"go.opentelemetry.io/collector/featuregate"
2223
"go.opentelemetry.io/collector/pdata/pcommon"
2324
"go.opentelemetry.io/collector/pdata/pmetric"
2425
"go.opentelemetry.io/collector/pdata/ptrace"
@@ -63,69 +64,145 @@ func TestConnectorShutdown(t *testing.T) {
6364
}
6465

6566
func TestConnectorConsume(t *testing.T) {
66-
t.Run("test common case", func(t *testing.T) {
67-
// Prepare
68-
cfg := &Config{
69-
Dimensions: []string{"some-attribute", "non-existing-attribute"},
70-
Store: StoreConfig{MaxItems: 10},
71-
}
72-
73-
set := componenttest.NewNopTelemetrySettings()
74-
set.Logger = zaptest.NewLogger(t)
75-
conn, err := newConnector(set, cfg, newMockMetricsExporter())
76-
require.NoError(t, err)
77-
assert.NoError(t, conn.Start(context.Background(), componenttest.NewNopHost()))
78-
79-
// Test & verify
80-
td := buildSampleTrace(t, "val")
81-
// The assertion is part of verifyHappyCaseMetrics func.
82-
assert.NoError(t, conn.ConsumeTraces(context.Background(), td))
83-
84-
// Force collection
85-
conn.store.Expire()
86-
md, err := conn.buildMetrics()
87-
assert.NoError(t, err)
88-
verifyHappyCaseMetrics(t, md)
89-
90-
// Shutdown the connector
91-
assert.NoError(t, conn.Shutdown(context.Background()))
92-
})
93-
t.Run("test fix failed label not work", func(t *testing.T) {
94-
cfg := &Config{
95-
Store: StoreConfig{MaxItems: 10},
96-
}
97-
set := componenttest.NewNopTelemetrySettings()
98-
set.Logger = zaptest.NewLogger(t)
99-
conn, err := newConnector(set, cfg, newMockMetricsExporter())
100-
require.NoError(t, err)
101-
102-
assert.NoError(t, conn.Start(context.Background(), componenttest.NewNopHost()))
103-
defer require.NoError(t, conn.Shutdown(context.Background()))
104-
105-
// this trace simulate two services' trace: foo, bar
106-
// foo called bar three times, two success, one failed
107-
td, err := golden.ReadTraces("testdata/failed-label-not-work-simple-trace.yaml")
108-
assert.NoError(t, err)
109-
assert.NoError(t, conn.ConsumeTraces(context.Background(), td))
110-
111-
// Force collection
112-
conn.store.Expire()
113-
actualMetrics, err := conn.buildMetrics()
114-
assert.NoError(t, err)
115-
116-
// Verify
117-
expectedMetrics, err := golden.ReadMetrics("testdata/failed-label-not-work-expect-metrics.yaml")
118-
assert.NoError(t, err)
119-
120-
err = pmetrictest.CompareMetrics(expectedMetrics, actualMetrics,
121-
pmetrictest.IgnoreMetricsOrder(),
122-
pmetrictest.IgnoreMetricDataPointsOrder(),
123-
pmetrictest.IgnoreStartTimestamp(),
124-
pmetrictest.IgnoreTimestamp(),
125-
pmetrictest.IgnoreDatapointAttributesOrder(),
126-
)
127-
require.NoError(t, err)
128-
})
67+
for _, tc := range []struct {
68+
name string
69+
cfg *Config
70+
gates []*featuregate.Gate
71+
sampleTraces ptrace.Traces
72+
verifyMetrics func(t *testing.T, md pmetric.Metrics)
73+
}{
74+
{
75+
name: "complete traces with client and server span",
76+
cfg: &Config{
77+
Dimensions: []string{"some-attribute", "non-existing-attribute"},
78+
Store: StoreConfig{
79+
MaxItems: 10,
80+
TTL: time.Nanosecond,
81+
},
82+
},
83+
sampleTraces: buildSampleTrace(t, "val"),
84+
verifyMetrics: verifyHappyCaseMetrics,
85+
},
86+
{
87+
name: "test fix failed label not work",
88+
cfg: &Config{
89+
Store: StoreConfig{
90+
MaxItems: 10,
91+
TTL: time.Nanosecond,
92+
},
93+
},
94+
sampleTraces: getGoldenTraces(t, "testdata/failed-label-not-work-simple-trace.yaml"),
95+
verifyMetrics: func(t *testing.T, actualMetrics pmetric.Metrics) {
96+
expectedMetrics, err := golden.ReadMetrics("testdata/failed-label-not-work-expect-metrics.yaml")
97+
assert.NoError(t, err)
98+
99+
err = pmetrictest.CompareMetrics(expectedMetrics, actualMetrics,
100+
pmetrictest.IgnoreMetricsOrder(),
101+
pmetrictest.IgnoreMetricDataPointsOrder(),
102+
pmetrictest.IgnoreStartTimestamp(),
103+
pmetrictest.IgnoreTimestamp(),
104+
pmetrictest.IgnoreDatapointAttributesOrder(),
105+
)
106+
require.NoError(t, err)
107+
},
108+
},
109+
{
110+
name: "incomplete traces with virtual server span",
111+
cfg: &Config{
112+
Dimensions: []string{"some-attribute", "non-existing-attribute"},
113+
Store: StoreConfig{
114+
MaxItems: 10,
115+
TTL: time.Nanosecond,
116+
},
117+
},
118+
sampleTraces: incompleteClientTraces(),
119+
verifyMetrics: func(t *testing.T, md pmetric.Metrics) {
120+
v, ok := md.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().At(0).Sum().DataPoints().At(0).Attributes().Get("server")
121+
assert.True(t, ok)
122+
assert.Equal(t, "AuthTokenCache", v.Str())
123+
},
124+
},
125+
{
126+
name: "incomplete traces with virtual client span",
127+
cfg: &Config{
128+
Dimensions: []string{"some-attribute", "non-existing-attribute"},
129+
Store: StoreConfig{
130+
MaxItems: 10,
131+
TTL: time.Nanosecond,
132+
},
133+
},
134+
sampleTraces: incompleteServerTraces(false),
135+
verifyMetrics: func(t *testing.T, md pmetric.Metrics) {
136+
v, ok := md.ResourceMetrics().At(0).ScopeMetrics().At(0).Metrics().At(0).Sum().DataPoints().At(0).Attributes().Get("client")
137+
assert.True(t, ok)
138+
assert.Equal(t, "user", v.Str())
139+
},
140+
},
141+
{
142+
name: "incomplete traces with client span lost",
143+
cfg: &Config{
144+
Dimensions: []string{"some-attribute", "non-existing-attribute"},
145+
Store: StoreConfig{
146+
MaxItems: 10,
147+
TTL: time.Nanosecond,
148+
},
149+
},
150+
sampleTraces: incompleteServerTraces(true),
151+
verifyMetrics: func(t *testing.T, md pmetric.Metrics) {
152+
assert.Equal(t, 0, md.MetricCount())
153+
},
154+
},
155+
{
156+
name: "complete traces with legacy latency metrics",
157+
cfg: &Config{
158+
Dimensions: []string{"some-attribute", "non-existing-attribute"},
159+
Store: StoreConfig{
160+
MaxItems: 10,
161+
TTL: time.Nanosecond,
162+
},
163+
},
164+
sampleTraces: buildSampleTrace(t, "val"),
165+
gates: []*featuregate.Gate{legacyLatencyUnitMsFeatureGate},
166+
verifyMetrics: verifyHappyCaseMetricsWithDuration(1000),
167+
},
168+
} {
169+
t.Run(tc.name, func(t *testing.T) {
170+
// Set feature gates
171+
for _, gate := range tc.gates {
172+
require.NoError(t, featuregate.GlobalRegistry().Set(gate.ID(), true))
173+
}
174+
175+
// Prepare
176+
set := componenttest.NewNopTelemetrySettings()
177+
set.Logger = zaptest.NewLogger(t)
178+
conn, err := newConnector(set, tc.cfg, newMockMetricsExporter())
179+
require.NoError(t, err)
180+
assert.NoError(t, conn.Start(context.Background(), componenttest.NewNopHost()))
181+
182+
// Send spans to the connector
183+
assert.NoError(t, conn.ConsumeTraces(context.Background(), tc.sampleTraces))
184+
185+
// Force collection
186+
conn.store.Expire()
187+
md, err := conn.buildMetrics()
188+
assert.NoError(t, err)
189+
tc.verifyMetrics(t, md)
190+
191+
// Shutdown the connector
192+
assert.NoError(t, conn.Shutdown(context.Background()))
193+
194+
// Unset feature gates
195+
for _, gate := range tc.gates {
196+
require.NoError(t, featuregate.GlobalRegistry().Set(gate.ID(), false))
197+
}
198+
})
199+
}
200+
}
201+
202+
func getGoldenTraces(t *testing.T, file string) ptrace.Traces {
203+
td, err := golden.ReadTraces(file)
204+
assert.NoError(t, err)
205+
return td
129206
}
130207

131208
func verifyHappyCaseMetrics(t *testing.T, md pmetric.Metrics) {
@@ -245,6 +322,53 @@ func buildSampleTrace(t *testing.T, attrValue string) ptrace.Traces {
245322
return traces
246323
}
247324

325+
func incompleteClientTraces() ptrace.Traces {
326+
tStart := time.Date(2022, 1, 2, 3, 4, 5, 6, time.UTC)
327+
tEnd := time.Date(2022, 1, 2, 3, 4, 6, 6, time.UTC)
328+
329+
traces := ptrace.NewTraces()
330+
331+
resourceSpans := traces.ResourceSpans().AppendEmpty()
332+
resourceSpans.Resource().Attributes().PutStr(semconv.AttributeServiceName, "some-client-service")
333+
334+
scopeSpans := resourceSpans.ScopeSpans().AppendEmpty()
335+
anotherTraceID := pcommon.TraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16})
336+
anotherClientSpanID := pcommon.SpanID([8]byte{1, 2, 3, 4, 4, 3, 2, 1})
337+
clientSpanNoServerSpan := scopeSpans.Spans().AppendEmpty()
338+
clientSpanNoServerSpan.SetName("client span")
339+
clientSpanNoServerSpan.SetSpanID(anotherClientSpanID)
340+
clientSpanNoServerSpan.SetTraceID(anotherTraceID)
341+
clientSpanNoServerSpan.SetKind(ptrace.SpanKindClient)
342+
clientSpanNoServerSpan.SetStartTimestamp(pcommon.NewTimestampFromTime(tStart))
343+
clientSpanNoServerSpan.SetEndTimestamp(pcommon.NewTimestampFromTime(tEnd))
344+
clientSpanNoServerSpan.Attributes().PutStr(semconv.AttributePeerService, "AuthTokenCache") // Attribute selected as dimension for metrics
345+
346+
return traces
347+
}
348+
349+
func incompleteServerTraces(withParentSpan bool) ptrace.Traces {
350+
tStart := time.Date(2022, 1, 2, 3, 4, 5, 6, time.UTC)
351+
tEnd := time.Date(2022, 1, 2, 3, 4, 6, 6, time.UTC)
352+
353+
traces := ptrace.NewTraces()
354+
355+
resourceSpans := traces.ResourceSpans().AppendEmpty()
356+
resourceSpans.Resource().Attributes().PutStr(semconv.AttributeServiceName, "some-server-service")
357+
scopeSpans := resourceSpans.ScopeSpans().AppendEmpty()
358+
anotherTraceID := pcommon.TraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1})
359+
serverSpanNoClientSpan := scopeSpans.Spans().AppendEmpty()
360+
serverSpanNoClientSpan.SetName("server span")
361+
serverSpanNoClientSpan.SetSpanID([8]byte{0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26})
362+
if withParentSpan {
363+
serverSpanNoClientSpan.SetParentSpanID([8]byte{0x27, 0x28, 0x29, 0x30, 0x31, 0x32, 0x33, 0x34})
364+
}
365+
serverSpanNoClientSpan.SetTraceID(anotherTraceID)
366+
serverSpanNoClientSpan.SetKind(ptrace.SpanKindServer)
367+
serverSpanNoClientSpan.SetStartTimestamp(pcommon.NewTimestampFromTime(tStart))
368+
serverSpanNoClientSpan.SetEndTimestamp(pcommon.NewTimestampFromTime(tEnd))
369+
return traces
370+
}
371+
248372
var _ exporter.Metrics = (*mockMetricsExporter)(nil)
249373

250374
func newMockMetricsExporter() *mockMetricsExporter {

0 commit comments

Comments
 (0)