Skip to content

Commit e52bb22

Browse files
songy23dragonlord93
authored andcommitted
[chore][exporter/datadogexporter] fix data race in tests again (open-telemetry#39802)
#### Description Having both the otlp grpc exporter & otlp grpc recevier in the tests introduces data race, so move all tests to use HTTP instead. Also make sure to properly close all go routines before tests complete. #### Link to tracking issue Fixes open-telemetry#39782 Fixes open-telemetry#39780 Fixes open-telemetry#39519 Fixes http://github.com/open-telemetry/opentelemetry-collector-contrib/issues/39804
1 parent 744e61a commit e52bb22

File tree

7 files changed

+136
-171
lines changed

7 files changed

+136
-171
lines changed

exporter/datadogexporter/integrationtest/go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ require (
2929
go.opentelemetry.io/collector/receiver v1.31.1-0.20250509190408-4ca0f1829e0a
3030
go.opentelemetry.io/collector/receiver/otlpreceiver v0.125.1-0.20250509190408-4ca0f1829e0a
3131
go.opentelemetry.io/otel v1.35.0
32-
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0
33-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0
32+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0
33+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0
3434
go.opentelemetry.io/otel/sdk v1.35.0
3535
go.opentelemetry.io/otel/sdk/log v0.11.0
3636
go.opentelemetry.io/otel/trace v1.35.0
@@ -338,11 +338,11 @@ require (
338338
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
339339
go.opentelemetry.io/contrib/otelconf v0.15.0 // indirect
340340
go.opentelemetry.io/contrib/propagators/b3 v1.35.0 // indirect
341-
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.11.0 // indirect
341+
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.11.0 // indirect
342342
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect
343343
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 // indirect
344344
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
345-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect
345+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect
346346
go.opentelemetry.io/otel/exporters/prometheus v0.57.0 // indirect
347347
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.11.0 // indirect
348348
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 // indirect

exporter/datadogexporter/integrationtest/integration_test.go

Lines changed: 132 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ import (
3939
"go.opentelemetry.io/collector/receiver/otlpreceiver"
4040
"go.opentelemetry.io/otel"
4141
"go.opentelemetry.io/otel/attribute"
42-
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
43-
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
42+
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
43+
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
4444
"go.opentelemetry.io/otel/sdk/log"
4545
"go.opentelemetry.io/otel/sdk/resource"
4646
sdktrace "go.opentelemetry.io/otel/sdk/trace"
@@ -73,46 +73,35 @@ type point struct {
7373
Value float64
7474
}
7575

76-
func TestIntegration_NativeOTelAPMStatsIngest(t *testing.T) {
77-
previousVal := datadogconnector.NativeIngestFeatureGate.IsEnabled()
78-
err := featuregate.GlobalRegistry().Set(datadogconnector.NativeIngestFeatureGate.ID(), true)
79-
require.NoError(t, err)
80-
defer func() {
81-
err = featuregate.GlobalRegistry().Set(datadogconnector.NativeIngestFeatureGate.ID(), previousVal)
82-
require.NoError(t, err)
83-
}()
84-
85-
testIntegration(t)
86-
}
87-
88-
func TestIntegration_LegacyOTelAPMStatsIngest(t *testing.T) {
89-
testIntegration(t)
90-
}
91-
92-
func testIntegration(t *testing.T) {
76+
func TestIntegration(t *testing.T) {
9377
// 1. Set up mock Datadog server
9478
// See also https://github.com/DataDog/datadog-agent/blob/49c16e0d4deab396626238fa1d572b684475a53f/cmd/trace-agent/test/backend.go
9579
apmstatsRec := &testutil.HTTPRequestRecorderWithChan{Pattern: testutil.APMStatsEndpoint, ReqChan: make(chan []byte)}
9680
tracesRec := &testutil.HTTPRequestRecorderWithChan{Pattern: testutil.TraceEndpoint, ReqChan: make(chan []byte)}
9781
server := testutil.DatadogServerMock(apmstatsRec.HandlerFunc, tracesRec.HandlerFunc)
9882
defer server.Close()
9983
t.Setenv("SERVER_URL", server.URL)
100-
t.Setenv("OTLP_HTTP_SERVER", commonTestutil.GetAvailableLocalAddress(t))
101-
otlpGRPCEndpoint := commonTestutil.GetAvailableLocalAddress(t)
102-
t.Setenv("OTLP_GRPC_SERVER", otlpGRPCEndpoint)
84+
otlpEndpoint := commonTestutil.GetAvailableLocalAddress(t)
85+
t.Setenv("OTLP_HTTP_SERVER", otlpEndpoint)
10386

10487
// 2. Start in-process collector
10588
factories := getIntegrationTestComponents(t)
10689
app := getIntegrationTestCollector(t, "integration_test_config.yaml", factories)
90+
var wg sync.WaitGroup
91+
wg.Add(1)
10792
go func() {
108-
assert.NoError(t, app.Run(context.Background()))
93+
_ = app.Run(context.Background()) // ignore shutdown error, core collector has race in shutdown: https://github.com/open-telemetry/opentelemetry-collector/issues/12944
94+
wg.Done()
95+
}()
96+
defer func() {
97+
app.Shutdown()
98+
wg.Wait()
10999
}()
110-
defer app.Shutdown()
111100

112101
waitForReadiness(app)
113102

114103
// 3. Generate and send traces
115-
sendTraces(t, otlpGRPCEndpoint)
104+
sendTraces(t, otlpEndpoint)
116105

117106
// 4. Validate traces and APM stats from the mock server
118107
var spans []*pb.Span
@@ -233,7 +222,7 @@ func sendTraces(t *testing.T, endpoint string) {
233222
ctx := context.Background()
234223

235224
// Set up OTel-Go SDK and exporter
236-
traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), otlptracegrpc.WithEndpoint(endpoint))
225+
traceExporter, err := otlptracehttp.New(ctx, otlptracehttp.WithInsecure(), otlptracehttp.WithEndpoint(endpoint))
237226
require.NoError(t, err)
238227
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
239228
r1, _ := resource.New(ctx, resource.WithAttributes(attribute.String("k8s.node.name", "aaaa")))
@@ -290,22 +279,27 @@ func TestIntegrationComputeTopLevelBySpanKind(t *testing.T) {
290279
server := testutil.DatadogServerMock(apmstatsRec.HandlerFunc, tracesRec.HandlerFunc)
291280
defer server.Close()
292281
t.Setenv("SERVER_URL", server.URL)
293-
t.Setenv("OTLP_HTTP_SERVER", commonTestutil.GetAvailableLocalAddress(t))
294-
otlpGRPCEndpoint := commonTestutil.GetAvailableLocalAddress(t)
295-
t.Setenv("OTLP_GRPC_SERVER", otlpGRPCEndpoint)
282+
otlpEndpoint := commonTestutil.GetAvailableLocalAddress(t)
283+
t.Setenv("OTLP_HTTP_SERVER", otlpEndpoint)
296284

297285
// 2. Start in-process collector
298286
factories := getIntegrationTestComponents(t)
299287
app := getIntegrationTestCollector(t, "integration_test_toplevel_config.yaml", factories)
288+
var wg sync.WaitGroup
289+
wg.Add(1)
300290
go func() {
301-
assert.NoError(t, app.Run(context.Background()))
291+
_ = app.Run(context.Background()) // ignore shutdown error, core collector has race in shutdown: https://github.com/open-telemetry/opentelemetry-collector/issues/12944
292+
wg.Done()
293+
}()
294+
defer func() {
295+
app.Shutdown()
296+
wg.Wait()
302297
}()
303-
defer app.Shutdown()
304298

305299
waitForReadiness(app)
306300

307301
// 3. Generate and send traces
308-
sendTracesComputeTopLevelBySpanKind(t, otlpGRPCEndpoint)
302+
sendTracesComputeTopLevelBySpanKind(t, otlpEndpoint)
309303

310304
// 4. Validate traces and APM stats from the mock server
311305
var spans []*pb.Span
@@ -397,7 +391,7 @@ func sendTracesComputeTopLevelBySpanKind(t *testing.T, endpoint string) {
397391
ctx := context.Background()
398392

399393
// Set up OTel-Go SDK and exporter
400-
traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), otlptracegrpc.WithEndpoint(endpoint))
394+
traceExporter, err := otlptracehttp.New(ctx, otlptracehttp.WithInsecure(), otlptracehttp.WithEndpoint(endpoint))
401395
require.NoError(t, err)
402396
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
403397
r1, _ := resource.New(ctx, resource.WithAttributes(attribute.String("k8s.node.name", "aaaa")))
@@ -478,17 +472,16 @@ func TestIntegrationLogs(t *testing.T) {
478472
})
479473
defer server.Close()
480474
t.Setenv("SERVER_URL", server.URL)
481-
t.Setenv("OTLP_HTTP_SERVER", commonTestutil.GetAvailableLocalAddress(t))
482-
otlpGRPCEndpoint := commonTestutil.GetAvailableLocalAddress(t)
483-
t.Setenv("OTLP_GRPC_SERVER", otlpGRPCEndpoint)
475+
otlpEndpoint := commonTestutil.GetAvailableLocalAddress(t)
476+
t.Setenv("OTLP_HTTP_SERVER", otlpEndpoint)
484477

485478
// 2. Start in-process collector
486479
factories := getIntegrationTestComponents(t)
487480
app := getIntegrationTestCollector(t, "integration_test_logs_config.yaml", factories)
488481
var wg sync.WaitGroup
489482
wg.Add(1)
490483
go func() {
491-
_ = app.Run(context.Background()) // ignore shutdown error
484+
_ = app.Run(context.Background()) // ignore shutdown error, core collector has race in shutdown: https://github.com/open-telemetry/opentelemetry-collector/issues/12944
492485
wg.Done()
493486
}()
494487
defer func() {
@@ -499,7 +492,7 @@ func TestIntegrationLogs(t *testing.T) {
499492
waitForReadiness(app)
500493

501494
// 3. Generate and send logs
502-
sendLogs(t, 5, otlpGRPCEndpoint)
495+
sendLogs(t, 5, otlpEndpoint)
503496

504497
// 4. Validate logs and metrics from the mock server
505498
// Wait until `doneChannel` is closed and internal metrics are received.
@@ -545,7 +538,7 @@ func TestIntegrationLogs(t *testing.T) {
545538

546539
func sendLogs(t *testing.T, numLogs int, endpoint string) {
547540
ctx := context.Background()
548-
logExporter, err := otlploggrpc.New(ctx, otlploggrpc.WithInsecure(), otlploggrpc.WithEndpoint(endpoint))
541+
logExporter, err := otlploghttp.New(ctx, otlploghttp.WithInsecure(), otlploghttp.WithEndpoint(endpoint))
549542
assert.NoError(t, err)
550543
lr := make([]log.Record, numLogs)
551544
assert.NoError(t, logExporter.Export(ctx, lr))
@@ -642,10 +635,16 @@ func testIntegrationHostMetrics(t *testing.T, expectedMetrics map[string]struct{
642635
// 2. Start in-process collector
643636
factories := getIntegrationTestComponents(t)
644637
app := getIntegrationTestCollector(t, "integration_test_host_metrics_config.yaml", factories)
638+
var wg sync.WaitGroup
639+
wg.Add(1)
645640
go func() {
646-
assert.NoError(t, app.Run(context.Background()))
641+
_ = app.Run(context.Background()) // ignore shutdown error, core collector has race in shutdown: https://github.com/open-telemetry/opentelemetry-collector/issues/12944
642+
wg.Done()
643+
}()
644+
defer func() {
645+
app.Shutdown()
646+
wg.Wait()
647647
}()
648-
defer app.Shutdown()
649648

650649
waitForReadiness(app)
651650

@@ -730,3 +729,95 @@ func seriesFromAPIClient(t *testing.T, metricsBytes []byte, expectedMetrics map[
730729
}
731730
return metricMap, nil
732731
}
732+
733+
func TestIntegrationInternalMetrics(t *testing.T) {
734+
require.NoError(t, featuregate.GlobalRegistry().Set("exporter.datadogexporter.metricexportserializerclient", false))
735+
defer func() {
736+
require.NoError(t, featuregate.GlobalRegistry().Set("exporter.datadogexporter.metricexportserializerclient", true))
737+
}()
738+
expectedMetrics := map[string]struct{}{
739+
// Datadog internal metrics on trace and stats writers
740+
"datadog.otlp_translator.resources.missing_source": {},
741+
"datadog.trace_agent.stats_writer.bytes": {},
742+
"datadog.trace_agent.stats_writer.retries": {},
743+
"datadog.trace_agent.stats_writer.stats_buckets": {},
744+
"datadog.trace_agent.stats_writer.stats_entries": {},
745+
"datadog.trace_agent.stats_writer.payloads": {},
746+
"datadog.trace_agent.stats_writer.client_payloads": {},
747+
"datadog.trace_agent.stats_writer.errors": {},
748+
"datadog.trace_agent.stats_writer.splits": {},
749+
"datadog.trace_agent.trace_writer.bytes": {},
750+
"datadog.trace_agent.trace_writer.retries": {},
751+
"datadog.trace_agent.trace_writer.spans": {},
752+
"datadog.trace_agent.trace_writer.traces": {},
753+
"datadog.trace_agent.trace_writer.payloads": {},
754+
"datadog.trace_agent.trace_writer.errors": {},
755+
"datadog.trace_agent.trace_writer.events": {},
756+
757+
// OTel collector internal metrics
758+
"otelcol_process_memory_rss": {},
759+
"otelcol_process_runtime_total_sys_memory_bytes": {},
760+
"otelcol_process_uptime": {},
761+
"otelcol_process_cpu_seconds": {},
762+
"otelcol_process_runtime_heap_alloc_bytes": {},
763+
"otelcol_process_runtime_total_alloc_bytes": {},
764+
"otelcol_receiver_accepted_metric_points": {},
765+
"otelcol_receiver_accepted_spans": {},
766+
"otelcol_exporter_queue_capacity": {},
767+
"otelcol_exporter_queue_size": {},
768+
"otelcol_exporter_sent_spans": {},
769+
"otelcol_exporter_sent_metric_points": {},
770+
}
771+
testIntegrationInternalMetrics(t, expectedMetrics)
772+
}
773+
774+
func testIntegrationInternalMetrics(t *testing.T, expectedMetrics map[string]struct{}) {
775+
// 1. Set up mock Datadog server
776+
seriesRec := &testutil.HTTPRequestRecorderWithChan{Pattern: testutil.MetricV2Endpoint, ReqChan: make(chan []byte, 100)}
777+
tracesRec := &testutil.HTTPRequestRecorderWithChan{Pattern: testutil.TraceEndpoint, ReqChan: make(chan []byte, 100)}
778+
server := testutil.DatadogServerMock(seriesRec.HandlerFunc, tracesRec.HandlerFunc)
779+
defer server.Close()
780+
t.Setenv("SERVER_URL", server.URL)
781+
otlpEndpoint := commonTestutil.GetAvailableLocalAddress(t)
782+
t.Setenv("OTLP_HTTP_SERVER", otlpEndpoint)
783+
784+
// 2. Start in-process collector
785+
factories := getIntegrationTestComponents(t)
786+
app := getIntegrationTestCollector(t, "integration_test_internal_metrics_config.yaml", factories)
787+
var wg sync.WaitGroup
788+
wg.Add(1)
789+
go func() {
790+
_ = app.Run(context.Background()) // ignore shutdown error, core collector has race in shutdown: https://github.com/open-telemetry/opentelemetry-collector/issues/12944
791+
wg.Done()
792+
}()
793+
defer func() {
794+
app.Shutdown()
795+
wg.Wait()
796+
}()
797+
798+
waitForReadiness(app)
799+
800+
// 3. Generate and send traces
801+
sendTraces(t, otlpEndpoint)
802+
803+
// 4. Validate Datadog trace agent & OTel internal metrics are sent to the mock server
804+
metricMap := make(map[string]series)
805+
for len(metricMap) < len(expectedMetrics) {
806+
select {
807+
case <-tracesRec.ReqChan:
808+
// Drain the channel, no need to look into the traces
809+
case metricsBytes := <-seriesRec.ReqChan:
810+
var metrics seriesSlice
811+
gz := getGzipReader(t, metricsBytes)
812+
dec := json.NewDecoder(gz)
813+
assert.NoError(t, dec.Decode(&metrics))
814+
for _, s := range metrics.Series {
815+
if _, ok := expectedMetrics[s.Metric]; ok {
816+
metricMap[s.Metric] = s
817+
}
818+
}
819+
case <-time.After(60 * time.Second):
820+
t.Fail()
821+
}
822+
}
823+
}

exporter/datadogexporter/integrationtest/integration_test_config.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ receivers:
44
protocols:
55
http:
66
endpoint: ${env:OTLP_HTTP_SERVER}
7-
grpc:
8-
endpoint: ${env:OTLP_GRPC_SERVER}
97

108
processors:
119
tail_sampling:
@@ -25,7 +23,6 @@ connectors:
2523

2624
exporters:
2725
debug:
28-
verbosity: detailed
2926
datadog:
3027
api:
3128
key: "aaa"

exporter/datadogexporter/integrationtest/integration_test_internal_metrics_config.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ receivers:
44
protocols:
55
http:
66
endpoint: ${env:OTLP_HTTP_SERVER}
7-
grpc:
8-
endpoint: ${env:OTLP_GRPC_SERVER}
97

108
exporters:
119
datadog:

exporter/datadogexporter/integrationtest/integration_test_logs_config.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ receivers:
44
protocols:
55
http:
66
endpoint: ${env:OTLP_HTTP_SERVER}
7-
grpc:
8-
endpoint: ${env:OTLP_GRPC_SERVER}
97

108
exporters:
119
datadog:

exporter/datadogexporter/integrationtest/integration_test_toplevel_config.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ receivers:
44
protocols:
55
http:
66
endpoint: ${env:OTLP_HTTP_SERVER}
7-
grpc:
8-
endpoint: ${env:OTLP_GRPC_SERVER}
97

108
connectors:
119
datadog/connector:
@@ -14,7 +12,6 @@ connectors:
1412

1513
exporters:
1614
debug:
17-
verbosity: detailed
1815
datadog:
1916
api:
2017
key: "aaa"

0 commit comments

Comments
 (0)