Skip to content

Commit 1803401

Browse files
committed
also implement function based matching
1 parent b42d1db commit 1803401

File tree

6 files changed

+138
-33
lines changed

6 files changed

+138
-33
lines changed

Sources/Tracing/NoOpTracer.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public struct NoOpTracer: Tracer {
2525
baggage: Baggage,
2626
ofKind kind: SpanKind,
2727
at time: DispatchWallTime,
28+
function: String,
2829
file fileID: String,
2930
line: UInt
3031
) -> Span {

Sources/Tracing/Tracer.swift

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ public protocol Tracer: Instrument {
3030
/// - baggage: The `Baggage` providing information on where to start the new ``Span``.
3131
/// - kind: The ``SpanKind`` of the new ``Span``.
3232
/// - time: The `DispatchTime` at which to start the new ``Span``.
33-
/// - file: The `fileID` where the span was started.
33+
/// - function: The function name in which the span was started
34+
/// - fileID: The `fileID` where the span was started.
3435
/// - line: The file line where the span was started.
3536
func startSpan(
3637
_ operationName: String,
3738
baggage: Baggage,
3839
ofKind kind: SpanKind,
3940
at time: DispatchWallTime,
41+
function: String,
4042
file fileID: String,
4143
line: UInt
4244
) -> Span
@@ -57,14 +59,19 @@ extension Tracer {
5759
/// - operationName: The name of the operation being traced. This may be a handler function, database call, ...
5860
/// - baggage: Baggage potentially containing trace identifiers of a parent ``Span``.
5961
/// - kind: The ``SpanKind`` of the ``Span`` to be created. Defaults to ``SpanKind/internal``.
62+
/// - function: The function name in which the span was started
63+
/// - fileID: The `fileID` where the span was started.
64+
/// - line: The file line where the span was started.
6065
public func startSpan(
6166
_ operationName: String,
6267
baggage: Baggage,
6368
ofKind kind: SpanKind = .internal,
69+
function: String = #function,
6470
file fileID: String = #fileID,
6571
line: UInt = #line
6672
) -> Span {
67-
self.startSpan(operationName, baggage: baggage, ofKind: kind, at: .now(), file: fileID, line: line)
73+
self.startSpan(operationName, baggage: baggage, ofKind: kind, at: .now(),
74+
function: function, file: fileID, line: line)
6875
}
6976
}
7077

@@ -81,17 +88,22 @@ extension Tracer {
8188
/// - baggage: Baggage potentially containing trace identifiers of a parent ``Span``.
8289
/// - kind: The ``SpanKind`` of the ``Span`` to be created. Defaults to ``SpanKind/internal``.
8390
/// - operation: operation to wrap in a span start/end and execute immediately
91+
/// - function: The function name in which the span was started
92+
/// - fileID: The `fileID` where the span was started.
93+
/// - line: The file line where the span was started.
8494
/// - Returns: the value returned by `operation`
8595
/// - Throws: the error the `operation` has thrown (if any)
8696
public func withSpan<T>(
8797
_ operationName: String,
8898
baggage: Baggage,
8999
ofKind kind: SpanKind = .internal,
100+
function: String = #function,
90101
file fileID: String = #fileID,
91102
line: UInt = #line,
92103
_ operation: (Span) throws -> T
93104
) rethrows -> T {
94-
let span = self.startSpan(operationName, baggage: baggage, ofKind: kind, at: .now(), file: fileID, line: line)
105+
let span = self.startSpan(operationName, baggage: baggage, ofKind: kind, at: .now(),
106+
function: function, file: fileID, line: line)
95107
defer { span.end() }
96108
do {
97109
return try operation(span)
@@ -117,16 +129,21 @@ extension Tracer {
117129
/// - operationName: The name of the operation being traced. This may be a handler function, database call, ...
118130
/// - kind: The ``SpanKind`` of the ``Span`` to be created. Defaults to ``SpanKind/internal``.
119131
/// - operation: operation to wrap in a span start/end and execute immediately
132+
/// - function: The function name in which the span was started
133+
/// - fileID: The `fileID` where the span was started.
134+
/// - line: The file line where the span was started.
120135
/// - Returns: the value returned by `operation`
121136
/// - Throws: the error the `operation` has thrown (if any)
122137
public func withSpan<T>(
123138
_ operationName: String,
124139
ofKind kind: SpanKind = .internal,
140+
function: String = #function,
125141
file fileID: String = #fileID,
126142
line: UInt = #line,
127143
_ operation: (Span) throws -> T
128144
) rethrows -> T {
129-
try self.withSpan(operationName, baggage: .current ?? .topLevel, ofKind: kind, file: fileID, line: line) { span in
145+
try self.withSpan(operationName, baggage: .current ?? .topLevel, ofKind: kind,
146+
function: function, file: fileID, line: line) { span in
130147
try Baggage.$current.withValue(span.baggage) {
131148
try operation(span)
132149
}
@@ -142,16 +159,21 @@ extension Tracer {
142159
/// - operationName: The name of the operation being traced. This may be a handler function, database call, ...
143160
/// - kind: The ``SpanKind`` of the ``Span`` to be created. Defaults to ``SpanKind/internal``.
144161
/// - operation: operation to wrap in a span start/end and execute immediately
162+
/// - function: The function name in which the span was started
163+
/// - fileID: The `fileID` where the span was started.
164+
/// - line: The file line where the span was started.
145165
/// - Returns: the value returned by `operation`
146166
/// - Throws: the error the `operation` has thrown (if any)
147167
public func withSpan<T>(
148168
_ operationName: String,
149169
ofKind kind: SpanKind = .internal,
170+
function: String = #function,
150171
file fileID: String = #fileID,
151172
line: UInt = #line,
152173
_ operation: (Span) async throws -> T
153174
) async rethrows -> T {
154-
let span = self.startSpan(operationName, baggage: .current ?? .topLevel, ofKind: kind, file: fileID, line: line)
175+
let span = self.startSpan(operationName, baggage: .current ?? .topLevel, ofKind: kind,
176+
function: function, file: fileID, line: line)
155177
defer { span.end() }
156178
do {
157179
return try await Baggage.$current.withValue(span.baggage) {
@@ -174,17 +196,21 @@ extension Tracer {
174196
// task local and modified before passing into this function. The baggage will be made the current task-local baggage for the duration of the `operation`.
175197
/// - kind: The `SpanKind` of the `Span` to be created. Defaults to `.internal`.
176198
/// - operation: operation to wrap in a span start/end and execute immediately
199+
/// - function: The function name in which the span was started
200+
/// - fileID: The `fileID` where the span was started.
201+
/// - line: The file line where the span was started.
177202
/// - Returns: the value returned by `operation`
178203
/// - Throws: the error the `operation` has thrown (if any)
179204
public func withSpan<T>(
180205
_ operationName: String,
181206
baggage: Baggage,
182207
ofKind kind: SpanKind = .internal,
208+
function: String = #function,
183209
file fileID: String = #fileID,
184210
line: UInt = #line,
185211
_ operation: (Span) async throws -> T
186212
) async rethrows -> T {
187-
let span = self.startSpan(operationName, baggage: baggage, ofKind: kind, file: fileID, line: line)
213+
let span = self.startSpan(operationName, baggage: baggage, ofKind: kind, function: function, file: fileID, line: line)
188214
defer { span.end() }
189215
do {
190216
return try await Baggage.$current.withValue(span.baggage) {

Tests/TracingTests/DynamicTracepointTracerTests+XCTest.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ extension DynamicTracepointTracerTests {
2626
@available(*, deprecated, message: "not actually deprecated. Just deprecated to allow deprecated tests (which test deprecated functionality) without warnings")
2727
static var allTests : [(String, (DynamicTracepointTracerTests) -> () throws -> Void)] {
2828
return [
29-
("test_adhoc_enableAdHoc", test_adhoc_enableAdHoc),
29+
("test_adhoc_enableBySourceLoc", test_adhoc_enableBySourceLoc),
30+
("test_adhoc_enableByFunction", test_adhoc_enableByFunction),
3031
]
3132
}
3233
}

Tests/TracingTests/DynamicTracepointTracerTests.swift

Lines changed: 101 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ final class DynamicTracepointTracerTests: XCTestCase {
2323
InstrumentationSystem.bootstrapInternal(nil)
2424
}
2525

26-
func test_adhoc_enableAdHoc() {
26+
func test_adhoc_enableBySourceLoc() {
2727
let tracer = DynamicTracepointTestTracer()
2828

2929
InstrumentationSystem.bootstrapInternal(tracer)
@@ -32,36 +32,101 @@ final class DynamicTracepointTracerTests: XCTestCase {
3232
}
3333

3434
let fileID = #fileID
35-
let line: UInt = 7777 // trick number, see withSpan below.
36-
tracer.enableTracepoint(fileID: fileID, line: line)
35+
let fakeLine: UInt = 77 // trick number, see withSpan below.
36+
let fakeNextLine: UInt = fakeLine + 11
37+
tracer.enableTracepoint(fileID: fileID, line: fakeLine)
3738
// Imagine this is set via some "ops command", e.g. `<control> <pid, or ssh or something> trace enable Sample.swift:1234`
3839
// Effectively enabling tracepoints is similar to tracer bullets, tho bullets are generally "one off",
3940
// but here we could attach a trace-rate, so e.g.: control `<pid> trace enable Sample:1234 .2` to set 20% sampling rate etc.
4041

4142
tracer.withSpan("dont") { _ in
4243
// don't capture this span...
4344
}
44-
tracer.withSpan("yes", file: #fileID, line: 7777) { _ in
45+
tracer.withSpan("yes", line: fakeLine) { _ in
4546
// do capture this span, and all child spans of it!
46-
tracer.withSpan("yes-inner", file: #fileID, line: 8888) { _ in
47+
tracer.withSpan("yes-inner", line: fakeNextLine) { _ in
4748
// since the parent of this span was captured, this shall be captured as well
4849
}
4950
}
5051

5152
XCTAssertEqual(tracer.spans.count, 2)
5253
for span in tracer.spans {
53-
XCTAssertEqual(span.baggage.traceID, "trace-id-fake-\(fileID)-\(line)")
54+
XCTAssertEqual(span.baggage.traceID, "trace-id-fake-\(fileID)-\(fakeLine)")
55+
}
56+
XCTAssertEqual(tracer.spans[0].baggage.spanID, "span-id-fake-\(fileID)-\(fakeLine)")
57+
XCTAssertEqual(tracer.spans[1].baggage.spanID, "span-id-fake-\(fileID)-\(fakeNextLine)")
58+
}
59+
60+
func test_adhoc_enableByFunction() {
61+
let tracer = DynamicTracepointTestTracer()
62+
63+
InstrumentationSystem.bootstrapInternal(tracer)
64+
defer {
65+
InstrumentationSystem.bootstrapInternal(NoOpTracer())
66+
}
67+
68+
let fileID = #fileID
69+
tracer.enableTracepoint(function: "traceMeLogic(fakeLine:)")
70+
71+
let fakeLine: UInt = 66
72+
let fakeNextLine: UInt = fakeLine + 11
73+
74+
logic(fakeLine: 55)
75+
traceMeLogic(fakeLine: fakeLine)
76+
77+
XCTAssertEqual(tracer.spans.count, 2)
78+
for span in tracer.spans {
79+
XCTAssertEqual(span.baggage.traceID, "trace-id-fake-\(fileID)-\(fakeLine)")
80+
}
81+
XCTAssertEqual(tracer.spans[0].baggage.spanID, "span-id-fake-\(fileID)-\(fakeLine)")
82+
XCTAssertEqual(tracer.spans[1].baggage.spanID, "span-id-fake-\(fileID)-\(fakeNextLine)")
83+
}
84+
85+
func logic(fakeLine: UInt) {
86+
InstrumentationSystem.tracer.withSpan("\(#function)-dont", line: fakeLine) { _ in
87+
88+
}
89+
}
90+
func traceMeLogic(fakeLine: UInt) {
91+
InstrumentationSystem.tracer.withSpan("\(#function)-yes", line: fakeLine) { _ in
92+
InstrumentationSystem.tracer.withSpan("\(#function)-yes-inside", line: fakeLine + 11) { _ in
93+
// inside
94+
}
5495
}
55-
XCTAssertEqual(tracer.spans[0].baggage.spanID, "span-id-fake-\(fileID)-\(line)")
56-
XCTAssertEqual(tracer.spans[1].baggage.spanID, "span-id-fake-\(fileID)-8888")
5796
}
5897
}
5998

6099
final class DynamicTracepointTestTracer: Tracer {
61100
private(set) var activeTracepoints: Set<TracepointID> = []
101+
62102
struct TracepointID: Hashable {
63-
let fileID: String
64-
let line: UInt
103+
let function: String?
104+
let fileID: String?
105+
let line: UInt?
106+
107+
func matches(tracepoint: TracepointID) -> Bool {
108+
var match = true
109+
if let fun = self.function {
110+
match = match && fun == tracepoint.function
111+
if !match { // short-circuit further checks
112+
return false
113+
}
114+
}
115+
if let fid = self.fileID {
116+
match = match && fid == tracepoint.fileID
117+
if !match { // short-circuit further checks
118+
return false
119+
}
120+
}
121+
if let l = self.line {
122+
match = match && l == tracepoint.line
123+
if !match { // short-circuit further checks
124+
return false
125+
}
126+
}
127+
128+
return match
129+
}
65130
}
66131

67132
private(set) var spans: [TracepointSpan] = []
@@ -72,22 +137,22 @@ final class DynamicTracepointTestTracer: Tracer {
72137
baggage: InstrumentationBaggage.Baggage,
73138
ofKind kind: Tracing.SpanKind,
74139
at time: DispatchWallTime,
140+
function: String,
75141
file fileID: String,
76-
line: UInt) -> Tracing.Span
77-
{
78-
let tracepoint = TracepointID(fileID: fileID, line: line)
142+
line: UInt) -> Tracing.Span {
143+
let tracepoint = TracepointID(function: function, fileID: fileID, line: line)
79144
guard self.shouldRecord(tracepoint: tracepoint) else {
80145
return NoOpTracer.NoOpSpan(baggage: baggage)
81146
}
82147

83148
let span = TracepointSpan(
84-
operationName: operationName,
85-
startTime: time,
86-
baggage: baggage,
87-
kind: kind,
88-
file: fileID,
89-
line: line,
90-
onEnd: onEndSpan
149+
operationName: operationName,
150+
startTime: time,
151+
baggage: baggage,
152+
kind: kind,
153+
file: fileID,
154+
line: line,
155+
onEnd: onEndSpan
91156
)
92157
self.spans.append(span)
93158
return span
@@ -115,15 +180,26 @@ final class DynamicTracepointTestTracer: Tracer {
115180
}
116181

117182
func isActive(tracepoint: TracepointID) -> Bool {
118-
self.activeTracepoints.contains(tracepoint)
183+
for activeTracepoint in self.activeTracepoints {
184+
if activeTracepoint.matches(tracepoint: tracepoint) {
185+
return true
186+
}
187+
}
188+
return false
119189
}
120190

121191
@discardableResult
122-
func enableTracepoint(fileID: String, line: UInt) -> Bool {
123-
self.activeTracepoints.insert(TracepointID(fileID: fileID, line: line)).inserted
192+
func enableTracepoint(fileID: String, line: UInt? = nil) -> Bool {
193+
self.activeTracepoints.insert(TracepointID(function: nil, fileID: fileID, line: line)).inserted
124194
}
125195

126-
func forceFlush() {}
196+
@discardableResult
197+
func enableTracepoint(function: String, fileID: String? = nil, line: UInt? = nil) -> Bool {
198+
self.activeTracepoints.insert(TracepointID(function: function, fileID: fileID, line: line)).inserted
199+
}
200+
201+
func forceFlush() {
202+
}
127203

128204
func extract<Carrier, Extract>(_ carrier: Carrier, into baggage: inout Baggage, using extractor: Extract) where Extract: Extractor, Extract.Carrier == Carrier {
129205
let traceID = extractor.extract(key: "trace-id", from: carrier) ?? UUID().uuidString
@@ -159,8 +235,7 @@ extension DynamicTracepointTestTracer {
159235
kind: SpanKind,
160236
file fileID: String,
161237
line: UInt,
162-
onEnd: @escaping (Span) -> Void)
163-
{
238+
onEnd: @escaping (Span) -> Void) {
164239
self.operationName = operationName
165240
self.startTime = startTime
166241
self.baggage = baggage

Tests/TracingTests/TestTracer.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ final class TestTracer: Tracer {
2727
baggage: Baggage,
2828
ofKind kind: SpanKind,
2929
at time: DispatchWallTime,
30+
function: String,
3031
file fileID: String,
3132
line: UInt
3233
) -> Span {

Tests/TracingTests/TracedLockTests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ private final class TracedLockPrintlnTracer: Tracer {
6464
baggage: Baggage,
6565
ofKind kind: SpanKind,
6666
at time: DispatchWallTime,
67+
function: String,
6768
file fileID: String,
6869
line: UInt
6970
) -> Span {

0 commit comments

Comments
 (0)