Skip to content

Commit

Permalink
Merge pull request #148 from tapih/handle-error-on-export-failure
Browse files Browse the repository at this point in the history
Show log and keep running on export failure
  • Loading branch information
kennytrytek-wf authored Feb 26, 2024
2 parents 6b030e0 + 26320cb commit a98c592
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 5 deletions.
26 changes: 21 additions & 5 deletions lib/src/sdk/trace/exporters/collector_exporter.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// Copyright 2021-2022 Workiva.
// Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information

import 'dart:async';

import 'package:fixnum/fixnum.dart';
import 'package:http/http.dart' as http;
import 'package:logging/logging.dart';

import '../../../../api.dart' as api;
import '../../../../sdk.dart' as sdk;
Expand All @@ -14,6 +17,8 @@ import '../../proto/opentelemetry/proto/resource/v1/resource.pb.dart'
import '../../proto/opentelemetry/proto/trace/v1/trace.pb.dart' as pb_trace;

class CollectorExporter implements sdk.SpanExporter {
final Logger _log = Logger('opentelemetry.CollectorExporter');

final Uri uri;
final http.Client client;
final Map<String, String> headers;
Expand All @@ -33,12 +38,23 @@ class CollectorExporter implements sdk.SpanExporter {
return;
}

final body = pb_trace_service.ExportTraceServiceRequest(
resourceSpans: _spansToProtobuf(spans));
final headers = {'Content-Type': 'application/x-protobuf'}
..addAll(this.headers);
unawaited(_send(uri, spans));
}

client.post(uri, body: body.writeToBuffer(), headers: headers);
Future<void> _send(
Uri uri,
List<sdk.ReadOnlySpan> spans,
) async {
try {
final body = pb_trace_service.ExportTraceServiceRequest(
resourceSpans: _spansToProtobuf(spans));
final headers = {'Content-Type': 'application/x-protobuf'}
..addAll(this.headers);

await client.post(uri, body: body.writeToBuffer(), headers: headers);
} catch (e) {
_log.warning('Failed to export ${spans.length} spans.', e);
}
}

/// Group and construct the protobuf equivalent of the given list of [api.Span]s.
Expand Down
36 changes: 36 additions & 0 deletions test/unit/sdk/exporters/collector_exporter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'dart:typed_data';

import 'package:mockito/mockito.dart';
import 'package:logging/logging.dart';
import 'package:opentelemetry/api.dart' as api;
import 'package:opentelemetry/sdk.dart' as sdk;
import 'package:opentelemetry/src/sdk/common/limits.dart';
Expand Down Expand Up @@ -166,6 +167,41 @@ void main() {
expect(traceRequest, equals(expectedBody));
});

test('shows a warning log when export failed', () {
final span = Span(
'foo',
api.SpanContext(api.TraceId([1, 2, 3]), api.SpanId([7, 8, 9]),
api.TraceFlags.none, api.TraceState.empty()),
api.SpanId([4, 5, 6]),
[],
sdk.DateTimeTimeProvider(),
sdk.Resource([]),
sdk.InstrumentationScope(
'library_name', 'library_version', 'url://schema', []),
api.SpanKind.internal,
[],
sdk.SpanLimits(),
sdk.DateTimeTimeProvider().now)
..end();

when(mockClient.post(uri,
body: anyNamed('body'),
headers: {'Content-Type': 'application/x-protobuf'}))
.thenThrow(Exception('Failed to connect'));

final records = <LogRecord>[];
final sub = Logger.root.onRecord.listen(records.add);
sdk.CollectorExporter(uri, httpClient: mockClient).export([span]);
sub.cancel();

verify(mockClient.post(uri,
body: anything, headers: {'Content-Type': 'application/x-protobuf'}))
.called(1);

expect(records, hasLength(1));
expect(records[0].level, equals(Level.WARNING));
});

test('does not send spans when shutdown', () {
final span = Span(
'foo',
Expand Down

0 comments on commit a98c592

Please sign in to comment.