Skip to content

Commit 89d8ccd

Browse files
authored
allow for tracingInstrument and tracingInstrument(of: Type) APIs (#101)
allow for tracingInstrument and tracingInstrument(of: Type) APIs
1 parent 8727655 commit 89d8ccd

File tree

8 files changed

+118
-31
lines changed

8 files changed

+118
-31
lines changed

Sources/Instrumentation/Instrument.swift

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,3 @@ public protocol Instrument {
6767
Injector.Carrier == Carrier
6868
}
6969

70-
public struct NoOpInstrument: Instrument {
71-
public func inject<Carrier, Injector>(_ baggage: BaggageContext, into carrier: inout Carrier, using injector: Injector)
72-
where
73-
Injector: InjectorProtocol,
74-
Carrier == Injector.Carrier {}
75-
76-
public func extract<Carrier, Extractor>(_ carrier: Carrier, into baggage: inout BaggageContext, using extractor: Extractor)
77-
where
78-
Extractor: ExtractorProtocol,
79-
Carrier == Extractor.Carrier {}
80-
}

Sources/Instrumentation/InstrumentationSystem.swift

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,24 +61,36 @@ public enum InstrumentationSystem {
6161
}
6262
}
6363

64-
/// Returns the globally configured `Instrument`. Defaults to a no-op `Instrument` if `boostrap` wasn't called before.
64+
/// Returns the globally configured `Instrument`.
65+
///
66+
/// Defaults to a no-op `Instrument` if `boostrap` wasn't called before.
6567
public static var instrument: Instrument {
6668
self.lock.withReaderLock { self._instrument }
6769
}
68-
}
6970

