Skip to content

Commit 8d6fa74

Browse files
authored
Merge pull request #460 from open-telemetry/batch-timeout-fix
expanded exporter APIs with explicitTimeout on force flush and shutdown
2 parents 5c74e87 + cbaad29 commit 8d6fa74

File tree

50 files changed

+2198
-2115
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2198
-2115
lines changed

Sources/Exporters/DatadogExporter/DatadogExporter.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class DatadogExporter: SpanExporter, MetricExporter {
1919
metricsExporter = try MetricsExporter(config: configuration)
2020
}
2121

22-
public func export(spans: [SpanData]) -> SpanExporterResultCode {
22+
public func export(spans: [SpanData], explicitTimeout: TimeInterval?) -> SpanExporterResultCode {
2323
spans.forEach {
2424
if $0.traceFlags.sampled || configuration.exportUnsampledSpans {
2525
spansExporter?.exportSpan(span: $0)
@@ -38,7 +38,7 @@ public class DatadogExporter: SpanExporter, MetricExporter {
3838
return .success
3939
}
4040

41-
public func flush() -> SpanExporterResultCode {
41+
public func flush(explicitTimeout: TimeInterval?) -> SpanExporterResultCode {
4242
spansExporter?.tracesStorage.writer.queue.sync {}
4343
logsExporter?.logsStorage.writer.queue.sync {}
4444
metricsExporter?.metricsStorage.writer.queue.sync {}
@@ -49,7 +49,7 @@ public class DatadogExporter: SpanExporter, MetricExporter {
4949
return .success
5050
}
5151

52-
public func shutdown() {
52+
public func shutdown(explicitTimeout: TimeInterval?) {
5353
_ = self.flush()
5454
}
5555

Sources/Exporters/InMemory/InMemoryExporter.swift

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,38 @@ import Foundation
77
import OpenTelemetrySdk
88

99
public class InMemoryExporter: SpanExporter {
10-
private var finishedSpanItems: [SpanData] = []
11-
private var isRunning: Bool = true
12-
13-
public init() {}
14-
15-
public func getFinishedSpanItems() -> [SpanData] {
16-
return finishedSpanItems
17-
}
18-
19-
public func export(spans: [SpanData]) -> SpanExporterResultCode {
20-
guard isRunning else {
21-
return .failure
22-
}
23-
24-
finishedSpanItems.append(contentsOf: spans)
25-
return .success
10+
private var finishedSpanItems: [SpanData] = []
11+
private var isRunning: Bool = true
12+
13+
public init() {}
14+
15+
public func getFinishedSpanItems() -> [SpanData] {
16+
return finishedSpanItems
17+
}
18+
19+
public func export(spans: [SpanData], explicitTimeout: TimeInterval? = nil) -> SpanExporterResultCode {
20+
guard isRunning else {
21+
return .failure
2622
}
27-
28-
public func flush() -> SpanExporterResultCode {
29-
guard isRunning else {
30-
return .failure
31-
}
32-
33-
return .success
34-
}
35-
36-
public func reset() {
37-
finishedSpanItems.removeAll()
38-
}
39-
40-
public func shutdown() {
41-
finishedSpanItems.removeAll()
42-
isRunning = false
23+
24+
finishedSpanItems.append(contentsOf: spans)
25+
return .success
26+
}
27+
28+
public func flush(explicitTimeout: TimeInterval? = nil) -> SpanExporterResultCode {
29+
guard isRunning else {
30+
return .failure
4331
}
32+
33+
return .success
34+
}
35+
36+
public func reset() {
37+
finishedSpanItems.removeAll()
38+
}
39+
40+
public func shutdown(explicitTimeout: TimeInterval? = nil) {
41+
finishedSpanItems.removeAll()
42+
isRunning = false
43+
}
4444
}

Sources/Exporters/Jaeger/JaegerSpanExporter.swift

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,29 @@ import OpenTelemetrySdk
1010
import Thrift
1111

1212
public class JaegerSpanExporter: SpanExporter {
13-
let collectorAddress: String
14-
let process: Process
15-
16-
public init(serviceName: String, collectorAddress: String) {
17-
process = Process(serviceName: serviceName, tags: TList<Tag>())
18-
self.collectorAddress = collectorAddress
19-
}
20-
21-
public func export(spans: [SpanData]) -> SpanExporterResultCode {
22-
var spanList = TList<Span>()
23-
spanList.append(contentsOf: Adapter.toJaeger(spans: spans))
24-
let batch = Batch(process: process, spans: spanList)
25-
let sender = Sender(host: collectorAddress)
26-
let success = sender.sendBatch(batch: batch)
27-
return success ? SpanExporterResultCode.success : SpanExporterResultCode.failure
28-
}
29-
30-
public func flush() -> SpanExporterResultCode {
31-
return .success
32-
}
33-
34-
public func shutdown() {
35-
}
13+
let collectorAddress: String
14+
let process: Process
15+
16+
public init(serviceName: String, collectorAddress: String) {
17+
process = Process(serviceName: serviceName, tags: TList<Tag>())
18+
self.collectorAddress = collectorAddress
19+
}
20+
21+
public func export(spans: [SpanData], explicitTimeout: TimeInterval? = nil) -> SpanExporterResultCode {
22+
var spanList = TList<Span>()
23+
spanList.append(contentsOf: Adapter.toJaeger(spans: spans))
24+
let batch = Batch(process: process, spans: spanList)
25+
let sender = Sender(host: collectorAddress)
26+
let success = sender.sendBatch(batch: batch)
27+
return success ? SpanExporterResultCode.success : SpanExporterResultCode.failure
28+
}
29+
30+
public func flush(explicitTimeout: TimeInterval? = nil) -> SpanExporterResultCode {
31+
return .success
32+
}
33+
34+
public func shutdown(explicitTimeout: TimeInterval? = nil) {
35+
}
3636
}
3737

3838
#endif

Sources/Exporters/OpenTelemetryProtocolGrpc/logs/OtlpLogExporter.swift

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,59 +13,59 @@ import OpenTelemetrySdk
1313
import OpenTelemetryProtocolExporterCommon
1414

1515
public class OtlpLogExporter : LogRecordExporter {
16-
let channel : GRPCChannel
17-
var logClient : Opentelemetry_Proto_Collector_Logs_V1_LogsServiceNIOClient
18-
let config : OtlpConfiguration
19-
var callOptions : CallOptions
20-
21-
public init(channel: GRPCChannel,
22-
config: OtlpConfiguration = OtlpConfiguration(),
23-
logger: Logging.Logger = Logging.Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() }),
24-
envVarHeaders: [(String, String)]? = EnvVarHeaders.attributes){
25-
self.channel = channel
26-
logClient = Opentelemetry_Proto_Collector_Logs_V1_LogsServiceNIOClient(channel: channel)
27-
self.config = config
28-
let userAgentHeader = (Constants.HTTP.userAgent, Headers.getUserAgentHeader())
29-
if let headers = envVarHeaders {
30-
var updatedHeaders = headers
31-
updatedHeaders.append(userAgentHeader)
32-
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
33-
} else if let headers = config.headers {
34-
var updatedHeaders = headers
35-
updatedHeaders.append(userAgentHeader)
36-
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
37-
}
38-
else {
39-
var headers = [(String, String)]()
40-
headers.append(userAgentHeader)
41-
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
42-
}
16+
let channel : GRPCChannel
17+
var logClient : Opentelemetry_Proto_Collector_Logs_V1_LogsServiceNIOClient
18+
let config : OtlpConfiguration
19+
var callOptions : CallOptions
20+
21+
public init(channel: GRPCChannel,
22+
config: OtlpConfiguration = OtlpConfiguration(),
23+
logger: Logging.Logger = Logging.Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() }),
24+
envVarHeaders: [(String, String)]? = EnvVarHeaders.attributes){
25+
self.channel = channel
26+
logClient = Opentelemetry_Proto_Collector_Logs_V1_LogsServiceNIOClient(channel: channel)
27+
self.config = config
28+
let userAgentHeader = (Constants.HTTP.userAgent, Headers.getUserAgentHeader())
29+
if let headers = envVarHeaders {
30+
var updatedHeaders = headers
31+
updatedHeaders.append(userAgentHeader)
32+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
33+
} else if let headers = config.headers {
34+
var updatedHeaders = headers
35+
updatedHeaders.append(userAgentHeader)
36+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
4337
}
44-
45-
public func export(logRecords: [ReadableLogRecord]) -> ExportResult {
46-
let logRequest = Opentelemetry_Proto_Collector_Logs_V1_ExportLogsServiceRequest.with { request in
47-
request.resourceLogs = LogRecordAdapter.toProtoResourceRecordLog(logRecordList: logRecords)
48-
}
49-
50-
if config.timeout > 0 {
51-
callOptions.timeLimit = TimeLimit.timeout(TimeAmount.nanoseconds(Int64(config.timeout.toNanoseconds)))
52-
}
53-
54-
55-
let export = logClient.export(logRequest, callOptions: callOptions)
56-
do {
57-
_ = try export.response.wait()
58-
return .success
59-
} catch {
60-
return .failure
61-
}
38+
else {
39+
var headers = [(String, String)]()
40+
headers.append(userAgentHeader)
41+
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
6242
}
63-
64-
public func shutdown() {
65-
_ = channel.close()
43+
}
44+
45+
public func export(logRecords: [ReadableLogRecord], explicitTimeout: TimeInterval? = nil) -> ExportResult {
46+
let logRequest = Opentelemetry_Proto_Collector_Logs_V1_ExportLogsServiceRequest.with { request in
47+
request.resourceLogs = LogRecordAdapter.toProtoResourceRecordLog(logRecordList: logRecords)
6648
}
67-
68-
public func forceFlush() -> ExportResult {
69-
.success
49+
let timeout = min(explicitTimeout ?? TimeInterval.greatestFiniteMagnitude, config.timeout)
50+
if timeout > 0 {
51+
callOptions.timeLimit = TimeLimit.timeout(TimeAmount.nanoseconds(Int64(timeout.toNanoseconds)))
52+
}
53+
54+
55+
let export = logClient.export(logRequest, callOptions: callOptions)
56+
do {
57+
_ = try export.response.wait()
58+
return .success
59+
} catch {
60+
return .failure
7061
}
62+
}
63+
64+
public func shutdown(explicitTimeout: TimeInterval? = nil) {
65+
_ = channel.close()
66+
}
67+
68+
public func forceFlush(explicitTimeout: TimeInterval? = nil) -> ExportResult {
69+
.success
70+
}
7171
}

Sources/Exporters/OpenTelemetryProtocolGrpc/trace/OtlpTraceExporter.swift

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -13,56 +13,58 @@ import OpenTelemetrySdk
1313
import OpenTelemetryProtocolExporterCommon
1414

1515
public class OtlpTraceExporter: SpanExporter {
16-
let channel: GRPCChannel
17-
var traceClient: Opentelemetry_Proto_Collector_Trace_V1_TraceServiceNIOClient
18-
let config : OtlpConfiguration
19-
var callOptions : CallOptions
20-
21-
public init(channel: GRPCChannel, config: OtlpConfiguration = OtlpConfiguration(), logger: Logging.Logger = Logging.Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() }), envVarHeaders: [(String,String)]? = EnvVarHeaders.attributes) {
22-
self.channel = channel
23-
traceClient = Opentelemetry_Proto_Collector_Trace_V1_TraceServiceNIOClient(channel: channel)
24-
self.config = config
25-
let userAgentHeader = (Constants.HTTP.userAgent, Headers.getUserAgentHeader())
26-
if let headers = envVarHeaders {
27-
var updatedHeaders = headers
28-
updatedHeaders.append(userAgentHeader)
29-
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
30-
} else if let headers = config.headers {
31-
var updatedHeaders = headers
32-
updatedHeaders.append(userAgentHeader)
33-
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
34-
} else {
35-
var headers = [(String, String)]()
36-
headers.append(userAgentHeader)
37-
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
38-
}
16+
17+
let channel: GRPCChannel
18+
var traceClient: Opentelemetry_Proto_Collector_Trace_V1_TraceServiceNIOClient
19+
let config : OtlpConfiguration
20+
var callOptions : CallOptions
21+
22+
public init(channel: GRPCChannel, config: OtlpConfiguration = OtlpConfiguration(), logger: Logging.Logger = Logging.Logger(label: "io.grpc", factory: { _ in SwiftLogNoOpLogHandler() }), envVarHeaders: [(String,String)]? = EnvVarHeaders.attributes) {
23+
self.channel = channel
24+
traceClient = Opentelemetry_Proto_Collector_Trace_V1_TraceServiceNIOClient(channel: channel)
25+
self.config = config
26+
let userAgentHeader = (Constants.HTTP.userAgent, Headers.getUserAgentHeader())
27+
if let headers = envVarHeaders {
28+
var updatedHeaders = headers
29+
updatedHeaders.append(userAgentHeader)
30+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
31+
} else if let headers = config.headers {
32+
var updatedHeaders = headers
33+
updatedHeaders.append(userAgentHeader)
34+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
35+
} else {
36+
var headers = [(String, String)]()
37+
headers.append(userAgentHeader)
38+
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
3939
}
40-
41-
public func export(spans: [SpanData]) -> SpanExporterResultCode {
42-
let exportRequest = Opentelemetry_Proto_Collector_Trace_V1_ExportTraceServiceRequest.with {
43-
$0.resourceSpans = SpanAdapter.toProtoResourceSpans(spanDataList: spans)
44-
}
45-
46-
if config.timeout > 0 {
47-
callOptions.timeLimit = TimeLimit.timeout(TimeAmount.nanoseconds(Int64(config.timeout.toNanoseconds)))
48-
}
49-
50-
let export = traceClient.export(exportRequest, callOptions: callOptions)
51-
52-
do {
53-
// wait() on the response to stop the program from exiting before the response is received.
54-
_ = try export.response.wait()
55-
return .success
56-
} catch {
57-
return .failure
58-
}
40+
}
41+
42+
43+
public func export(spans: [SpanData], explicitTimeout: TimeInterval? = nil) -> SpanExporterResultCode {
44+
let exportRequest = Opentelemetry_Proto_Collector_Trace_V1_ExportTraceServiceRequest.with {
45+
$0.resourceSpans = SpanAdapter.toProtoResourceSpans(spanDataList: spans)
5946
}
60-
61-
public func flush() -> SpanExporterResultCode {
62-
return .success
47+
let timeout = min(explicitTimeout ?? TimeInterval.greatestFiniteMagnitude, config.timeout)
48+
if timeout > 0 {
49+
callOptions.timeLimit = TimeLimit.timeout(TimeAmount.nanoseconds(Int64(timeout.toNanoseconds)))
6350
}
64-
65-
public func shutdown() {
66-
_ = channel.close()
51+
52+
let export = traceClient.export(exportRequest, callOptions: callOptions)
53+
54+
do {
55+
// wait() on the response to stop the program from exiting before the response is received.
56+
_ = try export.response.wait()
57+
return .success
58+
} catch {
59+
return .failure
6760
}
61+
}
62+
63+
public func flush(explicitTimeout: TimeInterval? = nil) -> SpanExporterResultCode {
64+
return .success
65+
}
66+
67+
public func shutdown(explicitTimeout: TimeInterval? = nil) {
68+
_ = channel.close()
69+
}
6870
}

0 commit comments

Comments
 (0)