Skip to content

Commit b6f1c05

Browse files
Mario CantoVadman97
authored andcommitted
feat: instrumentation and session managers
1 parent 64fba47 commit b6f1c05

File tree

8 files changed

+587
-0
lines changed

8 files changed

+587
-0
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc

Package.resolved

Lines changed: 222 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// swift-tools-version: 6.1
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "swift-launchdarkly-observability",
6+
platforms: [.iOS(.v16)],
7+
products: [
8+
.library(
9+
name: "LaunchDarklyObservability",
10+
targets: ["LaunchDarklyObservability"]),
11+
],
12+
dependencies: [
13+
.package(url: "https://github.com/open-telemetry/opentelemetry-swift", from: "1.0.0"),
14+
],
15+
targets: [
16+
.target(
17+
name: "LaunchDarklyObservability",
18+
dependencies: [
19+
"Shared",
20+
.product(name: "OpenTelemetryApi", package: "opentelemetry-swift"),
21+
.product(name: "OpenTelemetrySdk", package: "opentelemetry-swift"),
22+
.product(name: "OpenTelemetryProtocolExporterHTTP", package: "opentelemetry-swift"),
23+
.product(name: "StdoutExporter", package: "opentelemetry-swift"),
24+
.product(name: "SignPostIntegration", package: "opentelemetry-swift"),
25+
]
26+
),
27+
.testTarget(
28+
name: "LaunchDarklyObservabilityTests",
29+
dependencies: ["LaunchDarklyObservability"]
30+
),
31+
.target(name: "Shared"),
32+
.testTarget(
33+
name: "SharedTests",
34+
dependencies: ["Shared"]
35+
)
36+
]
37+
)
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import Foundation
2+
@preconcurrency import OpenTelemetryApi
3+
@preconcurrency import OpenTelemetrySdk
4+
@preconcurrency import OpenTelemetryProtocolExporterHttp
5+
@preconcurrency import StdoutExporter
6+
7+
import SignPostIntegration
8+
9+
10+
11+
public actor InstrumentationManager {
12+
private let openTelemetry: OpenTelemetry
13+
private let tracerProvider: TracerProvider
14+
15+
private let serviceName: String
16+
private let serviceVersion: String
17+
18+
private let sessionManager: SessionManager
19+
20+
public init(
21+
serviceName: String = "launchdarkly-observability-swift",
22+
serviceVersion: String = "1.0.0",
23+
openTelemetry: OpenTelemetry = OpenTelemetry.instance,
24+
sessionManager: SessionManager = SessionManager()
25+
) {
26+
let url = URL(string: "https://otel.observability.app.launchdarkly.com:4318/v1/traces")!
27+
let otlpHttpTraceExporter = OtlpHttpTraceExporter(
28+
endpoint: url,
29+
envVarHeaders: [
30+
("X-LaunchDarkly-Project", "sdk-465cf811-71a3-42ee-8a9f-e325b6ed3a26")
31+
]
32+
)
33+
34+
35+
let stdoutExporter = StdoutSpanExporter()
36+
let spanExporter = MultiSpanExporter(spanExporters: [otlpHttpTraceExporter, stdoutExporter])
37+
38+
let spanProcessor = SimpleSpanProcessor(spanExporter: spanExporter)
39+
40+
// TODO: api and sdk keys as env. variables
41+
let resource = Resource(
42+
attributes: [
43+
ResourceAttributes.serviceName.rawValue: AttributeValue.string(serviceName),
44+
ResourceAttributes.serviceVersion.rawValue: AttributeValue.string(serviceVersion),
45+
ResourceAttributes.telemetrySdkName.rawValue: AttributeValue.string("swift-launchdarkly-observability"),
46+
ResourceAttributes.telemetrySdkLanguage.rawValue: AttributeValue.string("swift"),
47+
"highlight.project_id": AttributeValue.string("sdk-465cf811-71a3-42ee-8a9f-e325b6ed3a26"),
48+
"highlight.session_id": AttributeValue.string(UUID().uuidString),
49+
"X-LaunchDarkly-Project": AttributeValue.string("6830e8e9e63ae80ddde9384b")
50+
]
51+
)
52+
53+
let traceProvider = TracerProviderBuilder()
54+
.add(spanProcessor: spanProcessor)
55+
.with(resource: resource)
56+
.build()
57+
OpenTelemetry.registerTracerProvider(tracerProvider: traceProvider)
58+
59+
60+
OpenTelemetry.registerPropagators(
61+
textPropagators: [
62+
W3CTraceContextPropagator(),
63+
B3Propagator(),
64+
JaegerPropagator(),
65+
],
66+
baggagePropagator: W3CBaggagePropagator()
67+
)
68+
69+
self.serviceName = serviceName
70+
self.serviceVersion = serviceVersion
71+
self.openTelemetry = openTelemetry
72+
self.tracerProvider = traceProvider
73+
self.sessionManager = sessionManager
74+
75+
if #available(iOS 15.0, macOS 12, tvOS 15.0, watchOS 8.0, *) {
76+
let tracerProviderSDK = OpenTelemetry.instance.tracerProvider as? TracerProviderSdk
77+
tracerProviderSDK?.addSpanProcessor(OSSignposterIntegration())
78+
} else {
79+
let tracerProviderSDK = OpenTelemetry.instance.tracerProvider as? TracerProviderSdk
80+
tracerProviderSDK?.addSpanProcessor(SignPostIntegration())
81+
}
82+
}
83+
84+
private func getTracer() -> Tracer {
85+
tracerProvider.get(instrumentationName: serviceName, instrumentationVersion: serviceVersion)
86+
}
87+
88+
let sampleKey = "sampleKey"
89+
let sampleValue = "sampleValue"
90+
}
91+
92+
// TODO: Remove test code
93+
extension InstrumentationManager {
94+
public func createSpans() {
95+
let tracer = getTracer()
96+
let parentSpan1 = tracer.spanBuilder(spanName: "main").setSpanKind(spanKind: .client).startSpan()
97+
parentSpan1.setAttribute(key: sampleKey, value: sampleValue)
98+
// ("X-LaunchDarkly-Project", "sdk-465cf811-71a3-42ee-8a9f-e325b6ed3a26")
99+
// parentSpan1.setAttribute(key: "X-LaunchDarkly-Project", value: .string("sdk-465cf811-71a3-42ee-8a9f-e325b6ed3a26"))
100+
openTelemetry.contextProvider.setActiveSpan(parentSpan1)
101+
for _ in 1 ... 3 {
102+
doWork()
103+
}
104+
Thread.sleep(forTimeInterval: 0.5)
105+
106+
let parentSpan2 = tracer.spanBuilder(spanName: "another").setSpanKind(spanKind: .client).setActive(true).startSpan()
107+
parentSpan2.setAttribute(key: sampleKey, value: sampleValue)
108+
// do more Work
109+
for _ in 1 ... 3 {
110+
doWork()
111+
}
112+
Thread.sleep(forTimeInterval: 0.5)
113+
114+
parentSpan2.end()
115+
parentSpan1.end()
116+
}
117+
118+
func doWork() {
119+
let tracer = getTracer()
120+
let childSpan = tracer.spanBuilder(spanName: "doWork").setSpanKind(spanKind: .client).startSpan()
121+
childSpan.setAttribute(key: sampleKey, value: sampleValue)
122+
Thread.sleep(forTimeInterval: Double.random(in: 0 ..< 10) / 100)
123+
childSpan.end()
124+
}
125+
}

0 commit comments

Comments
 (0)