@@ -16,9 +16,19 @@ import Dispatch
16
16
@_exported import Instrumentation
17
17
@_exported import InstrumentationBaggage
18
18
19
- /// An `Instrument` with added functionality for distributed tracing. It uses the span-based tracing model and is
20
- /// based on the OpenTracing/OpenTelemetry spec.
21
- public protocol TracerProtocol : InstrumentProtocol {
19
+ /// Convenience entry point to operations on the tracer configured
20
+ /// on the global ``InstrumentationSystem`` using the `InstrumentationSystem/bootstrap(_:)` method.
21
+ ///
22
+ /// If no tracer was bootstrapped, these operations will default to a no-op tracer (creating no spans).
23
+ ///
24
+ /// For implementing a new tracer, see ``TracerProtocol``.
25
+ enum Tracer : TracerStartSpanOps {
26
+ func startSpan( _ operationName: String , baggage: Baggage , ofKind kind: SpanKind , at time: DispatchWallTime ) -> Span {
27
+ InstrumentationSystem . tracer. startSpan ( operationName, baggage: baggage, ofKind: kind, at: time)
28
+ }
29
+ }
30
+
31
+ public protocol TracerStartSpanOps {
22
32
/// Start a new ``Span`` with the given `Baggage` at a given time.
23
33
///
24
34
/// - Note: Prefer to use `withSpan` to start a span as it automatically takes care of ending the span,
@@ -36,17 +46,9 @@ public protocol TracerProtocol: InstrumentProtocol {
36
46
ofKind kind: SpanKind ,
37
47
at time: DispatchWallTime
38
48
) -> Span
39
-
40
- /// Export all ended spans to the configured backend that have not yet been exported.
41
- ///
42
- /// This function should only be called in cases where it is absolutely necessary,
43
- /// such as when using some FaaS providers that may suspend the process after an invocation, but before the backend exports the completed spans.
44
- ///
45
- /// This function should not block indefinitely, implementations should offer a configurable timeout for flush operations.
46
- func forceFlush( )
47
49
}
48
50
49
- extension TracerProtocol {
51
+ extension TracerStartSpanOps {
50
52
/// Start a new ``Span`` with the given `Baggage` starting at `DispatchWallTime.now()`.
51
53
///
52
54
/// - Parameters:
@@ -65,7 +67,7 @@ extension TracerProtocol {
65
67
// ==== ----------------------------------------------------------------------------------------------------------------
66
68
// MARK: Starting spans: `withSpan`
67
69
68
- extension TracerProtocol {
70
+ extension TracerStartSpanOps {
69
71
/// Execute a specific task within a newly created ``Span``.
70
72
///
71
73
/// DO NOT `end()` the passed in span manually. It will be ended automatically when the `operation` returns.
@@ -92,14 +94,41 @@ extension TracerProtocol {
92
94
throw error // rethrow
93
95
}
94
96
}
97
+
98
+ /// Execute a specific task within a newly created ``Span``.
99
+ ///
100
+ /// DO NOT `end()` the passed in span manually. It will be ended automatically when the `operation` returns.
101
+ ///
102
+ /// - Parameters:
103
+ /// - operationName: The name of the operation being traced. This may be a handler function, database call, ...
104
+ /// - baggage: Baggage potentially containing trace identifiers of a parent ``Span``.
105
+ /// - kind: The ``SpanKind`` of the ``Span`` to be created. Defaults to ``SpanKind/internal``.
106
+ /// - operation: operation to wrap in a span start/end and execute immediately
107
+ /// - Returns: the value returned by `operation`
108
+ /// - Throws: the error the `operation` has thrown (if any)
109
+ public func withSpan< T> (
110
+ _ operationName: String ,
111
+ baggage: Baggage ,
112
+ ofKind kind: SpanKind = . internal,
113
+ _ operation: ( ) throws -> T
114
+ ) rethrows -> T {
115
+ let span = self . startSpan ( operationName, baggage: baggage, ofKind: kind)
116
+ defer { span. end ( ) }
117
+ do {
118
+ return try operation ( )
119
+ } catch {
120
+ span. recordError ( error)
121
+ throw error // rethrow
122
+ }
123
+ }
95
124
}
96
125
97
126
// ==== ----------------------------------------------------------------------------------------------------------------
98
127
// MARK: Starting spans: Task-local Baggage propagation
99
128
100
129
#if swift(>=5.5) && canImport(_Concurrency)
101
130
@available ( macOS 10 . 15 , iOS 13 . 0 , tvOS 13 . 0 , watchOS 6 . 0 , * )
102
- extension TracerProtocol {
131
+ extension TracerStartSpanOps {
103
132
/// Execute the given operation within a newly created ``Span``,
104
133
/// started as a child of the currently stored task local `Baggage.current` or as a root span if `nil`.
105
134
///
@@ -123,6 +152,32 @@ extension TracerProtocol {
123
152
}
124
153
}
125
154
155
+ /// Execute the given operation within a newly created ``Span``,
156
+ /// started as a child of the currently stored task local `Baggage.current` or as a root span if `nil`.
157
+ ///
158
+ /// DO NOT `end()` the passed in span manually. It will be ended automatically when the `operation` returns.
159
+ ///
160
+ /// - Parameters:
161
+ /// - operationName: The name of the operation being traced. This may be a handler function, database call, ...
162
+ /// - kind: The ``SpanKind`` of the ``Span`` to be created. Defaults to ``SpanKind/internal``.
163
+ /// - operation: operation to wrap in a span start/end and execute immediately
164
+ /// - Returns: the value returned by `operation`
165
+ /// - Throws: the error the `operation` has thrown (if any)
166
+ public func withSpan< T> (
167
+ _ operationName: String ,
168
+ ofKind kind: SpanKind = . internal,
169
+ _ operation: ( ) throws -> T
170
+ ) rethrows -> T {
171
+ try self . withSpan ( operationName, baggage: . current ?? . topLevel, ofKind: kind) { span in
172
+ try Baggage . $current. withValue ( span. baggage) {
173
+ try operation ( )
174
+ }
175
+ }
176
+ }
177
+ }
178
+
179
+ @available ( macOS 10 . 15 , iOS 13 . 0 , tvOS 13 . 0 , watchOS 6 . 0 , * )
180
+ extension TracerStartSpanOps {
126
181
/// Execute the given async operation within a newly created ``Span``,
127
182
/// started as a child of the currently stored task local `Baggage.current` or as a root span if `nil`.
128
183
///
@@ -183,3 +238,18 @@ extension TracerProtocol {
183
238
}
184
239
}
185
240
#endif
241
+
242
+ // ==== ----------------------------------------------------------------------------------------------------------------
243
+ // MARK: TracerProtocol
244
+
245
+ /// An `Instrument` with added functionality for distributed tracing. It uses the span-based tracing model and is
246
+ /// based on the OpenTracing/OpenTelemetry spec.
247
+ public protocol TracerProtocol : TracerStartSpanOps , InstrumentProtocol {
248
+ /// Export all ended spans to the configured backend that have not yet been exported.
249
+ ///
250
+ /// This function should only be called in cases where it is absolutely necessary,
251
+ /// such as when using some FaaS providers that may suspend the process after an invocation, but before the backend exports the completed spans.
252
+ ///
253
+ /// This function should not block indefinitely, implementations should offer a configurable timeout for flush operations.
254
+ func forceFlush( )
255
+ }
0 commit comments