70-
extension InstrumentationSystem {
7171
/// Get an `Instrument` instance of the given type.
7272
///
7373
/// When using `MultiplexInstrument`, this returns the first instance of the given type stored in the `MultiplexInstrument`.
74+
///
7475
/// - Parameter instrumentType: The type of `Instrument` you want to retrieve an instance for.
7576
/// - Returns: An `Instrument` instance of the given type or `nil` if no `Instrument` of that type has been bootstrapped.
76-
public static func instrument<I>(of instrumentType: I.Type) -> I? {
77+
public static func instrument<I>(of instrumentType: I.Type) -> I? where I: Instrument {
78+
self._findInstrument(where: { $0 is I }) as? I
79+
}
80+
81+
}
82+
83+
extension InstrumentationSystem {
84+
/// :nodoc: INTERNAL API: Do Not Use
85+
public static func _findInstrument(where predicate: (Instrument) -> Bool) -> Instrument? {
7786
self.lock.withReaderLock {
78-
if let multiplexInstrument = self._instrument as? MultiplexInstrument {
79-
return multiplexInstrument.firstInstance(of: I.self)
87+
if let multiplex = self._instrument as? MultiplexInstrument {
88+
return multiplex.firstInstrument(where: predicate)
89+
} else if predicate(self._instrument) {
90+
return self._instrument
91+
} else {
92+
return nil
8093
}
81-
return self._instrument as? I
8294
}
8395
}
8496
}

Sources/Instrumentation/MultiplexInstrument.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ public struct MultiplexInstrument {
2828
}
2929

3030
extension MultiplexInstrument {
31-
func firstInstance<I>(of instrument: I.Type) -> I? {
32-
self.instruments.first(where: { $0 is I }) as? I
31+
func firstInstrument(where predicate: (Instrument) -> Bool) -> Instrument? {
32+
self.instruments.first(where: predicate)
3333
}
3434
}
3535

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Distributed Tracing open source project
4+
//
5+
// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
//
10+
// SPDX-License-Identifier: Apache-2.0
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
import Baggage
15+
16+
/// A "no op" implementation of an `Instrument`.
17+
public struct NoOpInstrument: Instrument {
18+
19+
public init() {}
20+
21+
public func inject<Carrier, Injector>(_ baggage: BaggageContext, into carrier: inout Carrier, using injector: Injector)
22+
where
23+
Injector: InjectorProtocol,
24+
Carrier == Injector.Carrier {}
25+
26+
public func extract<Carrier, Extractor>(_ carrier: Carrier, into baggage: inout BaggageContext, using extractor: Extractor)
27+
where
28+
Extractor: ExtractorProtocol,
29+
Carrier == Extractor.Carrier {}
30+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Distributed Tracing open source project
4+
//
5+
// Copyright (c) 2020 Moritz Lang and the Swift Tracing project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
//
10+
// SPDX-License-Identifier: Apache-2.0
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
import Baggage
15+
import Instrumentation
16+
17+
18+
extension InstrumentationSystem {
19+
20+
/// Get a `TracingInstrument` instance of the given type.
21+
///
22+
/// When using `MultiplexInstrument`, this returns the first instance of the given type stored in the `MultiplexInstrument`.
23+
///
24+
/// Usually tracing libraries will provide their own convenience getter, e.g. CoolTracing could provide `InstrumentationSystem.coolTracer`;
25+
/// if available, prefer using those APIs rather than relying on this general function.
26+
///
27+
/// - Parameter instrumentType: The type of `Instrument` you want to retrieve an instance for.
28+
/// - Returns: An `Instrument` instance of the given type or `nil` if no `Instrument` of that type has been bootstrapped.
29+
public static func tracingInstrument<T>(of instrumentType: T.Type) -> T? where T: TracingInstrument {
30+
self._findInstrument(where: { $0 is T }) as? T
31+
}
32+
33+
/// Returns the `TracingInstrument` bootstrapped as part of the `InstrumentationSystem`.
34+
///
35+
/// If the system was bootstrapped with a `MultiplexInstrument` this function attempts to locate the _first_
36+
/// tracing instrument as passed to the multiplex instrument. If none is found, a `NoOpTracingInstrument` is returned.
37+
///
38+
/// - Returns: A `TracingInstrument` if the system was bootstrapped with one, and `NoOpTracingInstrument` otherwise.
39+
public static var tracingInstrument: TracingInstrument {
40+
(self._findInstrument(where: { $0 is TracingInstrument }) as? TracingInstrument) ?? NoOpTracingInstrument()
41+
}
42+
}

Sources/TracingInstrumentation/TracingInstrument.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,3 @@ extension TracingInstrument {
4747
self.startSpan(named: operationName, context: context, ofKind: .internal, at: nil)
4848
}
4949
}
50-
51-
extension InstrumentationSystem {
52-
/// Returns the `TracingInstrument` bootstrapped as part of the `InstrumentationSystem`.
53-
///
54-
/// - Warning: Only call this after you bootstrapped the `InstrumentationSystem`. Calling it before is
55-
/// considered a programmer error and leads to a crash.
56-
public static var tracingInstrument: TracingInstrument {
57-
instrument(of: TracingInstrument.self)!
58-
}
59-
}

Tests/TracingInstrumentationTests/TracingInstrumentTests.swift

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import Baggage
1515
import BaggageLogging
16-
import Instrumentation
16+
@testable import Instrumentation
1717
import TracingInstrumentation
1818
import XCTest
1919

@@ -27,6 +27,30 @@ final class TracingInstrumentTests: XCTestCase {
2727

2828
httpServer.receive(FakeHTTPRequest(path: "/", headers: []))
2929
}
30+
31+
func testItProvidesAccessToATracingInstrument() {
32+
let tracer = JaegerTracer()
33+
34+
XCTAssertNil(InstrumentationSystem.tracingInstrument(of: JaegerTracer.self))
35+
36+
InstrumentationSystem.bootstrapInternal(tracer)
37+
XCTAssertFalse(InstrumentationSystem.instrument is MultiplexInstrument)
38+
XCTAssert(InstrumentationSystem.instrument(of: JaegerTracer.self) === tracer)
39+
XCTAssertNil(InstrumentationSystem.instrument(of: NoOpInstrument.self))
40+
41+
XCTAssert(InstrumentationSystem.tracingInstrument(of: JaegerTracer.self) === tracer)
42+
XCTAssert(InstrumentationSystem.tracingInstrument is JaegerTracer)
43+
44+
let multiplexInstrument = MultiplexInstrument([tracer])
45+
InstrumentationSystem.bootstrapInternal(multiplexInstrument)
46+
XCTAssert(InstrumentationSystem.instrument is MultiplexInstrument)
47+
XCTAssert(InstrumentationSystem.instrument(of: JaegerTracer.self) === tracer)
48+
49+
XCTAssert(InstrumentationSystem.tracingInstrument(of: JaegerTracer.self) === tracer)
50+
XCTAssert(InstrumentationSystem.tracingInstrument is JaegerTracer)
51+
52+
53+
}
3054
}
3155

3256
// MARK: - JaegerTracer

0 commit comments

Comments
 (0)