From a8bb5a2595269f26d469e3ad5ac046bd4c8c68be Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Wed, 24 Sep 2025 12:56:17 -0700 Subject: [PATCH 01/27] initial curation, organizing symbols --- Sources/Tracing/Docs.docc/index.md | 58 +++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/Sources/Tracing/Docs.docc/index.md b/Sources/Tracing/Docs.docc/index.md index 26c61362..eeddc95c 100644 --- a/Sources/Tracing/Docs.docc/index.md +++ b/Sources/Tracing/Docs.docc/index.md @@ -1,4 +1,4 @@ -# ``Tracing`` +# ``/Tracing`` A Distributed Tracing API for Swift. @@ -26,3 +26,59 @@ as the subsequent guides dive deeper into patterns and details of instrumenting - - - + +### Boostrapping Tracing + +- ``InstrumentationSystem`` +- ``MultiplexInstrument`` +- ``Extractor`` +- ``Injector`` +- ``Instrument`` +- ``TracerInstant`` +- ``LegacyTracer`` + +### Creating Spans + +- ``withSpan(_:context:ofKind:function:file:line:_:)-65bom`` +- ``withSpan(_:at:context:ofKind:function:file:line:_:)-7pdo8`` +- ``withSpan(_:context:ofKind:isolation:function:file:line:_:)`` +- ``withSpan(_:at:context:ofKind:isolation:function:file:line:_:)`` +- ``withSpan(_:context:ofKind:at:function:file:line:_:)-6e2id`` +- ``withSpan(_:context:ofKind:at:isolation:function:file:line:_:)`` + +- ``withSpan(_:context:ofKind:function:file:line:_:)-tj8`` +- ``withSpan(_:at:context:ofKind:function:file:line:_:)-3h6gv`` +- ``withSpan(_:context:ofKind:at:function:file:line:_:)-8gw3v`` + +### Manually Managing Spans + +- ``startSpan(_:context:ofKind:function:file:line:)`` +- ``startSpan(_:at:context:ofKind:function:file:line:)`` +- ``startSpan(_:context:ofKind:at:function:file:line:)`` + +### Inspecting Spans + +- ``Span`` +- ``SpanAttributeConvertible`` +- ``SpanAttributeNamespace`` +- ``NestedSpanAttributesProtocol`` +- ``SpanAttributes`` +- ``SpanAttributeKey`` +- ``SpanAttribute`` +- ``SpanEvent`` +- ``SpanLink`` +- ``SpanStatus`` +- ``SpanKind`` +- ``TODOLocation`` + +### Service Context + +- ``ServiceContext`` +- ``ServiceContextKey`` +- ``AnyServiceContextKey`` + +### Default Tracers + +- ``DefaultTracerClock`` +- ``NoOpInstrument`` +- ``NoOpTracer`` From 04fc8bf623f460acf453a54de12b6b481cc67198 Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Wed, 24 Sep 2025 14:36:21 -0700 Subject: [PATCH 02/27] adds base curation and catalogs for each module, expands abstracts for in-memory tracing --- .../Documentation.docc/Documentation.md | 12 ++ Sources/InMemoryTracing/InMemorySpan.swift | 102 ++++++++++++---- .../InMemoryTracing/InMemorySpanContext.swift | 18 ++- Sources/InMemoryTracing/InMemoryTracer.swift | 111 ++++++++++++------ .../Documentation.docc/Documentation.md | 14 +++ Sources/Tracing/Docs.docc/index.md | 14 +-- 6 files changed, 192 insertions(+), 79 deletions(-) create mode 100644 Sources/InMemoryTracing/Documentation.docc/Documentation.md create mode 100644 Sources/Instrumentation/Documentation.docc/Documentation.md diff --git a/Sources/InMemoryTracing/Documentation.docc/Documentation.md b/Sources/InMemoryTracing/Documentation.docc/Documentation.md new file mode 100644 index 00000000..b6a0f39d --- /dev/null +++ b/Sources/InMemoryTracing/Documentation.docc/Documentation.md @@ -0,0 +1,12 @@ +# ``InMemoryTracing`` + +In-memory implementations of tracers to provide test-focused or other programmatic access to spans. + +## Topics + +### In-memory implementations + +- ``InMemoryTracer`` +- ``InMemorySpan`` +- ``InMemorySpanContext`` +- ``FinishedInMemorySpan`` diff --git a/Sources/InMemoryTracing/InMemorySpan.swift b/Sources/InMemoryTracing/InMemorySpan.swift index c61518c3..ac72ec4e 100644 --- a/Sources/InMemoryTracing/InMemorySpan.swift +++ b/Sources/InMemoryTracing/InMemorySpan.swift @@ -15,11 +15,14 @@ @_spi(Locking) import Instrumentation import Tracing -/// A ``Span`` created by the ``InMemoryTracer`` that will be retained in memory when ended. -/// See ``InMemoryTracer/ +/// A span created by the in-memory tracer that is retained in memory when the trace ends. +/// +/// See ``InMemoryTracer`` public struct InMemorySpan: Span { - + + /// The service context of the span. public let context: ServiceContext + /// The in-memory span context. public var spanContext: InMemorySpanContext { context.inMemorySpanContext! } @@ -33,12 +36,15 @@ public struct InMemorySpan: Span { spanContext.spanID } /// The ID of the parent span of this span, if there was any. - /// When this is `nil` it means this is the top-level span of this trace. + /// + /// When `nil`, this is the top-level span of this trace. public var parentSpanID: String? { spanContext.parentSpanID } - + + /// The kind of span public let kind: SpanKind + /// The time instant the span started. public let startInstant: any TracerInstant private let _operationName: LockedValueBox @@ -49,7 +55,15 @@ public struct InMemorySpan: Span { private let _status = LockedValueBox(nil) private let _isRecording = LockedValueBox(true) private let onEnd: @Sendable (FinishedInMemorySpan) -> Void - + + /// Creates a new in-memory span + /// - Parameters: + /// - operationName: The operation name this span represents. + /// - context: The service context for the span. + /// - spanContext: The in-memory span context. + /// - kind: The kind of span. + /// - startInstant: The time instant the span started. + /// - onEnd: A closure invoked when the span completes, providing access to the finished span. public init( operationName: String, context: ServiceContext, @@ -67,12 +81,15 @@ public struct InMemorySpan: Span { self.onEnd = onEnd } - /// The in memory span stops recording (storing mutations performed on the span) when it is ended. - /// In other words, a finished span no longer is mutable and will ignore all subsequent attempts to mutate. + /// A Boolean value that indicates whether the span is still recording mutations. + /// + /// The in memory span stops recording mutations performed on the span when it is ended. + /// In other words, a finished span is not mutable and ignores all subsequent attempts to mutate. public var isRecording: Bool { _isRecording.withValue { $0 } } - + + /// The operation name the span represents. public var operationName: String { get { _operationName.withValue { $0 } @@ -82,7 +99,8 @@ public struct InMemorySpan: Span { _operationName.withValue { $0 = newValue } } } - + + /// The span attributes. public var attributes: SpanAttributes { get { _attributes.withValue { $0 } @@ -92,29 +110,41 @@ public struct InMemorySpan: Span { _attributes.withValue { $0 = newValue } } } - + + /// The events associated with the span. public var events: [SpanEvent] { _events.withValue { $0 } } - + + /// Adds an event you provide to the span. + /// - Parameter event: The event to record. public func addEvent(_ event: SpanEvent) { guard isRecording else { return } _events.withValue { $0.append(event) } } - + + /// The span links. public var links: [SpanLink] { _links.withValue { $0 } } - + + /// Adds a link to the span. + /// - Parameter link: The link to add. public func addLink(_ link: SpanLink) { guard isRecording else { return } _links.withValue { $0.append(link) } } - + + /// The errors recorded by the span. public var errors: [RecordedError] { _errors.withValue { $0 } } - + + /// Records an error to the span. + /// - Parameters: + /// - error: The error to record. + /// - attributes: Span attributes associated with the error. + /// - instant: The time instant of the error. public func recordError( _ error: any Error, attributes: SpanAttributes, @@ -125,16 +155,21 @@ public struct InMemorySpan: Span { $0.append(RecordedError(error: error, attributes: attributes, instant: instant())) } } - + + /// The status of the span. public var status: SpanStatus? { _status.withValue { $0 } } - + + /// Updates the status of the span to the value you provide. + /// - Parameter status: The status to set. public func setStatus(_ status: SpanStatus) { guard isRecording else { return } _status.withValue { $0 = status } } - + + /// Finishes the span. + /// - Parameter instant: the time instant the span completed. public func end(at instant: @autoclosure () -> some TracerInstant) { let shouldRecord = _isRecording.withValue { let value = $0 @@ -157,20 +192,26 @@ public struct InMemorySpan: Span { ) onEnd(finishedSpan) } - + + /// An error recorded to a span. public struct RecordedError: Sendable { + /// The recorded error. public let error: Error + /// The span attributes associated with the error. public let attributes: SpanAttributes + /// The time instant the error occured. public let instant: any TracerInstant } } -/// Represents a finished span (a ``Span`` that `end()` was called on) -/// that was recorded by the ``InMemoryTracer``. +/// A type that represents a completed span recorded by the in-memory tracer. public struct FinishedInMemorySpan: Sendable { + /// The name of the operation the span represents. public var operationName: String - + + /// The service context of the finished span. public var context: ServiceContext + /// The in-memory span context. public var spanContext: InMemorySpanContext { get { context.inMemorySpanContext! @@ -189,7 +230,7 @@ public struct FinishedInMemorySpan: Sendable { spanContext.spanID = newValue } } - /// The ID of this concrete span. + /// The ID of this span. public var spanID: String { get { spanContext.spanID @@ -199,7 +240,8 @@ public struct FinishedInMemorySpan: Sendable { } } /// The ID of the parent span of this span, if there was any. - /// When this is `nil` it means this is the top-level span of this trace. + /// + /// When `nil`, this is the top-level span of this trace. public var parentSpanID: String? { get { spanContext.parentSpanID @@ -208,13 +250,21 @@ public struct FinishedInMemorySpan: Sendable { spanContext.parentSpanID = newValue } } - + + /// The kind of span. public var kind: SpanKind + /// The time instant the span started. public var startInstant: any TracerInstant + /// The time instant the span ended. public var endInstant: any TracerInstant + /// The span attributes. public var attributes: SpanAttributes + /// A list of events recorded to the span. public var events: [SpanEvent] + /// A list of links added to the span. public var links: [SpanLink] + /// A list of errors recorded to the span. public var errors: [InMemorySpan.RecordedError] + /// The span status. public var status: SpanStatus? } diff --git a/Sources/InMemoryTracing/InMemorySpanContext.swift b/Sources/InMemoryTracing/InMemorySpanContext.swift index 9f8c1919..85a56e20 100644 --- a/Sources/InMemoryTracing/InMemorySpanContext.swift +++ b/Sources/InMemoryTracing/InMemorySpanContext.swift @@ -14,18 +14,24 @@ import ServiceContextModule -/// Encapsulates the `traceID`, `spanID` and `parentSpanID` of an `InMemorySpan`. +/// A type that encapsulates the trace ID, span ID, and parent span ID of an in-memory span. +/// /// Generally used through the `ServiceContext/inMemorySpanContext` task local value. public struct InMemorySpanContext: Sendable, Hashable { - /// Idenfifier of top-level trace of which this span is a part of. + /// The idenfifier of top-level trace of which this span is a part of. public var traceID: String - /// Identifier of this specific span. + /// The identifier of this span. public var spanID: String - // Identifier of the parent of this span, if any. + /// The Identifier of the parent of this span, if any. public var parentSpanID: String? - + + /// Creates a new in-memory span context. + /// - Parameters: + /// - traceID: The trace ID for the context. + /// - spanID: The span ID for the context. + /// - parentSpanID: The context's parent span ID. public init(traceID: String, spanID: String, parentSpanID: String?) { self.traceID = traceID self.spanID = spanID @@ -34,7 +40,7 @@ public struct InMemorySpanContext: Sendable, Hashable { } extension ServiceContext { - /// Task-local value representing the current tracing ``Span`` as set by the ``InMemoryTracer``. + /// A task-local value that represents the current tracing span as set by the in-memory tracer. public var inMemorySpanContext: InMemorySpanContext? { get { self[InMemorySpanContextKey.self] diff --git a/Sources/InMemoryTracing/InMemoryTracer.swift b/Sources/InMemoryTracing/InMemoryTracer.swift index b66845d5..d40a026f 100644 --- a/Sources/InMemoryTracing/InMemoryTracer.swift +++ b/Sources/InMemoryTracing/InMemoryTracer.swift @@ -15,17 +15,16 @@ @_spi(Locking) import Instrumentation import Tracing -/// An in-memory implementation of the ``Tracer`` protocol which can be used either in testing, -/// or in manual collecting and interrogating traces within a process, and acting on them programatically. +/// An in-memory implementation of the `Tracer` protocol which can be used either in testing, +/// or in collecting and interrogating traces within a process, and acting on them programatically. /// /// ### Span lifecycle /// This tracer does _not_ automatically remove spans once they end. -/// Finished spans are retained and available for inspection using the `finishedSpans` property. -/// Spans which have been started but have not yet been called `Span/end()` on are also available -/// for inspection using the ``activeSpans`` property. +/// In-memory tracer retains finished spans and makes them available for inspection through the `finishedSpans` property. +/// Spans that started but have not yet called `Span/end()` are available for inspection through the ``activeSpans`` property. /// -/// Spans are retained by the `InMemoryTracer` until they are explicitly removed, e.g. by using -/// ``popFinishedSpans()`` or any of the `clear...` methods (e.g. ``clearFinishedSpans()``) +/// The `InMemoryTracer` retains spans until they are explicitly removed, for example by using +/// ``popFinishedSpans()`` or any of the `clear...` methods (such as ``clearFinishedSpans()``) public struct InMemoryTracer: Tracer { public let idGenerator: IDGenerator @@ -44,10 +43,11 @@ public struct InMemoryTracer: Tracer { var _state = LockedValueBox(.init()) /// Create a new ``InMemoryTracer``. - /// + /// /// - Parameters: - /// - Parameter idGenerator: strategy for generating trace and span identifiers - /// - Parameter idGenerator: strategy for generating trace and span identifiers + /// - idGenerator: strategy for generating trace and span identifiers + /// - recordInjections: A Boolean value that indicates whether the tracer records injected values. + /// - recordExtractions: A Boolean value that indicates whether the tracer records extracted values. public init( idGenerator: IDGenerator = .incrementing, recordInjections: Bool = true, @@ -62,7 +62,17 @@ public struct InMemoryTracer: Tracer { // MARK: - Tracer extension InMemoryTracer { - + + /// Start a new span and automatically ends the span when the operation completes, including recording the error in case the operation throws. + /// - Parameters: + /// - operationName: The name of the operation being traced. + /// - context: The service context that provides information on where to start the new span. + /// - kind: The kind of span. + /// - instant: The time instant at which the span started. + /// - 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. + /// - Returns: An in-memory span. public func startSpan( _ operationName: String, context: @autoclosure () -> ServiceContext, @@ -109,7 +119,8 @@ extension InMemoryTracer { _state.withValue { $0.activeSpans[spanContext] = span } return span } - + + /// Records a request to flush spans. public func forceFlush() { _state.withValue { $0.numberOfForceFlushes += 1 } } @@ -119,24 +130,30 @@ extension InMemoryTracer { extension InMemoryTracer { - /// Array of active spans, i.e. spans which have been started but have not yet finished (by calling `Span/end()`). + /// An array of active spans + /// + /// For example, spans which have been started but have not yet finished (by calling `Span/end()`). public var activeSpans: [InMemorySpan] { _state.withValue { Array($0.activeSpans.values) } } - /// Retrives a specific _active_ span, identified by the specific span, trace, and parent ID's + /// Retrives a specific _active_ span, identified by the service context you provide. + /// + /// The service context provides the span, trace, and parent IDs /// stored in the `inMemorySpanContext` public func activeSpan(identifiedBy context: ServiceContext) -> InMemorySpan? { guard let spanContext = context.inMemorySpanContext else { return nil } return _state.withValue { $0.activeSpans[spanContext] } } - /// Count of the number of times ``Tracer/forceFlush()`` was called on this tracer. + /// The number of times forced flushes were requested. + /// + /// The number of times that `Tracer/forceFlush()` was called on this tracer. public var numberOfForceFlushes: Int { _state.withValue { $0.numberOfForceFlushes } } - /// Gets, without removing, all the finished spans recorded by this tracer. + /// Retrieves, without removing, all the finished spans recorded by this tracer. /// /// - SeeAlso: `popFinishedSpans()` public var finishedSpans: [FinishedInMemorySpan] { @@ -151,7 +168,7 @@ extension InMemoryTracer { } } - /// Atomically clears any stored finished spans in this tracer. + /// Atomically clears the in-memory collection of finished spans in this tracer. public func clearFinishedSpans() { _state.withValue { $0.finishedSpans = [] } } @@ -172,10 +189,17 @@ extension InMemoryTracer { // MARK: - Instrument extension InMemoryTracer { - + + /// The trace ID key for the in-memory tracer. public static let traceIDKey = "in-memory-trace-id" + /// The span ID key for the in-memory tracer. public static let spanIDKey = "in-memory-span-id" - + + /// Collects the service context you provide and inserts it into tracing carrier. + /// - Parameters: + /// - context: The service context to add. + /// - carrier: The service implementation into which to add the service context. + /// - injector: The type that transfers service context into a carrier. public func inject( _ context: ServiceContext, into carrier: inout Carrier, @@ -196,28 +220,37 @@ extension InMemoryTracer { } } - /// Lists all recorded calls to this tracer's ``Instrument/inject(_:into:using:)`` method. + /// Lists all recorded calls to this tracer's inject method. + /// + /// Records calls to`Instrument/inject(_:into:using:)`. /// This may be used to inspect what span identifiers are being propagated by this tracer. public var performedContextInjections: [Injection] { _state.withValue { $0.injections } } - /// Clear the list of recorded context injections (calls to ``Instrument/inject(_:into:using:)``). + /// Clear the list of recorded context injections. + /// + /// Clears the list of calls to `Instrument/inject(_:into:using:)`. public func clearPerformedContextInjections() { _state.withValue { $0.injections = [] } } - /// Represents a recorded call to the InMemoryTracer's ``Instrument/inject(_:into:using:)`` method. + /// A type that represents a recorded call to the In-memory tracer's inject method. public struct Injection: Sendable { /// The context from which values were being injected. public let context: ServiceContext - /// The injected values, these will be specifically the trace and span identifiers of the propagated span. + /// The injected values; the trace and span identifiers of the propagated span. public let values: [String: String] } } extension InMemoryTracer { - + + /// Retrieves and returns the service context from the tracing carrier. + /// - Parameters: + /// - carrier: The service implementation from which to extract the service context. + /// - context:The service context to update. + /// - extractor: The type that transfers service context from a carrier. public func extract( _ carrier: Carrier, into context: inout ServiceContext, @@ -239,18 +272,19 @@ extension InMemoryTracer { context.inMemorySpanContext = InMemorySpanContext(traceID: traceID, spanID: spanID, parentSpanID: nil) } - /// Lists all recorded calls to this tracer's ``Instrument/extract(_:into:using:)`` method. - /// This may be used to inspect what span identifiers were extracted from an incoming carrier object into ``ServiceContext``. + /// Lists all recorded calls to this tracer's extract method. + /// + /// Lists calls to `Instrument/extract(_:into:using:)`. + /// This may be used to inspect the span identifiers extracted from an incoming carrier object into `ServiceContext`. public var performedContextExtractions: [Extraction] { _state.withValue { $0.extractions } } - /// Represents a recorded call to the InMemoryTracer's ``Instrument/extract(_:into:using:)`` method. + /// Represents a recorded call to the In-memory tracer's extract method. public struct Extraction: Sendable { - /// The carrier object from which the context values were extracted from, - /// e.g. this frequently is an HTTP request or similar. + /// The carrier object from which the context values were extracted from, such as an HTTP request. public let carrier: any Sendable - /// The constructed service context, containing the extracted ``ServiceContext/inMemorySpanContext``. + /// The constructed service context, containing the extracted in-memory span context. public let context: ServiceContext } } @@ -259,13 +293,21 @@ extension InMemoryTracer { extension InMemoryTracer { - /// Can be used to customize how trace and span IDs are generated by the ``InMemoryTracer``. + /// A type that generates trace and span IDs for the in-memory tracer. + /// You can customize how trace and span IDs are generated for the ``InMemoryTracer``. /// - /// Defaults to a simple sequential numeric scheme (`span-1`, `span-2`, `trace-1`, `trace-2` etc). + /// The defaul implementation, ``incrementing``, provides a simple sequential numeric scheme, + /// for example `span-1`, `span-2`, `trace-1`, `trace-2`, and so on. public struct IDGenerator: Sendable { + /// A closure that creates a trace ID. public let nextTraceID: @Sendable () -> String + /// A closure that creates a span ID. public let nextSpanID: @Sendable () -> String - + + /// Creates a new instance of an ID generator using the closures you provide. + /// - Parameters: + /// - nextTraceID: The closure to create the next trace ID. + /// - nextSpanID: The closure to create the next span ID. public init( nextTraceID: @Sendable @escaping () -> String, nextSpanID: @Sendable @escaping () -> String @@ -273,7 +315,8 @@ extension InMemoryTracer { self.nextTraceID = nextTraceID self.nextSpanID = nextSpanID } - + + /// An ID generator that provides incrementing IDs using a simple sequential numeric scheme. public static var incrementing: IDGenerator { let traceID = LockedValueBox(0) let spanID = LockedValueBox(0) diff --git a/Sources/Instrumentation/Documentation.docc/Documentation.md b/Sources/Instrumentation/Documentation.docc/Documentation.md new file mode 100644 index 00000000..05af4c9a --- /dev/null +++ b/Sources/Instrumentation/Documentation.docc/Documentation.md @@ -0,0 +1,14 @@ +# ``Instrumentation`` + +Common types to support tracers propogating spans and context across API boundaries. + +## Topics + +### Instruments + +- ``InstrumentationSystem`` +- ``MultiplexInstrument`` +- ``NoOpInstrument`` +- ``Instrument`` +- ``Extractor`` +- ``Injector`` diff --git a/Sources/Tracing/Docs.docc/index.md b/Sources/Tracing/Docs.docc/index.md index eeddc95c..e621ef44 100644 --- a/Sources/Tracing/Docs.docc/index.md +++ b/Sources/Tracing/Docs.docc/index.md @@ -29,11 +29,7 @@ as the subsequent guides dive deeper into patterns and details of instrumenting ### Boostrapping Tracing -- ``InstrumentationSystem`` -- ``MultiplexInstrument`` -- ``Extractor`` -- ``Injector`` -- ``Instrument`` +- ``Instrumentation`` - ``TracerInstant`` - ``LegacyTracer`` @@ -69,16 +65,8 @@ as the subsequent guides dive deeper into patterns and details of instrumenting - ``SpanLink`` - ``SpanStatus`` - ``SpanKind`` -- ``TODOLocation`` - -### Service Context - -- ``ServiceContext`` -- ``ServiceContextKey`` -- ``AnyServiceContextKey`` ### Default Tracers - ``DefaultTracerClock`` -- ``NoOpInstrument`` - ``NoOpTracer`` From 07a1420b5e964d640d3d9592e291c9f9d8d7662b Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Wed, 24 Sep 2025 16:01:50 -0700 Subject: [PATCH 03/27] updates to Instrumentation module symbols --- Sources/Instrumentation/Instrument.swift | 28 ++++++++++++------- .../InstrumentationSystem.swift | 19 +++++++++---- Sources/Instrumentation/Locks.swift | 10 +++---- .../Instrumentation/MultiplexInstrument.swift | 22 +++++++++++---- Sources/Instrumentation/NoOpInstrument.swift | 2 +- 5 files changed, 54 insertions(+), 27 deletions(-) diff --git a/Sources/Instrumentation/Instrument.swift b/Sources/Instrumentation/Instrument.swift index 156b311b..fdc6eb7a 100644 --- a/Sources/Instrumentation/Instrument.swift +++ b/Sources/Instrumentation/Instrument.swift @@ -14,7 +14,10 @@ import ServiceContextModule -/// Conforming types are used to extract values from a specific `Carrier`. +/// A type that allows tracing to extract values from an associated carrier. +/// +/// The assocaited type, `Carrier`, is a service request such as an HTTP request, +/// that has string values that can be extracted to provide information for a tracing span. public protocol Extractor: Sendable { /// The carrier to extract values from. associatedtype Carrier: Sendable @@ -22,12 +25,14 @@ public protocol Extractor: Sendable { /// Extract the value for the given key from the `Carrier`. /// /// - Parameters: - /// - key: The key to be extracted. + /// - key: The key to extract. /// - carrier: The `Carrier` to extract from. func extract(key: String, from carrier: Carrier) -> String? } -/// Conforming types are used to inject values into a specific `Carrier`. +/// A type that allows you to inject values to an associated carrier. +/// +/// The associated type, `Carrier`, is often a client or outgoing request into which values are inserted for tracing spans. public protocol Injector: Sendable { /// The carrier to inject values into. associatedtype Carrier: Sendable @@ -41,10 +46,13 @@ public protocol Injector: Sendable { func inject(_ value: String, forKey key: String, into carrier: inout Carrier) } -/// 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. +/// A type that represents a cross-cutting tool, such as a tracer, that provides the a means to extract and inject service contexts into an associated carrier. +/// +/// The types are agnostic of the specific `Carrier` used to propagate metadata across API boundaries. +/// Instead they specify the values to use for which keys. public protocol Instrument: Sendable { - /// Extract values from a `Carrier` by using the given extractor and inject them into the given `ServiceContext`. + /// Extract values from a carrier, using the given extractor, and inject them into the provided service context. + /// /// It's quite common for `Instrument`s to come up with new values if they weren't passed along in the given `Carrier`. /// /// - Parameters: @@ -54,12 +62,12 @@ public protocol Instrument: Sendable { func extract(_ carrier: Carrier, into context: inout ServiceContext, using extractor: Extract) where Extract: Extractor, Extract.Carrier == Carrier - /// Extract values from a `ServiceContext` and inject them into the given `Carrier` using the given ``Injector``. + /// Extract values from a service context and inject them into the given carrier using the provided injector. /// /// - Parameters: - /// - context: The `ServiceContext` from which relevant information will be extracted. - /// - carrier: The `Carrier` into which this information will be injected. - /// - injector: The ``Injector`` used to inject extracted `ServiceContext` into the given `Carrier`. + /// - context: The `ServiceContext` from which relevant information is extracted. + /// - carrier: The `Carrier` into which this information is injected. + /// - injector: The ``Injector`` to use to inject extracted `ServiceContext` into the given `Carrier`. func inject(_ context: ServiceContext, into carrier: inout Carrier, using injector: Inject) where Inject: Injector, Inject.Carrier == Carrier } diff --git a/Sources/Instrumentation/InstrumentationSystem.swift b/Sources/Instrumentation/InstrumentationSystem.swift index d0ebee0d..926b9c39 100644 --- a/Sources/Instrumentation/InstrumentationSystem.swift +++ b/Sources/Instrumentation/InstrumentationSystem.swift @@ -14,14 +14,20 @@ import ServiceContextModule -/// `InstrumentationSystem` is a global facility where the default cross-cutting tool can be configured. +/// 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 ``Instrument`` implementation. /// -/// # Bootstrap multiple Instruments +/// ### Bootstrap multiple Instruments /// If you need to use more that one cross-cutting tool you can do so by using ``MultiplexInstrument``. /// -/// # Access the Instrument -/// ``instrument``: Returns whatever you passed to ``bootstrap(_:)`` as an ``Instrument``. +/// ## Topics +/// +/// ### Configuring the Instrument +/// - ``bootstrap(_:)`` +/// +/// ### Accessing the Instrument +/// - ``instrument``: Returns whatyou pass to ``bootstrap(_:)`` as an ``Instrument``. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext public enum InstrumentationSystem { /// Marked as @unchecked Sendable due to the synchronization being @@ -73,7 +79,8 @@ public enum InstrumentationSystem { /// Globally select the desired ``Instrument`` implementation. /// /// - 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. + /// + /// > Warning: Do not call this method more than once. This will lead to a crash. public static func bootstrap(_ instrument: Instrument) { self.shared.bootstrap(instrument) } @@ -85,7 +92,7 @@ public enum InstrumentationSystem { self.shared.bootstrapInternal(instrument) } - /// Returns the globally configured ``Instrument``. + /// Returns the globally configured instrument. /// /// Defaults to a no-op ``Instrument`` if ``bootstrap(_:)`` wasn't called before. public static var instrument: Instrument { diff --git a/Sources/Instrumentation/Locks.swift b/Sources/Instrumentation/Locks.swift index b04ea62d..6e51ce4e 100644 --- a/Sources/Instrumentation/Locks.swift +++ b/Sources/Instrumentation/Locks.swift @@ -93,10 +93,10 @@ public final class ReadWriteLock { } extension ReadWriteLock { - /// Acquire the reader lock for the duration of the given block. + /// Acquire a reader lock for the duration of the given block. /// /// This convenience method should be preferred to `lock` and `unlock` in - /// most situations, as it ensures that the lock will be released regardless + /// most situations, as it ensures that the lock is released regardless /// of how `body` exits. /// /// - Parameter body: The block to execute while holding the lock. @@ -110,10 +110,10 @@ extension ReadWriteLock { return try body() } - /// Acquire the writer lock for the duration of the given block. + /// Acquire a writer lock for the duration of the given block. /// /// This convenience method should be preferred to `lock` and `unlock` in - /// most situations, as it ensures that the lock will be released regardless + /// most situations, as it ensures that the lock is released regardless /// of how `body` exits. /// /// - Parameter body: The block to execute while holding the lock. @@ -128,7 +128,7 @@ extension ReadWriteLock { } } -/// A wrapper providing locked access to a value. +/// A wrapper that provides locked access to a value. /// /// Marked as @unchecked Sendable due to the synchronization being /// performed manually using locks. diff --git a/Sources/Instrumentation/MultiplexInstrument.swift b/Sources/Instrumentation/MultiplexInstrument.swift index b35bc821..64d3052e 100644 --- a/Sources/Instrumentation/MultiplexInstrument.swift +++ b/Sources/Instrumentation/MultiplexInstrument.swift @@ -14,14 +14,15 @@ import ServiceContextModule -/// A pseudo-``Instrument`` that may be used to instrument using multiple other ``Instrument``s across a -/// common `ServiceContext`. +/// A pseudo instrument to use to instrument using multiple instrumentss across a +/// common service context. public struct MultiplexInstrument { private var instruments: [Instrument] - /// Create a ``MultiplexInstrument``. - /// - /// - Parameter instruments: An array of ``Instrument``s, each of which will be used to ``Instrument/inject(_:into:using:)`` or ``Instrument/extract(_:into:using:)`` + /// Create a multiplex instrument. + /// + /// - Parameter instruments: An array of ``Instrument``, each of which the tracer uses to + /// ``Instrument/inject(_:into:using:)`` or ``Instrument/extract(_:into:using:)`` /// through the same `ServiceContext`. public init(_ instruments: [Instrument]) { self.instruments = instruments @@ -35,11 +36,22 @@ extension MultiplexInstrument { } extension MultiplexInstrument: Instrument { + /// Extract values from a service context and inject them into the given carrier using the provided injector. + /// + /// - Parameters: + /// - context: The `ServiceContext` from which relevant information is extracted. + /// - carrier: The `Carrier` into which this information is injected. + /// - injector: The ``Injector`` to use to inject extracted `ServiceContext` into the given `Carrier`. public func inject(_ context: ServiceContext, into carrier: inout Carrier, using injector: Inject) where Inject: Injector, Carrier == Inject.Carrier { for instrument in self.instruments { instrument.inject(context, into: &carrier, using: injector) } } + /// Extract values from a carrier, using the given extractor, and inject them into the provided service context. + /// - Parameters: + /// - carrier: The `Carrier` that was used to propagate values across boundaries. + /// - context: The `ServiceContext` into which these values should be injected. + /// - extractor: The ``Extractor`` that extracts values from the given `Carrier`. public func extract( _ carrier: Carrier, into context: inout ServiceContext, diff --git a/Sources/Instrumentation/NoOpInstrument.swift b/Sources/Instrumentation/NoOpInstrument.swift index bcf36445..9b8c6aef 100644 --- a/Sources/Instrumentation/NoOpInstrument.swift +++ b/Sources/Instrumentation/NoOpInstrument.swift @@ -14,7 +14,7 @@ import ServiceContextModule -/// A "no op" implementation of an ``Instrument``. +/// A "no op" implementation of an Instrument. public struct NoOpInstrument: Instrument { public init() {} From 0e20f2faafb79eba21634dc40e6fc0a74dffec9b Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Wed, 24 Sep 2025 16:02:30 -0700 Subject: [PATCH 04/27] format cleanup --- Sources/InMemoryTracing/InMemorySpan.swift | 34 +++++++++---------- .../InMemoryTracing/InMemorySpanContext.swift | 4 +-- Sources/InMemoryTracing/InMemoryTracer.swift | 16 ++++----- .../Instrumentation/MultiplexInstrument.swift | 2 +- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Sources/InMemoryTracing/InMemorySpan.swift b/Sources/InMemoryTracing/InMemorySpan.swift index ac72ec4e..fe918e9d 100644 --- a/Sources/InMemoryTracing/InMemorySpan.swift +++ b/Sources/InMemoryTracing/InMemorySpan.swift @@ -19,7 +19,7 @@ import Tracing /// /// See ``InMemoryTracer`` public struct InMemorySpan: Span { - + /// The service context of the span. public let context: ServiceContext /// The in-memory span context. @@ -41,7 +41,7 @@ public struct InMemorySpan: Span { public var parentSpanID: String? { spanContext.parentSpanID } - + /// The kind of span public let kind: SpanKind /// The time instant the span started. @@ -55,7 +55,7 @@ public struct InMemorySpan: Span { private let _status = LockedValueBox(nil) private let _isRecording = LockedValueBox(true) private let onEnd: @Sendable (FinishedInMemorySpan) -> Void - + /// Creates a new in-memory span /// - Parameters: /// - operationName: The operation name this span represents. @@ -88,7 +88,7 @@ public struct InMemorySpan: Span { public var isRecording: Bool { _isRecording.withValue { $0 } } - + /// The operation name the span represents. public var operationName: String { get { @@ -99,7 +99,7 @@ public struct InMemorySpan: Span { _operationName.withValue { $0 = newValue } } } - + /// The span attributes. public var attributes: SpanAttributes { get { @@ -110,36 +110,36 @@ public struct InMemorySpan: Span { _attributes.withValue { $0 = newValue } } } - + /// The events associated with the span. public var events: [SpanEvent] { _events.withValue { $0 } } - + /// Adds an event you provide to the span. /// - Parameter event: The event to record. public func addEvent(_ event: SpanEvent) { guard isRecording else { return } _events.withValue { $0.append(event) } } - + /// The span links. public var links: [SpanLink] { _links.withValue { $0 } } - + /// Adds a link to the span. /// - Parameter link: The link to add. public func addLink(_ link: SpanLink) { guard isRecording else { return } _links.withValue { $0.append(link) } } - + /// The errors recorded by the span. public var errors: [RecordedError] { _errors.withValue { $0 } } - + /// Records an error to the span. /// - Parameters: /// - error: The error to record. @@ -155,19 +155,19 @@ public struct InMemorySpan: Span { $0.append(RecordedError(error: error, attributes: attributes, instant: instant())) } } - + /// The status of the span. public var status: SpanStatus? { _status.withValue { $0 } } - + /// Updates the status of the span to the value you provide. /// - Parameter status: The status to set. public func setStatus(_ status: SpanStatus) { guard isRecording else { return } _status.withValue { $0 = status } } - + /// Finishes the span. /// - Parameter instant: the time instant the span completed. public func end(at instant: @autoclosure () -> some TracerInstant) { @@ -192,7 +192,7 @@ public struct InMemorySpan: Span { ) onEnd(finishedSpan) } - + /// An error recorded to a span. public struct RecordedError: Sendable { /// The recorded error. @@ -208,7 +208,7 @@ public struct InMemorySpan: Span { public struct FinishedInMemorySpan: Sendable { /// The name of the operation the span represents. public var operationName: String - + /// The service context of the finished span. public var context: ServiceContext /// The in-memory span context. @@ -250,7 +250,7 @@ public struct FinishedInMemorySpan: Sendable { spanContext.parentSpanID = newValue } } - + /// The kind of span. public var kind: SpanKind /// The time instant the span started. diff --git a/Sources/InMemoryTracing/InMemorySpanContext.swift b/Sources/InMemoryTracing/InMemorySpanContext.swift index 85a56e20..46770a0c 100644 --- a/Sources/InMemoryTracing/InMemorySpanContext.swift +++ b/Sources/InMemoryTracing/InMemorySpanContext.swift @@ -15,7 +15,7 @@ import ServiceContextModule /// A type that encapsulates the trace ID, span ID, and parent span ID of an in-memory span. -/// +/// /// Generally used through the `ServiceContext/inMemorySpanContext` task local value. public struct InMemorySpanContext: Sendable, Hashable { /// The idenfifier of top-level trace of which this span is a part of. @@ -26,7 +26,7 @@ public struct InMemorySpanContext: Sendable, Hashable { /// The Identifier of the parent of this span, if any. public var parentSpanID: String? - + /// Creates a new in-memory span context. /// - Parameters: /// - traceID: The trace ID for the context. diff --git a/Sources/InMemoryTracing/InMemoryTracer.swift b/Sources/InMemoryTracing/InMemoryTracer.swift index d40a026f..23af8f45 100644 --- a/Sources/InMemoryTracing/InMemoryTracer.swift +++ b/Sources/InMemoryTracing/InMemoryTracer.swift @@ -43,7 +43,7 @@ public struct InMemoryTracer: Tracer { var _state = LockedValueBox(.init()) /// Create a new ``InMemoryTracer``. - /// + /// /// - Parameters: /// - idGenerator: strategy for generating trace and span identifiers /// - recordInjections: A Boolean value that indicates whether the tracer records injected values. @@ -62,7 +62,7 @@ public struct InMemoryTracer: Tracer { // MARK: - Tracer extension InMemoryTracer { - + /// Start a new span and automatically ends the span when the operation completes, including recording the error in case the operation throws. /// - Parameters: /// - operationName: The name of the operation being traced. @@ -119,7 +119,7 @@ extension InMemoryTracer { _state.withValue { $0.activeSpans[spanContext] = span } return span } - + /// Records a request to flush spans. public func forceFlush() { _state.withValue { $0.numberOfForceFlushes += 1 } @@ -189,12 +189,12 @@ extension InMemoryTracer { // MARK: - Instrument extension InMemoryTracer { - + /// The trace ID key for the in-memory tracer. public static let traceIDKey = "in-memory-trace-id" /// The span ID key for the in-memory tracer. public static let spanIDKey = "in-memory-span-id" - + /// Collects the service context you provide and inserts it into tracing carrier. /// - Parameters: /// - context: The service context to add. @@ -245,7 +245,7 @@ extension InMemoryTracer { } extension InMemoryTracer { - + /// Retrieves and returns the service context from the tracing carrier. /// - Parameters: /// - carrier: The service implementation from which to extract the service context. @@ -303,7 +303,7 @@ extension InMemoryTracer { public let nextTraceID: @Sendable () -> String /// A closure that creates a span ID. public let nextSpanID: @Sendable () -> String - + /// Creates a new instance of an ID generator using the closures you provide. /// - Parameters: /// - nextTraceID: The closure to create the next trace ID. @@ -315,7 +315,7 @@ extension InMemoryTracer { self.nextTraceID = nextTraceID self.nextSpanID = nextSpanID } - + /// An ID generator that provides incrementing IDs using a simple sequential numeric scheme. public static var incrementing: IDGenerator { let traceID = LockedValueBox(0) diff --git a/Sources/Instrumentation/MultiplexInstrument.swift b/Sources/Instrumentation/MultiplexInstrument.swift index 64d3052e..402a047d 100644 --- a/Sources/Instrumentation/MultiplexInstrument.swift +++ b/Sources/Instrumentation/MultiplexInstrument.swift @@ -20,7 +20,7 @@ public struct MultiplexInstrument { private var instruments: [Instrument] /// Create a multiplex instrument. - /// + /// /// - Parameter instruments: An array of ``Instrument``, each of which the tracer uses to /// ``Instrument/inject(_:into:using:)`` or ``Instrument/extract(_:into:using:)`` /// through the same `ServiceContext`. From 05651b80092f75bd26afc9345aa9a0fe9b48869e Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Thu, 25 Sep 2025 08:39:24 -0700 Subject: [PATCH 05/27] Update Sources/Instrumentation/Instrument.swift Co-authored-by: Konrad `ktoso` Malawski --- Sources/Instrumentation/Instrument.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Instrumentation/Instrument.swift b/Sources/Instrumentation/Instrument.swift index fdc6eb7a..264a3e7c 100644 --- a/Sources/Instrumentation/Instrument.swift +++ b/Sources/Instrumentation/Instrument.swift @@ -14,7 +14,7 @@ import ServiceContextModule -/// A type that allows tracing to extract values from an associated carrier. +/// A type that allows extracting values from an associated carrier. /// /// The assocaited type, `Carrier`, is a service request such as an HTTP request, /// that has string values that can be extracted to provide information for a tracing span. From 3b578860d1ab6a5eb5975cd44e9d1d9977c1e9bb Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Thu, 25 Sep 2025 08:39:55 -0700 Subject: [PATCH 06/27] Update Sources/Instrumentation/Documentation.docc/Documentation.md Co-authored-by: Konrad `ktoso` Malawski --- Sources/Instrumentation/Documentation.docc/Documentation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Instrumentation/Documentation.docc/Documentation.md b/Sources/Instrumentation/Documentation.docc/Documentation.md index 05af4c9a..8dca0af8 100644 --- a/Sources/Instrumentation/Documentation.docc/Documentation.md +++ b/Sources/Instrumentation/Documentation.docc/Documentation.md @@ -1,6 +1,6 @@ # ``Instrumentation`` -Common types to support tracers propogating spans and context across API boundaries. +Base set of types which can be used to instrument libraries, excluding tracing support. Instrument implementations can be used to extract or inject contextual metadata from carrier objects (such as http requests, messages, or similar), and can be used for context propagation across process boundaries, or enrichment of contextual data, such as injecting/extracting "authorized user" or similar metadata. ## Topics From e7aa6931d5a1b220a6a66e28f03755eba078b8bb Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Thu, 25 Sep 2025 08:40:26 -0700 Subject: [PATCH 07/27] Update Sources/Instrumentation/Instrument.swift Co-authored-by: Konrad `ktoso` Malawski --- Sources/Instrumentation/Instrument.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/Instrumentation/Instrument.swift b/Sources/Instrumentation/Instrument.swift index 264a3e7c..f92a8566 100644 --- a/Sources/Instrumentation/Instrument.swift +++ b/Sources/Instrumentation/Instrument.swift @@ -18,6 +18,9 @@ import ServiceContextModule /// /// The assocaited type, `Carrier`, is a service request such as an HTTP request, /// that has string values that can be extracted to provide information for a tracing span. +/// +/// Typically the library adopting instrumentation, would provide an implementation of this type, since it is aware of its carrier type. +/// Which then can be combined with instrumentation or tracing implementations, which are not aware of the concrete carrier, and only provide an ``Instrument`` (or `Tracer`) which makes use of injector/extractor to operate on carrier values. public protocol Extractor: Sendable { /// The carrier to extract values from. associatedtype Carrier: Sendable From 5ac237f8198b7bbef1836198fc8dd75e9972e7e7 Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Thu, 25 Sep 2025 08:40:37 -0700 Subject: [PATCH 08/27] Update Sources/Instrumentation/Instrument.swift Co-authored-by: Konrad `ktoso` Malawski --- Sources/Instrumentation/Instrument.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/Instrumentation/Instrument.swift b/Sources/Instrumentation/Instrument.swift index f92a8566..3535e18c 100644 --- a/Sources/Instrumentation/Instrument.swift +++ b/Sources/Instrumentation/Instrument.swift @@ -36,6 +36,9 @@ public protocol Extractor: Sendable { /// A type that allows you to inject values to an associated carrier. /// /// The associated type, `Carrier`, is often a client or outgoing request into which values are inserted for tracing spans. + +/// Typically the library adopting instrumentation, would provide an implementation of this type, since it is aware of its carrier type. +/// Which then can be combined with instrumentation or tracing implementations, which are not aware of the concrete carrier, and only provide an ``Instrument`` (or `Tracer`) which makes use of injector/extractor to operate on carrier values. public protocol Injector: Sendable { /// The carrier to inject values into. associatedtype Carrier: Sendable From c7cbfd27f673b6f5c3eb810e238e071338a9bc47 Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Thu, 25 Sep 2025 08:40:57 -0700 Subject: [PATCH 09/27] Update Sources/Instrumentation/InstrumentationSystem.swift Co-authored-by: Konrad `ktoso` Malawski --- Sources/Instrumentation/InstrumentationSystem.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Instrumentation/InstrumentationSystem.swift b/Sources/Instrumentation/InstrumentationSystem.swift index 926b9c39..4a9ba9f1 100644 --- a/Sources/Instrumentation/InstrumentationSystem.swift +++ b/Sources/Instrumentation/InstrumentationSystem.swift @@ -27,7 +27,7 @@ import ServiceContextModule /// - ``bootstrap(_:)`` /// /// ### Accessing the Instrument -/// - ``instrument``: Returns whatyou pass to ``bootstrap(_:)`` as an ``Instrument``. +/// - ``instrument``: Returns the globally bootstrapped instrument, that was passed to ``bootstrap(_:)``. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext public enum InstrumentationSystem { /// Marked as @unchecked Sendable due to the synchronization being From 8540b46c68cf32097407b6fec74139a7e3b7a2e1 Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Thu, 25 Sep 2025 08:48:28 -0700 Subject: [PATCH 10/27] Update Sources/Instrumentation/MultiplexInstrument.swift Co-authored-by: Konrad `ktoso` Malawski --- Sources/Instrumentation/MultiplexInstrument.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Instrumentation/MultiplexInstrument.swift b/Sources/Instrumentation/MultiplexInstrument.swift index 402a047d..17eb58d7 100644 --- a/Sources/Instrumentation/MultiplexInstrument.swift +++ b/Sources/Instrumentation/MultiplexInstrument.swift @@ -14,7 +14,7 @@ import ServiceContextModule -/// A pseudo instrument to use to instrument using multiple instrumentss across a +/// A pseudo instrument to use to instrument using multiple instruments across a /// common service context. public struct MultiplexInstrument { private var instruments: [Instrument] From f2715d0d4b8c68995153c765ada9f2a90c850355 Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Thu, 25 Sep 2025 08:57:55 -0700 Subject: [PATCH 11/27] reverting updates in vendored source --- Sources/Instrumentation/Locks.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/Instrumentation/Locks.swift b/Sources/Instrumentation/Locks.swift index 6e51ce4e..b04ea62d 100644 --- a/Sources/Instrumentation/Locks.swift +++ b/Sources/Instrumentation/Locks.swift @@ -93,10 +93,10 @@ public final class ReadWriteLock { } extension ReadWriteLock { - /// Acquire a reader lock for the duration of the given block. + /// Acquire the reader lock for the duration of the given block. /// /// This convenience method should be preferred to `lock` and `unlock` in - /// most situations, as it ensures that the lock is released regardless + /// most situations, as it ensures that the lock will be released regardless /// of how `body` exits. /// /// - Parameter body: The block to execute while holding the lock. @@ -110,10 +110,10 @@ extension ReadWriteLock { return try body() } - /// Acquire a writer lock for the duration of the given block. + /// Acquire the writer lock for the duration of the given block. /// /// This convenience method should be preferred to `lock` and `unlock` in - /// most situations, as it ensures that the lock is released regardless + /// most situations, as it ensures that the lock will be released regardless /// of how `body` exits. /// /// - Parameter body: The block to execute while holding the lock. @@ -128,7 +128,7 @@ extension ReadWriteLock { } } -/// A wrapper that provides locked access to a value. +/// A wrapper providing locked access to a value. /// /// Marked as @unchecked Sendable due to the synchronization being /// performed manually using locks. From 74efd5e7786490e003c31bf4529b92501994c2cc Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Thu, 25 Sep 2025 08:59:46 -0700 Subject: [PATCH 12/27] fixing verb tense mismatch --- Sources/InMemoryTracing/InMemoryTracer.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/InMemoryTracing/InMemoryTracer.swift b/Sources/InMemoryTracing/InMemoryTracer.swift index 23af8f45..6c1fb632 100644 --- a/Sources/InMemoryTracing/InMemoryTracer.swift +++ b/Sources/InMemoryTracing/InMemoryTracer.swift @@ -63,7 +63,7 @@ public struct InMemoryTracer: Tracer { extension InMemoryTracer { - /// Start a new span and automatically ends the span when the operation completes, including recording the error in case the operation throws. + /// Start a new span and automatically end it when the operation completes, including recording the error when the operation throws. /// - Parameters: /// - operationName: The name of the operation being traced. /// - context: The service context that provides information on where to start the new span. From de0b64f52b1044ecd73cb1f882ad24046f143787 Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Thu, 25 Sep 2025 09:07:40 -0700 Subject: [PATCH 13/27] fixing up redundant See Also intended link --- Sources/InMemoryTracing/InMemorySpan.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/InMemoryTracing/InMemorySpan.swift b/Sources/InMemoryTracing/InMemorySpan.swift index fe918e9d..8c166350 100644 --- a/Sources/InMemoryTracing/InMemorySpan.swift +++ b/Sources/InMemoryTracing/InMemorySpan.swift @@ -17,7 +17,7 @@ import Tracing /// A span created by the in-memory tracer that is retained in memory when the trace ends. /// -/// See ``InMemoryTracer`` +/// An `InMemorySpan` is created by a ``InMemoryTracer``. public struct InMemorySpan: Span { /// The service context of the span. From 9b4ea63b158551c413fe1f316341c14eb571609a Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Thu, 25 Sep 2025 09:33:43 -0700 Subject: [PATCH 14/27] reworking a segment that seems to be blowing up the docc compilation --- Sources/Instrumentation/InstrumentationSystem.swift | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Sources/Instrumentation/InstrumentationSystem.swift b/Sources/Instrumentation/InstrumentationSystem.swift index 4a9ba9f1..510e8635 100644 --- a/Sources/Instrumentation/InstrumentationSystem.swift +++ b/Sources/Instrumentation/InstrumentationSystem.swift @@ -18,16 +18,8 @@ import ServiceContextModule /// /// It is set up just once in a given program to select the desired ``Instrument`` implementation. /// -/// ### Bootstrap multiple Instruments +/// Set up the instrumentation using ``bootstrap(_:)``, and access the globally available instrument using ``instrument``. /// If you need to use more that one cross-cutting tool you can do so by using ``MultiplexInstrument``. -/// -/// ## Topics -/// -/// ### Configuring the Instrument -/// - ``bootstrap(_:)`` -/// -/// ### Accessing the Instrument -/// - ``instrument``: Returns the globally bootstrapped instrument, that was passed to ``bootstrap(_:)``. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext public enum InstrumentationSystem { /// Marked as @unchecked Sendable due to the synchronization being From e03cddf4904cf8ffadee77b7aeb8f9c291bb2c2e Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Thu, 25 Sep 2025 09:53:53 -0700 Subject: [PATCH 15/27] format fix --- Sources/Instrumentation/Instrument.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Instrumentation/Instrument.swift b/Sources/Instrumentation/Instrument.swift index 3535e18c..800ae2f9 100644 --- a/Sources/Instrumentation/Instrument.swift +++ b/Sources/Instrumentation/Instrument.swift @@ -19,7 +19,7 @@ import ServiceContextModule /// The assocaited type, `Carrier`, is a service request such as an HTTP request, /// that has string values that can be extracted to provide information for a tracing span. /// -/// Typically the library adopting instrumentation, would provide an implementation of this type, since it is aware of its carrier type. +/// Typically the library adopting instrumentation, would provide an implementation of this type, since it is aware of its carrier type. /// Which then can be combined with instrumentation or tracing implementations, which are not aware of the concrete carrier, and only provide an ``Instrument`` (or `Tracer`) which makes use of injector/extractor to operate on carrier values. public protocol Extractor: Sendable { /// The carrier to extract values from. @@ -37,7 +37,7 @@ public protocol Extractor: Sendable { /// /// The associated type, `Carrier`, is often a client or outgoing request into which values are inserted for tracing spans. -/// Typically the library adopting instrumentation, would provide an implementation of this type, since it is aware of its carrier type. +/// Typically the library adopting instrumentation, would provide an implementation of this type, since it is aware of its carrier type. /// Which then can be combined with instrumentation or tracing implementations, which are not aware of the concrete carrier, and only provide an ``Instrument`` (or `Tracer`) which makes use of injector/extractor to operate on carrier values. public protocol Injector: Sendable { /// The carrier to inject values into. From 4f7035bd88245cf360b5ae7526bcc20ec5fe98e1 Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Thu, 25 Sep 2025 12:53:04 -0700 Subject: [PATCH 16/27] expands curation for types within the Tracing module --- Sources/Tracing/Docs.docc/LegacyTracer.md | 7 ---- .../Reference/DefaultTracerClock-Timestamp.md | 18 +++++++++ .../Docs.docc/Reference/DefaultTracerClock.md | 14 +++++++ .../Reference/InstrumentationSystem.md | 6 +++ .../Docs.docc/Reference/LegacyTracer.md | 20 ++++++++++ .../Reference/NestedSpanAttributesProtocol.md | 8 ++++ .../Tracing/Docs.docc/Reference/NoOpTracer.md | 15 ++++++++ Sources/Tracing/Docs.docc/Reference/Span.md | 37 +++++++++++++++++++ .../Docs.docc/Reference/SpanAttribute.md | 23 ++++++++++++ .../Reference/SpanAttributeConvertible.md | 7 ++++ .../Docs.docc/Reference/SpanAttributeKey.md | 12 ++++++ .../Reference/SpanAttributeNamespace.md | 12 ++++++ .../Docs.docc/Reference/SpanAttributes.md | 29 +++++++++++++++ .../Tracing/Docs.docc/Reference/SpanEvent.md | 16 ++++++++ .../Tracing/Docs.docc/Reference/SpanKind.md | 11 ++++++ .../Tracing/Docs.docc/Reference/SpanLink.md | 12 ++++++ .../Docs.docc/Reference/SpanStatus-Code.md | 8 ++++ .../Tracing/Docs.docc/Reference/SpanStatus.md | 13 +++++++ Sources/Tracing/Docs.docc/Reference/Tracer.md | 31 ++++++++++++++++ .../Docs.docc/Reference/TracerInstant.md | 8 ++++ Sources/Tracing/Docs.docc/Tracer.md | 12 ------ Sources/Tracing/Docs.docc/index.md | 3 +- Sources/Tracing/TracingTime.swift | 1 + 23 files changed, 303 insertions(+), 20 deletions(-) delete mode 100644 Sources/Tracing/Docs.docc/LegacyTracer.md create mode 100644 Sources/Tracing/Docs.docc/Reference/DefaultTracerClock-Timestamp.md create mode 100644 Sources/Tracing/Docs.docc/Reference/DefaultTracerClock.md create mode 100644 Sources/Tracing/Docs.docc/Reference/InstrumentationSystem.md create mode 100644 Sources/Tracing/Docs.docc/Reference/LegacyTracer.md create mode 100644 Sources/Tracing/Docs.docc/Reference/NestedSpanAttributesProtocol.md create mode 100644 Sources/Tracing/Docs.docc/Reference/NoOpTracer.md create mode 100644 Sources/Tracing/Docs.docc/Reference/Span.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanAttribute.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanAttributeConvertible.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanAttributeKey.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanAttributeNamespace.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanAttributes.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanEvent.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanKind.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanLink.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanStatus-Code.md create mode 100644 Sources/Tracing/Docs.docc/Reference/SpanStatus.md create mode 100644 Sources/Tracing/Docs.docc/Reference/Tracer.md create mode 100644 Sources/Tracing/Docs.docc/Reference/TracerInstant.md delete mode 100644 Sources/Tracing/Docs.docc/Tracer.md diff --git a/Sources/Tracing/Docs.docc/LegacyTracer.md b/Sources/Tracing/Docs.docc/LegacyTracer.md deleted file mode 100644 index eb70bbb3..00000000 --- a/Sources/Tracing/Docs.docc/LegacyTracer.md +++ /dev/null @@ -1,7 +0,0 @@ -# ``Tracing/LegacyTracer`` - -## Topics - -### Future-proof Tracer API - -- ``Tracer`` diff --git a/Sources/Tracing/Docs.docc/Reference/DefaultTracerClock-Timestamp.md b/Sources/Tracing/Docs.docc/Reference/DefaultTracerClock-Timestamp.md new file mode 100644 index 00000000..34f432b2 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/DefaultTracerClock-Timestamp.md @@ -0,0 +1,18 @@ +# ``Tracing/DefaultTracerClock/Timestamp`` + +## Topics + +### Creating timestamps + +- ``init()`` +- ``init(nanosecondsSinceEpoch:)`` + +### Inspecting timestamps + +- ``nanosecondsSinceEpoch`` + +### Comparing timestamps + +- ``==(_:_:)`` +- ``<(_:_:)`` +- ``hash(into:)`` diff --git a/Sources/Tracing/Docs.docc/Reference/DefaultTracerClock.md b/Sources/Tracing/Docs.docc/Reference/DefaultTracerClock.md new file mode 100644 index 00000000..5a556907 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/DefaultTracerClock.md @@ -0,0 +1,14 @@ +# ``Tracing/DefaultTracerClock`` + +## Topics + +### Creating a default tracer clock + +- ``init()`` + +### Inspecting the clock + +- ``now-type.property`` +- ``now-property`` +- ``Instant`` +- ``Timestamp`` diff --git a/Sources/Tracing/Docs.docc/Reference/InstrumentationSystem.md b/Sources/Tracing/Docs.docc/Reference/InstrumentationSystem.md new file mode 100644 index 00000000..8c095be0 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/InstrumentationSystem.md @@ -0,0 +1,6 @@ +# ``Tracing/Instrumentation/InstrumentationSystem`` + +## Topics + +- ``tracer`` +- ``legacyTracer`` diff --git a/Sources/Tracing/Docs.docc/Reference/LegacyTracer.md b/Sources/Tracing/Docs.docc/Reference/LegacyTracer.md new file mode 100644 index 00000000..3690b467 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/LegacyTracer.md @@ -0,0 +1,20 @@ +# ``Tracing/LegacyTracer`` + +## Topics + +### Creating Spans + +- ``withAnySpan(_:context:ofKind:function:file:line:_:)-9jni8`` +- ``withAnySpan(_:at:context:ofKind:function:file:line:_:)-7fz6i`` +- ``withAnySpan(_:context:ofKind:isolation:function:file:line:_:)`` +- ``withAnySpan(_:at:context:ofKind:isolation:function:file:line:_:)`` + +- ``withAnySpan(_:context:ofKind:function:file:line:_:)-369ou`` +- ``withAnySpan(_:at:context:ofKind:function:file:line:_:)-6jzit`` + +### Manually Managing Spans + +- ``startAnySpan(_:context:ofKind:function:file:line:)`` +- ``startAnySpan(_:at:context:ofKind:function:file:line:)`` +- ``startAnySpan(_:context:ofKind:at:function:file:line:)`` +- ``forceFlush()`` diff --git a/Sources/Tracing/Docs.docc/Reference/NestedSpanAttributesProtocol.md b/Sources/Tracing/Docs.docc/Reference/NestedSpanAttributesProtocol.md new file mode 100644 index 00000000..617323d6 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/NestedSpanAttributesProtocol.md @@ -0,0 +1,8 @@ +# ``Tracing/NestedSpanAttributesProtocol`` + +## Topics + +### Created a nested set of attributes + +- ``init()`` +- ``Key`` diff --git a/Sources/Tracing/Docs.docc/Reference/NoOpTracer.md b/Sources/Tracing/Docs.docc/Reference/NoOpTracer.md new file mode 100644 index 00000000..53ca4996 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/NoOpTracer.md @@ -0,0 +1,15 @@ +# ``Tracing/NoOpTracer`` + +## Topics + +### Creating a no-op tracer + +- ``init()`` +- ``startAnySpan(_:context:ofKind:at:function:file:line:)`` +- ``Span`` + +### Tracer Methods + +- ``extract(_:into:using:)`` +- ``inject(_:into:using:)`` +- ``forceFlush()`` diff --git a/Sources/Tracing/Docs.docc/Reference/Span.md b/Sources/Tracing/Docs.docc/Reference/Span.md new file mode 100644 index 00000000..ba6c4beb --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/Span.md @@ -0,0 +1,37 @@ +# ``Tracing/Span`` + +## Topics + +### Inspecting Spans + +- ``operationName`` +- ``context`` +- ``isRecording`` +- ``attributes`` + +### Updating Spans + +- ``setStatus(_:)`` +- ``updateAttributes(_:)`` + +### Recording Events + +- ``addEvent(_:)`` + +### Recording Errors + +- ``recordError(_:)`` +- ``recordError(_:attributes:)`` +- ``recordError(_:attributes:at:)`` + +### Recording Links + +- ``addLink(_:)`` +- ``addLink(_:attributes:)`` + +### Ending Spans + +- ``end()`` +- ``end(at:)`` + + diff --git a/Sources/Tracing/Docs.docc/Reference/SpanAttribute.md b/Sources/Tracing/Docs.docc/Reference/SpanAttribute.md new file mode 100644 index 00000000..fc015897 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanAttribute.md @@ -0,0 +1,23 @@ +# ``Tracing/SpanAttribute`` + +## Topics + +### Types of attributes + +- ``string(_:)`` +- ``stringArray(_:)`` +- ``stringConvertible(_:)`` +- ``stringConvertibleArray(_:)`` +- ``bool(_:)`` +- ``boolArray(_:)`` +- ``int(_:)`` +- ``int32(_:)`` +- ``int32Array(_:)`` +- ``int64(_:)`` +- ``int64Array(_:)`` +- ``double(_:)`` +- ``doubleArray(_:)`` + +### Comparing span attributes + +- ``==(_:_:)`` diff --git a/Sources/Tracing/Docs.docc/Reference/SpanAttributeConvertible.md b/Sources/Tracing/Docs.docc/Reference/SpanAttributeConvertible.md new file mode 100644 index 00000000..a8214e1d --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanAttributeConvertible.md @@ -0,0 +1,7 @@ +# ``Tracing/SpanAttributeConvertible`` + +## Topics + +### Converting to a span attribute + +- ``toSpanAttribute()`` diff --git a/Sources/Tracing/Docs.docc/Reference/SpanAttributeKey.md b/Sources/Tracing/Docs.docc/Reference/SpanAttributeKey.md new file mode 100644 index 00000000..ef8af77f --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanAttributeKey.md @@ -0,0 +1,12 @@ +# ``Tracing/SpanAttributeKey`` + +## Topics + +### Creating span attribute keys + +- ``init(name:)`` +- ``init(stringLiteral:)`` + +### Inspecting span attribute keys + +- ``name`` diff --git a/Sources/Tracing/Docs.docc/Reference/SpanAttributeNamespace.md b/Sources/Tracing/Docs.docc/Reference/SpanAttributeNamespace.md new file mode 100644 index 00000000..a622564c --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanAttributeNamespace.md @@ -0,0 +1,12 @@ +# ``Tracing/SpanAttributeNamespace`` + +## Topics + +### Inspecting nested attributes + +- ``NestedSpanAttributes`` +- ``attributes`` +- ``subscript(dynamicMember:)-2lvpt`` +- ``subscript(dynamicMember:)-2pclq`` +- ``subscript(dynamicMember:)-b3cs`` +- ``subscript(dynamicMember:)-7xk26`` diff --git a/Sources/Tracing/Docs.docc/Reference/SpanAttributes.md b/Sources/Tracing/Docs.docc/Reference/SpanAttributes.md new file mode 100644 index 00000000..c5fc9062 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanAttributes.md @@ -0,0 +1,29 @@ +# ``Tracing/SpanAttributes`` + +## Topics + +### Creating span attributes + +- ``init(_:)`` + +### Accessing span attributes + +- ``get(_:)`` +- ``subscript(dynamicMember:)->SpanAttribute?`` +- ``subscript(_:)`` +- ``subscript(dynamicMember:)->Namespace`` + +### Updating span attributes + +- ``set(_:value:)`` +- ``merge(_:)`` + +### Inspecting span attributes + +- ``count`` +- ``isEmpty`` + +### Iterating span attributes + +- ``forEach(_:)`` + diff --git a/Sources/Tracing/Docs.docc/Reference/SpanEvent.md b/Sources/Tracing/Docs.docc/Reference/SpanEvent.md new file mode 100644 index 00000000..99fe9aeb --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanEvent.md @@ -0,0 +1,16 @@ +# ``Tracing/SpanEvent`` + +## Topics + +### Creating span events + +- ``init(stringLiteral:)`` +- ``init(name:attributes:)`` +- ``init(name:at:attributes:)`` + +### Inspecting span events + +- ``name`` +- ``attributes`` +- ``millisecondsSinceEpoch`` +- ``nanosecondsSinceEpoch`` diff --git a/Sources/Tracing/Docs.docc/Reference/SpanKind.md b/Sources/Tracing/Docs.docc/Reference/SpanKind.md new file mode 100644 index 00000000..799176a6 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanKind.md @@ -0,0 +1,11 @@ +# ``Tracing/SpanKind`` + +## Topics + +### Kind of spans + +- ``server`` +- ``internal`` +- ``client`` +- ``consumer`` +- ``producer`` diff --git a/Sources/Tracing/Docs.docc/Reference/SpanLink.md b/Sources/Tracing/Docs.docc/Reference/SpanLink.md new file mode 100644 index 00000000..f626997a --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanLink.md @@ -0,0 +1,12 @@ +# ``Tracing/SpanLink`` + +## Topics + +### Creating span links + +- ``init(context:attributes:)`` + +### Inspecting span links + +- ``context`` +- ``attributes`` diff --git a/Sources/Tracing/Docs.docc/Reference/SpanStatus-Code.md b/Sources/Tracing/Docs.docc/Reference/SpanStatus-Code.md new file mode 100644 index 00000000..39bc9322 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanStatus-Code.md @@ -0,0 +1,8 @@ +# ``Tracing/SpanStatus/Code`` + +## Topics + +### Span Status Codes + +- ``ok`` +- ``error`` diff --git a/Sources/Tracing/Docs.docc/Reference/SpanStatus.md b/Sources/Tracing/Docs.docc/Reference/SpanStatus.md new file mode 100644 index 00000000..e9e16972 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/SpanStatus.md @@ -0,0 +1,13 @@ +# ``Tracing/SpanStatus`` + +## Topics + +### Creating span status + +- ``init(code:message:)`` + +### Inspecting span status + +- ``code`` +- ``message`` +- ``Code`` diff --git a/Sources/Tracing/Docs.docc/Reference/Tracer.md b/Sources/Tracing/Docs.docc/Reference/Tracer.md new file mode 100644 index 00000000..eb6e6ab1 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/Tracer.md @@ -0,0 +1,31 @@ +# ``Tracing/Tracer`` + +## Topics + +### Creating Spans + +- ``withSpan(_:context:ofKind:function:file:line:_:)-9r5mu`` +- ``withSpan(_:context:ofKind:isolation:function:file:line:_:)`` +- ``withSpan(_:context:ofKind:at:function:file:line:_:)-7hfa8`` +- ``withSpan(_:context:ofKind:at:isolation:function:file:line:_:)`` + +- ``withAnySpan(_:at:context:ofKind:function:file:line:_:)-3tj0e`` +- ``withAnySpan(_:at:context:ofKind:isolation:function:file:line:_:)`` + +- ``Span`` + +- ``withSpan(_:context:ofKind:function:file:line:_:)-49gj4`` +- ``withSpan(_:context:ofKind:at:function:file:line:_:)-7o9y1`` +- ``withSpan(_:context:ofKind:at:function:file:line:_:)-8gw3v`` +- ``withAnySpan(_:at:context:ofKind:function:file:line:_:)-1aiz`` + +### Manual Span management + +- ``startSpan(_:context:ofKind:at:function:file:line:)-c9un`` +- ``startSpan(_:context:ofKind:at:function:file:line:)`` +- ``Span/end()`` + +### Accessing Spans + +- ``activeSpan(identifiedBy:)-4ttod`` +- ``activeSpan(identifiedBy:)-4mers`` diff --git a/Sources/Tracing/Docs.docc/Reference/TracerInstant.md b/Sources/Tracing/Docs.docc/Reference/TracerInstant.md new file mode 100644 index 00000000..b9032e59 --- /dev/null +++ b/Sources/Tracing/Docs.docc/Reference/TracerInstant.md @@ -0,0 +1,8 @@ +# ``Tracing/TracerInstant`` + +## Topics + +### Converting to UNIX time values + +- ``millisecondsSinceEpoch`` +- ``nanosecondsSinceEpoch`` diff --git a/Sources/Tracing/Docs.docc/Tracer.md b/Sources/Tracing/Docs.docc/Tracer.md deleted file mode 100644 index f2e3e597..00000000 --- a/Sources/Tracing/Docs.docc/Tracer.md +++ /dev/null @@ -1,12 +0,0 @@ -# ``Tracing/Tracer`` - -## Topics - -### Creating Spans - -- ``withSpan(_:context:ofKind:at:function:file:line:_:)-8gw3v`` - -### Manual Span management - -- ``startSpan(_:context:ofKind:at:function:file:line:)-c9un`` -- ``Span/end()`` diff --git a/Sources/Tracing/Docs.docc/index.md b/Sources/Tracing/Docs.docc/index.md index e621ef44..ada0afc6 100644 --- a/Sources/Tracing/Docs.docc/index.md +++ b/Sources/Tracing/Docs.docc/index.md @@ -29,7 +29,8 @@ as the subsequent guides dive deeper into patterns and details of instrumenting ### Boostrapping Tracing -- ``Instrumentation`` +- ``Tracing/Instrumentation/InstrumentationSystem`` +- ``Tracing/Tracer`` - ``TracerInstant`` - ``LegacyTracer`` diff --git a/Sources/Tracing/TracingTime.swift b/Sources/Tracing/TracingTime.swift index 328b5332..caa81b3e 100644 --- a/Sources/Tracing/TracingTime.swift +++ b/Sources/Tracing/TracingTime.swift @@ -33,6 +33,7 @@ import WASILibc import _CWASI #endif +/// A type that represents a point in time down to the nanosecond. public protocol TracerInstant: Comparable, Hashable, Sendable { /// Representation of this instant as the number of nanoseconds since UNIX Epoch (January 1st 1970) var nanosecondsSinceEpoch: UInt64 { get } From cf109e0128ae27b0b217cc196037e4351af69e9e Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Thu, 25 Sep 2025 15:19:02 -0700 Subject: [PATCH 17/27] adds abstracts and cleans up existing abstracts to full sentences, removes some passive voice, and apply style guidelines. --- Sources/Instrumentation/NoOpInstrument.swift | 13 +- Sources/Tracing/NoOpTracer.swift | 62 ++++- Sources/Tracing/SpanProtocol.swift | 251 ++++++++++++------- Sources/Tracing/Tracer.swift | 176 ++++++++----- Sources/Tracing/TracerProtocol+Legacy.swift | 208 ++++++++------- Sources/Tracing/TracerProtocol.swift | 132 +++++----- Sources/Tracing/TracingTime.swift | 26 +- Tests/TracingTests/TestTracer.swift | 6 + Tests/TracingTests/TracedLockTests.swift | 6 + 9 files changed, 581 insertions(+), 299 deletions(-) diff --git a/Sources/Instrumentation/NoOpInstrument.swift b/Sources/Instrumentation/NoOpInstrument.swift index 9b8c6aef..15dbe331 100644 --- a/Sources/Instrumentation/NoOpInstrument.swift +++ b/Sources/Instrumentation/NoOpInstrument.swift @@ -17,12 +17,23 @@ import ServiceContextModule /// A "no op" implementation of an Instrument. public struct NoOpInstrument: Instrument { public init() {} - + /// Extract values from a service context and inject them into the given carrier using the provided injector. + /// + /// - Parameters: + /// - context: The `ServiceContext` from which relevant information is extracted. + /// - carrier: The `Carrier` into which this information is injected. + /// - injector: The ``Injector`` to use to inject extracted `ServiceContext` into the given `Carrier`. public func inject(_ context: ServiceContext, into carrier: inout Carrier, using injector: Inject) where Inject: Injector, Carrier == Inject.Carrier { // no-op } + /// Extract values from a carrier, using the given extractor, and inject them into the provided service context. + /// + /// - Parameters: + /// - carrier: The `Carrier` that was used to propagate values across boundaries. + /// - context: The `ServiceContext` into which these values should be injected. + /// - extractor: The ``Extractor`` that extracts values from the given `Carrier`. public func extract( _ carrier: Carrier, into context: inout ServiceContext, diff --git a/Sources/Tracing/NoOpTracer.swift b/Sources/Tracing/NoOpTracer.swift index 746a48c2..3b72e1a4 100644 --- a/Sources/Tracing/NoOpTracer.swift +++ b/Sources/Tracing/NoOpTracer.swift @@ -18,10 +18,22 @@ /// Tracer that ignores all operations, used when no tracing is required. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext public struct NoOpTracer: LegacyTracer { + + /// The type used to represent a span. public typealias Span = NoOpSpan + /// Creates a no-op tracer. public init() {} + /// Start a new span using the global bootstrapped tracer reimplementation. + /// - Parameters: + /// - operationName: The name of the operation being traced. This may be a handler function, database call, ... + /// - context: The `ServiceContext` providing information on where to start the new ``Span``. + /// - kind: The ``SpanKind`` of the new ``Span``. + /// - instant: the time instant at which the span started + /// - 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. public func startAnySpan( _ operationName: String, context: @autoclosure () -> ServiceContext, @@ -34,13 +46,31 @@ public struct NoOpTracer: LegacyTracer { NoOpSpan(context: context()) } + /// Export all ended spans to the configured backend that have not yet been exported. + /// + /// This function should only be called in cases where it is absolutely necessary, + /// such as when using some FaaS providers that may suspend the process after an invocation, but before the backend exports the completed spans. + /// + /// This function should not block indefinitely, implementations should offer a configurable timeout for flush operations. public func forceFlush() {} + /// Extract values from a service context and inject them into the given carrier using the provided injector. + /// + /// - Parameters: + /// - context: The `ServiceContext` from which relevant information is extracted. + /// - carrier: The `Carrier` into which this information is injected. + /// - injector: The `Injector` to use to inject extracted `ServiceContext` into the given `Carrier`. public func inject(_ context: ServiceContext, into carrier: inout Carrier, using injector: Inject) where Inject: Injector, Carrier == Inject.Carrier { // no-op } + /// Extract values from a carrier, using the given extractor, and inject them into the provided service context. + /// + /// - Parameters: + /// - carrier: The `Carrier` that was used to propagate values across boundaries. + /// - context: The `ServiceContext` into which these values should be injected. + /// - extractor: The `Extractor` that extracts values from the given `Carrier`. public func extract( _ carrier: Carrier, into context: inout ServiceContext, @@ -50,12 +80,18 @@ public struct NoOpTracer: LegacyTracer { // no-op } + /// A span created by the no-op tracer. + /// + /// This span maintains its context, but does not record events, links, or errors and provides no attributes. public struct NoOpSpan: Tracing.Span { + /// The service context of the span. public let context: ServiceContext + /// A Boolean value that indicates whether the span is actively recording updates. public var isRecording: Bool { false } + /// The operation name this span represents. public var operationName: String { get { "noop" @@ -65,22 +101,35 @@ public struct NoOpTracer: LegacyTracer { } } + /// Creates a new no-op span with the context you provide. + /// - Parameter context: The service context. public init(context: ServiceContext) { self.context = context } - + /// Updates the status of the span to the value you provide. + /// - Parameter status: The status to set. public func setStatus(_ status: SpanStatus) {} + /// Adds a link to the span. + /// - Parameter link: The link to add. public func addLink(_ link: SpanLink) {} + /// Adds an event you provide to the span. + /// - Parameter event: The event to record. public func addEvent(_ event: SpanEvent) {} + /// Records an error to the span. + /// - Parameters: + /// - error: The error to record. + /// - attributes: Span attributes associated with the error. + /// - instant: The time instant of the error. public func recordError( _ error: Error, attributes: SpanAttributes, at instant: @autoclosure () -> Instant ) {} + /// The span attributes. public var attributes: SpanAttributes { get { [:] @@ -90,6 +139,8 @@ public struct NoOpTracer: LegacyTracer { } } + /// Finishes the span. + /// - Parameter instant: the time instant the span completed. public func end(at instant: @autoclosure () -> Instant) { // ignore } @@ -98,6 +149,15 @@ public struct NoOpTracer: LegacyTracer { @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) extension NoOpTracer: Tracer { + /// Start a new span using the global bootstrapped tracer reimplementation. + /// - Parameters: + /// - operationName: The name of the operation being traced. This may be a handler function, database call, ... + /// - context: The `ServiceContext` providing information on where to start the new ``Span``. + /// - kind: The ``SpanKind`` of the new ``Span``. + /// - instant: the time instant at which the span started + /// - 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. public func startSpan( _ operationName: String, context: @autoclosure () -> ServiceContext, diff --git a/Sources/Tracing/SpanProtocol.swift b/Sources/Tracing/SpanProtocol.swift index b61a76aa..275fa2fc 100644 --- a/Sources/Tracing/SpanProtocol.swift +++ b/Sources/Tracing/SpanProtocol.swift @@ -14,39 +14,40 @@ @_exported import ServiceContextModule -/// A `Span` represents an interval from the start of an operation to its end, along with additional metadata included +/// A span represents an interval from the start of an operation to its end, along with additional metadata included /// with it. /// /// A `Span` can be created from a `ServiceContext` or `LoggingContext` which MAY contain existing span identifiers, -/// in which case this span should be considered as "child" of the previous span. +/// in which case this span should be considered as child of the previous span. /// -/// Spans are created by invoking the `withSpan`` method which delegates to the currently configured bootstrapped -/// tracer.By default the task-local "current" `ServiceContext` is used to perform this association. +/// Spans are created by invoking the `withSpan` method that delegates to the currently configured bootstrapped +/// tracer. By default tracers use the current task-local `ServiceContext` to perform this association. /// /// ### Reference semantics +/// /// A `Span` always exhibits reference semantics. Even if a span were to be implemented using a struct (or enum), /// it must exhibit reference semantics. In other words, passing around a `Span` object and mutating it from multiple -/// places must mutate the same underlying storage, and must do so safely (i.e. take locks or use other synchronization +/// places must mutate the same underlying storage, and must do so safely (that is, take locks or use other synchronization /// mechanisms to protect the mutations). This is because conceptually a span is not a value, and refers to a specific -/// resource that must be started, accumulate all possible information from the span's duration, and ended exactly once. +/// resource that must be started, accumulate all possible information from the span's duration, and end exactly once. /// /// - SeeAlso: For more details refer to the [OpenTelemetry Specification: Span](https://github.com/open-telemetry/opentelemetry-specification/blob/v0.7.0/specification/trace/api.md#span) which this type is compatible with. public protocol Span: Sendable { - /// The read-only `ServiceContext` of this `Span`, set when starting this `Span`. + /// The read-only service context of this span, set when it starts. var context: ServiceContext { get } - /// Returns the name of the operation this span represents. + /// The name of the operation this span represents. /// - /// The name may be changed during the lifetime of a `Span`, this change - /// may or may not impact the sampling decision and actually emitting the span, - /// depending on how a backend decides to treat renames. + /// The name may be changed during the lifetime of a `Span`. This change + /// may or may not impact sampling decisions or emitting the span, + /// depending on how a tracing backend handles renames. /// - /// This can still be useful when, for example, we want to immediately start - /// span when receiving a request but make it more precise as handling of the request proceeds. - /// For example, we can start a span immediately when a request is received in a server, - /// and update it to reflect the matched route, if it did match one: + /// This can still be useful when, for example, you want to immediately start a + /// span when you receive a request and make it more precise as the handling of the request proceeds. + /// For example, you can start a span immediately when a request is received in a server, + /// then update it to reflect the matched route, if it did match one: /// - /// - 1) Start span with basic path (e.g. `operationName = request.head.uri` during `withSpan`) + /// - 1) Start span with basic path (such as `operationName = request.head.uri` during `withSpan`) /// - 2.1) "Route Not Found" -> Record error /// - 2.2) "Route Found" -> Rename to route (`/users/1` becomes `/users/:userID`) /// - 3) End span @@ -60,89 +61,87 @@ public protocol Span: Sendable { /// - Parameter status: The status of this `Span`. func setStatus(_ status: SpanStatus) - /// Add a ``SpanEvent`` to this span. + /// Adds an event to this span. /// - /// Span events are similar to log statements in logging systems, in the sense - /// that they can carry a name of some event that has happened as well as an associated timestamp. + /// Span events (``SpanEvent``) are similar to log statements in logging systems, in the sense + /// that they can carry a name of some event that has happened with an associated timestamp. /// - /// Events can be used to complement a span with "interesting" point-in-time information. - /// For example if code executing a span has been cancelled it might be useful interesting + /// Events can be used to complement a span with interesting point-in-time information. + /// For example, if code executing a span has been cancelled it might be useful /// to emit an event representing this task cancellation, which then (presumably) leads - /// to an quicker termination of the task. + /// to a quicker termination of the task. /// /// - Parameter event: The ``SpanEvent`` to add to this `Span`. func addEvent(_ event: SpanEvent) - /// Record an error of the given type described by the the given message. + /// Record an error and attributes associated with the error into the span. /// /// - Parameters: - /// - error: The error to be recorded - /// - attributes: Additional attributes describing the error - /// - instant: the time instant at which the event occurred + /// - error: The error to be recorded. + /// - attributes: Additional attributes that describe the error. + /// - instant: the time instant at which the event occurred. func recordError( _ error: Error, attributes: SpanAttributes, at instant: @autoclosure () -> Instant ) - /// The attributes describing this `Span`. + /// The attributes that describe this span. var attributes: SpanAttributes { get nonmutating set } - /// Returns true if this `Span` is recording information like events, attributes, status, etc. + /// A Boolean value that indicates whether the span is recording information such as events, attributes, status, and so on. var isRecording: Bool { get } - /// Add a ``SpanLink`` in place. + /// Add a link to the span. /// /// - Parameter link: The `SpanLink` to add to this `Span`. func addLink(_ link: SpanLink) - /// End this `Span` at the given time. + /// End the span. /// /// ### Rules about ending Spans - /// A Span must be ended only ONCE. Ending a Span multiple times or never at all is considered a programming error. + /// A Span must be ended only ONCE. Ending a Span multiple times or never at all is a programming error. /// - /// A tracer implementation MAY decide to crash the application if e.g. running in debug mode and noticing such misuse. + /// A tracer implementation MAY decide to crash the application if, for example, running in debug mode and noticing such misuse. /// - /// Implementations SHOULD prevent double-emitting by marking a span as ended internally, however it still is a + /// Implementations SHOULD prevent double-emitting by marking a span as ended internally, however it is a /// programming mistake to rely on this behavior. /// - /// Parameters: - /// - instant: the time instant at which the span ended - /// - /// - SeeAlso: `Span.end()` which automatically uses the "current" time. + /// - Parameter instant: the time instant at which the span ended + /// - SeeAlso: ``end()`` which automatically uses the current time. func end(at instant: @autoclosure () -> Instant) } extension Span { - /// Record an error of the given type, at the current time, described by the the given message + /// Record an error and attributes associated with the error into the span. /// /// - Parameters: - /// - error: The error to be recorded - /// - attributes: Additional attributes describing the error + /// - error: The error to record. + /// - attributes: Additional attributes that describe the error. public func recordError(_ error: Error, attributes: SpanAttributes) { self.recordError(error, attributes: attributes, at: DefaultTracerClock.now) } - /// End this `Span` at the current time. + /// End the span. /// /// ### Rules about ending Spans - /// A Span must be ended only ONCE. Ending a Span multiple times or never at all is considered a programming error. + /// A Span must be ended only ONCE. Ending a Span multiple times or never at all is a programming error. /// - /// A tracer implementation MAY decide to crash the application if e.g. running in debug mode and noticing such misuse. + /// A tracer implementation MAY decide to crash the application if, for example, running in debug mode and noticing such misuse. /// - /// Implementations SHOULD prevent double-emitting by marking a span as ended internally, however it still is a + /// Implementations SHOULD prevent double-emitting by marking a span as ended internally, however it is a /// programming mistake to rely on this behavior. /// - /// - SeeAlso: ``end(at:)`` which allows passing in a specific time, e.g. if the operation was ended and recorded somewhere and we need to post-factum record it. - /// Generally though prefer using the ``end()`` version of this API in user code and structure your system such that it can be called in the right place and time. + /// - SeeAlso: ``end(at:)`` which allows you to provide a specific time, for example if the operation was ended and recorded somewhere and we need to post-factum record it. + /// Prefer to use the ``end()`` version of this API in user code and structure your system such that it can be called in the right place and time. public func end() { self.end(at: DefaultTracerClock.now) } - /// Adds a ``SpanLink`` between this `Span` and the given `Span`. + /// Add a link to the span. /// /// - Parameter other: The `Span` to link to. /// - Parameter attributes: The ``SpanAttributes`` describing this link. Defaults to no attributes. @@ -152,21 +151,21 @@ extension Span { } extension Span { - /// Record a failure described by the given error. + /// Record an error into the span. /// /// - Parameters: - /// - error: The error to be recorded. + /// - error: The error to record. public func recordError(_ error: Error) { self.recordError(error, attributes: [:]) } } extension Span { - /// Update Span attributes in a block instead of individually. + /// Update the span attributes in a block instead of individually. /// - /// Updating a span attribute will involve some type of thread synchronisation + /// Updating a span attribute involves some type of thread synchronisation /// primitive to avoid multiple threads updating the attributes at the same - /// time. If you update each attributes individually this can cause slowdown. + /// time. If you update each attribute individually, this can cause slowdown. /// This function updates the attributes in one call to avoid hitting the /// thread synchronisation code multiple times. /// @@ -181,29 +180,31 @@ extension Span { // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Span Event -/// An event that occurred during a ``Span``. +/// An event that occurred during a span. public struct SpanEvent: Equatable { - /// The human-readable name of this `SpanEvent`. + /// The human-readable name of this event. public let name: String - /// One or more ``SpanAttribute``s with the same restrictions as defined for ``Span`` attributes. + /// One or more span attributes. + /// + /// The span event attributes have the same restrictions as defined for span attributes. public var attributes: SpanAttributes - /// The timestamp at which this event occurred. + /// The timestamp of the event. /// - /// It should be expressed as the number of nanoseconds since UNIX Epoch (January 1st 1970). + /// The timestamp is expressed as the number of nanoseconds since UNIX Epoch (January 1st 1970). public let nanosecondsSinceEpoch: UInt64 - /// Representation of the timestamp this event occurred as the number of milliseconds since UNIX Epoch (January 1st 1970). + /// The timestamp of the event represented as the number of milliseconds since UNIX Epoch (January 1st 1970). public var millisecondsSinceEpoch: UInt64 { self.nanosecondsSinceEpoch / 1_000_000 } - /// Create a new `SpanEvent`. + /// Create a span event. /// - Parameters: /// - name: The human-readable name of this event. - /// - attributes: attributes describing this event. Defaults to no attributes. - /// - instant: the time instant at which the event occurred + /// - attributes: Attributes that describe this event. Defaults to no attributes. + /// - instant: The time instant at which the event occurred. public init( name: String, at instant: @autoclosure () -> Instant, @@ -214,6 +215,10 @@ public struct SpanEvent: Equatable { self.nanosecondsSinceEpoch = instant().nanosecondsSinceEpoch } + /// Create a span event. + /// - Parameters: + /// - name: The human-readable name of this event. + /// - attributes: Attributes that describe this event. Defaults to no attributes. public init( name: String, attributes: SpanAttributes = [:] @@ -225,6 +230,8 @@ public struct SpanEvent: Equatable { } extension SpanEvent: ExpressibleByStringLiteral { + /// Create a span event. + /// - Parameter name: The human-readable name of this event. public init(stringLiteral name: String) { self.init(name: name) } @@ -233,31 +240,43 @@ extension SpanEvent: ExpressibleByStringLiteral { // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Span Attribute +/// A span attribute key. public struct SpanAttributeKey: Hashable, ExpressibleByStringLiteral where T: SpanAttributeConvertible { + /// The name of the span attribute key. public let name: String + /// Creates a span attribute key with the name you provide. + /// - Parameter name: The name of the span attribute key. public init(name: String) { self.name = name } + /// Creates a span attribute key using a string literal value you provide.. + /// - Parameter value: The name of the span attribute key. public init(stringLiteral value: StringLiteralType) { self.name = value } } +/// A type that provides a namespace for span attributes. @dynamicMemberLookup public protocol SpanAttributeNamespace { - /// Type that contains the nested attributes, e.g. HTTPAttributes which would contain `statusCode` and similar vars. + /// The type that contains the nested attributes for the namespace. + /// + /// For example, `HTTPAttributes` contains `statusCode` and similar keys. associatedtype NestedSpanAttributes: NestedSpanAttributesProtocol + /// The attributes of the name space. var attributes: SpanAttributes { get set } + /// Get or update a span attribute with the keypath you provide. subscript(dynamicMember dynamicMember: KeyPath>) -> T? where T: SpanAttributeConvertible { get set } + /// Returns the namespace for the keypath you provide. subscript(dynamicMember dynamicMember: KeyPath) -> Namespace where Namespace: SpanAttributeNamespace { @@ -265,6 +284,7 @@ public protocol SpanAttributeNamespace { } } +/// A type that provides nested span attributes. public protocol NestedSpanAttributesProtocol { init() @@ -276,16 +296,19 @@ public protocol NestedSpanAttributesProtocol { } extension NestedSpanAttributesProtocol { + /// Create a nested set of attributes. public static var __namespace: Self { .init() } } extension NestedSpanAttributesProtocol { + /// The type that represents span keys for the nested attributes. public typealias Key = SpanAttributeKey } extension SpanAttributeNamespace { + /// Get or update a span attribute with the keypath you provide. public subscript(dynamicMember dynamicMember: KeyPath>) -> T? where T: SpanAttributeConvertible { @@ -319,40 +342,55 @@ extension SpanAttributeNamespace { } } + /// Returns the namespace for the keypath you provide. public subscript(dynamicMember dynamicMember: KeyPath) -> Namespace where Namespace: SpanAttributeNamespace { SpanAttribute.int(0)[keyPath: dynamicMember] } } -/// The value of an attribute used to describe a ``Span`` or ``SpanEvent``. +/// The value of an attribute used to describe a span or span event. /// /// Arrays are allowed but are enforced to be homogenous. /// -/// Attributes cannot be "nested" their structure is a flat key/value representation. +/// Attributes cannot be nested, the structure is a flat key/value representation. public enum SpanAttribute: Equatable { + /// The type that represents keys for the span attributes. public typealias Key = SpanAttributeKey + /// A 32-bit integer value. case int32(Int32) + /// A 64-bit integer value. case int64(Int64) + /// An array of 32-bit integers. case int32Array([Int32]) + /// An array of 64-bit integers. case int64Array([Int64]) + /// A floating point value. case double(Double) + /// An array of floating point values. case doubleArray([Double]) + /// A Boolean value. case bool(Bool) + /// An array of Boolean values. case boolArray([Bool]) + /// A string value. case string(String) + /// An array of strings. case stringArray([String]) case __DO_NOT_SWITCH_EXHAUSTIVELY_OVER_THIS_ENUM_USE_DEFAULT_INSTEAD + /// A value that converts to a string. case stringConvertible(CustomStringConvertible & Sendable) + /// An array of values that convert to strings. case stringConvertibleArray([CustomStringConvertible & Sendable]) + /// Creates a 64-bit integer value. public static func int(_ value: Int64) -> SpanAttribute { .int64(value) } @@ -393,6 +431,11 @@ public enum SpanAttribute: Equatable { } } + /// Returns a Boolean value that indicates whether two span attributes are equivalent. + /// - Parameters: + /// - lhs: The first span attribute. + /// - rhs: The second span attribute. + /// - Returns: Return `true` if the values are equivalent; otherwise `false`. public static func == (lhs: SpanAttribute, rhs: SpanAttribute) -> Bool { switch (lhs, rhs) { case (.int32(let l), .int32(let r)): return l == r @@ -414,6 +457,7 @@ public enum SpanAttribute: Equatable { } extension SpanAttribute: SpanAttributeConvertible { + /// Returns a span attribute that represents the type. public func toSpanAttribute() -> SpanAttribute { self } @@ -421,8 +465,10 @@ extension SpanAttribute: SpanAttributeConvertible { // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Attribute Values - +// +/// A type that converts to a span attribute. public protocol SpanAttributeConvertible { + /// Returns the span attribute that represents the type. func toSpanAttribute() -> SpanAttribute } @@ -430,6 +476,7 @@ public protocol SpanAttributeConvertible { // MARK: Attribute Values: Arrays extension Array where Element == Int { + /// Returns the span attribute representation of the array of integers. public func toSpanAttribute() -> SpanAttribute { if MemoryLayout.stride == 8 { return .int64Array(self.map(Int64.init)) @@ -442,18 +489,21 @@ extension Array where Element == Int { } extension Array where Element == Int32 { + /// Returns the span attribute representation of the array of 32-bit integers. public func toSpanAttribute() -> SpanAttribute { .int32Array(self) } } extension Array where Element == Int64 { + /// Returns the span attribute representation of the array of 64-bit integers. public func toSpanAttribute() -> SpanAttribute { .int64Array(self) } } extension Array where Element == Double { + /// Returns the span attribute representation of the array of floating point numbers. public func toSpanAttribute() -> SpanAttribute { .doubleArray(self) } @@ -461,6 +511,7 @@ extension Array where Element == Double { // fallback implementation extension Array: SpanAttributeConvertible where Element: SpanAttributeConvertible { + /// Returns the span attribute representation of the array. public func toSpanAttribute() -> SpanAttribute { if let value = self as? [Int32] { return .int32Array(value) @@ -483,18 +534,21 @@ extension Array: SpanAttributeConvertible where Element: SpanAttributeConvertibl // MARK: Attribute Values: String extension String: SpanAttributeConvertible { + /// Returns the span attribute representation of the string. public func toSpanAttribute() -> SpanAttribute { .string(self) } } extension SpanAttribute: ExpressibleByStringLiteral { + /// Returns the span attribute representation of the string literal. public init(stringLiteral value: String) { self = .string(value) } } extension SpanAttribute: ExpressibleByStringInterpolation { + /// Returns the span attribute representation of the interpolated string value. public init(stringInterpolation value: SpanAttribute.StringInterpolation) { self = .string("\(value)") } @@ -504,12 +558,14 @@ extension SpanAttribute: ExpressibleByStringInterpolation { // MARK: Attribute Values: Int extension SpanAttribute: ExpressibleByIntegerLiteral { + /// Returns the span attribute representation of the integer. public init(integerLiteral value: Int) { self = .int(Int64(value)) } } extension Int: SpanAttributeConvertible { + /// Returns the span attribute representation of the integer. public func toSpanAttribute() -> SpanAttribute { if MemoryLayout.stride == 8 { return .int64(Int64(self)) @@ -522,12 +578,14 @@ extension Int: SpanAttributeConvertible { } extension Int32: SpanAttributeConvertible { + /// Returns the span attribute representation of the 32-bit integer. public func toSpanAttribute() -> SpanAttribute { .int32(self) } } extension Int64: SpanAttributeConvertible { + /// Returns the span attribute representation of the 64-bit integer. public func toSpanAttribute() -> SpanAttribute { .int64(self) } @@ -537,18 +595,21 @@ extension Int64: SpanAttributeConvertible { // MARK: Attribute Values: Float/Double extension Float: SpanAttributeConvertible { + /// Returns the span attribute representation of the floating point value. public func toSpanAttribute() -> SpanAttribute { .double(Double(self)) } } extension Double: SpanAttributeConvertible { + /// Returns the span attribute representation of the floating point value. public func toSpanAttribute() -> SpanAttribute { .double(self) } } extension SpanAttribute: ExpressibleByFloatLiteral { + /// Returns the span attribute representation of the float literal value. public init(floatLiteral value: Double) { self = .double(value) } @@ -558,12 +619,14 @@ extension SpanAttribute: ExpressibleByFloatLiteral { // MARK: Attribute Values: Bool extension Bool: SpanAttributeConvertible { + /// Returns the span attribute representation of the Boolean value. public func toSpanAttribute() -> SpanAttribute { .bool(self) } } extension SpanAttribute: ExpressibleByBooleanLiteral { + /// Returns the span attribute representation of the Boolean literal value. public init(booleanLiteral value: Bool) { self = .bool(value) } @@ -572,21 +635,21 @@ extension SpanAttribute: ExpressibleByBooleanLiteral { // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: SpanAttributes: Namespaces -/// A container of ``SpanAttribute``s. +/// A container of span attributes. @dynamicMemberLookup public struct SpanAttributes: Equatable { private var _attributes = [String: SpanAttribute]() } extension SpanAttributes { - /// Create a set of attributes by wrapping the given dictionary. + /// Create a set of attributes from the dictionary you provide. /// /// - Parameter attributes: The attributes dictionary to wrap. public init(_ attributes: [String: SpanAttribute]) { self._attributes = attributes } - /// Accesses the ``SpanAttribute`` with the given name for reading and writing. + /// Accesses the span attribute with the given name for reading and writing. /// /// Please be cautious to not abuse this APIs power to read attributes to "smuggle" values between calls. /// Only `ServiceContext` is intended to carry information in a readable fashion between functions / processes / nodes. @@ -605,32 +668,43 @@ extension SpanAttributes { } } + /// Returns the span attribue for the name you provide. + /// /// Similar to `subscript(_:)` however returns the stored `SpanAttribute` rather than going through `SpanAttributeConvertible`. + /// - Parameter name: The name of the span attribute to retrieve. public func get(_ name: String) -> SpanAttribute? { self._attributes[name] } + /// Updates the span attribute for the name you provide. + /// /// Similar to `subscript(_:)` however accepts a `SpanAttribute` rather than going through `SpanAttributeConvertible`. + /// - Parameters: + /// - name: The name of the span attribute to update. + /// - value: The span attribute value. public mutating func set(_ name: String, value: SpanAttribute?) { self._attributes[name] = value } - /// - Parameter callback: The function to call for each attribute. + /// Iterate over the collection of span attributes, invoking the closure you provide for each key/value pair. + /// - Parameter callback: The closure to call for each attribute. public func forEach(_ callback: (String, SpanAttribute) -> Void) { for (key, value) in self._attributes { callback(key, value) } } - /// Merges the given `SpanAttributes` into these `SpanAttributes` by overwriting values of duplicate keys with those of the + /// Merges the collection of span attributes you provide into the existing span attributes. + /// + /// This method overwrites the values of duplicate keys with those of the /// `other` attributes. /// - /// - Parameter other: `SpanAttributes` to merge. + /// - Parameter other: The ``SpanAttributes`` to merge. public mutating func merge(_ other: SpanAttributes) { self._attributes.merge(other._attributes, uniquingKeysWith: { _, rhs in rhs }) } - /// - Returns: Number of attributes stored. + /// The number of span attributes stored. public var count: Int { self._attributes.count } @@ -662,6 +736,8 @@ extension SpanAttributes { } extension SpanAttributes: ExpressibleByDictionaryLiteral { + /// Creates a collection of span attributes from the dictionary literal elements you provide. + /// - Parameter elements: the elements to convert into a collection of span attributes. public init(dictionaryLiteral elements: (String, SpanAttribute)...) { self._attributes = [String: SpanAttribute](uniqueKeysWithValues: elements) } @@ -670,14 +746,16 @@ extension SpanAttributes: ExpressibleByDictionaryLiteral { // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Span Status -/// Represents the status of a finished Span. +/// The status of a finished span. /// -/// It's composed of a status code in conjunction with an optional descriptive message. +/// The status is composed of a status code with an optional descriptive message. public struct SpanStatus: Equatable { + /// The status code of the span. public let code: Code + /// A descriptive message that represents the span status. public let message: String? - /// Create a new `SpanStatus`. + /// Create a span status. /// /// - Parameters: /// - code: The ``SpanStatus/Code-swift.enum`` of this `SpanStatus`. @@ -687,7 +765,7 @@ public struct SpanStatus: Equatable { self.message = message } - /// A code representing the status of a ``Span``. + /// A code that represents the status of a span. /// /// - SeeAlso: For the semantics of status codes see [OpenTelemetry Specification: setStatus](https://github.com/open-telemetry/opentelemetry-specification/blob/v0.7.0/specification/trace/api.md#set-status) public enum Code { @@ -704,35 +782,40 @@ public struct SpanStatus: Equatable { /// Describes the relationship between the ``Span``, its parents, and its children in a Trace. public enum SpanKind { /// Indicates that the span covers server-side handling of a synchronous RPC or other remote request. + /// /// This span is the child of a remote `.client` span that was expected to wait for a response. case server /// Indicates that the span describes a synchronous request to some remote service. + /// /// This span is the parent of a remote `.server` span and waits for its response. case client - /// Indicates that the span describes the parent of an asynchronous request. This parent span is expected to end before the corresponding child + /// Indicates that the span describes the parent of an asynchronous request. + /// + /// This parent span is expected to end before the corresponding child /// `.consumer` span, possibly even before the child span starts. In messaging scenarios with batching, /// tracing individual messages requires a new `.producer` span per message to be created. case producer /// Indicates that the span describes the child of an asynchronous `.producer` request. case consumer - /// Indicates that the span represents an internal operation within an application, as opposed to an operations with remote parents or children. + /// Indicates that the span represents an internal operation within an application, as opposed to an operation within remote parents or children. case `internal` } // ==== ---------------------------------------------------------------------------------------------------------------- // MARK: Span Link -/// A link to another ``Span``. -/// The other ``Span``s information is stored in `context` and `attributes` may be used to -/// further describe the link. +/// A link to another span. +/// +/// The information stored in `context` and `attributes` may be used to +/// further describe the span the link indicates. public struct SpanLink { - /// A `ServiceContext` containing identifying information about the link target ``Span``. + /// A service context that contains identifying information about the link target span. public let context: ServiceContext - /// ``SpanAttributes`` further describing the connection between the ``Span``s. + /// Span attributes that further describe the connection between the spans. public let attributes: SpanAttributes - /// Create a new `SpanLink`. + /// Creates a span link. /// /// - Parameters: /// - context: The `ServiceContext` identifying the targeted ``Span``. diff --git a/Sources/Tracing/Tracer.swift b/Sources/Tracing/Tracer.swift index 0a3242f7..b7692bba 100644 --- a/Sources/Tracing/Tracer.swift +++ b/Sources/Tracing/Tracer.swift @@ -15,7 +15,7 @@ @_exported import Instrumentation @_exported import ServiceContextModule -/// Start a new ``Span`` using the global bootstrapped tracer reimplementation. +/// Start a new span using the global bootstrapped tracer reimplementation. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -32,11 +32,11 @@ /// 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, ... -/// - instant: the time instant at which the span started -/// - context: The `ServiceContext` 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 +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - instant: The time instant at which the span started. +/// - context: The `ServiceContext` that provides information on where to start the span. +/// - kind: The kind of 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 ServiceContext @@ -62,7 +62,7 @@ public func startSpan( ) } -/// Start a new ``Span`` using the global bootstrapped tracer reimplementation. +/// Start a new span using the global bootstrapped tracer reimplementation. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -79,10 +79,10 @@ public func startSpan( /// 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, ... -/// - context: The `ServiceContext` 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 +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - context: The `ServiceContext` that provides information on where to start the span. +/// - kind: The kind of 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 ServiceContext @@ -107,7 +107,7 @@ public func startSpan( ) } -/// Start a new ``Span`` using the global bootstrapped tracer reimplementation. +/// Start a new span using the global bootstrapped tracer reimplementation. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -124,11 +124,11 @@ public func startSpan( /// 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, ... -/// - context: The `ServiceContext` providing information on where to start the new ``Span``. -/// - kind: The ``SpanKind`` of the new ``Span``. -/// - instant: the time instant at which the span started -/// - function: The function name in which the span was started +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - context: The `ServiceContext` that provides information on where to start the span. +/// - kind: The kind of span. +/// - instant: The time instant at which the span started. +/// - 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 ServiceContext @@ -156,8 +156,8 @@ public func startSpan( // ==== withSpan + sync --------------------------------------------------- -/// Start a new ``Span`` and automatically end when the `operation` completes, -/// including recording the `error` in case the operation throws. +/// Start a new span and automatically end when the operation completes, +/// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -169,16 +169,16 @@ public func startSpan( /// 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, ... -/// - instant: the time instant at which the span started -/// - context: The `ServiceContext` providing information on where to start the new ``Span``. -/// - kind: The ``SpanKind`` of the new ``Span``. +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - instant: The time instant at which the span started. +/// - context: The `ServiceContext` that provides information on where to start the span. +/// - kind: The kind of 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) +/// - operation: The operation that this span measures. +/// - Returns: the value returned by `operation`. +/// - Throws: the error the `operation` throws (if any). @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext public func withSpan( _ operationName: String, @@ -203,8 +203,8 @@ public func withSpan( } } -/// Start a new ``Span`` and automatically end when the `operation` completes, -/// including recording the `error` in case the operation throws. +/// Start a new span and automatically end when the operation completes, +/// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -216,15 +216,15 @@ public func 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, ... -/// - context: The `ServiceContext` 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 +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - context: The `ServiceContext` that provides information on where to start the span. +/// - kind: The kind of 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) +/// - operation: The operation that this span measures. +/// - Returns: the value returned by `operation`. +/// - Throws: the error the `operation` throws (if any). @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext public func withSpan( _ operationName: String, @@ -248,8 +248,8 @@ public func withSpan( } } -/// Start a new ``Span`` and automatically end when the `operation` completes, -/// including recording the `error` in case the operation throws. +/// Start a new span and automatically end when the operation completes, +/// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -261,16 +261,16 @@ public func 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, ... -/// - instant: the time instant at which the span started -/// - context: The `ServiceContext` 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 +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - context: The `ServiceContext` that provides information on where to start the span. +/// - kind: The kind of span. +/// - instant: The time instant at which the span started. +/// - 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) +/// - operation: The operation that this span measures. +/// - Returns: the value returned by `operation`. +/// - Throws: the error the `operation` throws (if any). @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) public func withSpan( _ operationName: String, @@ -297,8 +297,8 @@ public func withSpan( // ==== withSpan + async -------------------------------------------------- -/// Start a new ``Span`` and automatically end when the `operation` completes, -/// including recording the `error` in case the operation throws. +/// Start a new span and automatically end when the operation completes, +/// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -310,17 +310,17 @@ public func 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, ... -/// - instant: the time instant at which the span started +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - instant: The time instant at which the span started. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. -/// - isolation: Defaulted parameter for inheriting isolation of calling actor -/// - function: The function name in which the span was started +/// - isolation: Defaulted parameter for inheriting isolation of calling actor. +/// - 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) +/// - operation: The operation that this span measures. +/// - Returns: the value returned by `operation`. +/// - Throws: the error the `operation` throws (if any). #if compiler(>=6.0) @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext public func withSpan( @@ -351,6 +351,21 @@ public func withSpan( #if compiler(>=6.0) @_disfavoredOverload @available(*, deprecated, message: "Prefer #isolation version of this API") #endif +/// Start a new span and automatically end when the operation completes, +/// including recording the error in case the operation throws. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - instant: The time instant at which the span started. +/// - context: The `ServiceContext` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - isolation: Defaulted parameter for inheriting isolation of calling actor. +/// - 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 measures. +/// - Returns: the value returned by `operation`. +/// - Throws: the error the `operation` throws (if any). @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext public func withSpan( _ operationName: String, @@ -375,8 +390,8 @@ public func withSpan( } } -/// Start a new ``Span`` and automatically end when the `operation` completes, -/// including recording the `error` in case the operation throws. +/// Start a new span and automatically end when the operation completes, +/// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -388,16 +403,16 @@ public func 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, ... +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. -/// - ofKind: The ``SpanKind`` of the new ``Span``. -/// - isolation: Defaulted parameter for inheriting isolation of calling actor +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - isolation: Defaulted parameter for inheriting isolation of calling actor. /// - 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) +/// - operation: The operation that this span measures. +/// - Returns: the value returned by `operation`. +/// - Throws: the error the `operation` throws (if any). #if compiler(>=6.0) @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext public func withSpan( @@ -428,6 +443,19 @@ public func withSpan( @_disfavoredOverload @available(*, deprecated, message: "Prefer #isolation version of this API") #endif @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext +/// Start a new span and automatically end when the operation completes, +/// including recording the error in case the operation throws. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - context: The `ServiceContext` 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 measures. +/// - Returns: the value returned by `operation`. +/// - Throws: the error the `operation` throws (if any). public func withSpan( _ operationName: String, context: @autoclosure () -> ServiceContext = .current ?? .topLevel, @@ -450,8 +478,8 @@ public func withSpan( } } -/// Start a new ``Span`` and automatically end when the `operation` completes, -/// including recording the `error` in case the operation throws. +/// Start a new span and automatically end when the operation completes, +/// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -463,11 +491,11 @@ public func 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, ... +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. -/// - instant: the time instant at which the span started -/// - isolation: Defaulted parameter for inheriting isolation of calling actor +/// - instant: The time instant at which the span started. +/// - isolation: Defaulted parameter for inheriting isolation of calling actor. /// - 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. @@ -504,6 +532,20 @@ public func withSpan( #if compiler(>=6.0) @_disfavoredOverload @available(*, deprecated, message: "Prefer #isolation version of this API") #endif +/// Start a new span and automatically end when the operation completes, +/// including recording the error in case the operation throws. +/// +/// - Parameters: +/// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. +/// - context: The `ServiceContext` providing information on where to start the new ``Span``. +/// - kind: The ``SpanKind`` of the new ``Span``. +/// - instant: The time instant at which the span started. +/// - 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 measures. +/// - Returns: the value returned by `operation`. +/// - Throws: the error the `operation` throws (if any). @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) public func withSpan( _ operationName: String, diff --git a/Sources/Tracing/TracerProtocol+Legacy.swift b/Sources/Tracing/TracerProtocol+Legacy.swift index 94b1233d..7bf2a68d 100644 --- a/Sources/Tracing/TracerProtocol+Legacy.swift +++ b/Sources/Tracing/TracerProtocol+Legacy.swift @@ -15,7 +15,7 @@ @_exported import Instrumentation @_exported import ServiceContextModule -/// A tracer protocol intended to support Swift 5.6 specifically. +/// A tracer protocol that supports Swift 5.6. /// /// **This protocol will be deprecated as soon as possible**, and the library will continue recommending Swift 5.7+ /// in order to make use of new language features that make expressing the tracing API free of existential types when not necessary. @@ -26,7 +26,7 @@ @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext @available(*, deprecated, renamed: "Tracer") public protocol LegacyTracer: Instrument { - /// Start a new span returning an existential ``Span`` reference. + /// Start a new span returning an existential span reference. /// /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// @@ -47,14 +47,13 @@ public protocol LegacyTracer: Instrument { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - 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. - + /// - instant: the time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. @available(*, deprecated, message: "prefer withSpan") func startAnySpan( _ operationName: String, @@ -83,7 +82,7 @@ public protocol LegacyTracer: Instrument { extension LegacyTracer { // ==== startSpan --------------------------------------------------------- - /// Start a new span returning an existential ``Span`` reference. + /// Start a new span returning an existential span reference. /// /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// @@ -104,13 +103,13 @@ extension LegacyTracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - 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. + /// - instant: the time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. @available(*, deprecated, message: "prefer withSpan") public func startAnySpan( _ operationName: String, @@ -132,7 +131,7 @@ extension LegacyTracer { ) } - /// Start a new span returning an existential ``Span`` reference. + /// Start a new span returning an existential span reference. /// /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// @@ -154,12 +153,12 @@ extension LegacyTracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` 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. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. public func startAnySpan( _ operationName: String, context: @autoclosure () -> ServiceContext = .current ?? .topLevel, @@ -194,16 +193,16 @@ extension LegacyTracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - 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) + /// - instant: the time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). public func withAnySpan( _ operationName: String, at instant: @autoclosure () -> Instant, @@ -234,8 +233,8 @@ extension LegacyTracer { } } - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. + /// 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 `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// @@ -249,15 +248,15 @@ extension LegacyTracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` 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) + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). public func withAnySpan( _ operationName: String, context: @autoclosure () -> ServiceContext = .current ?? .topLevel, @@ -281,8 +280,8 @@ extension LegacyTracer { // ==== withAnySpan async ------------------------------------------------- - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. + /// 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 `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// @@ -296,16 +295,16 @@ extension LegacyTracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - isolation: Defaulted parameter for inheriting isolation of calling actor - /// - 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) + /// - isolation: Defaulted parameter for inheriting isolation of calling actor. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). #if compiler(>=6.0) public func withAnySpan( _ operationName: String, @@ -343,6 +342,21 @@ extension LegacyTracer { // swift-format-ignore: Spacing // fights with formatter @_disfavoredOverload @available(*, deprecated, message: "Prefer #isolation version of this API") #endif + /// Start a new span and automatically end when the operation completes, + /// including recording the error in case the operation throws. + /// + /// - Parameters: + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. + /// - instant: the time instant at which the span started. + /// - context: The `ServiceContext` providing information on where to start the new ``Span``. + /// - kind: The ``SpanKind`` of the new ``Span``. + /// - isolation: Defaulted parameter for inheriting isolation of calling actor. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). public func withAnySpan( _ operationName: String, at instant: @autoclosure () -> Instant, @@ -373,8 +387,8 @@ extension LegacyTracer { } } - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. + /// 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 `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// @@ -386,18 +400,17 @@ extension LegacyTracer { /// /// - 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - isolation: Defaulted parameter for inheriting isolation of calling actor - /// - 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) + /// - isolation: Defaulted parameter for inheriting isolation of calling actor. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). #if compiler(>=6.0) public func withAnySpan( _ operationName: String, @@ -434,6 +447,19 @@ extension LegacyTracer { // swift-format-ignore: Spacing // fights with formatter @_disfavoredOverload @available(*, deprecated, message: "Prefer #isolation version of this API") #endif + /// Start a new span and automatically end when the operation completes, + /// including recording the error in case the operation throws. + /// + /// - Parameters: + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. + /// - context: The `ServiceContext` providing information on where to start the new ``Span``. + /// - kind: The ``SpanKind`` of the new ``Span``. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). public func withAnySpan( _ operationName: String, context: @autoclosure () -> ServiceContext = .current ?? .topLevel, @@ -467,7 +493,7 @@ extension LegacyTracer { // Provide compatibility shims of the `...AnySpan` APIs @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) extension Tracer { - /// Start a new span returning an existential ``Span`` reference. + /// Start a new span returning an existential span reference. /// /// - Warning: This method will be deprecated in favor of `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// @@ -488,13 +514,13 @@ extension Tracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - 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. + /// - instant: the time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. public func startAnySpan( _ operationName: String, context: @autoclosure () -> ServiceContextModule.ServiceContext, @@ -515,8 +541,8 @@ extension Tracer { ) } - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. + /// 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 `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// @@ -537,16 +563,16 @@ extension Tracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - 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) + /// - instant: the time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). public func withAnySpan( _ operationName: String, at instant: @autoclosure () -> some TracerInstant = DefaultTracerClock.now, @@ -570,8 +596,8 @@ extension Tracer { } } - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. + /// 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 `Tracer/withSpan` as soon as this project is able to require Swift 5.7. /// @@ -592,17 +618,17 @@ extension Tracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - isolation: Defaulted parameter for inheriting isolation of calling actor - /// - 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) + /// - instant: the time instant at which the span started. + /// - isolation: Defaulted parameter for inheriting isolation of calling actor. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). #if compiler(>=6.0) public func withAnySpan( _ operationName: String, @@ -633,6 +659,20 @@ extension Tracer { // swift-format-ignore: Spacing // fights with formatter @_disfavoredOverload @available(*, deprecated, message: "Prefer #isolation version of this API") #endif + /// Start a new span and automatically end when the operation completes, + /// including recording the error in case the operation throws. + /// + /// - Parameters: + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. + /// - context: The `ServiceContext` providing information on where to start the new ``Span``. + /// - kind: The ``SpanKind`` of the new ``Span``. + /// - instant: the time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). public func withAnySpan( _ operationName: String, at instant: @autoclosure () -> some TracerInstant = DefaultTracerClock.now, diff --git a/Sources/Tracing/TracerProtocol.swift b/Sources/Tracing/TracerProtocol.swift index 35df5fa8..aedaa838 100644 --- a/Sources/Tracing/TracerProtocol.swift +++ b/Sources/Tracing/TracerProtocol.swift @@ -23,10 +23,10 @@ /// 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 ServiceContext public protocol Tracer: LegacyTracer { - /// The concrete type of span this tracer will be producing/ + /// The concrete type of span this tracer produces. associatedtype Span: Tracing.Span - /// Start a new ``Span`` with the given `ServiceContext`. + /// Start a new span with the given service context. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -43,13 +43,13 @@ public protocol Tracer: LegacyTracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - 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. + /// - instant: The time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. func startSpan( _ operationName: String, context: @autoclosure () -> ServiceContext, @@ -60,10 +60,10 @@ public protocol Tracer: LegacyTracer { line: UInt ) -> Self.Span - /// Retrieve the active span for the given `ServiceContext`. + /// Retrieve the active span for the given service context. /// - /// - Note: This API does not enable look up of already finished spans. - /// It was added retroactively with a default implementation returning `nil` and therefore isn't guaranteed to be implemented by all `Tracer`s. + /// - Note: This API does not enable look up of completed spans. + /// It was added retroactively with a default implementation returning `nil` and therefore isn't guaranteed to be implemented by all Tracers. /// - Parameter context: The context containing information that uniquely identifies the span being obtained. /// - Returns: The span identified by the given `ServiceContext` in case it's still recording. func activeSpan(identifiedBy context: ServiceContext) -> Span? @@ -71,7 +71,7 @@ public protocol Tracer: LegacyTracer { @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext extension Tracer { - /// Start a new ``Span`` with the given `ServiceContext`. + /// Start a new span with the given service context. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -88,13 +88,13 @@ extension Tracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - 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. + /// - instant: The time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. public func startSpan( _ operationName: String, context: @autoclosure () -> ServiceContext = .current ?? .topLevel, @@ -115,7 +115,8 @@ extension Tracer { ) } - /// Default implementation for ``activeSpan(identifiedBy:)`` which always returns `nil`. + /// Default implementation that always returns `nil`. + /// /// This default exists in order to facilitate source-compatible introduction of the ``activeSpan(identifiedBy:)`` protocol requirement. /// /// - Parameter context: The context containing information that uniquely identifies the span being obtained. @@ -130,8 +131,8 @@ extension Tracer { @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) extension Tracer { - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. + /// Start a new span and automatically end when the operation completes, + /// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -143,16 +144,16 @@ extension Tracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - 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) + /// - instant: The time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). public func withSpan( _ operationName: String, context: @autoclosure () -> ServiceContext = .current ?? .topLevel, @@ -183,8 +184,8 @@ extension Tracer { } } - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. + /// Start a new span and automatically end when the operation completes, + /// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -196,15 +197,15 @@ extension Tracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` 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) + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). public func withSpan( _ operationName: String, context: @autoclosure () -> ServiceContext = .current ?? .topLevel, @@ -234,8 +235,8 @@ extension Tracer { } } - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. + /// Start a new span and automatically end when the operation completes, + /// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -247,17 +248,17 @@ extension Tracer { /// 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - isolation: Defaulted parameter for inheriting isolation of calling actor - /// - 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) + /// - instant: the time instant at which the span started. + /// - isolation: Defaulted parameter for inheriting isolation of calling actor. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). #if compiler(>=6.0) public func withSpan( _ operationName: String, @@ -323,8 +324,8 @@ extension Tracer { } } - /// Start a new ``Span`` and automatically end when the `operation` completes, - /// including recording the `error` in case the operation throws. + /// Start a new span and automatically end when the operation completes, + /// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting @@ -334,19 +335,18 @@ extension Tracer { /// /// - 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, ... + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. /// - context: The `ServiceContext` providing information on where to start the new ``Span``. /// - kind: The ``SpanKind`` of the new ``Span``. - /// - instant: the time instant at which the span started - /// - isolation: Defaulted parameter for inheriting isolation of calling actor - /// - 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) + /// - instant: the time instant at which the span started. + /// - isolation: Defaulted parameter for inheriting isolation of calling actor. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). #if compiler(>=6.0) public func withSpan( _ operationName: String, @@ -384,6 +384,20 @@ extension Tracer { // swift-format-ignore: Spacing // fights with formatter @_disfavoredOverload @available(*, deprecated, message: "Prefer #isolation version of this API") #endif + /// Start a new span and automatically end when the operation completes, + /// including recording the error in case the operation throws. + /// + /// - Parameters: + /// - operationName: The name of the operation being traced. This may be a handler function, a database call, and so on. + /// - context: The `ServiceContext` providing information on where to start the new ``Span``. + /// - kind: The ``SpanKind`` of the new ``Span``. + /// - instant: the time instant at which the span started. + /// - function: The function name in which the span started. + /// - fileID: The `fileID` where the span started. + /// - line: The file line where the span started. + /// - operation: The operation that this span measures. + /// - Returns: the value returned by `operation`. + /// - Throws: the error the `operation` throws (if any). public func withSpan( _ operationName: String, context: @autoclosure () -> ServiceContext = .current ?? .topLevel, diff --git a/Sources/Tracing/TracingTime.swift b/Sources/Tracing/TracingTime.swift index caa81b3e..c14c165f 100644 --- a/Sources/Tracing/TracingTime.swift +++ b/Sources/Tracing/TracingTime.swift @@ -35,12 +35,12 @@ import _CWASI /// A type that represents a point in time down to the nanosecond. public protocol TracerInstant: Comparable, Hashable, Sendable { - /// Representation of this instant as the number of nanoseconds since UNIX Epoch (January 1st 1970) + /// The representation of this instant as the number of nanoseconds since UNIX Epoch (January 1st 1970). var nanosecondsSinceEpoch: UInt64 { get } } extension TracerInstant { - /// Representation of this instant as the number of milliseconds since UNIX Epoch (January 1st 1970) + /// The representation of this instant as the number of milliseconds since UNIX Epoch (January 1st 1970). @inlinable public var millisecondsSinceEpoch: UInt64 { self.nanosecondsSinceEpoch / 1_000_000 @@ -50,7 +50,7 @@ extension TracerInstant { /// A specialized clock protocol for purposes of tracing. /// /// A tracer clock must ONLY be able to offer the current time in the form of an unix timestamp. -/// It does not have to allow sleeping, nor is it interchangeable with other notions of clocks (e.g. such as monotonic time etc). +/// It does not have to allow sleeping, nor is it interchangeable with other notions of clocks (such as monotonic time). /// /// If the standard library, or foundation, or someone else were to implement an UTCClock or UNIXTimestampClock, /// they can be made to conform to `TracerClock`. @@ -59,36 +59,56 @@ extension TracerInstant { /// especially when the system is already using some notion of simulated or mocked time, such that traces are /// expressed using the same notion of time. public struct DefaultTracerClock { + /// The type that represents the a time instant. public typealias Instant = Timestamp + /// Create a default tracer clock public init() { // empty } + /// An instant point in time public struct Timestamp: TracerInstant { + /// The representation of this instant as the number of nanoseconds since UNIX Epoch (January 1st 1970). public let nanosecondsSinceEpoch: UInt64 + /// Creates a new point in time. + /// - Parameter nanosecondsSinceEpoch: the number of nanoseconds since UNIX Epoch (January 1st 1970). public init(nanosecondsSinceEpoch: UInt64) { self.nanosecondsSinceEpoch = nanosecondsSinceEpoch } + /// A Boolean value that indicates the first timestamp is less than the second. + /// - Parameters: + /// - lhs: The first time stamp. + /// - rhs: The second time stamp + /// - Returns: `true` if the first time stamp is less than the second; otherwise `false`. public static func < (lhs: Instant, rhs: Instant) -> Bool { lhs.nanosecondsSinceEpoch < rhs.nanosecondsSinceEpoch } + /// A Boolean value that indicates whether the time stamps are equivalent. + /// - Parameters: + /// - lhs: The first time stamp. + /// - rhs: The second time stamp + /// - Returns: `true` if the time stamps are equivalent; otherwise `false`. public static func == (lhs: Instant, rhs: Instant) -> Bool { lhs.nanosecondsSinceEpoch == rhs.nanosecondsSinceEpoch } + /// Hashes the essential components of this value by feeding them into the given hasher. + /// - Parameter hasher: The hasher to use when combining the components of this instance. public func hash(into hasher: inout Hasher) { self.nanosecondsSinceEpoch.hash(into: &hasher) } } + /// The current instant in time. public static var now: Self.Instant { DefaultTracerClock().now } + /// Returns the current instant in time. public var now: Self.Instant { var ts = timespec() #if os(WASI) diff --git a/Tests/TracingTests/TestTracer.swift b/Tests/TracingTests/TestTracer.swift index 5930e3ad..efa086d2 100644 --- a/Tests/TracingTests/TestTracer.swift +++ b/Tests/TracingTests/TestTracer.swift @@ -43,6 +43,12 @@ final class TestTracer: LegacyTracer { return span } + /// Export all ended spans to the configured backend that have not yet been exported. + /// + /// This function should only be called in cases where it is absolutely necessary, + /// such as when using some FaaS providers that may suspend the process after an invocation, but before the backend exports the completed spans. + /// + /// This function should not block indefinitely, implementations should offer a configurable timeout for flush operations. public func forceFlush() {} func extract(_ carrier: Carrier, into context: inout ServiceContext, using extractor: Extract) diff --git a/Tests/TracingTests/TracedLockTests.swift b/Tests/TracingTests/TracedLockTests.swift index 339735c1..a9240087 100644 --- a/Tests/TracingTests/TracedLockTests.swift +++ b/Tests/TracingTests/TracedLockTests.swift @@ -78,6 +78,12 @@ private final class TracedLockPrintlnTracer: LegacyTracer { ) } + /// Export all ended spans to the configured backend that have not yet been exported. + /// + /// This function should only be called in cases where it is absolutely necessary, + /// such as when using some FaaS providers that may suspend the process after an invocation, but before the backend exports the completed spans. + /// + /// This function should not block indefinitely, implementations should offer a configurable timeout for flush operations. public func forceFlush() {} func inject( From baed655c0b8bd312f58726d79d5aefe6ba2c1987 Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Fri, 26 Sep 2025 08:36:01 -0700 Subject: [PATCH 18/27] Update Sources/Tracing/TracerProtocol.swift Co-authored-by: Konrad `ktoso` Malawski --- Sources/Tracing/TracerProtocol.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Tracing/TracerProtocol.swift b/Sources/Tracing/TracerProtocol.swift index aedaa838..9efadd52 100644 --- a/Sources/Tracing/TracerProtocol.swift +++ b/Sources/Tracing/TracerProtocol.swift @@ -71,7 +71,7 @@ public protocol Tracer: LegacyTracer { @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal ServiceContext extension Tracer { - /// Start a new span with the given service context. + /// Start a new span with the current, or the explicitly passed, service context. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. /// It is also possible to pass a specific `context` explicitly, in which case attempting From 8e57cb84c574b6bb58efe80bc360f76c2b6624ce Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Fri, 26 Sep 2025 08:36:15 -0700 Subject: [PATCH 19/27] Update Sources/Tracing/TracerProtocol.swift Co-authored-by: Konrad `ktoso` Malawski --- Sources/Tracing/TracerProtocol.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Tracing/TracerProtocol.swift b/Sources/Tracing/TracerProtocol.swift index 9efadd52..73fa07d8 100644 --- a/Sources/Tracing/TracerProtocol.swift +++ b/Sources/Tracing/TracerProtocol.swift @@ -384,7 +384,7 @@ extension Tracer { // swift-format-ignore: Spacing // fights with formatter @_disfavoredOverload @available(*, deprecated, message: "Prefer #isolation version of this API") #endif - /// Start a new span and automatically end when the operation completes, + /// Start a new span and automatically end it when the operation completes, /// including recording the error in case the operation throws. /// /// - Parameters: From dedcfa8acbf086358d9989a75bcd7199b562028e Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Fri, 26 Sep 2025 08:36:28 -0700 Subject: [PATCH 20/27] Update Sources/Tracing/TracerProtocol.swift Co-authored-by: Konrad `ktoso` Malawski --- Sources/Tracing/TracerProtocol.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Tracing/TracerProtocol.swift b/Sources/Tracing/TracerProtocol.swift index 73fa07d8..dc08f483 100644 --- a/Sources/Tracing/TracerProtocol.swift +++ b/Sources/Tracing/TracerProtocol.swift @@ -324,7 +324,7 @@ extension Tracer { } } - /// Start a new span and automatically end when the operation completes, + /// Start a new span and automatically end it when the operation completes, /// including recording the error in case the operation throws. /// /// The current task-local `ServiceContext` is picked up and provided to the underlying tracer. From 06dc401d93e85e33c69851d7a80c452032610122 Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Fri, 26 Sep 2025 08:38:45 -0700 Subject: [PATCH 21/27] adding end() method into list of methods for manual span management --- Sources/Tracing/Docs.docc/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Tracing/Docs.docc/index.md b/Sources/Tracing/Docs.docc/index.md index ada0afc6..8bddf4ab 100644 --- a/Sources/Tracing/Docs.docc/index.md +++ b/Sources/Tracing/Docs.docc/index.md @@ -52,6 +52,7 @@ as the subsequent guides dive deeper into patterns and details of instrumenting - ``startSpan(_:context:ofKind:function:file:line:)`` - ``startSpan(_:at:context:ofKind:function:file:line:)`` - ``startSpan(_:context:ofKind:at:function:file:line:)`` +- ``Span/end()`` ### Inspecting Spans From 156f464e54592f5586884692ee0c51e7c9eb69b9 Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Fri, 26 Sep 2025 08:39:49 -0700 Subject: [PATCH 22/27] revert docs added to test types --- Tests/TracingTests/TestTracer.swift | 6 ------ Tests/TracingTests/TracedLockTests.swift | 6 ------ 2 files changed, 12 deletions(-) diff --git a/Tests/TracingTests/TestTracer.swift b/Tests/TracingTests/TestTracer.swift index efa086d2..5930e3ad 100644 --- a/Tests/TracingTests/TestTracer.swift +++ b/Tests/TracingTests/TestTracer.swift @@ -43,12 +43,6 @@ final class TestTracer: LegacyTracer { return span } - /// Export all ended spans to the configured backend that have not yet been exported. - /// - /// This function should only be called in cases where it is absolutely necessary, - /// such as when using some FaaS providers that may suspend the process after an invocation, but before the backend exports the completed spans. - /// - /// This function should not block indefinitely, implementations should offer a configurable timeout for flush operations. public func forceFlush() {} func extract(_ carrier: Carrier, into context: inout ServiceContext, using extractor: Extract) diff --git a/Tests/TracingTests/TracedLockTests.swift b/Tests/TracingTests/TracedLockTests.swift index a9240087..339735c1 100644 --- a/Tests/TracingTests/TracedLockTests.swift +++ b/Tests/TracingTests/TracedLockTests.swift @@ -78,12 +78,6 @@ private final class TracedLockPrintlnTracer: LegacyTracer { ) } - /// Export all ended spans to the configured backend that have not yet been exported. - /// - /// This function should only be called in cases where it is absolutely necessary, - /// such as when using some FaaS providers that may suspend the process after an invocation, but before the backend exports the completed spans. - /// - /// This function should not block indefinitely, implementations should offer a configurable timeout for flush operations. public func forceFlush() {} func inject( From 466a16324dada6d1393fff7932069ea11cabccc9 Mon Sep 17 00:00:00 2001 From: Joseph Heck Date: Fri, 26 Sep 2025 08:40:26 -0700 Subject: [PATCH 23/27] Apply suggestion from @ktoso Co-authored-by: Konrad `ktoso` Malawski --- Sources/Instrumentation/Instrument.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/Instrumentation/Instrument.swift b/Sources/Instrumentation/Instrument.swift index 800ae2f9..fbab99d7 100644 --- a/Sources/Instrumentation/Instrument.swift +++ b/Sources/Instrumentation/Instrument.swift @@ -56,6 +56,8 @@ public protocol Injector: Sendable { /// /// The types are agnostic of the specific `Carrier` used to propagate metadata across API boundaries. /// Instead they specify the values to use for which keys. +/// +/// Typically this type is implemented by an instrumentation, or tracing, library, while the injector/extractor types are implemented by a concrete library adopting the instrumentation library. public protocol Instrument: Sendable { /// Extract values from a carrier, using the given extractor, and inject them into the provided service context. /// From 582fff5ea77d7e09e81a7cca87f6ae377bc21a6d Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Fri, 26 Sep 2025 08:42:52 -0700 Subject: [PATCH 24/27] cleaned up the sentences around carriers, knowledge of types, and injecting and extracting values --- Sources/Instrumentation/Instrument.swift | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Sources/Instrumentation/Instrument.swift b/Sources/Instrumentation/Instrument.swift index fbab99d7..af7e27d1 100644 --- a/Sources/Instrumentation/Instrument.swift +++ b/Sources/Instrumentation/Instrument.swift @@ -19,8 +19,9 @@ import ServiceContextModule /// The assocaited type, `Carrier`, is a service request such as an HTTP request, /// that has string values that can be extracted to provide information for a tracing span. /// -/// Typically the library adopting instrumentation, would provide an implementation of this type, since it is aware of its carrier type. -/// Which then can be combined with instrumentation or tracing implementations, which are not aware of the concrete carrier, and only provide an ``Instrument`` (or `Tracer`) which makes use of injector/extractor to operate on carrier values. +/// Typically the library adopting instrumentation provides an implementation of this type, since it is aware of its carrier type. +/// That type can be combined with instrumentation or tracing implementations, which are not aware of the concrete carrier, +/// and only provide an ``Instrument`` (or `Tracer`) which makes use of injector/extractor to operate on carrier values. public protocol Extractor: Sendable { /// The carrier to extract values from. associatedtype Carrier: Sendable @@ -36,9 +37,10 @@ public protocol Extractor: Sendable { /// A type that allows you to inject values to an associated carrier. /// /// The associated type, `Carrier`, is often a client or outgoing request into which values are inserted for tracing spans. - -/// Typically the library adopting instrumentation, would provide an implementation of this type, since it is aware of its carrier type. -/// Which then can be combined with instrumentation or tracing implementations, which are not aware of the concrete carrier, and only provide an ``Instrument`` (or `Tracer`) which makes use of injector/extractor to operate on carrier values. +/// +/// Typically the library adopting instrumentation provides an implementation of this type, since it is aware of its carrier type. +/// That type can be combined with instrumentation or tracing implementations, which are not aware of the concrete carrier, +/// and only provide an ``Instrument`` (or `Tracer`) which makes use of injector/extractor to operate on carrier values. public protocol Injector: Sendable { /// The carrier to inject values into. associatedtype Carrier: Sendable From 25e0e045eb40501db78b11533352f1e4efb3bae5 Mon Sep 17 00:00:00 2001 From: Joe Heck Date: Fri, 26 Sep 2025 10:12:18 -0700 Subject: [PATCH 25/27] cleanup format --- Sources/Instrumentation/Instrument.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Instrumentation/Instrument.swift b/Sources/Instrumentation/Instrument.swift index af7e27d1..a9500e9e 100644 --- a/Sources/Instrumentation/Instrument.swift +++ b/Sources/Instrumentation/Instrument.swift @@ -37,7 +37,7 @@ public protocol Extractor: Sendable { /// A type that allows you to inject values to an associated carrier. /// /// The associated type, `Carrier`, is often a client or outgoing request into which values are inserted for tracing spans. -/// +/// /// Typically the library adopting instrumentation provides an implementation of this type, since it is aware of its carrier type. /// That type can be combined with instrumentation or tracing implementations, which are not aware of the concrete carrier, /// and only provide an ``Instrument`` (or `Tracer`) which makes use of injector/extractor to operate on carrier values. @@ -59,7 +59,7 @@ public protocol Injector: Sendable { /// The types are agnostic of the specific `Carrier` used to propagate metadata across API boundaries. /// Instead they specify the values to use for which keys. /// -/// Typically this type is implemented by an instrumentation, or tracing, library, while the injector/extractor types are implemented by a concrete library adopting the instrumentation library. +/// Typically this type is implemented by an instrumentation, or tracing, library, while the injector/extractor types are implemented by a concrete library adopting the instrumentation library. public protocol Instrument: Sendable { /// Extract values from a carrier, using the given extractor, and inject them into the provided service context. /// From ce7aaa560f4ce1706aeb06df48115bfabb440642 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 30 Sep 2025 23:06:50 +0100 Subject: [PATCH 26/27] Update Sources/Tracing/NoOpTracer.swift --- Sources/Tracing/NoOpTracer.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Tracing/NoOpTracer.swift b/Sources/Tracing/NoOpTracer.swift index 3b72e1a4..825c41ae 100644 --- a/Sources/Tracing/NoOpTracer.swift +++ b/Sources/Tracing/NoOpTracer.swift @@ -25,7 +25,7 @@ public struct NoOpTracer: LegacyTracer { /// Creates a no-op tracer. public init() {} - /// Start a new span using the global bootstrapped tracer reimplementation. + /// Start a new span using the global bootstrapped tracer implementation. /// - Parameters: /// - operationName: The name of the operation being traced. This may be a handler function, database call, ... /// - context: The `ServiceContext` providing information on where to start the new ``Span``. From ee821123ee942455c1d0aac3a65d385e5daf99a9 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Tue, 30 Sep 2025 23:07:02 +0100 Subject: [PATCH 27/27] Update Sources/Tracing/NoOpTracer.swift --- Sources/Tracing/NoOpTracer.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Tracing/NoOpTracer.swift b/Sources/Tracing/NoOpTracer.swift index 825c41ae..e270051c 100644 --- a/Sources/Tracing/NoOpTracer.swift +++ b/Sources/Tracing/NoOpTracer.swift @@ -149,7 +149,7 @@ public struct NoOpTracer: LegacyTracer { @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) extension NoOpTracer: Tracer { - /// Start a new span using the global bootstrapped tracer reimplementation. + /// Start a new span using the global bootstrapped tracer implementation. /// - Parameters: /// - operationName: The name of the operation being traced. This may be a handler function, database call, ... /// - context: The `ServiceContext` providing information on where to start the new ``Span``.