Skip to content

Commit 94e9cfe

Browse files
authored
Only emit sampled spans to reporter (#8)
1 parent 206d663 commit 94e9cfe

File tree

5 files changed

+101
-84
lines changed

5 files changed

+101
-84
lines changed

Sources/Jaeger/JaegerSpan.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,19 @@ public final class JaegerSpan: Span {
3131
public private(set) var links = [SpanLink]()
3232

3333
private let lock = Lock()
34-
private let onReport: (JaegerSpan) -> Void
34+
private let onEnd: (JaegerSpan) -> Void
3535

3636
init(
3737
operationName: String,
3838
kind: SpanKind,
3939
startTimestamp: Timestamp,
4040
baggage: Baggage,
41-
onReport: @escaping (JaegerSpan) -> Void
41+
onEnd: @escaping (JaegerSpan) -> Void
4242
) {
4343
self.operationName = operationName
4444
self.kind = kind
4545
self.startTimestamp = startTimestamp
46-
self.onReport = onReport
46+
self.onEnd = onEnd
4747
self.baggage = baggage
4848
}
4949

@@ -68,7 +68,7 @@ public final class JaegerSpan: Span {
6868
self.lock.withLockVoid {
6969
guard self.endTimestamp == nil else { return }
7070
self.endTimestamp = timestamp
71-
self.onReport(self)
71+
self.onEnd(self)
7272
}
7373
}
7474
}

Sources/Jaeger/JaegerTracer.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public final class JaegerTracer: Tracer {
9696
startTimestamp: timestamp,
9797
baggage: childBaggage
9898
) { [weak self] endedSpan in
99+
guard endedSpan.isRecording else { return }
99100
self?.spansToEmit.append(endedSpan)
100101
}
101102

@@ -124,6 +125,7 @@ public final class JaegerTracer: Tracer {
124125
self.spansToEmit.removeFirst(spans.count)
125126
return spans
126127
}
128+
guard !spansToFlush.isEmpty else { return self.eventLoop.makeSucceededFuture(()) }
127129
return self.reporter.flush(spans: spansToFlush, inService: self.settings.serviceName)
128130
}
129131
}

Tests/JaegerTests/JaegerSpanTests.swift

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import XCTest
1919

2020
final class JaegerSpanTests: XCTestCase {
2121
func test_recordError_sets_exception_attributes() {
22-
let span = JaegerSpan()
22+
let span = JaegerSpan(sampled: false, onEnd: { _ in })
2323
XCTAssertEqual(span.attributes, [:])
2424

2525
span.recordError(TestError.test)
@@ -29,10 +29,21 @@ final class JaegerSpanTests: XCTestCase {
2929
])
3030
}
3131

