Skip to content

Commit 3dad181

Browse files
authored
[exporterhelper] Add observability to the new exporter helper (#8244)
This change adds collector's internal metrics and tracing to the new request-based exporter helpers. Only those metrics and traces are added that are already adopted by the existing exporter helpers for backward compatibility. The new exporter helpers can and should expose more metrics in the future, e.g. for tracking converter errors. Tracking Issue: #8122
1 parent 76e0540 commit 3dad181

File tree

6 files changed

+198
-12
lines changed

6 files changed

+198
-12
lines changed

exporter/exporterhelper/logs.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,12 @@ func NewLogsRequestExporter(
149149
if err != nil {
150150
return nil, err
151151
}
152-
153-
// TODO: Add new observability tracing/metrics to the new exporterhelper.
152+
be.wrapConsumerSender(func(nextSender requestSender) requestSender {
153+
return &logsExporterWithObservability{
154+
obsrep: be.obsrep,
155+
nextSender: nextSender,
156+
}
157+
})
154158

155159
lc, err := consumer.NewLogs(func(ctx context.Context, ld plog.Logs) error {
156160
req, cErr := converter.RequestFromLogs(ctx, ld)
@@ -160,10 +164,15 @@ func NewLogsRequestExporter(
160164
zap.Error(err))
161165
return consumererror.NewPermanent(cErr)
162166
}
163-
return be.sender.send(&request{
167+
r := &request{
164168
baseRequest: baseRequest{ctx: ctx},
165169
Request: req,
166-
})
170+
}
171+
sErr := be.sender.send(r)
172+
if errors.Is(sErr, errSendingQueueIsFull) {
173+
be.obsrep.recordLogsEnqueueFailure(r.Context(), int64(r.Count()))
174+
}
175+
return sErr
167176
}, bs.consumerOptions...)
168177

169178
return &logsExporter{

exporter/exporterhelper/logs_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,18 @@ func TestLogsExporter_WithRecordMetrics(t *testing.T) {
160160
checkRecordedMetricsForLogsExporter(t, tt, le, nil)
161161
}
162162

163+
func TestLogsRequestExporter_WithRecordMetrics(t *testing.T) {
164+
tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName)
165+
require.NoError(t, err)
166+
t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) })
167+
168+
le, err := NewLogsRequestExporter(context.Background(), tt.ToExporterCreateSettings(), &fakeRequestConverter{})
169+
require.NoError(t, err)
170+
require.NotNil(t, le)
171+
172+
checkRecordedMetricsForLogsExporter(t, tt, le, nil)
173+
}
174+
163175
func TestLogsExporter_WithRecordMetrics_ReturnError(t *testing.T) {
164176
want := errors.New("my_error")
165177
tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName)
@@ -173,6 +185,20 @@ func TestLogsExporter_WithRecordMetrics_ReturnError(t *testing.T) {
173185
checkRecordedMetricsForLogsExporter(t, tt, le, want)
174186
}
175187

188+
func TestLogsRequestExporter_WithRecordMetrics_ExportError(t *testing.T) {
189+
want := errors.New("export_error")
190+
tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName)
191+
require.NoError(t, err)
192+
t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) })
193+
194+
le, err := NewLogsRequestExporter(context.Background(), tt.ToExporterCreateSettings(),
195+
&fakeRequestConverter{requestError: want})
196+
require.Nil(t, err)
197+
require.NotNil(t, le)
198+
199+
checkRecordedMetricsForLogsExporter(t, tt, le, want)
200+
}
201+
176202
func TestLogsExporter_WithRecordEnqueueFailedMetrics(t *testing.T) {
177203
tt, err := obsreporttest.SetupTelemetry(fakeLogsExporterName)
178204
require.NoError(t, err)
@@ -211,6 +237,19 @@ func TestLogsExporter_WithSpan(t *testing.T) {
211237
checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, nil, 1)
212238
}
213239

