Skip to content

Commit

Permalink
Implement TracerClock and abstract away "now" (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
ktoso authored Mar 29, 2023
1 parent b42cf43 commit a5b5160
Show file tree
Hide file tree
Showing 30 changed files with 886 additions and 230 deletions.
2 changes: 1 addition & 1 deletion Sources/Instrumentation/Instrument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// 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
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
Expand Down
2 changes: 1 addition & 1 deletion Sources/Instrumentation/InstrumentationSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// 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
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
Expand Down
2 changes: 1 addition & 1 deletion Sources/Instrumentation/Locks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// This source file is part of the Swift Distributed Tracing open source project
//
// Copyright (c) 2020-2021 Apple Inc. and the Swift Distributed Tracing project
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
Expand Down
2 changes: 1 addition & 1 deletion Sources/Instrumentation/MultiplexInstrument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// 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
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
Expand Down
2 changes: 1 addition & 1 deletion Sources/Instrumentation/NoOpInstrument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// 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
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
Expand Down
2 changes: 1 addition & 1 deletion Sources/Tracing/InstrumentationSystem+Tracing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// 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
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
Expand Down
23 changes: 12 additions & 11 deletions Sources/Tracing/NoOpTracer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// 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
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
Expand All @@ -17,18 +17,19 @@ import Dispatch
@_exported import InstrumentationBaggage

/// Tracer that ignores all operations, used when no tracing is required.
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) // for TaskLocal Baggage
public struct NoOpTracer: LegacyTracerProtocol {
public typealias TracerSpan = NoOpSpan

public init() {}

public func startAnySpan(_ operationName: String,
baggage: @autoclosure () -> Baggage,
ofKind kind: SpanKind,
at time: DispatchWallTime,
function: String,
file fileID: String,
line: UInt) -> any Span
public func startAnySpan<Clock: TracerClock>(_ operationName: String,
baggage: @autoclosure () -> Baggage,
ofKind kind: SpanKind,
clock: Clock,
function: String,
file fileID: String,
line: UInt) -> any Span
{
NoOpSpan(baggage: baggage())
}
Expand Down Expand Up @@ -83,19 +84,19 @@ public struct NoOpTracer: LegacyTracerProtocol {
}
}

public func end(at time: DispatchWallTime) {
public func end<Clock: TracerClock>(clock: Clock) {
// ignore
}
}
}

#if swift(>=5.7.0)
extension NoOpTracer: TracerProtocol {
public func startSpan(
public func startSpan<Clock: TracerClock>(
_ operationName: String,
baggage: @autoclosure () -> Baggage,
ofKind kind: SpanKind,
at time: DispatchWallTime,
clock: Clock,
function: String,
file fileID: String,
line: UInt
Expand Down
41 changes: 24 additions & 17 deletions Sources/Tracing/SpanProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// 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
// Copyright (c) 2020-2023 Apple Inc. and the Swift Distributed Tracing project
// authors
// Licensed under Apache License v2.0
//
Expand All @@ -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
Expand Down Expand Up @@ -98,10 +93,11 @@ public protocol Span: _SwiftTracingSendableSpan {
/// Implementations SHOULD prevent double-emitting by marking a span as ended internally, however it still is a
/// programming mistake to rely on this behavior.
///
/// - Parameter time: The `DispatchWallTime` at which the span ended.
/// Parameters:
/// - clock: The clock to use as time source for the start time of the ``Span``
///
/// - SeeAlso: `Span.end()` which automatically uses the "current" time.
func end(at time: DispatchWallTime)
func end<Clock: TracerClock>(clock: Clock)
}

extension Span {
Expand All @@ -115,12 +111,10 @@ extension Span {
/// Implementations SHOULD prevent double-emitting by marking a span as ended internally, however it still is a
/// programming mistake to rely on this behavior.
///
/// - Parameter time: The `DispatchWallTime` at which the span ended.
///
/// - 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.
/// - SeeAlso: ``end(clock:)`` 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.
public func end() {
self.end(at: .now())
self.end(clock: DefaultTracerClock())
}

/// Adds a ``SpanLink`` between this `Span` and the given `Span`.
Expand Down Expand Up @@ -153,18 +147,31 @@ 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 timestamp at which this event occurred.
///
/// It should be expressed as the number of milliseconds since UNIX Epoch (January 1st 1970).
public let millisecondsSinceEpoch: UInt64

/// 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()) {
/// - clock: The clock to use as time source for the start time of the ``Span``
public init<Clock: TracerClock>(name: String,
clock: Clock,
attributes: SpanAttributes = [:])
{
self.name = name
self.attributes = attributes
self.millisecondsSinceEpoch = clock.now.millisecondsSinceEpoch
}

public init(name: String,
attributes: SpanAttributes = [:])
{
self.name = name
self.attributes = attributes
self.time = time
self.millisecondsSinceEpoch = DefaultTracerClock.now.millisecondsSinceEpoch
}
}

Expand Down
Loading

0 comments on commit a5b5160

Please sign in to comment.