From 63a9c24c0cf05cb99d5eec6621b82f7ead9fc066 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 31 Mar 2023 15:18:42 +0900 Subject: [PATCH] Introduce top level withSpan; reclaim Tracer and Instrument for protocols (#113) --- README.md | 20 +- Sources/Instrumentation/Instrument.swift | 4 +- .../InstrumentationSystem.swift | 24 +- .../Instrumentation/MultiplexInstrument.swift | 12 +- Sources/Instrumentation/NoOpInstrument.swift | 4 +- Sources/Tracing/Docs.docc/InDepthGuide.md | 18 +- Sources/Tracing/Docs.docc/index.md | 2 +- .../InstrumentationSystem+Tracing.swift | 12 +- Sources/Tracing/NoOpTracer.swift | 4 +- Sources/Tracing/Tracer.swift | 681 +++++++++++------- Sources/Tracing/TracerProtocol+Legacy.swift | 26 +- Sources/Tracing/TracerProtocol.swift | 6 +- .../InstrumentTests.swift | 4 +- .../InstrumentationSystemTests.swift | 6 +- Tests/TracingTests/ActorTracingTests.swift | 2 +- .../DynamicTracepointTracerTests.swift | 4 +- Tests/TracingTests/TestTracer.swift | 4 +- Tests/TracingTests/TracedLockTests.swift | 4 +- Tests/TracingTests/TracerTests+swift57.swift | 2 +- Tests/TracingTests/TracerTests.swift | 4 +- .../TracingInstrumentationSystemTests.swift | 6 +- 21 files changed, 488 insertions(+), 361 deletions(-) diff --git a/README.md b/README.md index 7588e9f..00330cc 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ This project uses the context progagation type defined independently in: + [Extracting & injecting Baggage](#extracting--injecting-baggage) + [Tracing your library](#tracing-your-library) * In-Depth Guide for: **Instrument developers** - + [Creating an `InstrumentProtocol`](#instrument-developers--creating-an-instrument) + + [Creating an `Instrument`](#instrument-developers--creating-an-instrument) + [Creating a `Tracer`](#creating-a--tracer-) * [Contributing](#contributing) @@ -119,7 +119,7 @@ To your main target, add a dependency on `Tracing` library and the instrument yo ), ``` -Then (in an application, libraries should _never_ invoke `bootstrap`), you will want to bootstrap the specific tracer you want to use in your application. A `Tracer` is a type of `InstrumentProtocol` and can be offered used to globally bootstrap the tracing system, like this: +Then (in an application, libraries should _never_ invoke `bootstrap`), you will want to bootstrap the specific tracer you want to use in your application. A `Tracer` is a type of `Instrument` and can be offered used to globally bootstrap the tracing system, like this: ```swift @@ -295,7 +295,7 @@ To your main target, add a dependency on the `Instrumentation library` and the i Instead of providing each instrumented library with a specific instrument explicitly, you *bootstrap* the `InstrumentationSystem` which acts as a singleton that libraries/frameworks access when calling out to the configured -`InstrumentProtocol`: +`Instrument`: ```swift InstrumentationSystem.bootstrap(FancyInstrument()) @@ -316,7 +316,7 @@ This is because tracing systems may attempt to emit metrics about their status e #### Bootstrapping multiple instruments using MultiplexInstrument -It is important to note that `InstrumentationSystem.bootstrap(_: InstrumentProtocol)` must only be called once. In case you +It is important to note that `InstrumentationSystem.bootstrap(_: Instrument)` must only be called once. In case you want to bootstrap the system to use multiple instruments, you group them in a `MultiplexInstrument` first, which you then pass along to the `bootstrap` method like this: @@ -444,7 +444,7 @@ Spans form hierarchies with their parent spans, and end up being visualized usin The above trace is achieved by starting and ending spans in all the mentioned functions, for example, like this: ```swift -let tracer: any TracerProtocol +let tracer: any Tracer func makeDinner(context: LoggingContext) async throws -> Meal { tracer.withSpan(operationName: "makeDinner", context) { @@ -481,7 +481,7 @@ func get(url: String, context: LoggingContext) { } ``` -On the receiving side, an HTTP server should use the following `InstrumentProtocol` API to extract the HTTP headers of the given +On the receiving side, an HTTP server should use the following `Instrument` API to extract the HTTP headers of the given `HTTPRequest` into: ```swift @@ -538,10 +538,10 @@ func get(url: String, context: LoggingContext) { ## Instrument developers: Creating an instrument -Creating an instrument means adopting the `InstrumentProtocol` protocol (or `TracerProtocol` in case you develop a tracer). -`InstrumentProtocol` is part of the `Instrumentation` library & `Tracing` contains the `TracerProtocol` protocol. +Creating an instrument means adopting the `Instrument` protocol (or `Tracer` in case you develop a tracer). +`Instrument` is part of the `Instrumentation` library & `Tracing` contains the `Tracer` protocol. -`InstrumentProtocol` has two requirements: +`Instrument` has two requirements: 1. A method to inject values inside a `LoggingContext` into a generic carrier (e.g. HTTP headers) 2. A method to extract values from a generic carrier (e.g. HTTP headers) and store them in a `LoggingContext` @@ -556,7 +556,7 @@ how to retrieve values from the `LoggingContext` and how to set values on it. When creating a tracer you need to create two types: -1. Your tracer conforming to `TracerProtocol` +1. Your tracer conforming to `Tracer` 2. A span class conforming to `Span` > The `Span` conforms to the standard rules defined in [OpenTelemetry](https://github.com/open-telemetry/opentelemetry-specification/blob/v0.7.0/specification/trace/api.md#span), so if unsure about usage patterns, you can refer to this specification and examples referring to it. diff --git a/Sources/Instrumentation/Instrument.swift b/Sources/Instrumentation/Instrument.swift index 7695535..5ee8724 100644 --- a/Sources/Instrumentation/Instrument.swift +++ b/Sources/Instrumentation/Instrument.swift @@ -50,9 +50,9 @@ public protocol Injector: _SwiftInstrumentationSendable { /// Conforming types are usually cross-cutting tools like tracers. They are agnostic of what specific `Carrier` is used /// to propagate metadata across boundaries, but instead just specify what values to use for which keys. -public protocol InstrumentProtocol: _SwiftInstrumentationSendable { +public protocol Instrument: _SwiftInstrumentationSendable { /// Extract values from a `Carrier` by using the given extractor and inject them into the given `Baggage`. - /// It's quite common for `InstrumentProtocol`s to come up with new values if they weren't passed along in the given `Carrier`. + /// It's quite common for `Instrument`s to come up with new values if they weren't passed along in the given `Carrier`. /// /// - Parameters: /// - carrier: The `Carrier` that was used to propagate values across boundaries. diff --git a/Sources/Instrumentation/InstrumentationSystem.swift b/Sources/Instrumentation/InstrumentationSystem.swift index 11e9b7d..e25e388 100644 --- a/Sources/Instrumentation/InstrumentationSystem.swift +++ b/Sources/Instrumentation/InstrumentationSystem.swift @@ -15,24 +15,24 @@ import InstrumentationBaggage /// `InstrumentationSystem` is a global facility where the default cross-cutting tool can be configured. -/// It is set up just once in a given program to select the desired ``InstrumentProtocol`` implementation. +/// It is set up just once in a given program to select the desired ``Instrument`` implementation. /// /// # Bootstrap multiple Instruments /// If you need to use more that one cross-cutting tool you can do so by using ``MultiplexInstrument``. /// -/// # Access the InstrumentProtocol -/// ``instrument``: Returns whatever you passed to ``bootstrap(_:)`` as an ``InstrumentProtocol``. +/// # Access the Instrument +/// ``instrument``: Returns whatever you passed to ``bootstrap(_:)`` as an ``Instrument``. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage public enum InstrumentationSystem { private static let lock = ReadWriteLock() - private static var _instrument: InstrumentProtocol = NoOpInstrument() + private static var _instrument: Instrument = NoOpInstrument() private static var isInitialized = false - /// Globally select the desired ``InstrumentProtocol`` implementation. + /// Globally select the desired ``Instrument`` implementation. /// - /// - Parameter instrument: The ``InstrumentProtocol`` you want to share globally within your system. + /// - Parameter instrument: The ``Instrument`` you want to share globally within your system. /// - Warning: Do not call this method more than once. This will lead to a crash. - public static func bootstrap(_ instrument: InstrumentProtocol) { + public static func bootstrap(_ instrument: Instrument) { self.lock.withWriterLock { precondition( !self.isInitialized, """ @@ -48,16 +48,16 @@ public enum InstrumentationSystem { /// For testing scenarios one may want to set instruments multiple times, rather than the set-once semantics enforced by ``bootstrap(_:)``. /// /// - Parameter instrument: the instrument to boostrap the system with, if `nil` the ``NoOpInstrument`` is bootstrapped. - internal static func bootstrapInternal(_ instrument: InstrumentProtocol?) { + internal static func bootstrapInternal(_ instrument: Instrument?) { self.lock.withWriterLock { self._instrument = instrument ?? NoOpInstrument() } } - /// Returns the globally configured ``InstrumentProtocol``. + /// Returns the globally configured ``Instrument``. /// - /// Defaults to a no-op ``InstrumentProtocol`` if ``bootstrap(_:)`` wasn't called before. - public static var instrument: InstrumentProtocol { + /// Defaults to a no-op ``Instrument`` if ``bootstrap(_:)`` wasn't called before. + public static var instrument: Instrument { self.lock.withReaderLock { self._instrument } } } @@ -65,7 +65,7 @@ public enum InstrumentationSystem { @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage extension InstrumentationSystem { /// :nodoc: INTERNAL API: Do Not Use - public static func _findInstrument(where predicate: (InstrumentProtocol) -> Bool) -> InstrumentProtocol? { + public static func _findInstrument(where predicate: (Instrument) -> Bool) -> Instrument? { self.lock.withReaderLock { if let multiplex = self._instrument as? MultiplexInstrument { return multiplex.firstInstrument(where: predicate) diff --git a/Sources/Instrumentation/MultiplexInstrument.swift b/Sources/Instrumentation/MultiplexInstrument.swift index 21e03c4..44461e7 100644 --- a/Sources/Instrumentation/MultiplexInstrument.swift +++ b/Sources/Instrumentation/MultiplexInstrument.swift @@ -14,27 +14,27 @@ import InstrumentationBaggage -/// A pseudo-``InstrumentProtocol`` that may be used to instrument using multiple other ``InstrumentProtocol``s across a +/// A pseudo-``Instrument`` that may be used to instrument using multiple other ``Instrument``s across a /// common `Baggage`. public struct MultiplexInstrument { - private var instruments: [InstrumentProtocol] + private var instruments: [Instrument] /// Create a ``MultiplexInstrument``. /// - /// - Parameter instruments: An array of ``InstrumentProtocol``s, each of which will be used to ``InstrumentProtocol/inject(_:into:using:)`` or ``InstrumentProtocol/extract(_:into:using:)`` + /// - Parameter instruments: An array of ``Instrument``s, each of which will be used to ``Instrument/inject(_:into:using:)`` or ``Instrument/extract(_:into:using:)`` /// through the same `Baggage`. - public init(_ instruments: [InstrumentProtocol]) { + public init(_ instruments: [Instrument]) { self.instruments = instruments } } extension MultiplexInstrument { - func firstInstrument(where predicate: (InstrumentProtocol) -> Bool) -> InstrumentProtocol? { + func firstInstrument(where predicate: (Instrument) -> Bool) -> Instrument? { self.instruments.first(where: predicate) } } -extension MultiplexInstrument: InstrumentProtocol { +extension MultiplexInstrument: Instrument { public func inject(_ baggage: Baggage, into carrier: inout Carrier, using injector: Inject) where Inject: Injector, Carrier == Inject.Carrier { diff --git a/Sources/Instrumentation/NoOpInstrument.swift b/Sources/Instrumentation/NoOpInstrument.swift index f007566..ddfd3f8 100644 --- a/Sources/Instrumentation/NoOpInstrument.swift +++ b/Sources/Instrumentation/NoOpInstrument.swift @@ -14,8 +14,8 @@ import InstrumentationBaggage -/// A "no op" implementation of an ``InstrumentProtocol``. -public struct NoOpInstrument: InstrumentProtocol { +/// A "no op" implementation of an ``Instrument``. +public struct NoOpInstrument: Instrument { public init() {} public func inject(_ baggage: Baggage, into carrier: inout Carrier, using injector: Inject) diff --git a/Sources/Tracing/Docs.docc/InDepthGuide.md b/Sources/Tracing/Docs.docc/InDepthGuide.md index 9dd1eeb..99d9ca6 100644 --- a/Sources/Tracing/Docs.docc/InDepthGuide.md +++ b/Sources/Tracing/Docs.docc/InDepthGuide.md @@ -8,7 +8,7 @@ When instrumenting server applications there are typically three parties involve 1. **Application developers** create server-side applications 2. **Library/Framework developers** provide building blocks to create these applications -3. **InstrumentProtocol developers** provide tools to collect distributed metadata about your application +3. **Instrument developers** provide tools to collect distributed metadata about your application For applications to be instrumented correctly these three parts have to play along nicely. @@ -42,7 +42,7 @@ To your main target, add a dependency on the `Instrumentation library` and the i Instead of providing each instrumented library with a specific instrument explicitly, you *bootstrap* the `InstrumentationSystem` which acts as a singleton that libraries/frameworks access when calling out to the configured -`InstrumentProtocol`: +`Instrument`: ```swift InstrumentationSystem.bootstrap(FancyInstrument()) @@ -63,7 +63,7 @@ This is because tracing systems may attempt to emit metrics about their status e #### Bootstrapping multiple instruments using MultiplexInstrument -It is important to note that `InstrumentationSystem.bootstrap(_: InstrumentProtocol)` must only be called once. In case you +It is important to note that `InstrumentationSystem.bootstrap(_: Instrument)` must only be called once. In case you want to bootstrap the system to use multiple instruments, you group them in a `MultiplexInstrument` first, which you then pass along to the `bootstrap` method like this: @@ -188,7 +188,7 @@ Spans form hierarchies with their parent spans, and end up being visualized usin The above trace is achieved by starting and ending spans in all the mentioned functions, for example, like this: ```swift -let tracer: any TracerProtocol +let tracer: any Tracer func makeDinner(context: LoggingContext) async throws -> Meal { tracer.withSpan(operationName: "makeDinner", context) { @@ -225,7 +225,7 @@ func get(url: String, context: LoggingContext) { } ``` -On the receiving side, an HTTP server should use the following `InstrumentProtocol` API to extract the HTTP headers of the given +On the receiving side, an HTTP server should use the following `Instrument` API to extract the HTTP headers of the given `HTTPRequest` into: ```swift @@ -280,12 +280,12 @@ func get(url: String, context: LoggingContext) { > In the above example we used the semantic `http.method` attribute that gets exposed via the `TracingOpenTelemetrySupport` library. -## InstrumentProtocol developers: Creating an instrument +## Instrument developers: Creating an instrument -Creating an instrument means adopting the `InstrumentProtocol` protocol (or ``Tracer`` in case you develop a tracer). -`InstrumentProtocol` is part of the `Instrumentation` library & `Tracing` contains the ``Tracer`` protocol. +Creating an instrument means adopting the `Instrument` protocol (or ``Tracer`` in case you develop a tracer). +`Instrument` is part of the `Instrumentation` library & `Tracing` contains the ``Tracer`` protocol. -`InstrumentProtocol` has two requirements: +`Instrument` has two requirements: 1. A method to inject values inside a `LoggingContext` into a generic carrier (e.g. HTTP headers) 2. A method to extract values from a generic carrier (e.g. HTTP headers) and store them in a `LoggingContext` diff --git a/Sources/Tracing/Docs.docc/index.md b/Sources/Tracing/Docs.docc/index.md index db770d3..f541c06 100644 --- a/Sources/Tracing/Docs.docc/index.md +++ b/Sources/Tracing/Docs.docc/index.md @@ -62,7 +62,7 @@ To your main target, add a dependency on the `Tracing` library and the instrumen ), ``` -Then (in an application, libraries should _never_ invoke `bootstrap`), you will want to bootstrap the specific tracer you want to use in your application. A ``Tracer`` is a type of `InstrumentProtocol` and can be offered used to globally bootstrap the tracing system, like this: +Then (in an application, libraries should _never_ invoke `bootstrap`), you will want to bootstrap the specific tracer you want to use in your application. A ``Tracer`` is a type of `Instrument` and can be offered used to globally bootstrap the tracing system, like this: ```swift diff --git a/Sources/Tracing/InstrumentationSystem+Tracing.swift b/Sources/Tracing/InstrumentationSystem+Tracing.swift index feef86b..8eafce3 100644 --- a/Sources/Tracing/InstrumentationSystem+Tracing.swift +++ b/Sources/Tracing/InstrumentationSystem+Tracing.swift @@ -22,9 +22,9 @@ extension InstrumentationSystem { /// tracing instrument as passed to the multiplex instrument. If none is found, a ``NoOpTracer`` is returned. /// /// - Returns: A ``Tracer`` if the system was bootstrapped with one, and ``NoOpTracer`` otherwise. - public static var tracer: any TracerProtocol { - let found: (any TracerProtocol)? = - (self._findInstrument(where: { $0 is (any TracerProtocol) }) as? (any TracerProtocol)) + public static var tracer: any Tracer { + let found: (any Tracer)? = + (self._findInstrument(where: { $0 is (any Tracer) }) as? (any Tracer)) return found ?? NoOpTracer() } #endif @@ -35,9 +35,9 @@ extension InstrumentationSystem { /// tracing instrument as passed to the multiplex instrument. If none is found, a ``NoOpTracer`` is returned. /// /// - Returns: A ``Tracer`` if the system was bootstrapped with one, and ``NoOpTracer`` otherwise. - public static var legacyTracer: any LegacyTracerProtocol { - let found: (any LegacyTracerProtocol)? = - (self._findInstrument(where: { $0 is (any LegacyTracerProtocol) }) as? (any LegacyTracerProtocol)) + public static var legacyTracer: any LegacyTracer { + let found: (any LegacyTracer)? = + (self._findInstrument(where: { $0 is (any LegacyTracer) }) as? (any LegacyTracer)) return found ?? NoOpTracer() } } diff --git a/Sources/Tracing/NoOpTracer.swift b/Sources/Tracing/NoOpTracer.swift index 1fe2d7a..acaf59c 100644 --- a/Sources/Tracing/NoOpTracer.swift +++ b/Sources/Tracing/NoOpTracer.swift @@ -18,7 +18,7 @@ import Dispatch /// Tracer that ignores all operations, used when no tracing is required. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage -public struct NoOpTracer: LegacyTracerProtocol { +public struct NoOpTracer: LegacyTracer { public typealias TracerSpan = NoOpSpan public init() {} @@ -91,7 +91,7 @@ public struct NoOpTracer: LegacyTracerProtocol { } #if swift(>=5.7.0) -extension NoOpTracer: TracerProtocol { +extension NoOpTracer: Tracer { public func startSpan( _ operationName: String, baggage: @autoclosure () -> Baggage, diff --git a/Sources/Tracing/Tracer.swift b/Sources/Tracing/Tracer.swift index 110bdd3..03103f7 100644 --- a/Sources/Tracing/Tracer.swift +++ b/Sources/Tracing/Tracer.swift @@ -16,301 +16,428 @@ import Dispatch @_exported import Instrumentation @_exported import InstrumentationBaggage -/// Convenience access to static `startSpan` and `withSpan` APIs invoked on the globally bootstrapped tracer. +/// Start a new ``Span`` using the global bootstrapped tracer reimplementation. /// -/// If no tracer was bootstrapped using ``InstrumentationSystem/bootstrap(_:)`` these operations are no-ops. +/// The current task-local `Baggage` is picked up and provided to the underlying tracer. +/// It is also possible to pass a specific `baggage` explicitly, in which case attempting +/// to pick up the task-local baggage is prevented. This can be useful when we know that +/// we're about to start a top-level span, or if a span should be started from a different, +/// stored away previously, +/// +/// - Note: Prefer ``withSpan(_:baggage:ofKind:at:function:file:line:operation:)`` to start +/// a span as it automatically takes care of ending the span, and recording errors when thrown. +/// Use `startSpan` iff you need to pass the span manually to a different +/// location in your source code to end it. +/// +/// - Warning: You must `end()` the span when it the measured operation has completed explicitly, +/// otherwise the span object will potentially never be released nor reported. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, database call, ... +/// - clock: The clock to use as time source for the start time of the ``Span`` +/// - baggage: The `Baggage` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - function: The function name in which the span was started +/// - fileID: The `fileID` where the span was started. +/// - line: The file line where the span was started. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage -public enum Tracer { - // namespace for short-hand operations on global bootstrapped tracer +public func startSpan( + _ operationName: String, + clock: Clock, + baggage: @autoclosure () -> Baggage = .current ?? .topLevel, + ofKind kind: SpanKind = .internal, + function: String = #function, + file fileID: String = #fileID, + line: UInt = #line +) -> any Span { + // Effectively these end up calling the same method, however + // we try to not use the deprecated methods ourselves anyway + InstrumentationSystem.legacyTracer.startAnySpan( + operationName, + clock: clock, + baggage: baggage(), + ofKind: kind, + function: function, + file: fileID, + line: line + ) } +/// Start a new ``Span`` using the global bootstrapped tracer reimplementation. +/// +/// The current task-local `Baggage` is picked up and provided to the underlying tracer. +/// It is also possible to pass a specific `baggage` explicitly, in which case attempting +/// to pick up the task-local baggage is prevented. This can be useful when we know that +/// we're about to start a top-level span, or if a span should be started from a different, +/// stored away previously, +/// +/// - Note: Prefer ``withSpan(_:baggage:ofKind:at:function:file:line:operation:)`` to start +/// a span as it automatically takes care of ending the span, and recording errors when thrown. +/// Use `startSpan` iff you need to pass the span manually to a different +/// location in your source code to end it. +/// +/// - Warning: You must `end()` the span when it the measured operation has completed explicitly, +/// otherwise the span object will potentially never be released nor reported. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, database call, ... +/// - baggage: The `Baggage` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - function: The function name in which the span was started +/// - fileID: The `fileID` where the span was started. +/// - line: The file line where the span was started. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage -extension Tracer { - /// Start a new ``Span`` using the global bootstrapped tracer reimplementation. - /// - /// The current task-local `Baggage` is picked up and provided to the underlying tracer. - /// It is also possible to pass a specific `baggage` explicitly, in which case attempting - /// to pick up the task-local baggage is prevented. This can be useful when we know that - /// we're about to start a top-level span, or if a span should be started from a different, - /// stored away previously, - /// - /// - Note: Prefer ``withSpan(_:baggage:ofKind:at:function:file:line:operation:)`` to start - /// a span as it automatically takes care of ending the span, and recording errors when thrown. - /// Use `startSpan` iff you need to pass the span manually to a different - /// location in your source code to end it. - /// - /// - Warning: You must `end()` the span when it the measured operation has completed explicitly, - /// otherwise the span object will potentially never be released nor reported. - /// - /// - Parameters: - /// - operationName: The name of the operation being traced. This may be a handler function, database call, ... - /// - clock: The clock to use as time source for the start time of the ``Span`` - /// - baggage: The `Baggage` providing information on where to start the new ``Span``. - /// - kind: The ``SpanKind`` of the new ``Span``. - /// - function: The function name in which the span was started - /// - fileID: The `fileID` where the span was started. - /// - line: The file line where the span was started. - @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage - static func startSpan( - _ operationName: String, - clock: Clock, - baggage: @autoclosure () -> Baggage = .current ?? .topLevel, - ofKind kind: SpanKind = .internal, - function: String = #function, - file fileID: String = #fileID, - line: UInt = #line - ) -> any Span { - // Effectively these end up calling the same method, however - // we try to not use the deprecated methods ourselves anyway - InstrumentationSystem.legacyTracer.startAnySpan( - operationName, - clock: clock, - baggage: baggage(), - ofKind: kind, - function: function, - file: fileID, - line: line - ) - } - - @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage - static func startSpan( - _ operationName: String, - baggage: @autoclosure () -> Baggage = .current ?? .topLevel, - ofKind kind: SpanKind = .internal, - function: String = #function, - file fileID: String = #fileID, - line: UInt = #line - ) -> any Span { - // Effectively these end up calling the same method, however - // we try to not use the deprecated methods ourselves anyway - InstrumentationSystem.legacyTracer.startAnySpan( - operationName, - clock: DefaultTracerClock(), - baggage: baggage(), - ofKind: kind, - function: function, - file: fileID, - line: line - ) - } +public func startSpan( + _ operationName: String, + baggage: @autoclosure () -> Baggage = .current ?? .topLevel, + ofKind kind: SpanKind = .internal, + function: String = #function, + file fileID: String = #fileID, + line: UInt = #line +) -> any Span { + // Effectively these end up calling the same method, however + // we try to not use the deprecated methods ourselves anyway + InstrumentationSystem.legacyTracer.startAnySpan( + operationName, + clock: DefaultTracerClock(), + baggage: baggage(), + ofKind: kind, + function: function, + file: fileID, + line: line + ) +} - #if swift(>=5.7.0) - @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage - static func startSpan( - _ operationName: String, - baggage: @autoclosure () -> Baggage = .current ?? .topLevel, - ofKind kind: SpanKind = .internal, - clock: some TracerClock = DefaultTracerClock(), - function: String = #function, - file fileID: String = #fileID, - line: UInt = #line - ) -> any Span { - // Effectively these end up calling the same method, however - // we try to not use the deprecated methods ourselves anyway - InstrumentationSystem.tracer.startAnySpan( - operationName, - clock: clock, - baggage: baggage(), - ofKind: kind, - function: function, - file: fileID, - line: line - ) - } - #endif +#if swift(>=5.7.0) +/// Start a new ``Span`` using the global bootstrapped tracer reimplementation. +/// +/// The current task-local `Baggage` is picked up and provided to the underlying tracer. +/// It is also possible to pass a specific `baggage` explicitly, in which case attempting +/// to pick up the task-local baggage is prevented. This can be useful when we know that +/// we're about to start a top-level span, or if a span should be started from a different, +/// stored away previously, +/// +/// - Note: Prefer ``withSpan(_:baggage:ofKind:at:function:file:line:operation:)`` to start +/// a span as it automatically takes care of ending the span, and recording errors when thrown. +/// Use `startSpan` iff you need to pass the span manually to a different +/// location in your source code to end it. +/// +/// - Warning: You must `end()` the span when it the measured operation has completed explicitly, +/// otherwise the span object will potentially never be released nor reported. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, database call, ... +/// - baggage: The `Baggage` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - clock: The clock to use as time source for the start time of the ``Span`` +/// - function: The function name in which the span was started +/// - fileID: The `fileID` where the span was started. +/// - line: The file line where the span was started. +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage +public func startSpan( + _ operationName: String, + baggage: @autoclosure () -> Baggage = .current ?? .topLevel, + ofKind kind: SpanKind = .internal, + clock: some TracerClock = DefaultTracerClock(), + function: String = #function, + file fileID: String = #fileID, + line: UInt = #line +) -> any Span { + // Effectively these end up calling the same method, however + // we try to not use the deprecated methods ourselves anyway + InstrumentationSystem.tracer.startAnySpan( + operationName, + clock: clock, + baggage: baggage(), + ofKind: kind, + function: function, + file: fileID, + line: line + ) +} +#endif - // ==== withSpan + sync --------------------------------------------------- +// ==== withSpan + sync --------------------------------------------------- - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. - /// - /// The current task-local `Baggage` is picked up and provided to the underlying tracer. - /// It is also possible to pass a specific `baggage` explicitly, in which case attempting - /// to pick up the task-local baggage is prevented. This can be useful when we know that - /// we're about to start a top-level span, or if a span should be started from a different, - /// stored away previously, - /// - /// - Warning: You MUST NOT ``Span/end()`` the span explicitly, because at the end of the `withSpan` - /// operation closure returning the span will be closed automatically. - /// - /// - Parameters: - /// - operationName: The name of the operation being traced. This may be a handler function, database call, ... - /// - baggage: The `Baggage` providing information on where to start the new ``Span``. - /// - kind: The ``SpanKind`` of the new ``Span``. - /// - clock: The clock to use as time source for the start time of the ``Span`` - /// - function: The function name in which the span was started - /// - fileID: The `fileID` where the span was started. - /// - line: The file line where the span was started. - /// - operation: The operation that this span should be measuring - /// - Returns: the value returned by `operation` - /// - Throws: the error the `operation` has thrown (if any) - @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage - public static func withSpan( - _ operationName: String, - clock: Clock, - baggage: @autoclosure () -> Baggage = .current ?? .topLevel, - ofKind kind: SpanKind = .internal, - function: String = #function, - file fileID: String = #fileID, - line: UInt = #line, - _ operation: (any Span) throws -> T - ) rethrows -> T { - try InstrumentationSystem.legacyTracer.withAnySpan( - operationName, - clock: DefaultTracerClock(), - baggage: baggage(), - ofKind: kind, - function: function, - file: fileID, - line: line - ) { anySpan in - try operation(anySpan) - } +/// Start a new ``Span`` and automatically end when the `operation` completes, +/// including recording the `error` in case the operation throws. +/// +/// The current task-local `Baggage` is picked up and provided to the underlying tracer. +/// It is also possible to pass a specific `baggage` explicitly, in which case attempting +/// to pick up the task-local baggage is prevented. This can be useful when we know that +/// we're about to start a top-level span, or if a span should be started from a different, +/// stored away previously, +/// +/// - Warning: You MUST NOT ``Span/end()`` the span explicitly, because at the end of the `withSpan` +/// operation closure returning the span will be closed automatically. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, database call, ... +/// - clock: The clock to use as time source for the start time of the ``Span`` +/// - baggage: The `Baggage` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - function: The function name in which the span was started +/// - fileID: The `fileID` where the span was started. +/// - line: The file line where the span was started. +/// - operation: The operation that this span should be measuring +/// - Returns: the value returned by `operation` +/// - Throws: the error the `operation` has thrown (if any) +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage +public func withSpan( + _ operationName: String, + clock: Clock, + baggage: @autoclosure () -> Baggage = .current ?? .topLevel, + ofKind kind: SpanKind = .internal, + function: String = #function, + file fileID: String = #fileID, + line: UInt = #line, + _ operation: (any Span) throws -> T +) rethrows -> T { + try InstrumentationSystem.legacyTracer.withAnySpan( + operationName, + clock: DefaultTracerClock(), + baggage: baggage(), + ofKind: kind, + function: function, + file: fileID, + line: line + ) { anySpan in + try operation(anySpan) } +} - @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage - public static func withSpan( - _ operationName: String, - baggage: @autoclosure () -> Baggage = .current ?? .topLevel, - ofKind kind: SpanKind = .internal, - function: String = #function, - file fileID: String = #fileID, - line: UInt = #line, - _ operation: (any Span) throws -> T - ) rethrows -> T { - try InstrumentationSystem.legacyTracer.withAnySpan( - operationName, - clock: DefaultTracerClock(), - baggage: baggage(), - ofKind: kind, - function: function, - file: fileID, - line: line - ) { anySpan in - try operation(anySpan) - } +/// Start a new ``Span`` and automatically end when the `operation` completes, +/// including recording the `error` in case the operation throws. +/// +/// The current task-local `Baggage` is picked up and provided to the underlying tracer. +/// It is also possible to pass a specific `baggage` explicitly, in which case attempting +/// to pick up the task-local baggage is prevented. This can be useful when we know that +/// we're about to start a top-level span, or if a span should be started from a different, +/// stored away previously, +/// +/// - Warning: You MUST NOT ``Span/end()`` the span explicitly, because at the end of the `withSpan` +/// operation closure returning the span will be closed automatically. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, database call, ... +/// - baggage: The `Baggage` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - function: The function name in which the span was started +/// - fileID: The `fileID` where the span was started. +/// - line: The file line where the span was started. +/// - operation: The operation that this span should be measuring +/// - Returns: the value returned by `operation` +/// - Throws: the error the `operation` has thrown (if any) +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage +public func withSpan( + _ operationName: String, + baggage: @autoclosure () -> Baggage = .current ?? .topLevel, + ofKind kind: SpanKind = .internal, + function: String = #function, + file fileID: String = #fileID, + line: UInt = #line, + _ operation: (any Span) throws -> T +) rethrows -> T { + try InstrumentationSystem.legacyTracer.withAnySpan( + operationName, + clock: DefaultTracerClock(), + baggage: baggage(), + ofKind: kind, + function: function, + file: fileID, + line: line + ) { anySpan in + try operation(anySpan) } +} + +#if swift(>=5.7.0) - #if swift(>=5.7.0) - public static func withSpan( - _ operationName: String, - baggage: @autoclosure () -> Baggage = .current ?? .topLevel, - ofKind kind: SpanKind = .internal, - clock: some TracerClock = DefaultTracerClock(), - function: String = #function, - file fileID: String = #fileID, - line: UInt = #line, - _ operation: (any Span) throws -> T - ) rethrows -> T { - try InstrumentationSystem.legacyTracer.withAnySpan( - operationName, - clock: clock, - baggage: baggage(), - ofKind: kind, - function: function, - file: fileID, - line: line - ) { anySpan in - try operation(anySpan) - } +/// Start a new ``Span`` and automatically end when the `operation` completes, +/// including recording the `error` in case the operation throws. +/// +/// The current task-local `Baggage` is picked up and provided to the underlying tracer. +/// It is also possible to pass a specific `baggage` explicitly, in which case attempting +/// to pick up the task-local baggage is prevented. This can be useful when we know that +/// we're about to start a top-level span, or if a span should be started from a different, +/// stored away previously, +/// +/// - Warning: You MUST NOT ``Span/end()`` the span explicitly, because at the end of the `withSpan` +/// operation closure returning the span will be closed automatically. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, database call, ... +/// - clock: The clock to use as time source for the start time of the ``Span`` +/// - baggage: The `Baggage` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - function: The function name in which the span was started +/// - fileID: The `fileID` where the span was started. +/// - line: The file line where the span was started. +/// - operation: The operation that this span should be measuring +/// - Returns: the value returned by `operation` +/// - Throws: the error the `operation` has thrown (if any) +public func withSpan( + _ operationName: String, + baggage: @autoclosure () -> Baggage = .current ?? .topLevel, + ofKind kind: SpanKind = .internal, + clock: some TracerClock = DefaultTracerClock(), + function: String = #function, + file fileID: String = #fileID, + line: UInt = #line, + _ operation: (any Span) throws -> T +) rethrows -> T { + try InstrumentationSystem.legacyTracer.withAnySpan( + operationName, + clock: clock, + baggage: baggage(), + ofKind: kind, + function: function, + file: fileID, + line: line + ) { anySpan in + try operation(anySpan) } - #endif +} +#endif - // ==== withSpan + async -------------------------------------------------- +// ==== withSpan + async -------------------------------------------------- - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. - /// - /// The current task-local `Baggage` is picked up and provided to the underlying tracer. - /// It is also possible to pass a specific `baggage` explicitly, in which case attempting - /// to pick up the task-local baggage is prevented. This can be useful when we know that - /// we're about to start a top-level span, or if a span should be started from a different, - /// stored away previously, - /// - /// - Warning: You MUST NOT ``Span/end()`` the span explicitly, because at the end of the `withSpan` - /// operation closure returning the span will be closed automatically. - /// - /// - Parameters: - /// - operationName: The name of the operation being traced. This may be a handler function, database call, ... - /// - baggage: The `Baggage` providing information on where to start the new ``Span``. - /// - kind: The ``SpanKind`` of the new ``Span``. - /// - clock: The clock to use as time source for the start time of the ``Span`` - /// - function: The function name in which the span was started - /// - fileID: The `fileID` where the span was started. - /// - line: The file line where the span was started. - /// - operation: The operation that this span should be measuring - /// - Returns: the value returned by `operation` - /// - Throws: the error the `operation` has thrown (if any) - @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage - public static func withSpan( - _ operationName: String, - clock: Clock, - baggage: @autoclosure () -> Baggage = .current ?? .topLevel, - ofKind kind: SpanKind = .internal, - function: String = #function, - file fileID: String = #fileID, - line: UInt = #line, - _ operation: (any Span) async throws -> T - ) async rethrows -> T { - try await InstrumentationSystem.legacyTracer.withAnySpan( - operationName, - clock: DefaultTracerClock(), - baggage: baggage(), - ofKind: kind, - function: function, - file: fileID, - line: line - ) { anySpan in - try await operation(anySpan) - } +/// Start a new ``Span`` and automatically end when the `operation` completes, +/// including recording the `error` in case the operation throws. +/// +/// The current task-local `Baggage` is picked up and provided to the underlying tracer. +/// It is also possible to pass a specific `baggage` explicitly, in which case attempting +/// to pick up the task-local baggage is prevented. This can be useful when we know that +/// we're about to start a top-level span, or if a span should be started from a different, +/// stored away previously, +/// +/// - Warning: You MUST NOT ``Span/end()`` the span explicitly, because at the end of the `withSpan` +/// operation closure returning the span will be closed automatically. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, database call, ... +/// - clock: The clock to use as time source for the start time of the ``Span`` +/// - baggage: The `Baggage` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - function: The function name in which the span was started +/// - fileID: The `fileID` where the span was started. +/// - line: The file line where the span was started. +/// - operation: The operation that this span should be measuring +/// - Returns: the value returned by `operation` +/// - Throws: the error the `operation` has thrown (if any) +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage +public func withSpan( + _ operationName: String, + clock: Clock, + baggage: @autoclosure () -> Baggage = .current ?? .topLevel, + ofKind kind: SpanKind = .internal, + function: String = #function, + file fileID: String = #fileID, + line: UInt = #line, + _ operation: (any Span) async throws -> T +) async rethrows -> T { + try await InstrumentationSystem.legacyTracer.withAnySpan( + operationName, + clock: DefaultTracerClock(), + baggage: baggage(), + ofKind: kind, + function: function, + file: fileID, + line: line + ) { anySpan in + try await operation(anySpan) } +} - @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage - public static func withSpan( - _ operationName: String, - baggage: @autoclosure () -> Baggage = .current ?? .topLevel, - ofKind kind: SpanKind = .internal, - function: String = #function, - file fileID: String = #fileID, - line: UInt = #line, - _ operation: (any Span) async throws -> T - ) async rethrows -> T { - try await InstrumentationSystem.legacyTracer.withAnySpan( - operationName, - clock: DefaultTracerClock(), - baggage: baggage(), - ofKind: kind, - function: function, - file: fileID, - line: line - ) { anySpan in - try await operation(anySpan) - } +/// Start a new ``Span`` and automatically end when the `operation` completes, +/// including recording the `error` in case the operation throws. +/// +/// The current task-local `Baggage` is picked up and provided to the underlying tracer. +/// It is also possible to pass a specific `baggage` explicitly, in which case attempting +/// to pick up the task-local baggage is prevented. This can be useful when we know that +/// we're about to start a top-level span, or if a span should be started from a different, +/// stored away previously, +/// +/// - Warning: You MUST NOT ``Span/end()`` the span explicitly, because at the end of the `withSpan` +/// operation closure returning the span will be closed automatically. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, database call, ... +/// - baggage: The `Baggage` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - function: The function name in which the span was started +/// - fileID: The `fileID` where the span was started. +/// - line: The file line where the span was started. +/// - operation: The operation that this span should be measuring +/// - Returns: the value returned by `operation` +/// - Throws: the error the `operation` has thrown (if any) +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage +public func withSpan( + _ operationName: String, + baggage: @autoclosure () -> Baggage = .current ?? .topLevel, + ofKind kind: SpanKind = .internal, + function: String = #function, + file fileID: String = #fileID, + line: UInt = #line, + _ operation: (any Span) async throws -> T +) async rethrows -> T { + try await InstrumentationSystem.legacyTracer.withAnySpan( + operationName, + clock: DefaultTracerClock(), + baggage: baggage(), + ofKind: kind, + function: function, + file: fileID, + line: line + ) { anySpan in + try await operation(anySpan) } +} - #if swift(>=5.7.0) - public static func withSpan( - _ operationName: String, - baggage: @autoclosure () -> Baggage = .current ?? .topLevel, - ofKind kind: SpanKind = .internal, - clock: some TracerClock = DefaultTracerClock(), - function: String = #function, - file fileID: String = #fileID, - line: UInt = #line, - _ operation: (any Span) async throws -> T - ) async rethrows -> T { - try await InstrumentationSystem.legacyTracer.withAnySpan( - operationName, - clock: clock, - baggage: baggage(), - ofKind: kind, - function: function, - file: fileID, - line: line - ) { anySpan in - try await operation(anySpan) - } +#if swift(>=5.7.0) +/// Start a new ``Span`` and automatically end when the `operation` completes, +/// including recording the `error` in case the operation throws. +/// +/// The current task-local `Baggage` is picked up and provided to the underlying tracer. +/// It is also possible to pass a specific `baggage` explicitly, in which case attempting +/// to pick up the task-local baggage is prevented. This can be useful when we know that +/// we're about to start a top-level span, or if a span should be started from a different, +/// stored away previously, +/// +/// - Warning: You MUST NOT ``Span/end()`` the span explicitly, because at the end of the `withSpan` +/// operation closure returning the span will be closed automatically. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, database call, ... +/// - baggage: The `Baggage` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - clock: The clock to use as time source for the start time of the ``Span`` +/// - function: The function name in which the span was started +/// - fileID: The `fileID` where the span was started. +/// - line: The file line where the span was started. +/// - operation: The operation that this span should be measuring +/// - Returns: the value returned by `operation` +/// - Throws: the error the `operation` has thrown (if any) +public func withSpan( + _ operationName: String, + baggage: @autoclosure () -> Baggage = .current ?? .topLevel, + ofKind kind: SpanKind = .internal, + clock: some TracerClock = DefaultTracerClock(), + function: String = #function, + file fileID: String = #fileID, + line: UInt = #line, + _ operation: (any Span) async throws -> T +) async rethrows -> T { + try await InstrumentationSystem.legacyTracer.withAnySpan( + operationName, + clock: clock, + baggage: baggage(), + ofKind: kind, + function: function, + file: fileID, + line: line + ) { anySpan in + try await operation(anySpan) } - #endif } +#endif diff --git a/Sources/Tracing/TracerProtocol+Legacy.swift b/Sources/Tracing/TracerProtocol+Legacy.swift index bd2d21a..fc6696c 100644 --- a/Sources/Tracing/TracerProtocol+Legacy.swift +++ b/Sources/Tracing/TracerProtocol+Legacy.swift @@ -17,10 +17,10 @@ import Dispatch @_exported import InstrumentationBaggage @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage -public protocol LegacyTracerProtocol: InstrumentProtocol { +public protocol LegacyTracer: Instrument { /// Start a new span returning an existential ``Span`` reference. /// - /// - Warning: This method will be deprecated in favor of `TracerProtocol/withSpan` as soon as this project is able to require Swift 5.7. + /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `baggage` explicitly, in which case attempting @@ -69,12 +69,12 @@ public protocol LegacyTracerProtocol: InstrumentProtocol { // MARK: Legacy implementations for Swift 5.7 @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage -extension LegacyTracerProtocol { +extension LegacyTracer { // ==== startSpan --------------------------------------------------------- /// Start a new span returning an existential ``Span`` reference. /// - /// - Warning: This method will be deprecated in favor of `TracerProtocol/withSpan` as soon as this project is able to require Swift 5.7. + /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `baggage` explicitly, in which case attempting @@ -122,7 +122,7 @@ extension LegacyTracerProtocol { /// Start a new span returning an existential ``Span`` reference. /// - /// - Warning: This method will be deprecated in favor of `TracerProtocol/withSpan` as soon as this project is able to require Swift 5.7. + /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. @@ -225,7 +225,7 @@ extension LegacyTracerProtocol { /// Start a new ``Span`` and automatically end when the `operation` completes, /// including recording the `error` in case the operation throws. /// - /// - Warning: This method will be deprecated in favor of `TracerProtocol/withSpan` as soon as this project is able to require Swift 5.7. + /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `baggage` explicitly, in which case attempting @@ -272,7 +272,7 @@ extension LegacyTracerProtocol { /// Start a new ``Span`` and automatically end when the `operation` completes, /// including recording the `error` in case the operation throws. /// - /// - Warning: This method will be deprecated in favor of `TracerProtocol/withSpan` as soon as this project is able to require Swift 5.7. + /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `baggage` explicitly, in which case attempting @@ -326,7 +326,7 @@ extension LegacyTracerProtocol { /// Start a new ``Span`` and automatically end when the `operation` completes, /// including recording the `error` in case the operation throws. /// - /// - Warning: This method will be deprecated in favor of `TracerProtocol/withSpan` as soon as this project is able to require Swift 5.7. + /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `baggage` explicitly, in which case attempting @@ -378,12 +378,12 @@ extension LegacyTracerProtocol { } #if swift(>=5.7.0) -// Provide compatibility shims of the `...AnySpan` APIs to the 5.7 requiring `TracerProtocol`. +// Provide compatibility shims of the `...AnySpan` APIs to the 5.7 requiring `Tracer`. -extension TracerProtocol { +extension Tracer { /// Start a new span returning an existential ``Span`` reference. /// - /// - Warning: This method will be deprecated in favor of `TracerProtocol/withSpan` as soon as this project is able to require Swift 5.7. + /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `baggage` explicitly, in which case attempting @@ -432,7 +432,7 @@ extension TracerProtocol { /// Start a new ``Span`` and automatically end when the `operation` completes, /// including recording the `error` in case the operation throws. /// - /// - Warning: This method will be deprecated in favor of `TracerProtocol/withSpan` as soon as this project is able to require Swift 5.7. + /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `baggage` explicitly, in which case attempting @@ -487,7 +487,7 @@ extension TracerProtocol { /// Start a new ``Span`` and automatically end when the `operation` completes, /// including recording the `error` in case the operation throws. /// - /// - Warning: This method will be deprecated in favor of `TracerProtocol/withSpan` as soon as this project is able to require Swift 5.7. + /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `baggage` explicitly, in which case attempting diff --git a/Sources/Tracing/TracerProtocol.swift b/Sources/Tracing/TracerProtocol.swift index c063a42..6000710 100644 --- a/Sources/Tracing/TracerProtocol.swift +++ b/Sources/Tracing/TracerProtocol.swift @@ -24,7 +24,7 @@ /// /// A tracer is a special kind of instrument with the added ability to start a ``Span``. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage -public protocol TracerProtocol: LegacyTracerProtocol { +public protocol Tracer: LegacyTracer { /// The concrete type of span this tracer will be producing/ associatedtype TracerSpan: Span @@ -64,7 +64,7 @@ public protocol TracerProtocol: LegacyTracerProtocol { } @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage -extension TracerProtocol { +extension Tracer { /// Start a new ``Span`` with the given `Baggage`. /// /// The current task-local `Baggage` is picked up and provided to the underlying tracer. @@ -113,7 +113,7 @@ extension TracerProtocol { // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Starting spans: `withSpan` -extension TracerProtocol { +extension Tracer { /// Start a new ``Span`` and automatically end when the `operation` completes, /// including recording the `error` in case the operation throws. /// diff --git a/Tests/InstrumentationTests/InstrumentTests.swift b/Tests/InstrumentationTests/InstrumentTests.swift index f33e8b9..b0fdb56 100644 --- a/Tests/InstrumentationTests/InstrumentTests.swift +++ b/Tests/InstrumentationTests/InstrumentTests.swift @@ -52,7 +52,7 @@ private struct DictionaryExtractor: Extractor { } } -private final class FirstFakeTracer: InstrumentProtocol { +private final class FirstFakeTracer: Instrument { enum TraceIDKey: BaggageKey { typealias Value = String @@ -77,7 +77,7 @@ private final class FirstFakeTracer: InstrumentProtocol { } } -private final class SecondFakeTracer: InstrumentProtocol { +private final class SecondFakeTracer: Instrument { enum TraceIDKey: BaggageKey { typealias Value = String diff --git a/Tests/InstrumentationTests/InstrumentationSystemTests.swift b/Tests/InstrumentationTests/InstrumentationSystemTests.swift index efd2d4c..9334242 100644 --- a/Tests/InstrumentationTests/InstrumentationSystemTests.swift +++ b/Tests/InstrumentationTests/InstrumentationSystemTests.swift @@ -17,7 +17,7 @@ import InstrumentationBaggage import XCTest extension InstrumentationSystem { - public static func _instrument(of instrumentType: I.Type) -> I? where I: InstrumentProtocol { + public static func _instrument(of instrumentType: I.Type) -> I? where I: Instrument { self._findInstrument(where: { $0 is I }) as? I } } @@ -48,7 +48,7 @@ final class InstrumentationSystemTests: XCTestCase { } } -private final class FakeTracer: InstrumentProtocol { +private final class FakeTracer: Instrument { func inject( _ baggage: Baggage, into carrier: inout Carrier, @@ -68,7 +68,7 @@ private final class FakeTracer: InstrumentProtocol { Carrier == Extract.Carrier {} } -private final class FakeInstrument: InstrumentProtocol { +private final class FakeInstrument: Instrument { func inject( _ baggage: Baggage, into carrier: inout Carrier, diff --git a/Tests/TracingTests/ActorTracingTests.swift b/Tests/TracingTests/ActorTracingTests.swift index 6d6bd7f..5ace8a7 100644 --- a/Tests/TracingTests/ActorTracingTests.swift +++ b/Tests/TracingTests/ActorTracingTests.swift @@ -30,7 +30,7 @@ actor Foo { var bar = 0 func foo() async { var num = 0 - await Tracer.withSpan(#function) { _ in + await withSpan(#function) { _ in bar += 1 await work() num += 1 diff --git a/Tests/TracingTests/DynamicTracepointTracerTests.swift b/Tests/TracingTests/DynamicTracepointTracerTests.swift index cc872b3..533b9a2 100644 --- a/Tests/TracingTests/DynamicTracepointTracerTests.swift +++ b/Tests/TracingTests/DynamicTracepointTracerTests.swift @@ -128,7 +128,7 @@ final class DynamicTracepointTracerTests: XCTestCase { } /// Only intended to be used in single-threaded testing. -final class DynamicTracepointTestTracer: LegacyTracerProtocol { +final class DynamicTracepointTestTracer: LegacyTracer { private(set) var activeTracepoints: Set = [] struct TracepointID: Hashable { @@ -330,7 +330,7 @@ extension DynamicTracepointTestTracer { } #if compiler(>=5.7.0) -extension DynamicTracepointTestTracer: TracerProtocol { +extension DynamicTracepointTestTracer: Tracer { typealias TracerSpan = TracepointSpan func startSpan(_ operationName: String, diff --git a/Tests/TracingTests/TestTracer.swift b/Tests/TracingTests/TestTracer.swift index eee74e6..7ad28f7 100644 --- a/Tests/TracingTests/TestTracer.swift +++ b/Tests/TracingTests/TestTracer.swift @@ -19,7 +19,7 @@ import InstrumentationBaggage import Tracing /// Only intended to be used in single-threaded testing. -final class TestTracer: LegacyTracerProtocol { +final class TestTracer: LegacyTracer { private(set) var spans = [TestSpan]() var onEndSpan: (TestSpan) -> Void = { _ in } @@ -65,7 +65,7 @@ final class TestTracer: LegacyTracerProtocol { } #if swift(>=5.7.0) -extension TestTracer: TracerProtocol { +extension TestTracer: Tracer { func startSpan( _ operationName: String, baggage: @autoclosure () -> Baggage, diff --git a/Tests/TracingTests/TracedLockTests.swift b/Tests/TracingTests/TracedLockTests.swift index 9294bf9..23d3e73 100644 --- a/Tests/TracingTests/TracedLockTests.swift +++ b/Tests/TracingTests/TracedLockTests.swift @@ -59,7 +59,7 @@ enum TaskIDKey: BaggageKey { // MARK: PrintLn Tracer /// Only intended to be used in single-threaded testing. -private final class TracedLockPrintlnTracer: LegacyTracerProtocol { +private final class TracedLockPrintlnTracer: LegacyTracer { func startAnySpan( _ operationName: String, baggage: @autoclosure () -> Baggage, @@ -162,7 +162,7 @@ private final class TracedLockPrintlnTracer: LegacyTracerProtocol { } #if swift(>=5.7.0) -extension TracedLockPrintlnTracer: TracerProtocol { +extension TracedLockPrintlnTracer: Tracer { func startSpan( _ operationName: String, baggage: @autoclosure () -> Baggage, diff --git a/Tests/TracingTests/TracerTests+swift57.swift b/Tests/TracingTests/TracerTests+swift57.swift index 4bf9a13..1c3cdb3 100644 --- a/Tests/TracingTests/TracerTests+swift57.swift +++ b/Tests/TracingTests/TracerTests+swift57.swift @@ -20,7 +20,7 @@ import XCTest #if swift(>=5.7.0) // Specifically make sure we don't have to implement startAnySpan -final class SampleSwift57Tracer: TracerProtocol { +final class SampleSwift57Tracer: Tracer { private(set) var spans = [SampleSwift57Span]() var onEndSpan: (SampleSwift57Span) -> Void = { _ in } diff --git a/Tests/TracingTests/TracerTests.swift b/Tests/TracingTests/TracerTests.swift index f463e4f..fdb7df5 100644 --- a/Tests/TracingTests/TracerTests.swift +++ b/Tests/TracingTests/TracerTests.swift @@ -280,7 +280,7 @@ final class TracerTests: XCTestCase { self.testAsync { do { - _ = try await Tracer.withSpan("hello", operation) + _ = try await withSpan("hello", operation) } catch { XCTAssertTrue(spanEnded) XCTAssertEqual(error as? ExampleSpanError, ExampleSpanError()) @@ -310,7 +310,7 @@ final class TracerTests: XCTestCase { self.testAsync { do { - _ = try Tracer.withSpan("hello", operation) + _ = try withSpan("hello", operation) } catch { XCTAssertTrue(spanEnded) XCTAssertEqual(error as? ExampleSpanError, ExampleSpanError()) diff --git a/Tests/TracingTests/TracingInstrumentationSystemTests.swift b/Tests/TracingTests/TracingInstrumentationSystemTests.swift index d7ed546..d0d0ee6 100644 --- a/Tests/TracingTests/TracingInstrumentationSystemTests.swift +++ b/Tests/TracingTests/TracingInstrumentationSystemTests.swift @@ -17,17 +17,17 @@ import Tracing import XCTest extension InstrumentationSystem { - public static func _legacyTracer(of tracerType: T.Type) -> T? where T: LegacyTracerProtocol { + public static func _legacyTracer(of tracerType: T.Type) -> T? where T: LegacyTracer { self._findInstrument(where: { $0 is T }) as? T } #if swift(>=5.7.0) - public static func _tracer(of tracerType: T.Type) -> T? where T: TracerProtocol { + public static func _tracer(of tracerType: T.Type) -> T? where T: Tracer { self._findInstrument(where: { $0 is T }) as? T } #endif - public static func _instrument(of instrumentType: I.Type) -> I? where I: InstrumentProtocol { + public static func _instrument(of instrumentType: I.Type) -> I? where I: Instrument { self._findInstrument(where: { $0 is I }) as? I } }