240+
func TestLogsRequestExporter_WithSpan(t *testing.T) {
241+
set := exportertest.NewNopCreateSettings()
242+
sr := new(tracetest.SpanRecorder)
243+
set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr))
244+
otel.SetTracerProvider(set.TracerProvider)
245+
defer otel.SetTracerProvider(trace.NewNoopTracerProvider())
246+
247+
le, err := NewLogsRequestExporter(context.Background(), set, &fakeRequestConverter{})
248+
require.Nil(t, err)
249+
require.NotNil(t, le)
250+
checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, nil, 1)
251+
}
252+
214253
func TestLogsExporter_WithSpan_ReturnError(t *testing.T) {
215254
set := exportertest.NewNopCreateSettings()
216255
sr := new(tracetest.SpanRecorder)
@@ -225,6 +264,20 @@ func TestLogsExporter_WithSpan_ReturnError(t *testing.T) {
225264
checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, want, 1)
226265
}
227266

267+
func TestLogsRequestExporter_WithSpan_ReturnError(t *testing.T) {
268+
set := exportertest.NewNopCreateSettings()
269+
sr := new(tracetest.SpanRecorder)
270+
set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr))
271+
otel.SetTracerProvider(set.TracerProvider)
272+
defer otel.SetTracerProvider(trace.NewNoopTracerProvider())
273+
274+
want := errors.New("my_error")
275+
le, err := NewLogsRequestExporter(context.Background(), set, &fakeRequestConverter{requestError: want})
276+
require.Nil(t, err)
277+
require.NotNil(t, le)
278+
checkWrapSpanForLogsExporter(t, sr, set.TracerProvider.Tracer("test"), le, want, 1)
279+
}
280+
228281
func TestLogsExporter_WithShutdown(t *testing.T) {
229282
shutdownCalled := false
230283
shutdown := func(context.Context) error { shutdownCalled = true; return nil }

exporter/exporterhelper/metrics.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,12 @@ func NewMetricsRequestExporter(
149149
if err != nil {
150150
return nil, err
151151
}
152-
153-
// TODO: Add new observability tracing/metrics to the new exporterhelper.
152+
be.wrapConsumerSender(func(nextSender requestSender) requestSender {
153+
return &metricsSenderWithObservability{
154+
obsrep: be.obsrep,
155+
nextSender: nextSender,
156+
}
157+
})
154158

155159
mc, err := consumer.NewMetrics(func(ctx context.Context, md pmetric.Metrics) error {
156160
req, cErr := converter.RequestFromMetrics(ctx, md)
@@ -160,10 +164,15 @@ func NewMetricsRequestExporter(
160164
zap.Error(err))
161165
return consumererror.NewPermanent(cErr)
162166
}
163-
return be.sender.send(&request{
167+
r := &request{
164168
Request: req,
165169
baseRequest: baseRequest{ctx: ctx},
166-
})
170+
}
171+
sErr := be.sender.send(r)
172+
if errors.Is(sErr, errSendingQueueIsFull) {
173+
be.obsrep.recordMetricsEnqueueFailure(r.Context(), int64(r.Count()))
174+
}
175+
return sErr
167176
}, bs.consumerOptions...)
168177

169178
return &metricsExporter{

exporter/exporterhelper/metrics_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,18 @@ func TestMetricsExporter_WithRecordMetrics(t *testing.T) {
161161
checkRecordedMetricsForMetricsExporter(t, tt, me, nil)
162162
}
163163

164+
func TestMetricsRequestExporter_WithRecordMetrics(t *testing.T) {
165+
tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName)
166+
require.NoError(t, err)
167+
t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) })
168+
169+
me, err := NewMetricsRequestExporter(context.Background(), tt.ToExporterCreateSettings(), fakeRequestConverter{})
170+
require.NoError(t, err)
171+
require.NotNil(t, me)
172+
173+
checkRecordedMetricsForMetricsExporter(t, tt, me, nil)
174+
}
175+
164176
func TestMetricsExporter_WithRecordMetrics_ReturnError(t *testing.T) {
165177
want := errors.New("my_error")
166178
tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName)
@@ -174,6 +186,19 @@ func TestMetricsExporter_WithRecordMetrics_ReturnError(t *testing.T) {
174186
checkRecordedMetricsForMetricsExporter(t, tt, me, want)
175187
}
176188