32-
func test_calls_report_on_end() {
32+
func test_calls_onEnd_if_sampled() {
3333
var reportedSpan: JaegerSpan?
3434

35-
let span = JaegerSpan { span in
35+
let span = JaegerSpan(sampled: true) { span in
36+
reportedSpan = span
37+
}
38+
span.end()
39+
40+
XCTAssert(reportedSpan === span)
41+
}
42+
43+
func test_calls_onEnd_if_not_sampled() {
44+
var reportedSpan: JaegerSpan?
45+
46+
let span = JaegerSpan(sampled: false) { span in
3647
reportedSpan = span
3748
}
3849
span.end()
@@ -43,7 +54,7 @@ final class JaegerSpanTests: XCTestCase {
4354
func test_calls_report_on_end_only_once() {
4455
var invocationCount = 0
4556

46-
let span = JaegerSpan { _ in
57+
let span = JaegerSpan(sampled: true) { _ in
4758
invocationCount += 1
4859
}
4960

@@ -56,11 +67,12 @@ final class JaegerSpanTests: XCTestCase {
5667
}
5768

5869
extension JaegerSpan {
59-
fileprivate convenience init(
60-
baggage: Baggage = .topLevel,
61-
onReport: @escaping (JaegerSpan) -> Void = { _ in }
62-
) {
63-
self.init(operationName: "test", kind: .server, startTimestamp: .now(), baggage: baggage, onReport: onReport)
70+
fileprivate convenience init(sampled: Bool, onEnd: @escaping (JaegerSpan) -> Void) {
71+
var baggage = Baggage.topLevel
72+
var traceContext = TraceContext(parent: .random(), state: .none)
73+
traceContext.sampled = sampled
74+
baggage.traceContext = traceContext
75+
self.init(operationName: "test", kind: .client, startTimestamp: .now(), baggage: baggage, onEnd: onEnd)
6476
}
6577
}
6678

Tests/JaegerTests/JaegerTracerTests.swift

Lines changed: 73 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,10 @@ import XCTest
2424
final class JaegerTracerTests: XCTestCase {
2525
// MARK: - Context Propagation
2626

27-
func test_extract_w3c_trace_context_into_baggage() {
28-
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
29-
let reporter = TestSpanReporter(eventLoop: eventLoopGroup.next())
30-
let settings = JaegerTracer.Settings(serviceName: "test", reporter: .custom(reporter), sampler: ConstantSampler(samples: false))
31-
let tracer = JaegerTracer(settings: settings, group: eventLoopGroup)
27+
func test_extract_w3c_trace_context_into_baggage() throws {
28+
let tracer: JaegerTracer = .test()
3229

33-
let traceContext = TraceContext(parent: .random(), state: .none)
30+
let traceContext = TraceContext(parent: .random(), state: TraceState(rawValue: "rojo=123")!)
3431
var baggage = Baggage.topLevel
3532

3633
tracer.extract(
@@ -42,24 +39,8 @@ final class JaegerTracerTests: XCTestCase {
4239
XCTAssertEqual(baggage.traceContext, traceContext)
4340
}
4441

45-
func test_extract_missing_w3c_trace_context_into_baggage() {
46-
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
47-
let reporter = TestSpanReporter(eventLoop: eventLoopGroup.next())
48-
let settings = JaegerTracer.Settings(serviceName: "test", reporter: .custom(reporter), sampler: ConstantSampler(samples: false))
49-
let tracer = JaegerTracer(settings: settings, group: eventLoopGroup)
50-
51-
var baggage = Baggage.topLevel
52-
53-
tracer.extract([:], into: &baggage, using: HTTPHeadersExtractor())
54-
55-
XCTAssertNil(baggage.traceContext)
56-
}
57-
58-
func test_extract_missing_w3c_trace_context_without_state_into_baggage() {
59-
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
60-
let reporter = TestSpanReporter(eventLoop: eventLoopGroup.next())
61-
let settings = JaegerTracer.Settings(serviceName: "test", reporter: .custom(reporter), sampler: ConstantSampler(samples: false))
62-
let tracer = JaegerTracer(settings: settings, group: eventLoopGroup)
42+
func test_extract_w3c_trace_context_without_state_into_baggage() throws {
43+
let tracer: JaegerTracer = .test()
6344

6445
let traceContext = TraceContext(parent: .random(), state: .none)
6546
var baggage = Baggage.topLevel
@@ -73,11 +54,18 @@ final class JaegerTracerTests: XCTestCase {
7354
XCTAssertEqual(baggage.traceContext, traceContext)
7455
}
7556

76-
func test_inject_w3c_trace_context_into_headers() {
77-
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
78-
let reporter = TestSpanReporter(eventLoop: eventLoopGroup.next())
79-
let settings = JaegerTracer.Settings(serviceName: "test", reporter: .custom(reporter), sampler: ConstantSampler(samples: false))
80-
let tracer = JaegerTracer(settings: settings, group: eventLoopGroup)
57+
func test_extract_missing_w3c_trace_context_into_baggage() throws {
58+
let tracer: JaegerTracer = .test()
59+
60+
var baggage = Baggage.topLevel
61+
62+
tracer.extract([:], into: &baggage, using: HTTPHeadersExtractor())
63+
64+
XCTAssertNil(baggage.traceContext)
65+
}
66+
67+
func test_inject_w3c_trace_context_into_headers() throws {
68+
let tracer: JaegerTracer = .test()
8169

8270
let traceContext = TraceContext(parent: .random(), state: .none)
8371
var baggage = Baggage.topLevel
@@ -91,68 +79,48 @@ final class JaegerTracerTests: XCTestCase {
9179
XCTAssertEqual(headers.first(name: TraceState.headerName), traceContext.state.rawValue)
9280
}
9381

94-
func test_inject_missing_w3c_trace_context_into_headers() {
95-
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
96-
let reporter = TestSpanReporter(eventLoop: eventLoopGroup.next())
97-
let settings = JaegerTracer.Settings(serviceName: "test", reporter: .custom(reporter), sampler: ConstantSampler(samples: false))
98-
let tracer = JaegerTracer(settings: settings, group: eventLoopGroup)
82+
func test_inject_missing_w3c_trace_context_into_headers() throws {
83+
let tracer: JaegerTracer = .test()
9984

10085
let baggage = Baggage.topLevel
10186
var headers = HTTPHeaders()
10287

10388
tracer.inject(baggage, into: &headers, using: HTTPHeadersInjector())
10489

105-
XCTAssertTrue(headers.isEmpty)
90+
XCTAssert(headers.isEmpty)
10691
}
10792

108-
func test_creates_trace_context_for_root_span() {
109-
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
110-
let reporter = TestSpanReporter(eventLoop: eventLoopGroup.next())
111-
let settings = JaegerTracer.Settings(serviceName: "test", reporter: .custom(reporter), sampler: ConstantSampler(samples: false))
112-
let tracer = JaegerTracer(settings: settings, group: eventLoopGroup)
93+
func test_creates_trace_context_for_root_span() throws {
94+
let tracer: JaegerTracer = .test()
95+
96+
let span = tracer.startSpan(named: "test", baggage: .topLevel, ofKind: .server)
11397

114-
let span = tracer.startSpan(named: "test", baggage: .topLevel, ofKind: .server, at: .now())
11598
XCTAssertNotNil(span.baggage.traceContext)
11699
}
117100

118-
func test_regenerates_parent_id_in_existing_trace_context() {
119-
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
120-
let reporter = TestSpanReporter(eventLoop: eventLoopGroup.next())
121-
let settings = JaegerTracer.Settings(serviceName: "test", reporter: .custom(reporter), sampler: ConstantSampler(samples: false))
122-
let tracer = JaegerTracer(settings: settings, group: eventLoopGroup)
123-
124-
var parentBaggage = Baggage.topLevel
125-
parentBaggage.traceContext = TraceContext(parent: .random(), state: TraceState(rawValue: "rojo=123")!)
101+
func test_regenerates_parent_id_in_existing_trace_context() throws {
102+
let tracer: JaegerTracer = .test()
126103

127-
let parent = tracer.startSpan(named: "test", baggage: parentBaggage, ofKind: .server, at: .now()) as! JaegerSpan
128-
let child = tracer.startSpan(named: "test", baggage: parent.baggage, ofKind: .server, at: .now()) as! JaegerSpan
104+
var childBaggage = Baggage.topLevel
105+
childBaggage.traceContext = TraceContext(parent: .random(), state: TraceState(rawValue: "rojo=123")!)
106+
let parent = tracer.startSpan(named: "client", baggage: childBaggage, ofKind: .client)
107+
let child = tracer.startSpan(named: "server", baggage: parent.baggage, ofKind: .server) as! JaegerSpan
129108

130109
XCTAssertNotNil(child.baggage.traceContext)
131-
XCTAssertEqual(child.baggage.traceContext?.state, parentBaggage.traceContext?.state)
132-
XCTAssertEqual(child.baggage.traceContext?.parent.traceID, parentBaggage.traceContext?.parent.traceID)
133-
XCTAssertNotEqual(child.baggage.traceContext?.parent.parentID, parentBaggage.traceContext?.parent.parentID)
134-
XCTAssertEqual(child.baggage.traceContext?.parent.traceFlags, parentBaggage.traceContext?.parent.traceFlags)
110+
XCTAssertEqual(child.baggage.traceContext?.state, childBaggage.traceContext?.state)
111+
XCTAssertEqual(child.baggage.traceContext?.parent.traceID, childBaggage.traceContext?.parent.traceID)
112+
XCTAssertNotEqual(child.baggage.traceContext?.parent.parentID, childBaggage.traceContext?.parent.parentID)
113+
XCTAssertEqual(child.baggage.traceContext?.parent.traceFlags, childBaggage.traceContext?.parent.traceFlags)
135114
XCTAssertEqual(child.links.first?.baggage.traceContext, parent.baggage.traceContext)
136115
}
137116

138117
// MARK: - Flushing
139118

140-
func test_emits_spans_to_reporter_on_forceFlush() {
141-
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
142-
let reporter = TestSpanReporter(eventLoop: eventLoopGroup.next())
143-
144-
let settings = JaegerTracer.Settings(serviceName: "test", reporter: .custom(reporter), sampler: ConstantSampler(samples: false))
145-
let tracer = JaegerTracer(settings: settings, group: eventLoopGroup)
119+
func test_flushes_sampled_spans() throws {
120+
let (tracer, reporter) = JaegerTracer.test(sampler: ConstantSampler(samples: true))
146121

147-
var spans = [JaegerSpan]()
148-
149-
for _ in 0 ..< 10 {
150-
let span = tracer.startSpan(named: "test", baggage: .topLevel, ofKind: .server, at: .now())
151-
spans.append(span as! JaegerSpan)
152-
span.end()
153-
}
154-
155-
XCTAssertEqual(reporter.numberOfFlushes, 0)
122+
let spans = (0 ..< 10).map { _ in tracer.startSpan(named: "test", baggage: .topLevel) }
123+
spans.forEach { $0.end() }
156124

157125
tracer.forceFlush()
158126

@@ -162,6 +130,41 @@ final class JaegerTracerTests: XCTestCase {
162130
XCTAssert(spans[index] === span)
163131
}
164132
}
133+
134+
func test_does_not_flush_unsampled_spans() throws {
135+
let (tracer, reporter) = JaegerTracer.test(sampler: ConstantSampler(samples: false))
136+
137+
let spans = (0 ..< 10).map { _ in tracer.startSpan(named: "test", baggage: .topLevel) }
138+
spans.forEach { $0.end() }
139+
140+
tracer.forceFlush()
141+
142+
XCTAssertEqual(reporter.numberOfFlushes, 0)
143+
}
144+
}
145+
146+
extension JaegerTracer {
147+
fileprivate static func test(
148+
sampler: Sampler = ConstantSampler(samples: false),
149+
file: StaticString = #file,
150+
line: UInt = #line
151+
) -> (JaegerTracer, TestSpanReporter) {
152+
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
153+
let reporter = TestSpanReporter(eventLoop: eventLoopGroup.next())
154+
155+
let settings = JaegerTracer.Settings(serviceName: "test", reporter: .custom(reporter), sampler: sampler)
156+
let tracer = JaegerTracer(settings: settings, group: eventLoopGroup)
157+
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully(), file: file, line: line) }
158+
return (tracer, reporter)
159+
}
160+
161+
fileprivate static func test(
162+
sampler: Sampler = ConstantSampler(samples: false),
163+
file: StaticString = #file,
164+
line: UInt = #line
165+
) -> JaegerTracer {
166+
self.test(sampler: sampler).0
167+
}
165168
}
166169

167170
private final class TestSpanReporter: SpanReporter {

Tests/ZipkinReportingTests/ZipkinSpanRepresentationTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ final class ZipkinSpanRepresentationTests: XCTestCase {
6767
kind: .client,
6868
startTimestamp: .now(),
6969
baggage: baggage,
70-
onReport: { _ in }
70+
onEnd: { _ in }
7171
)
7272

7373
XCTAssertNil(span.zipkinRepresentation(forService: "test"))

0 commit comments

Comments
 (0)