From 210abc67a1428d6a0622a2c997cfb60cd8718e3f Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Thu, 2 Feb 2023 13:40:52 +0900 Subject: [PATCH] introduce tracing time --- Sources/Tracing/NoOpTracer.swift | 5 +- Sources/Tracing/Span.swift | 13 ++-- Sources/Tracing/Tracer.swift | 3 +- Sources/Tracing/TracingTime.swift | 72 +++++++++++++++++++ .../DynamicTracepointTracerTests.swift | 10 +-- Tests/TracingTests/TestTracer.swift | 10 +-- Tests/TracingTests/TracedLockTests.swift | 10 +-- 7 files changed, 94 insertions(+), 29 deletions(-) create mode 100644 Sources/Tracing/TracingTime.swift diff --git a/Sources/Tracing/NoOpTracer.swift b/Sources/Tracing/NoOpTracer.swift index 97bfc35e..23ab5331 100644 --- a/Sources/Tracing/NoOpTracer.swift +++ b/Sources/Tracing/NoOpTracer.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import Dispatch @_exported import Instrumentation @_exported import InstrumentationBaggage @@ -24,7 +23,7 @@ public struct NoOpTracer: Tracer { _ operationName: String, baggage: Baggage, ofKind kind: SpanKind, - at time: DispatchWallTime, + at time: TracingTime, function: String, file fileID: String, line: UInt @@ -71,7 +70,7 @@ public struct NoOpTracer: Tracer { } } - public func end(at time: DispatchWallTime) { + public func end(at time: TracingTime) { // ignore } } diff --git a/Sources/Tracing/Span.swift b/Sources/Tracing/Span.swift index ad15b2c3..934fdd61 100644 --- a/Sources/Tracing/Span.swift +++ b/Sources/Tracing/Span.swift @@ -12,11 +12,6 @@ // //===----------------------------------------------------------------------===// -#if swift(>=5.6.0) -@preconcurrency import struct Dispatch.DispatchWallTime -#else -import struct Dispatch.DispatchWallTime -#endif @_exported import InstrumentationBaggage /// A `Span` represents an interval from the start of an operation to its end, along with additional metadata included @@ -67,7 +62,7 @@ public protocol Span: AnyObject, _SwiftTracingSendableSpan { /// - Parameter time: The `DispatchWallTime` at which the span ended. /// /// - SeeAlso: `Span.end()` which automatically uses the "current" time. - func end(at time: DispatchWallTime) + func end(at time: TracingTime) } extension Span { @@ -108,15 +103,15 @@ public struct SpanEvent: Equatable { /// One or more ``SpanAttribute``s with the same restrictions as defined for ``Span`` attributes. public var attributes: SpanAttributes - /// The `DispatchWallTime` at which this event occurred. - public let time: DispatchWallTime + /// The time at which this event occurred. + public let time: TracingTime /// Create a new `SpanEvent`. /// - Parameters: /// - name: The human-readable name of this event. /// - attributes: attributes describing this event. Defaults to no attributes. /// - time: The `DispatchWallTime` at which this event occurred. Defaults to `.now()`. - public init(name: String, attributes: SpanAttributes = [:], at time: DispatchWallTime = .now()) { + public init(name: String, attributes: SpanAttributes = [:], at time: TracingTime = .now()) { self.name = name self.attributes = attributes self.time = time diff --git a/Sources/Tracing/Tracer.swift b/Sources/Tracing/Tracer.swift index e0b7eb2f..31119643 100644 --- a/Sources/Tracing/Tracer.swift +++ b/Sources/Tracing/Tracer.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import Dispatch @_exported import Instrumentation @_exported import InstrumentationBaggage @@ -37,7 +36,7 @@ public protocol Tracer: Instrument { _ operationName: String, baggage: Baggage, ofKind kind: SpanKind, - at time: DispatchWallTime, + at time: TracingTime, function: String, file fileID: String, line: UInt diff --git a/Sources/Tracing/TracingTime.swift b/Sources/Tracing/TracingTime.swift new file mode 100644 index 00000000..95283854 --- /dev/null +++ b/Sources/Tracing/TracingTime.swift @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Distributed Tracing open source project +// +// Copyright (c) 2020-2022 Apple Inc. and the Swift Distributed Tracing project +// authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +#if swift(>=5.6.0) +@_implementationOnly @preconcurrency import struct Dispatch.DispatchWallTime +#else +@_implementationOnly import struct Dispatch.DispatchWallTime +#endif + +/// A wall-clock based time value used to mark the beginning and end of a trace ``Span``. +/// +/// ### Rationale for this type +/// This type is introduced in order to abstract between various time sources, such as +/// Dispatch's `DispatchWallTime` or any potential future `Clock` type in the Swift +/// standard library (or elsewhere) that we might want to use as source of time. +/// +/// Abstracting away the source of the measurement into this wrapper allows us to +/// have ``Tracer`` implementations don't care about the user API that is surfaced as `startSpan` +/// to end-users. As time goes on, this API may evolve, but we will not have to make breaking changes +/// to tracer implementations themselves. +public struct TracingTime: Sendable { + enum Repr { + case dispatchWallTime(DispatchWallTime) + } + private var repr: Repr + + private init(dispatchWallTime: DispatchWallTime) { + self.repr = .dispatchWallTime(dispatchWallTime) + } + + public static func now() -> TracingTime { + .init(dispatchWallTime: .now()) + } + + public var rawValue: UInt64 { + switch self.repr { + case .dispatchWallTime(let wallTime): + return wallTime.rawValue + } + } +} + +extension TracingTime: Equatable { + public static func ==(lhs: TracingTime, rhs: TracingTime) -> Bool { + switch (lhs.repr, rhs.repr) { + case (.dispatchWallTime(let l), .dispatchWallTime(let r)): + return l.rawValue == r.rawValue + } + } + +} + +extension TracingTime: CustomStringConvertible { + public var description: String { + switch self.repr { + case .dispatchWallTime(let wallTime): + return "TracingTime(\(wallTime.rawValue))" + } + + } +} \ No newline at end of file diff --git a/Tests/TracingTests/DynamicTracepointTracerTests.swift b/Tests/TracingTests/DynamicTracepointTracerTests.swift index 0738b8f1..b87ca9cc 100644 --- a/Tests/TracingTests/DynamicTracepointTracerTests.swift +++ b/Tests/TracingTests/DynamicTracepointTracerTests.swift @@ -145,7 +145,7 @@ final class DynamicTracepointTestTracer: Tracer { func startSpan(_ operationName: String, baggage: InstrumentationBaggage.Baggage, ofKind kind: Tracing.SpanKind, - at time: DispatchWallTime, + at time: TracingTime, function: String, file fileID: String, line: UInt) -> Tracing.Span @@ -235,8 +235,8 @@ extension DynamicTracepointTestTracer { private var status: SpanStatus? - private let startTime: DispatchWallTime - private(set) var endTime: DispatchWallTime? + private let startTime: TracingTime + private(set) var endTime: TracingTime? private(set) var baggage: Baggage private(set) var isRecording: Bool = false @@ -244,7 +244,7 @@ extension DynamicTracepointTestTracer { let onEnd: (Span) -> Void init(operationName: String, - startTime: DispatchWallTime, + startTime: TracingTime, baggage: Baggage, kind: SpanKind, file fileID: String, @@ -284,7 +284,7 @@ extension DynamicTracepointTestTracer { // nothing } - func end(at time: DispatchWallTime) { + func end(at time: TracingTime) { self.endTime = time self.onEnd(self) } diff --git a/Tests/TracingTests/TestTracer.swift b/Tests/TracingTests/TestTracer.swift index 397809f4..91b9dc58 100644 --- a/Tests/TracingTests/TestTracer.swift +++ b/Tests/TracingTests/TestTracer.swift @@ -27,7 +27,7 @@ final class TestTracer: Tracer { _ operationName: String, baggage: Baggage, ofKind kind: SpanKind, - at time: DispatchWallTime, + at time: TracingTime, function: String, file fileID: String, line: UInt @@ -101,8 +101,8 @@ final class TestSpan: Span { private var status: SpanStatus? - private let startTime: DispatchWallTime - private(set) var endTime: DispatchWallTime? + private let startTime: TracingTime + private(set) var endTime: TracingTime? let baggage: Baggage @@ -126,7 +126,7 @@ final class TestSpan: Span { init( operationName: String, - startTime: DispatchWallTime, + startTime: TracingTime, baggage: Baggage, kind: SpanKind, onEnd: @escaping (Span) -> Void @@ -153,7 +153,7 @@ final class TestSpan: Span { func recordError(_ error: Error) {} - func end(at time: DispatchWallTime) { + func end(at time: TracingTime) { self.endTime = time self.onEnd(self) } diff --git a/Tests/TracingTests/TracedLockTests.swift b/Tests/TracingTests/TracedLockTests.swift index e7caee5a..8eff1efb 100644 --- a/Tests/TracingTests/TracedLockTests.swift +++ b/Tests/TracingTests/TracedLockTests.swift @@ -64,7 +64,7 @@ private final class TracedLockPrintlnTracer: Tracer { _ operationName: String, baggage: Baggage, ofKind kind: SpanKind, - at time: DispatchWallTime, + at time: TracingTime, function: String, file fileID: String, line: UInt @@ -103,8 +103,8 @@ private final class TracedLockPrintlnTracer: Tracer { private var status: SpanStatus? - private let startTime: DispatchWallTime - private(set) var endTime: DispatchWallTime? + private let startTime: TracingTime + private(set) var endTime: TracingTime? let baggage: Baggage @@ -126,7 +126,7 @@ private final class TracedLockPrintlnTracer: Tracer { init( operationName: String, - startTime: DispatchWallTime, + startTime: TracingTime, kind: SpanKind, baggage: Baggage ) { @@ -153,7 +153,7 @@ private final class TracedLockPrintlnTracer: Tracer { func recordError(_ error: Error) {} - func end(at time: DispatchWallTime) { + func end(at time: TracingTime) { self.endTime = time print(" span [\(self.operationName): \(self.baggage[TaskIDKey.self] ?? "no-name")] @ \(time): end") }