189+
func TestMetricsRequestExporter_WithRecordMetrics_ExportError(t *testing.T) {
190+
want := errors.New("my_error")
191+
tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName)
192+
require.NoError(t, err)
193+
t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) })
194+
195+
me, err := NewMetricsRequestExporter(context.Background(), tt.ToExporterCreateSettings(), fakeRequestConverter{requestError: want})
196+
require.NoError(t, err)
197+
require.NotNil(t, me)
198+
199+
checkRecordedMetricsForMetricsExporter(t, tt, me, want)
200+
}
201+
177202
func TestMetricsExporter_WithRecordEnqueueFailedMetrics(t *testing.T) {
178203
tt, err := obsreporttest.SetupTelemetry(fakeMetricsExporterName)
179204
require.NoError(t, err)
@@ -212,6 +237,19 @@ func TestMetricsExporter_WithSpan(t *testing.T) {
212237
checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, nil, 2)
213238
}
214239

240+
func TestMetricsRequestExporter_WithSpan(t *testing.T) {
241+
set := exportertest.NewNopCreateSettings()
242+
sr := new(tracetest.SpanRecorder)
243+
set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr))
244+
otel.SetTracerProvider(set.TracerProvider)
245+
defer otel.SetTracerProvider(trace.NewNoopTracerProvider())
246+
247+
me, err := NewMetricsRequestExporter(context.Background(), set, fakeRequestConverter{})
248+
require.NoError(t, err)
249+
require.NotNil(t, me)
250+
checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, nil, 2)
251+
}
252+
215253
func TestMetricsExporter_WithSpan_ReturnError(t *testing.T) {
216254
set := exportertest.NewNopCreateSettings()
217255
sr := new(tracetest.SpanRecorder)
@@ -226,6 +264,20 @@ func TestMetricsExporter_WithSpan_ReturnError(t *testing.T) {
226264
checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, want, 2)
227265
}
228266

267+
func TestMetricsRequestExporter_WithSpan_ExportError(t *testing.T) {
268+
set := exportertest.NewNopCreateSettings()
269+
sr := new(tracetest.SpanRecorder)
270+
set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr))
271+
otel.SetTracerProvider(set.TracerProvider)
272+
defer otel.SetTracerProvider(trace.NewNoopTracerProvider())
273+
274+
want := errors.New("my_error")
275+
me, err := NewMetricsRequestExporter(context.Background(), set, fakeRequestConverter{requestError: want})
276+
require.NoError(t, err)
277+
require.NotNil(t, me)
278+
checkWrapSpanForMetricsExporter(t, sr, set.TracerProvider.Tracer("test"), me, want, 2)
279+
}
280+
229281
func TestMetricsExporter_WithShutdown(t *testing.T) {
230282
shutdownCalled := false
231283
shutdown := func(context.Context) error { shutdownCalled = true; return nil }

exporter/exporterhelper/traces.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,12 @@ func NewTracesRequestExporter(
149149
if err != nil {
150150
return nil, err
151151
}
152-
153-
// TODO: Add new observability tracing/metrics to the new exporterhelper.
152+
be.wrapConsumerSender(func(nextSender requestSender) requestSender {
153+
return &tracesExporterWithObservability{
154+
obsrep: be.obsrep,
155+
nextSender: nextSender,
156+
}
157+
})
154158

155159
tc, err := consumer.NewTraces(func(ctx context.Context, td ptrace.Traces) error {
156160
req, cErr := converter.RequestFromTraces(ctx, td)
@@ -160,10 +164,15 @@ func NewTracesRequestExporter(
160164
zap.Error(err))
161165
return consumererror.NewPermanent(cErr)
162166
}
163-
return be.sender.send(&request{
167+
r := &request{
164168
baseRequest: baseRequest{ctx: ctx},
165169
Request: req,
166-
})
170+
}
171+
sErr := be.sender.send(r)
172+
if errors.Is(sErr, errSendingQueueIsFull) {
173+
be.obsrep.recordTracesEnqueueFailure(r.Context(), int64(r.Count()))
174+
}
175+
return sErr
167176
}, bs.consumerOptions...)
168177

169178
return &traceExporter{

exporter/exporterhelper/traces_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,18 @@ func TestTracesExporter_WithRecordMetrics(t *testing.T) {
158158
checkRecordedMetricsForTracesExporter(t, tt, te, nil)
159159
}
160160

161+
func TestTracesRequestExporter_WithRecordMetrics(t *testing.T) {
162+
tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName)
163+
require.NoError(t, err)
164+
t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) })
165+
166+
te, err := NewTracesRequestExporter(context.Background(), tt.ToExporterCreateSettings(), &fakeRequestConverter{})
167+
require.NoError(t, err)
168+
require.NotNil(t, te)
169+
170+
checkRecordedMetricsForTracesExporter(t, tt, te, nil)
171+
}
172+
161173
func TestTracesExporter_WithRecordMetrics_ReturnError(t *testing.T) {
162174
want := errors.New("my_error")
163175
tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName)
@@ -171,6 +183,19 @@ func TestTracesExporter_WithRecordMetrics_ReturnError(t *testing.T) {
171183
checkRecordedMetricsForTracesExporter(t, tt, te, want)
172184
}
173185

