Line data Source code
1 : // Copyright The OpenTelemetry Authors
2 : // SPDX-License-Identifier: Apache-2.0
3 :
4 : import 'package:dartastic_opentelemetry_api/dartastic_opentelemetry_api.dart';
5 :
6 : import '../span.dart';
7 : import '../span_processor.dart';
8 :
9 : /// Automatically copies baggage entries to span attributes on span start.
10 : ///
11 : /// https://opentelemetry.io/docs/specs/otel/baggage/api/#baggage-propagation
12 : /// "Because a common use case for Baggage is to add data to Span Attributes
13 : /// across a whole trace, several languages have Baggage Span Processors that
14 : /// add data from baggage as attributes on span creation."
15 : ///
16 : /// This BaggageSpanProcessor extracts all baggage entries from the parent or
17 : /// current context and adds them as span attributes when spans are created.
18 : ///
19 : /// This enables baggage values to be:
20 : /// - Visible in tracing backends (HyperDX, Jaeger, etc.)
21 : /// - Searchable and filterable for trace queries
22 : /// - Automatically propagated to all spans without manual attribute setting
23 : ///
24 : /// Example usage:
25 : ///
26 : /// ```dart
27 : /// final tracerProvider = OTel.tracerProvider();
28 : /// tracerProvider.addSpanProcessor(BaggageSpanProcessor());
29 : /// ```
30 : class BaggageSpanProcessor implements SpanProcessor {
31 : /// Creates a [BaggageSpanProcessor] instance.
32 1 : const BaggageSpanProcessor();
33 :
34 1 : @override
35 : Future<void> onStart(Span span, Context? parentContext) async {
36 : // Extract baggage from the current context
37 2 : final baggage = Context.current.baggage;
38 : if (baggage == null) {
39 : return;
40 : }
41 :
42 1 : final entries = baggage.getAllEntries();
43 1 : if (entries.isEmpty) {
44 : return;
45 : }
46 :
47 : // Convert baggage entries to a map for span attributes
48 : // Note: Baggage metadata is intentionally not included as it's not part of the value
49 1 : final attributeMap = <String, String>{};
50 2 : for (final entry in entries.entries) {
51 4 : attributeMap[entry.key] = entry.value.value;
52 : }
53 :
54 : // Add all baggage attributes to the span at once
55 1 : if (attributeMap.isNotEmpty) {
56 2 : span.addAttributes(Attributes.of(attributeMap));
57 : }
58 : }
59 :
60 1 : @override
61 : Future<void> onEnd(Span span) async {
62 : // No-op: baggage attributes are already added during onStart
63 : }
64 :
65 1 : @override
66 : Future<void> onNameUpdate(Span span, String newName) async {
67 : // No-op: baggage values don't change when span name is updated
68 : }
69 :
70 1 : @override
71 : Future<void> shutdown() async {
72 : // No-op: this processor has no resources to clean up
73 : }
74 :
75 1 : @override
76 : Future<void> forceFlush() async {
77 : // No-op: this processor doesn't batch or queue spans
78 : }
79 : }
|