-
Notifications
You must be signed in to change notification settings - Fork 108
/
OtlpHttpTraceExporter.swift
86 lines (78 loc) · 3.07 KB
/
OtlpHttpTraceExporter.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
//
import Foundation
import OpenTelemetryProtocolExporterCommon
import OpenTelemetrySdk
public func defaultOltpHttpTracesEndpoint() -> URL {
URL(string: "http://localhost:4318/v1/traces")!
}
public class OtlpHttpTraceExporter: OtlpHttpExporterBase, SpanExporter {
var pendingSpans: [SpanData] = []
private let exporterLock = Lock()
override
public init(endpoint: URL = defaultOltpHttpTracesEndpoint(), config: OtlpConfiguration = OtlpConfiguration(),
useSession: URLSession? = nil, envVarHeaders: [(String, String)]? = EnvVarHeaders.attributes) {
super.init(endpoint: endpoint, config: config, useSession: useSession)
}
public func export(spans: [SpanData], explicitTimeout: TimeInterval? = nil) -> SpanExporterResultCode {
var sendingSpans: [SpanData] = []
exporterLock.withLockVoid {
pendingSpans.append(contentsOf: spans)
sendingSpans = pendingSpans
pendingSpans = []
}
let body = Opentelemetry_Proto_Collector_Trace_V1_ExportTraceServiceRequest.with {
$0.resourceSpans = SpanAdapter.toProtoResourceSpans(spanDataList: sendingSpans)
}
var request = createRequest(body: body, endpoint: endpoint)
if let headers = envVarHeaders {
headers.forEach { key, value in
request.addValue(value, forHTTPHeaderField: key)
}
} else if let headers = config.headers {
headers.forEach { key, value in
request.addValue(value, forHTTPHeaderField: key)
}
}
httpClient.send(request: request) { [weak self] result in
switch result {
case .success:
break
case let .failure(error):
self?.exporterLock.withLockVoid {
self?.pendingSpans.append(contentsOf: sendingSpans)
}
print(error)
}
}
return .success
}
public func flush(explicitTimeout: TimeInterval? = nil) -> SpanExporterResultCode {
var resultValue: SpanExporterResultCode = .success
var pendingSpans: [SpanData] = []
exporterLock.withLockVoid {
pendingSpans = self.pendingSpans
}
if !pendingSpans.isEmpty {
let body = Opentelemetry_Proto_Collector_Trace_V1_ExportTraceServiceRequest.with {
$0.resourceSpans = SpanAdapter.toProtoResourceSpans(spanDataList: pendingSpans)
}
let semaphore = DispatchSemaphore(value: 0)
let request = createRequest(body: body, endpoint: endpoint)
httpClient.send(request: request) { result in
switch result {
case .success:
break
case let .failure(error):
print(error)
resultValue = .failure
}
semaphore.signal()
}
semaphore.wait()
}
return resultValue
}
}