Skip to content

Commit 1a39e25

Browse files
deprecate context manager and implement attach/detach APIs
1 parent 1c1b25d commit 1a39e25

30 files changed

+710
-565
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## [0.18.6](https://github.com/Workiva/opentelemetry-dart/tree/0.18.6) (2024-08-15)
4+
5+
[Full Changelog](https://github.com/Workiva/opentelemetry-dart/compare/0.18.5...0.18.6)
6+
7+
**Merged pull requests:**
8+
9+
- Make registerGlobalContextManager public API [\#183](https://github.com/Workiva/opentelemetry-dart/pull/183) ([jonathancampbell-wk](https://github.com/jonathancampbell-wk))
10+
- O11Y-4831: Use test URL in test [\#181](https://github.com/Workiva/opentelemetry-dart/pull/181) ([kennytrytek-wf](https://github.com/kennytrytek-wf))
11+
312
## [0.18.5](https://github.com/Workiva/opentelemetry-dart/tree/0.18.5) (2024-08-01)
413

514
[Full Changelog](https://github.com/Workiva/opentelemetry-dart/compare/0.18.4...0.18.5)

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ void main(List<String> args) {
6868

6969
In order to parent spans, context must be propagated. Propagation can be achieved by manually passing an instance of `Context` or by using Dart [`Zones`](https://dart.dev/libraries/async/zones).
7070

71-
See the [noop context manager example](./example/noop_context_manager.dart) and [zone context manager example](./example/zone_context_manager.dart) for more information.
71+
See the [attach detach context example](./example/attach_detach_context)for more information.
7272

7373
### Inter-process
7474

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Attach Detach Context Example
2+
3+
This example demonstrates context propagation using the attach/detach context APIs.
4+
5+
The example produces two traces represented by the following diagram:
6+
7+
```mermaid
8+
flowchart LR
9+
r1[Root 1 Span] --> c[Child Span]
10+
c --> g1[Grandchild 1 Span]
11+
c --> g2[Grandchild 2 Span]
12+
r2[Root 2 Span]
13+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2021-2022 Workiva.
2+
// Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information
3+
4+
import 'package:opentelemetry/api.dart';
5+
import 'package:opentelemetry/sdk.dart'
6+
show ConsoleExporter, SimpleSpanProcessor, TracerProviderBase;
7+
8+
void main() {
9+
final tp = TracerProviderBase(
10+
processors: [SimpleSpanProcessor(ConsoleExporter())]),
11+
tracer = tp.getTracer('instrumentation-name');
12+
13+
// Attach the root span to the current context (the root context) making the
14+
// span the current span until it is detached.
15+
final rootToken = Context.attach(
16+
contextWithSpan(Context.current, tracer.startSpan('root-1')..end()));
17+
18+
// Starting a child span will automatically parent the span to the span held
19+
// by the attached context.
20+
final child1 = tracer.startSpan('child')..end();
21+
final context = contextWithSpan(Context.current, child1);
22+
23+
// Starting a span doesn't automatically attach the span. So to make the
24+
// parent span actually parent a span, its context needs to be attached.
25+
final childToken = Context.attach(context);
26+
tracer.startSpan('grandchild-1').end();
27+
if (!Context.detach(childToken)) {
28+
throw Exception('Failed to detach context');
29+
}
30+
31+
// Alternatively, manually specifying the desired parent context avoids the
32+
// need to attach and detach the context.
33+
tracer.startSpan('grandchild-2', context: context).end();
34+
35+
if (!Context.detach(rootToken)) {
36+
throw Exception('Failed to detach context');
37+
}
38+
39+
// Since the previous root span context was detached, spans will no longer be
40+
// automatically parented.
41+
tracer.startSpan('root-2').end();
42+
}

example/main.dart

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright 2021-2022 Workiva.
22
// Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information
33

4+
import 'dart:async';
5+
46
import 'package:opentelemetry/api.dart';
57
import 'package:opentelemetry/sdk.dart';
68

@@ -28,20 +30,21 @@ final tracer = provider.getTracer('instrumentation-name');
2830

2931
/// Demonstrates creating a trace with a parent and child span.
3032
void main() async {
31-
// The current active span is available via the global context manager.
32-
var context = globalContextManager.active;
33+
// The current active context is available via a static getter.
34+
var context = Context.current;
3335

3436
// A trace starts with a root span which has no parent.
3537
final parentSpan = tracer.startSpan('parent-span');
3638

3739
// A new context can be created in order to propagate context manually.
3840
context = contextWithSpan(context, parentSpan);
3941

40-
// The traceContext and traceContextSync functions will automatically
42+
// The [traceContext] and [traceContextSync] functions will automatically
4143
// propagate context, capture errors, and end the span.
42-
await traceContext(
43-
'child-span', (_context) => Future.delayed(Duration(milliseconds: 100)),
44-
context: context);
44+
await traceContext('child-span', (_) {
45+
tracer.startSpan('grandchild-span').end();
46+
return Future.delayed(Duration(milliseconds: 100));
47+
}, context: context, tracer: tracer);
4548

4649
// Spans must be ended or they will not be exported.
4750
parentSpan.end();

example/noop_context_manager.dart

-28
This file was deleted.

example/stream_context/README.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Stream Context Propagation Example
2+
3+
This example demonstrates context propagation over a `Stream` or `StreamController`.
4+
5+
The example produces three traces represented by the following diagram:
6+
7+
```mermaid
8+
flowchart LR
9+
subgraph a[Zone A]
10+
direction LR
11+
ap[Zone A Parent Span] --> ac[Zone A Child Span]
12+
r[New Root Span]
13+
ec[Event Child Span]
14+
end
15+
ep[Event Parent Span] --> ec
16+
```
17+
18+
Note: When registering a stream listener, A stream listener callback is executed in the Zone where the callback was registered. This can lead to long running traces if the stream gets an event long after it was registered. To avoid this issue, the `trace` and `traceSync` functions will attach and detach the span they create before and after invoking the callback given to them.
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2021-2022 Workiva.
2+
// Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information
3+
4+
import 'dart:async';
5+
6+
import 'package:opentelemetry/api.dart';
7+
import 'package:opentelemetry/sdk.dart'
8+
show ConsoleExporter, SimpleSpanProcessor, TracerProviderBase;
9+
10+
mixin EventContext {
11+
final Context context = Context.current;
12+
}
13+
14+
class MyEvent with EventContext {
15+
MyEvent();
16+
}
17+
18+
void main() async {
19+
final tp = TracerProviderBase(
20+
processors: [SimpleSpanProcessor(ConsoleExporter())]),
21+
tracer = tp.getTracer('instrumentation-name');
22+
23+
final controller = StreamController<MyEvent>();
24+
25+
traceSync('zone-a-parent', () {
26+
tracer.startSpan('zone-a-child').end();
27+
28+
controller.stream.listen((e) {
29+
tracer.startSpan('new-root').end();
30+
tracer.startSpan('event-child', context: e.context).end();
31+
});
32+
}, tracer: tracer);
33+
34+
traceSync('event-parent', () => controller.add(MyEvent()), tracer: tracer);
35+
36+
await controller.close();
37+
}

example/w3c_context_propagation.dart

+2-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import 'package:opentelemetry/api.dart';
55
import 'package:opentelemetry/sdk.dart'
66
show ConsoleExporter, SimpleSpanProcessor, TracerProviderBase;
7-
import 'package:opentelemetry/src/experimental_api.dart' show NoopContextManager;
87

98
class MapSetter implements TextMapSetter<Map> {
109
@override
@@ -30,15 +29,12 @@ void main(List<String> args) async {
3029
TracerProviderBase(processors: [SimpleSpanProcessor(ConsoleExporter())]);
3130
registerGlobalTracerProvider(tp);
3231

33-
final cm = NoopContextManager();
34-
registerGlobalContextManager(cm);
35-
3632
final tmp = W3CTraceContextPropagator();
3733
registerGlobalTextMapPropagator(tmp);
3834

3935
final span = tp.getTracer('instrumentation-name').startSpan('test-span-0');
4036
final carrier = <String, String>{};
41-
tmp.inject(contextWithSpan(cm.active, span), carrier, MapSetter());
37+
tmp.inject(contextWithSpan(Context.current, span), carrier, MapSetter());
4238
await test(carrier);
4339
span.end();
4440
}
@@ -48,6 +44,6 @@ Future test(Map<String, String> carrier) async {
4844
.getTracer('instrumentation-name')
4945
.startSpan('test-span-1',
5046
context: globalTextMapPropagator.extract(
51-
globalContextManager.active, carrier, MapGetter()))
47+
Context.current, carrier, MapGetter()))
5248
.end();
5349
}

example/zone_context_manager.dart

-32
This file was deleted.

lib/api.dart

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ export 'src/api/context/context.dart'
88
show
99
Context,
1010
ContextKey,
11+
contextFromZone,
1112
contextWithSpan,
1213
contextWithSpanContext,
1314
spanContextFromContext,
14-
spanFromContext;
15+
spanFromContext,
16+
zone,
17+
zoneWithContext;
1518
export 'src/api/context/context_manager.dart'
1619
show globalContextManager, registerGlobalContextManager;
1720
export 'src/api/exporters/span_exporter.dart' show SpanExporter;

0 commit comments

Comments
 (0)