diff --git a/.gitignore b/.gitignore index d05eb758..df66b908 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .dart_tool .packages -pubspec.lock \ No newline at end of file +pubspec.lock +lib/src/sdk/trace/exporters/opentelemetry diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..63943155 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/src/sdk/trace/exporters/opentelemetry-proto"] + path = lib/src/sdk/trace/exporters/opentelemetry-proto + url = git@github.com:open-telemetry/opentelemetry-proto.git diff --git a/Makefile b/Makefile index 1a8dac7d..ba84775d 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,20 @@ -deps: - @pub get +init: + git submodule update --init + pub get + pub global activate protoc_plugin + cd lib/src/sdk/trace/exporters && \ + protoc --proto_path opentelemetry-proto \ + --dart_out . \ + opentelemetry-proto/opentelemetry/proto/common/v1/common.proto \ + opentelemetry-proto/opentelemetry/proto/collector/trace/v1/trace_service.proto \ + opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto \ + opentelemetry-proto/opentelemetry/proto/resource/v1/resource.proto -analyze-lib: +analyze: @dart analyze ./lib - -analyze-test: @dart analyze ./test -test: analyze-lib +test: @dart test ./test --chain-stack-traces -.PHONY: deps analyze-lib analyze-test test +.PHONY: init analyze test diff --git a/README.md b/README.md index f9bbdcaf..62a749eb 100644 --- a/README.md +++ b/README.md @@ -63,4 +63,8 @@ main() async { span.end(); } -``` \ No newline at end of file +``` + +## Development + +In order to generate protobuf definitions, you must have [protoc](https://github.com/protocolbuffers/protobuf/releases) installed and available in your path. diff --git a/analysis_options.yaml b/analysis_options.yaml index c55a1abe..b721915f 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1 +1,4 @@ include: package:workiva_analysis_options/v1.recommended.yaml +analyzer: + exclude: + - src/sdk/trace/exporters/opentelemetry diff --git a/lib/sdk.dart b/lib/sdk.dart index abc4044b..2e0c90d5 100644 --- a/lib/sdk.dart +++ b/lib/sdk.dart @@ -1,3 +1,6 @@ +export 'src/sdk/trace/exporters/collector_exporter.dart' + show + CollectorExporter; export 'src/sdk/trace/exporters/console_exporter.dart' show ConsoleExporter; diff --git a/lib/src/api/trace/id_generator.dart b/lib/src/api/trace/id_generator.dart index 2adefd65..85f5b800 100644 --- a/lib/src/api/trace/id_generator.dart +++ b/lib/src/api/trace/id_generator.dart @@ -1,8 +1,8 @@ /// Generator capable of creating OTel compliant IDs. abstract class IdGenerator { /// Generate an ID for a Span. - String generateSpanId(); + List generateSpanId(); /// Generate an ID for a trace. - String generateTraceId(); + List generateTraceId(); } diff --git a/lib/src/api/trace/span.dart b/lib/src/api/trace/span.dart index d526ae03..092200df 100644 --- a/lib/src/api/trace/span.dart +++ b/lib/src/api/trace/span.dart @@ -1,6 +1,7 @@ -import 'package:opentelemetry/src/api/trace/span_status.dart'; - +import 'package:fixnum/fixnum.dart'; import 'span_context.dart'; +import 'span_status.dart'; +import 'tracer.dart'; /// A representation of a single operation within a trace. /// @@ -17,13 +18,13 @@ abstract class Span { SpanContext get spanContext; /// Get the time when the span was closed, or null if still open. - int get endTime; + Int64 get endTime; /// Get the time when the span was started. - int get startTime; + Int64 get startTime; /// The parent span id. - String get parentSpanId; + List get parentSpanId; /// The name of the span. String get name; @@ -40,6 +41,9 @@ abstract class Span { /// Retrieve the status of the [Span]. SpanStatus get status; + /// Tracer responsible for creating the [Span]. + Tracer get tracer; + /// Marks the end of this span's execution. void end(); } diff --git a/lib/src/api/trace/span_context.dart b/lib/src/api/trace/span_context.dart index 91907977..c131f745 100644 --- a/lib/src/api/trace/span_context.dart +++ b/lib/src/api/trace/span_context.dart @@ -3,10 +3,10 @@ import 'trace_state.dart'; /// Representation of the context of the context of an individual span. abstract class SpanContext { /// Get the ID of the span. - String get spanId; + List get spanId; /// Get the ID of the trace the span is a part of. - String get traceId; + List get traceId; /// Get the state of the entire trace. TraceState get traceState; diff --git a/lib/src/api/trace/tracer.dart b/lib/src/api/trace/tracer.dart index 27ace663..cae02fcd 100644 --- a/lib/src/api/trace/tracer.dart +++ b/lib/src/api/trace/tracer.dart @@ -9,4 +9,7 @@ abstract class Tracer { /// Starts a new [Span] without setting it as the current span in this /// tracer's context. Span startSpan(String name, {Context context}); + + /// The Tracer's name. + String get name; } diff --git a/lib/src/sdk/trace/exporters/collector_exporter.dart b/lib/src/sdk/trace/exporters/collector_exporter.dart new file mode 100644 index 00000000..add55bcb --- /dev/null +++ b/lib/src/sdk/trace/exporters/collector_exporter.dart @@ -0,0 +1,82 @@ +import 'package:http/http.dart' as http; + +import '../../../api/trace/span.dart'; +import '../../../api/trace/span_status.dart'; + +import 'opentelemetry/proto/collector/trace/v1/trace_service.pb.dart'; +import 'opentelemetry/proto/common/v1/common.pb.dart'; +import 'opentelemetry/proto/resource/v1/resource.pb.dart'; +import 'opentelemetry/proto/trace/v1/trace.pb.dart' as pb; +import 'span_exporter.dart'; + +class CollectorExporter implements SpanExporter { + Uri uri; + http.Client client; + var _isShutdown = false; + + CollectorExporter(this.uri, {http.Client httpClient}) { + client = httpClient ?? http.Client(); + } + + @override + void export(List spans) { + if (_isShutdown) { + return; + } + + if (spans.isEmpty) { + return; + } + + final pbSpans = []; + for (var i = 0; i < spans.length; i++) { + pbSpans.add(_spanToProtobuf(spans[i])); + } + + final body = ExportTraceServiceRequest(resourceSpans: [ + pb.ResourceSpans( + resource: Resource(attributes: [ + KeyValue( + key: 'service.name', + value: AnyValue(stringValue: spans[0].tracer.name)) + ]), + instrumentationLibrarySpans: [ + pb.InstrumentationLibrarySpans(spans: pbSpans) + ]) + ]); + + client.post(uri, + body: body.writeToBuffer(), + headers: {'Content-Type': 'application/x-protobuf'}); + } + + pb.Span _spanToProtobuf(Span span) { + pb.Status_StatusCode statusCode; + + switch (span.status.code) { + case StatusCode.UNSET: + statusCode = pb.Status_StatusCode.STATUS_CODE_UNSET; + break; + case StatusCode.ERROR: + statusCode = pb.Status_StatusCode.STATUS_CODE_ERROR; + break; + case StatusCode.OK: + statusCode = pb.Status_StatusCode.STATUS_CODE_OK; + break; + } + + return pb.Span( + traceId: span.spanContext.traceId, + spanId: span.spanContext.spanId, + parentSpanId: span.parentSpanId, + name: span.name, + startTimeUnixNano: span.startTime * 1000, + endTimeUnixNano: span.endTime * 1000, + status: pb.Status(code: statusCode, message: span.status.description)); + } + + @override + void shutdown() { + _isShutdown = true; + } +} diff --git a/lib/src/sdk/trace/exporters/console_exporter.dart b/lib/src/sdk/trace/exporters/console_exporter.dart index 5ba63f13..fe98809a 100644 --- a/lib/src/sdk/trace/exporters/console_exporter.dart +++ b/lib/src/sdk/trace/exporters/console_exporter.dart @@ -9,10 +9,16 @@ class ConsoleExporter implements SpanExporter { for (var i=0; i < spans.length; i++) { final span = spans[i]; print({ - 'traceId': span.spanContext.traceId, - 'parentId': span.parentSpanId, + 'traceId': span.spanContext.traceId + .map((x) => x.toRadixString(16).padLeft(2, '0')) + .join(), + 'parentId': span.parentSpanId + .map((x) => x.toRadixString(16).padLeft(2, '0')) + .join(), 'name': span.name, - 'id': span.spanContext.spanId, + 'id': span.spanContext.spanId + .map((x) => x.toRadixString(16).padLeft(2, '0')) + .join(), 'timestamp': span.startTime, 'duration': span.endTime - span.startTime, 'status': span.status.code diff --git a/lib/src/sdk/trace/exporters/opentelemetry-proto b/lib/src/sdk/trace/exporters/opentelemetry-proto new file mode 160000 index 00000000..86724942 --- /dev/null +++ b/lib/src/sdk/trace/exporters/opentelemetry-proto @@ -0,0 +1 @@ +Subproject commit 8672494217bfc858e2a82a4e8c623d4a5530473a diff --git a/lib/src/sdk/trace/id_generator.dart b/lib/src/sdk/trace/id_generator.dart index 2b1f272e..1dfbca29 100644 --- a/lib/src/sdk/trace/id_generator.dart +++ b/lib/src/sdk/trace/id_generator.dart @@ -6,17 +6,17 @@ import '../../../src/api/trace/id_generator.dart' as api; class IdGenerator implements api.IdGenerator { static final Random _random = Random.secure(); - static String _generateId(int byteLength) { - final buffer = StringBuffer(); + static List _generateId(int byteLength) { + final buffer = []; for (var i = 0; i < byteLength; i++) { - buffer.write(_random.nextInt(256).toRadixString(16).padLeft(2, '0')); + buffer.add(_random.nextInt(256)); } - return buffer.toString(); + return buffer.cast(); } @override - String generateSpanId() => _generateId(8); + List generateSpanId() => _generateId(8); @override - String generateTraceId() => _generateId(16); + List generateTraceId() => _generateId(16); } diff --git a/lib/src/sdk/trace/span.dart b/lib/src/sdk/trace/span.dart index 28963723..9ed83fb0 100644 --- a/lib/src/sdk/trace/span.dart +++ b/lib/src/sdk/trace/span.dart @@ -1,28 +1,28 @@ +import 'package:fixnum/fixnum.dart'; + import '../../api/trace/span.dart' as span_api; import '../../api/trace/span_context.dart'; import '../../api/trace/span_status.dart'; +import '../../api/trace/tracer.dart'; import 'span_processors/span_processor.dart'; /// A representation of a single operation within a trace. class Span implements span_api.Span { - int _startTime; - int _endTime; - final String _parentSpanId; + Int64 _startTime; + Int64 _endTime; + final List _parentSpanId; final SpanContext _spanContext; final SpanStatus _status = SpanStatus(); final List _processors; + final Tracer _tracer; @override String name; /// Construct a [Span]. - Span( - this.name, - this._spanContext, - this._parentSpanId, - this._processors - ) { - _startTime = DateTime.now().toUtc().microsecondsSinceEpoch; + Span(this.name, this._spanContext, this._parentSpanId, this._processors, + this._tracer) { + _startTime = Int64(DateTime.now().toUtc().microsecondsSinceEpoch); for (var i = 0; i < _processors.length; i++) { _processors[i].onStart(); } @@ -32,17 +32,17 @@ class Span implements span_api.Span { SpanContext get spanContext => _spanContext; @override - int get endTime => _endTime; + Int64 get endTime => _endTime; @override - int get startTime => _startTime; + Int64 get startTime => _startTime; @override - String get parentSpanId => _parentSpanId; + List get parentSpanId => _parentSpanId; @override void end() { - _endTime ??= DateTime.now().toUtc().microsecondsSinceEpoch; + _endTime ??= Int64(DateTime.now().toUtc().microsecondsSinceEpoch); for (var i = 0; i < _processors.length; i++) { _processors[i].onEnd(this); } @@ -66,4 +66,7 @@ class Span implements span_api.Span { @override SpanStatus get status => _status; + + @override + Tracer get tracer => _tracer; } diff --git a/lib/src/sdk/trace/span_context.dart b/lib/src/sdk/trace/span_context.dart index 9f35e5c2..c24ea27a 100644 --- a/lib/src/sdk/trace/span_context.dart +++ b/lib/src/sdk/trace/span_context.dart @@ -3,15 +3,15 @@ import '../../../src/api/trace/trace_state.dart'; /// Representation of the context of the context of an individual span. class SpanContext implements span_context_api.SpanContext { - final String _spanId; - final String _traceId; + final List _spanId; + final List _traceId; final TraceState _traceState; @override - String get spanId => _spanId; + List get spanId => _spanId; @override - String get traceId => _traceId; + List get traceId => _traceId; @override TraceState get traceState => _traceState; diff --git a/lib/src/sdk/trace/span_processors/batch_processor.dart b/lib/src/sdk/trace/span_processors/batch_processor.dart index 31ad998c..4e91ca76 100644 --- a/lib/src/sdk/trace/span_processors/batch_processor.dart +++ b/lib/src/sdk/trace/span_processors/batch_processor.dart @@ -15,13 +15,13 @@ class BatchSpanProcessor implements SpanProcessor { final List _spanBuffer = []; Timer _timer; - int _maxExportBatchSize = 512; + int _maxExportBatchSize; final int _maxQueueSize = 2048; - int _scheduledDelay = 5000; + int _scheduledDelay; BatchSpanProcessor(this._exporter, {int maxExportBatchSize, int scheduledDelay}) { - _maxExportBatchSize = maxExportBatchSize; - _scheduledDelay = scheduledDelay; + _maxExportBatchSize = maxExportBatchSize ?? 512; + _scheduledDelay = scheduledDelay ?? 5000; } @override diff --git a/lib/src/sdk/trace/tracer.dart b/lib/src/sdk/trace/tracer.dart index 14bd18da..c9e8fb54 100644 --- a/lib/src/sdk/trace/tracer.dart +++ b/lib/src/sdk/trace/tracer.dart @@ -9,17 +9,21 @@ import 'span_processors/span_processor.dart'; /// An interface for creating [Span]s and propagating context in-process. class Tracer implements tracer_api.Tracer { + final String _name; final IdGenerator _idGenerator = IdGenerator(); final List _processors; - Tracer(this._processors); + Tracer(this._name, this._processors); + + @override + String get name => _name; @override Span startSpan(String name, {Context context}) { context ??= Context.current; - String parentSpanId; - String traceId; + List parentSpanId; + List traceId; TraceState traceState; final spanId = _idGenerator.generateSpanId(); @@ -36,6 +40,6 @@ class Tracer implements tracer_api.Tracer { final spanContext = SpanContext(traceId, spanId, traceState); - return Span(name, spanContext, parentSpanId, _processors); + return Span(name, spanContext, parentSpanId, _processors, this); } } diff --git a/lib/src/sdk/trace/tracer_provider.dart b/lib/src/sdk/trace/tracer_provider.dart index 86d771f7..1edab1ac 100644 --- a/lib/src/sdk/trace/tracer_provider.dart +++ b/lib/src/sdk/trace/tracer_provider.dart @@ -22,7 +22,7 @@ class TracerProvider implements api.TracerProvider { @override Tracer getTracer(String name, {String version = ''}) { final key = '$name@$version'; - return _tracers.putIfAbsent(key, () => Tracer(_processors)); + return _tracers.putIfAbsent(key, () => Tracer(name, _processors)); } @override diff --git a/pubspec.yaml b/pubspec.yaml index fe4a5341..8b14fc2c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,9 @@ environment: sdk: '>=2.7.0 <3.0.0' dependencies: + http: ^0.12.2 logging: ^0.11.4 + protobuf: ^2.0.0 dev_dependencies: mockito: ^5.0.13 diff --git a/test/integration/sdk/span_test.dart b/test/integration/sdk/span_test.dart index 3b83f785..0f735d07 100644 --- a/test/integration/sdk/span_test.dart +++ b/test/integration/sdk/span_test.dart @@ -3,6 +3,7 @@ import 'package:mockito/mockito.dart'; import 'package:opentelemetry/src/sdk/trace/span.dart'; import 'package:opentelemetry/src/sdk/trace/span_context.dart'; import 'package:opentelemetry/src/sdk/trace/trace_state.dart'; +import 'package:opentelemetry/src/sdk/trace/tracer.dart'; import 'package:test/test.dart'; import '../../unit/mocks.dart'; @@ -11,14 +12,12 @@ void main() { test('span set and end time', () { final mockProcessor1 = MockSpanProcessor(); final mockProcessor2 = MockSpanProcessor(); - final span = Span('foo', SpanContext('trace123', '789', TraceState()), 'span456', [ - mockProcessor1, - mockProcessor2 - ]); + final span = Span('foo', SpanContext([1, 2, 3], [7, 8, 9], TraceState()), + [4, 5, 6], [mockProcessor1, mockProcessor2], Tracer('bar', [])); - expect(span.startTime, isA()); + expect(span.startTime, isNotNull); expect(span.endTime, isNull); - expect(span.parentSpanId, 'span456'); + expect(span.parentSpanId, [4, 5, 6]); expect(span.name, 'foo'); verify(mockProcessor1.onStart()).called(1); @@ -27,8 +26,8 @@ void main() { verifyNever(mockProcessor2.onEnd(span)); span.end(); - expect(span.startTime, isA()); - expect(span.endTime, isA()); + expect(span.startTime, isNotNull); + expect(span.endTime, isNotNull); expect(span.endTime, greaterThan(span.startTime)); verify(mockProcessor1.onEnd(span)).called(1); @@ -36,8 +35,8 @@ void main() { }); test('span status', () { - final span = - Span('foo', SpanContext('trace123', '789', TraceState()), 'span456', []); + final span = Span('foo', SpanContext([1, 2, 3], [7, 8, 9], TraceState()), + [4, 5, 6], [], Tracer('bar', [])); // Verify span status' defaults. expect(span.status.code, equals(StatusCode.UNSET)); diff --git a/test/integration/sdk/tracer_test.dart b/test/integration/sdk/tracer_test.dart index 9973d464..e963f33e 100644 --- a/test/integration/sdk/tracer_test.dart +++ b/test/integration/sdk/tracer_test.dart @@ -5,30 +5,30 @@ import 'package:test/test.dart'; void main() { test('startSpan new trace', () { - final tracer = Tracer([]); + final tracer = Tracer('bar', []); final span = tracer.startSpan('foo'); - expect(span.startTime, isA()); + expect(span.startTime, isNotNull); expect(span.endTime, isNull); - expect(span.spanContext.traceId, isA()); - expect(span.spanContext.spanId, isA()); + expect(span.spanContext.traceId, isNotNull); + expect(span.spanContext.spanId, isNotNull); }); test('startSpan child span', () { - final tracer = Tracer([]); + final tracer = Tracer('baz', []); final parentSpan = tracer.startSpan('foo'); final context = setSpan(Context.current, parentSpan); final childSpan = tracer.startSpan('bar', context: context); - expect(childSpan.startTime, isA()); + expect(childSpan.startTime, isNotNull); expect(childSpan.endTime, isNull); expect(childSpan.spanContext.traceId, equals(parentSpan.spanContext.traceId)); expect(childSpan.spanContext.traceState, equals(parentSpan.spanContext.traceState)); expect(childSpan.spanContext.spanId, allOf([ - isA(), + isNotNull, isNot(equals(parentSpan.spanContext.spanId)) ])); }); diff --git a/test/unit/api/context_utils_test.dart b/test/unit/api/context_utils_test.dart index 555c3c49..92428a63 100644 --- a/test/unit/api/context_utils_test.dart +++ b/test/unit/api/context_utils_test.dart @@ -4,13 +4,15 @@ import 'package:opentelemetry/src/api/trace/context_utils.dart'; import 'package:opentelemetry/src/sdk/trace/span.dart'; import 'package:opentelemetry/src/sdk/trace/span_context.dart'; import 'package:opentelemetry/src/sdk/trace/trace_state.dart'; +import 'package:opentelemetry/src/sdk/trace/tracer.dart'; import 'package:test/test.dart'; import '../mocks.dart'; void main() { - final testSpanContext = SpanContext('123', '789', TraceState()); - final testSpan = Span('foo', testSpanContext, '456', []); + final testSpanContext = SpanContext([1, 2, 3], [7, 8, 9], TraceState()); + final testSpan = + Span('foo', testSpanContext, [4, 5, 6], [], Tracer('bar', [])); group('getSpan', () { test('returns Span when exists', () { diff --git a/test/unit/mocks.dart b/test/unit/mocks.dart index 11f4b2ae..1b94a2a5 100644 --- a/test/unit/mocks.dart +++ b/test/unit/mocks.dart @@ -1,3 +1,4 @@ +import 'package:http/http.dart' as http; import 'package:mockito/mockito.dart'; import 'package:opentelemetry/src/api/context/context.dart'; import 'package:opentelemetry/src/api/trace/span.dart'; @@ -5,6 +6,7 @@ import 'package:opentelemetry/src/sdk/trace/exporters/span_exporter.dart'; import 'package:opentelemetry/src/sdk/trace/span_processors/span_processor.dart'; class MockContext extends Mock implements Context {} +class MockHTTPClient extends Mock implements http.Client {} class MockSpan extends Mock implements Span {} class MockSpanExporter extends Mock implements SpanExporter {} class MockSpanProcessor extends Mock implements SpanProcessor {} diff --git a/test/unit/sdk/exporters/collector_exporter_test.dart b/test/unit/sdk/exporters/collector_exporter_test.dart new file mode 100644 index 00000000..f70d9614 --- /dev/null +++ b/test/unit/sdk/exporters/collector_exporter_test.dart @@ -0,0 +1,94 @@ +import 'package:mockito/mockito.dart'; +import 'package:opentelemetry/src/sdk/trace/exporters/collector_exporter.dart'; +import 'package:opentelemetry/src/sdk/trace/exporters/opentelemetry/proto/collector/trace/v1/trace_service.pb.dart'; +import 'package:opentelemetry/src/sdk/trace/exporters/opentelemetry/proto/common/v1/common.pb.dart'; +import 'package:opentelemetry/src/sdk/trace/exporters/opentelemetry/proto/resource/v1/resource.pb.dart'; +import 'package:opentelemetry/src/sdk/trace/exporters/opentelemetry/proto/trace/v1/trace.pb.dart' + as pb; +import 'package:opentelemetry/src/sdk/trace/span.dart'; +import 'package:opentelemetry/src/sdk/trace/span_context.dart'; +import 'package:opentelemetry/src/sdk/trace/trace_state.dart'; +import 'package:opentelemetry/src/sdk/trace/tracer.dart'; +import 'package:test/test.dart'; + +import '../../mocks.dart'; + +void main() { + MockHTTPClient mockClient; + final uri = + Uri.parse('https://h.wdesk.org/s/opentelemetry-collector/v1/traces'); + + setUp(() { + mockClient = MockHTTPClient(); + }); + + tearDown(() { + reset(mockClient); + }); + + test('sends spans', () { + final tracer = Tracer('bar', []); + final span1 = Span('foo', SpanContext([1, 2, 3], [7, 8, 9], TraceState()), + [4, 5, 6], [], tracer) + ..end(); + final span2 = Span( + 'baz', + SpanContext([1, 2, 3], [10, 11, 12], TraceState()), + [4, 5, 6], + [], + tracer) + ..end(); + + CollectorExporter(uri, httpClient: mockClient).export([span1, span2]); + + final expectedBody = ExportTraceServiceRequest(resourceSpans: [ + pb.ResourceSpans( + resource: Resource(attributes: [ + KeyValue(key: 'service.name', value: AnyValue(stringValue: 'bar')) + ]), + instrumentationLibrarySpans: [ + pb.InstrumentationLibrarySpans(spans: [ + pb.Span( + traceId: [1, 2, 3], + spanId: [7, 8, 9], + parentSpanId: [4, 5, 6], + name: 'foo', + startTimeUnixNano: span1.startTime * 1000, + endTimeUnixNano: span1.endTime * 1000, + status: pb.Status( + code: pb.Status_StatusCode.STATUS_CODE_UNSET, + message: null)), + pb.Span( + traceId: [1, 2, 3], + spanId: [10, 11, 12], + parentSpanId: [4, 5, 6], + name: 'baz', + startTimeUnixNano: span2.startTime * 1000, + endTimeUnixNano: span2.endTime * 1000, + status: pb.Status( + code: pb.Status_StatusCode.STATUS_CODE_UNSET, + message: null)) + ]) + ]) + ]); + + verify(mockClient.post(uri, + body: expectedBody.writeToBuffer(), + headers: {'Content-Type': 'application/x-protobuf'})).called(1); + }); + + test('does not send spans when shutdown', () { + final tracer = Tracer('bar', []); + final span = Span('foo', SpanContext([1, 2, 3], [7, 8, 9], TraceState()), + [4, 5, 6], [], tracer) + ..end(); + + CollectorExporter(uri, httpClient: mockClient) + ..shutdown() + ..export([span]); + + verifyNever(mockClient.post(uri, + body: anything, + headers: {'Content-Type': 'application/x-protobuf'})); + }); +} diff --git a/test/unit/sdk/exporters/console_exporter_test.dart b/test/unit/sdk/exporters/console_exporter_test.dart index 2ce46614..988f3b09 100644 --- a/test/unit/sdk/exporters/console_exporter_test.dart +++ b/test/unit/sdk/exporters/console_exporter_test.dart @@ -4,6 +4,7 @@ import 'package:opentelemetry/src/sdk/trace/exporters/console_exporter.dart'; import 'package:opentelemetry/src/sdk/trace/span.dart'; import 'package:opentelemetry/src/sdk/trace/span_context.dart'; import 'package:opentelemetry/src/sdk/trace/trace_state.dart'; +import 'package:opentelemetry/src/sdk/trace/tracer.dart'; import 'package:test/test.dart'; List printLogs = []; @@ -24,18 +25,21 @@ void main() { }); test('prints', overridePrint(() { - final span = Span('foo', SpanContext('trace123', 'span789', TraceState()), 'span456', []) - ..end(); + final span = Span('foo', SpanContext([1, 2, 3], [7, 8, 9], TraceState()), + [4, 5, 6], [], Tracer('bar', [])) + ..end(); ConsoleExporter().export([span]); - final expected = RegExp(r'^{traceId: trace123, parentId: span456, name: foo, id: span789, timestamp: \d+, duration: \d+, status: StatusCode.UNSET}$'); + final expected = RegExp( + r'{traceId: 010203, parentId: 040506, name: foo, id: 070809, timestamp: \d+, duration: \d+, status: StatusCode.UNSET}'); expect(printLogs.length, 1); expect(expected.hasMatch(printLogs[0]), true); })); test('does not print after shutdown', overridePrint(() { - final span = Span('foo', SpanContext('trace123', 'span789', TraceState()), 'span456', []); + final span = Span('foo', SpanContext([1, 2, 3], [7, 8, 9], TraceState()), + [4, 5, 6], [], Tracer('bar', [])); ConsoleExporter() ..shutdown() diff --git a/test/unit/sdk/id_generator_test.dart b/test/unit/sdk/id_generator_test.dart index 5349f8ed..0c658341 100644 --- a/test/unit/sdk/id_generator_test.dart +++ b/test/unit/sdk/id_generator_test.dart @@ -5,10 +5,10 @@ void main() { final generator = IdGenerator(); test('generateSpanId is the correct length', () { - expect(generator.generateSpanId().length, equals(16)); + expect(generator.generateSpanId().length, equals(8)); }); test('generateTraceId is the correct length', () { - expect(generator.generateTraceId().length, equals(32)); + expect(generator.generateTraceId().length, equals(16)); }); } diff --git a/test/unit/sdk/span_context_test.dart b/test/unit/sdk/span_context_test.dart index 1ba36583..1966f3ab 100644 --- a/test/unit/sdk/span_context_test.dart +++ b/test/unit/sdk/span_context_test.dart @@ -5,10 +5,10 @@ import 'package:test/test.dart'; void main() { test('spanContext getters', () { final traceState = TraceState(); - final spanContext = SpanContext('trace123', 'span456', traceState); + final spanContext = SpanContext([1, 2, 3], [4, 5, 6], traceState); - expect(spanContext.traceId, equals('trace123')); - expect(spanContext.spanId, equals('span456')); + expect(spanContext.traceId, [1, 2, 3]); + expect(spanContext.spanId, [4, 5, 6]); expect(spanContext.traceState, same(traceState)); }); } diff --git a/test/unit/sdk/span_test.dart b/test/unit/sdk/span_test.dart index b2dd62c8..17d46930 100644 --- a/test/unit/sdk/span_test.dart +++ b/test/unit/sdk/span_test.dart @@ -1,11 +1,13 @@ import 'package:opentelemetry/src/sdk/trace/span.dart'; import 'package:opentelemetry/src/sdk/trace/span_context.dart'; import 'package:opentelemetry/src/sdk/trace/trace_state.dart'; +import 'package:opentelemetry/src/sdk/trace/tracer.dart'; import 'package:test/test.dart'; void main() { test('span change name', () { - final span = Span('foo', SpanContext('trace123', '789', TraceState()), 'span456', []); + final span = Span('foo', SpanContext([1, 2, 3], [7, 8, 9], TraceState()), + [4, 5, 6], [], Tracer('bar', [])); expect(span.name, 'foo'); span.name = 'bar';