Skip to content

Commit ae520ec

Browse files
author
Ignacio Bonafonte
authored
Merge branch 'main' into network-instrumentation
2 parents 7fcaa1a + 35ac7ac commit ae520ec

File tree

9 files changed

+150
-18
lines changed

9 files changed

+150
-18
lines changed

Sources/OpenTelemetryApi/Trace/Propagation/W3CTraceContextPropagator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public struct W3CTraceContextPropagator: TextMapPropagator {
3333
private static let traceparentLengthV0 = versionAndTraceIdAndSpanIdLength + optionsLength
3434

3535
static let traceparent = "traceparent"
36-
static let traceState = "traceState"
36+
static let traceState = "tracestate"
3737

3838
public init() {}
3939

Sources/OpenTelemetrySdk/Trace/MultiSpanProcessor.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ import OpenTelemetryApi
1818

1919
/// Implementation of the SpanProcessor that simply forwards all received events to a list of
2020
/// SpanProcessors.
21-
public struct MultiSpanProcessor: SpanProcessor {
21+
struct MultiSpanProcessor: SpanProcessor {
2222
var spanProcessorsStart = [SpanProcessor]()
2323
var spanProcessorsEnd = [SpanProcessor]()
2424
var spanProcessorsAll = [SpanProcessor]()
2525

26-
public init(spanProcessors: [SpanProcessor]) {
26+
init(spanProcessors: [SpanProcessor]) {
2727
spanProcessorsAll = spanProcessors
2828
spanProcessorsAll.forEach {
2929
if $0.isStartRequired {
@@ -35,33 +35,33 @@ public struct MultiSpanProcessor: SpanProcessor {
3535
}
3636
}
3737

38-
public var isStartRequired: Bool {
38+
var isStartRequired: Bool {
3939
return spanProcessorsStart.count > 0
4040
}
4141

42-
public var isEndRequired: Bool {
42+
var isEndRequired: Bool {
4343
return spanProcessorsEnd.count > 0
4444
}
4545

46-
public func onStart(parentContext: SpanContext?, span: ReadableSpan) {
46+
func onStart(parentContext: SpanContext?, span: ReadableSpan) {
4747
spanProcessorsStart.forEach {
4848
$0.onStart(parentContext: parentContext, span: span)
4949
}
5050
}
5151

52-
public func onEnd(span: ReadableSpan) {
52+
func onEnd(span: ReadableSpan) {
5353
for var processor in spanProcessorsEnd {
5454
processor.onEnd(span: span)
5555
}
5656
}
5757

58-
public func shutdown() {
58+
func shutdown() {
5959
for var processor in spanProcessorsAll {
6060
processor.shutdown()
6161
}
6262
}
6363

64-
public func forceFlush() {
64+
func forceFlush() {
6565
spanProcessorsAll.forEach {
6666
$0.forceFlush()
6767
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2020, OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
16+
import Foundation
17+
import OpenTelemetryApi
18+
19+
/**
20+
* Implementation of a EnvironmentContextPropagation propagation, using W3CTraceContextPropagator
21+
*/
22+
23+
public struct EnvironmentContextPropagator: TextMapPropagator {
24+
static let traceParent = "OTEL_TRACE_PARENT"
25+
static let traceState = "OTEL_TRACE_STATE"
26+
let w3cPropagator = W3CTraceContextPropagator()
27+
28+
public let fields: Set<String> = [traceState, traceParent]
29+
30+
public init() {}
31+
32+
public func inject<S>(spanContext: SpanContext, carrier: inout [String: String], setter: S) where S: Setter {
33+
var auxCarrier = [String: String]()
34+
w3cPropagator.inject(spanContext: spanContext, carrier: &auxCarrier, setter: setter)
35+
carrier[EnvironmentContextPropagator.traceParent] = auxCarrier["traceparent"]
36+
carrier[EnvironmentContextPropagator.traceState] = auxCarrier["tracestate"]
37+
}
38+
39+
public func extract<G>(carrier: [String: String], getter: G) -> SpanContext? where G: Getter {
40+
var auxCarrier = [String: String]()
41+
auxCarrier["traceparent"] = carrier[EnvironmentContextPropagator.traceParent]
42+
auxCarrier["tracestate"] = carrier[EnvironmentContextPropagator.traceState]
43+
return w3cPropagator.extract(carrier: auxCarrier, getter: getter)
44+
}
45+
}

Sources/OpenTelemetrySdk/Trace/SpanBuilderSdk.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,20 @@ class SpanBuilderSdk: SpanBuilder {
166166

167167
private func getParentContext(parentType: ParentType, explicitParent: Span?, remoteParent: SpanContext?) -> SpanContext? {
168168
let currentSpan = OpenTelemetry.instance.contextProvider.activeSpan
169+
170+
var parentContext: SpanContext?
169171
switch parentType {
170172
case .noParent:
171-
return nil
173+
parentContext = nil
172174
case .currentSpan:
173-
return currentSpan?.context
175+
parentContext = currentSpan?.context
174176
case .explicitParent:
175-
return explicitParent?.context
177+
parentContext = explicitParent?.context
176178
case .explicitRemoteParent:
177-
return remoteParent
179+
parentContext = remoteParent
178180
}
181+
182+
return parentContext ?? tracerSharedState.launchEnvironmentContext
179183
}
180184

181185
private static func getParentSpan(parentType: ParentType, explicitParent: Span?) -> Span? {

Sources/OpenTelemetrySdk/Trace/TracerProviderSdk.swift

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import Foundation
1717
import OpenTelemetryApi
1818

19-
/// This class is not intended to be used in application code and it is used only by OpenTelemetry.
2019
public class TracerProviderSdk: TracerProvider {
2120
private var tracerProvider = [InstrumentationLibraryInfo: TracerSdk]()
2221
internal var sharedState: TracerSharedState
@@ -66,24 +65,78 @@ public class TracerProviderSdk: TracerProvider {
6665
}
6766
}
6867

68+
/// Returns the active Clock.
69+
public func getActiveClock() -> Clock {
70+
return sharedState.clock
71+
}
72+
73+
/// Updates the active Clock.
74+
public func updateActiveClock(_ newClock: Clock) {
75+
sharedState.clock = newClock
76+
}
77+
78+
/// Returns the active IdGenerator.
79+
public func getActiveIdGenerator() -> IdGenerator {
80+
return sharedState.idGenerator
81+
}
82+
83+
/// Updates the active IdGenerator.
84+
public func updateActiveIdGenerator(_ newGenerator: IdGenerator) {
85+
sharedState.idGenerator = newGenerator
86+
}
87+
88+
/// Returns the active Resource.
89+
public func getActiveResource() -> Resource {
90+
return sharedState.resource
91+
}
92+
93+
/// Updates the active Resource.
94+
public func updateActiveResource(_ newResource: Resource) {
95+
sharedState.resource = newResource
96+
}
97+
6998
/// Returns the active SpanLimits.
7099
public func getActiveSpanLimits() -> SpanLimits {
71-
sharedState.activeSpanLimits
100+
return sharedState.activeSpanLimits
72101
}
73102

74103
/// Updates the active SpanLimits.
75104
public func updateActiveSpanLimits(_ spanLimits: SpanLimits) {
76105
sharedState.setActiveSpanLimits(spanLimits)
77106
}
78107

79-
/// Adds a new SpanProcessor to this Tracer.
108+
/// Returns the active Sampler.
109+
public func getActiveSampler() -> Sampler {
110+
return sharedState.sampler
111+
}
112+
113+
/// Updates the active Sampler.
114+
public func updateActiveSampler(_ newSampler: Sampler) {
115+
sharedState.setSampler(newSampler)
116+
}
117+
118+
/// Returns the active SpanProcessors.
119+
public func getActiveSpanProcessors() -> [SpanProcessor] {
120+
if let processor = sharedState.activeSpanProcessor as? MultiSpanProcessor {
121+
return processor.spanProcessorsAll
122+
} else {
123+
return [sharedState.activeSpanProcessor]
124+
}
125+
}
126+
127+
/// Adds a new SpanProcessor to this TracerProvider.
80128
/// Any registered processor cause overhead, consider to use an async/batch processor especially
81129
/// for span exporting, and export to multiple backends using the MultiSpanExporter
82130
/// - Parameter spanProcessor: the new SpanProcessor to be added.
83131
public func addSpanProcessor(_ spanProcessor: SpanProcessor) {
84132
sharedState.addSpanProcessor(spanProcessor)
85133
}
86134

135+
/// Removes all SpanProcessors from this provider
136+
public func resetSpanProcessors() {
137+
sharedState.activeSpanProcessor = NoopSpanProcessor()
138+
}
139+
87140
/// Attempts to stop all the activity for this Tracer. Calls SpanProcessor.shutdown()
88141
/// for all registered SpanProcessors.
89142
/// This operation may block until all the Spans are processed. Must be called before turning

Sources/OpenTelemetrySdk/Trace/TracerSharedState.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//
1515

1616
import Foundation
17+
import OpenTelemetryApi
1718

1819
/// Represents the shared state/config between all Tracers created by the same TracerProvider.
1920
class TracerSharedState {
@@ -25,6 +26,7 @@ class TracerSharedState {
2526
var sampler: Sampler
2627
var activeSpanProcessor: SpanProcessor
2728
var hasBeenShutdown = false
29+
var launchEnvironmentContext: SpanContext?
2830

2931
var registeredSpanProcessors = [SpanProcessor]()
3032

@@ -49,6 +51,11 @@ class TracerSharedState {
4951
} else {
5052
activeSpanProcessor = NoopSpanProcessor()
5153
}
54+
55+
/// Recovers explicit parent context from process environment variables, it allows to automatic
56+
/// trace context propagation to child processes
57+
let environmentPropagator = EnvironmentContextPropagator()
58+
self.launchEnvironmentContext = environmentPropagator.extract(carrier: ProcessInfo.processInfo.environment, getter: EnvironmentGetter())
5259
}
5360

5461
/// Adds a new SpanProcessor
@@ -89,4 +96,13 @@ class TracerSharedState {
8996
return setSampler(Samplers.traceIdRatio(ratio: samplerProbability))
9097
}
9198
}
99+
100+
private struct EnvironmentGetter: Getter {
101+
func get(carrier: [String: String], key: String) -> [String]? {
102+
if let value = carrier[key] {
103+
return [value]
104+
}
105+
return nil
106+
}
107+
}
92108
}

Tests/OpenTelemetryApiTests/Trace/Propagation/W3CTraceContextPropagatorTest.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class W3CTraceContextPropagatorTest: XCTestCase {
187187

188188
func testHeaderNames() {
189189
XCTAssertEqual(W3CTraceContextPropagator.traceparent, "traceparent")
190-
XCTAssertEqual(W3CTraceContextPropagator.traceState, "traceState")
190+
XCTAssertEqual(W3CTraceContextPropagator.traceState, "tracestate")
191191
}
192192

193193
func testExtract_EmptyCarrier() {

Tests/OpenTelemetrySdkTests/Trace/MultiSpanProcessorTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
// limitations under the License.
1414
//
1515

16-
import OpenTelemetrySdk
1716
import OpenTelemetryApi
17+
@testable import OpenTelemetrySdk
1818
import XCTest
1919

2020
class MultiSpanProcessorTest: XCTestCase {

Tests/OpenTelemetrySdkTests/Trace/SpanBuilderSdkTests.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,20 @@ class SpanBuilderSdkTest: XCTestCase {
249249
span.end()
250250
}
251251

252+
func testParentEnvironmentContext() {
253+
setenv("OTEL_TRACE_PARENT", "00-ff000000000000000000000000000041-ff00000000000041-01", 1)
254+
let providerWithEnv = TracerProviderSdk()
255+
let tracerAux = providerWithEnv.get(instrumentationName: "SpanBuilderWithEnvTest")
256+
let parent = tracerAux.spanBuilder(spanName: spanName).setNoParent().startSpan()
257+
OpenTelemetry.instance.contextProvider.setActiveSpan(parent)
258+
let span = tracerAux.spanBuilder(spanName: spanName).setParent(parent).startSpan()
259+
XCTAssertEqual(span.context.traceId, parent.context.traceId)
260+
XCTAssertEqual(parent.context.traceId.hexString, "ff000000000000000000000000000041")
261+
span.end()
262+
parent.end()
263+
unsetenv("OTEL_TRACE_PARENT")
264+
}
265+
252266
func testParent_timestampConverter() {
253267
let parent = tracerSdk.spanBuilder(spanName: spanName).startSpan()
254268
let span = tracerSdk.spanBuilder(spanName: spanName).setParent(parent).startSpan() as! RecordEventsReadableSpan

0 commit comments

Comments
 (0)