186+
func TestTracesRequestExporter_WithRecordMetrics_RequestSenderError(t *testing.T) {
187+
want := errors.New("export_error")
188+
tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName)
189+
require.NoError(t, err)
190+
t.Cleanup(func() { require.NoError(t, tt.Shutdown(context.Background())) })
191+
192+
te, err := NewTracesRequestExporter(context.Background(), tt.ToExporterCreateSettings(), &fakeRequestConverter{requestError: want})
193+
require.NoError(t, err)
194+
require.NotNil(t, te)
195+
196+
checkRecordedMetricsForTracesExporter(t, tt, te, want)
197+
}
198+
174199
func TestTracesExporter_WithRecordEnqueueFailedMetrics(t *testing.T) {
175200
tt, err := obsreporttest.SetupTelemetry(fakeTracesExporterName)
176201
require.NoError(t, err)
@@ -210,6 +235,20 @@ func TestTracesExporter_WithSpan(t *testing.T) {
210235
checkWrapSpanForTracesExporter(t, sr, set.TracerProvider.Tracer("test"), te, nil, 1)
211236
}
212237

238+
func TestTracesRequestExporter_WithSpan(t *testing.T) {
239+
set := exportertest.NewNopCreateSettings()
240+
sr := new(tracetest.SpanRecorder)
241+
set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr))
242+
otel.SetTracerProvider(set.TracerProvider)
243+
defer otel.SetTracerProvider(trace.NewNoopTracerProvider())
244+
245+
te, err := NewTracesRequestExporter(context.Background(), set, &fakeRequestConverter{})
246+
require.NoError(t, err)
247+
require.NotNil(t, te)
248+
249+
checkWrapSpanForTracesExporter(t, sr, set.TracerProvider.Tracer("test"), te, nil, 1)
250+
}
251+
213252
func TestTracesExporter_WithSpan_ReturnError(t *testing.T) {
214253
set := exportertest.NewNopCreateSettings()
215254
sr := new(tracetest.SpanRecorder)
@@ -225,6 +264,21 @@ func TestTracesExporter_WithSpan_ReturnError(t *testing.T) {
225264
checkWrapSpanForTracesExporter(t, sr, set.TracerProvider.Tracer("test"), te, want, 1)
226265
}
227266

267+
func TestTracesRequestExporter_WithSpan_ExportError(t *testing.T) {
268+
set := exportertest.NewNopCreateSettings()
269+
sr := new(tracetest.SpanRecorder)
270+
set.TracerProvider = sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(sr))
271+
otel.SetTracerProvider(set.TracerProvider)
272+
defer otel.SetTracerProvider(trace.NewNoopTracerProvider())
273+
274+
want := errors.New("export_error")
275+
te, err := NewTracesRequestExporter(context.Background(), set, &fakeRequestConverter{requestError: want})
276+
require.NoError(t, err)
277+
require.NotNil(t, te)
278+
279+
checkWrapSpanForTracesExporter(t, sr, set.TracerProvider.Tracer("test"), te, want, 1)
280+
}
281+
228282
func TestTracesExporter_WithShutdown(t *testing.T) {
229283
shutdownCalled := false
230284
shutdown := func(context.Context) error { shutdownCalled = true; return nil }

0 commit comments

Comments
 (0)