Skip to content

Commit 6969ff9

Browse files
author
Ignacio Bonafonte
authored
Merge branch 'main' into fix-span-end-check
2 parents 102dbd1 + 2d7f897 commit 6969ff9

File tree

11 files changed

+115
-14
lines changed

11 files changed

+115
-14
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//
2+
// Copyright The OpenTelemetry Authors
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
import Foundation
7+
8+
public enum Constants {
9+
enum HTTP {
10+
static let userAgent = "User-Agent"
11+
}
12+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// Copyright The OpenTelemetry Authors
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
import Foundation
7+
import OpenTelemetryApi
8+
9+
public struct Headers {
10+
// GetUserAgentHeader returns an OTLP header value of the form "OTel OTLP Exporter Swift/{{ .Version }}"
11+
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#user-agent
12+
public static func getUserAgentHeader() -> String {
13+
var version = OpenTelemetry.version
14+
if !version.isEmpty && version.hasPrefix("v") {
15+
version = String(version.dropFirst(1))
16+
}
17+
let userAgent = "OTel-OTLP-Exporter-Swift/\(version)"
18+
19+
return userAgent
20+
}
21+
}

Sources/Exporters/OpenTelemetryProtocol/common/OtlpHttpExporterBase.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class OtlpHttpExporterBase {
2525
do {
2626
request.httpMethod = "POST"
2727
request.httpBody = try body.serializedData()
28+
request.setValue(Headers.getUserAgentHeader(), forHTTPHeaderField: Constants.HTTP.userAgent)
2829
request.setValue("application/x-protobuf", forHTTPHeaderField: "Content-Type")
2930
} catch {
3031
print("Error serializing body: \(error)")

Sources/Exporters/OpenTelemetryProtocol/logs/OtlpLogExporter.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,20 @@ public class OtlpLogExporter : LogRecordExporter {
2424
self.channel = channel
2525
logClient = Opentelemetry_Proto_Collector_Logs_V1_LogsServiceNIOClient(channel: channel)
2626
self.config = config
27+
let userAgentHeader = (Constants.HTTP.userAgent, Headers.getUserAgentHeader())
2728
if let headers = envVarHeaders {
28-
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
29+
var updatedHeaders = headers
30+
updatedHeaders.append(userAgentHeader)
31+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
2932
} else if let headers = config.headers {
30-
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
33+
var updatedHeaders = headers
34+
updatedHeaders.append(userAgentHeader)
35+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
3136
}
3237
else {
33-
callOptions = CallOptions(logger: logger)
38+
var headers = [(String, String)]()
39+
headers.append(userAgentHeader)
40+
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
3441
}
3542
}
3643

Sources/Exporters/OpenTelemetryProtocol/metric/OtlpMetricExporter.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,20 @@ public class OtlpMetricExporter: MetricExporter {
2323
self.channel = channel
2424
self.config = config
2525
self.metricClient = Opentelemetry_Proto_Collector_Metrics_V1_MetricsServiceNIOClient(channel: self.channel)
26+
let userAgentHeader = (Constants.HTTP.userAgent, Headers.getUserAgentHeader())
2627
if let headers = envVarHeaders {
27-
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
28+
var updatedHeaders = headers
29+
updatedHeaders.append(userAgentHeader)
30+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
2831
} else if let headers = config.headers {
29-
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
32+
var updatedHeaders = headers
33+
updatedHeaders.append(userAgentHeader)
34+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
3035
}
3136
else {
32-
callOptions = CallOptions(logger: logger)
37+
var headers = [(String, String)]()
38+
headers.append(userAgentHeader)
39+
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
3340
}
3441
}
3542

Sources/Exporters/OpenTelemetryProtocol/trace/OtlpTraceExporter.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,20 @@ public class OtlpTraceExporter: SpanExporter {
2121
self.channel = channel
2222
traceClient = Opentelemetry_Proto_Collector_Trace_V1_TraceServiceNIOClient(channel: channel)
2323
self.config = config
24+
let userAgentHeader = (Constants.HTTP.userAgent, Headers.getUserAgentHeader())
2425
if let headers = envVarHeaders {
25-
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
26+
var updatedHeaders = headers
27+
updatedHeaders.append(userAgentHeader)
28+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
2629
} else if let headers = config.headers {
30+
var updatedHeaders = headers
31+
updatedHeaders.append(userAgentHeader)
32+
callOptions = CallOptions(customMetadata: HPACKHeaders(updatedHeaders), logger: logger)
33+
} else {
34+
var headers = [(String, String)]()
35+
headers.append(userAgentHeader)
2736
callOptions = CallOptions(customMetadata: HPACKHeaders(headers), logger: logger)
2837
}
29-
else {
30-
callOptions = CallOptions(logger: logger)
31-
}
3238
}
3339

3440
public func export(spans: [SpanData]) -> SpanExporterResultCode {

Tests/ExportersTests/OpenTelemetryProtocol/OtlpHttpLogRecordExporterTests.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,14 @@ class OtlpHttpLogRecordExporterTests: XCTestCase {
4545

4646
let endpoint = URL(string: "http://localhost:\(testServer.serverPort)")!
4747
let exporter = OtlpHttpLogExporter(endpoint: endpoint)
48-
4948
let _ = exporter.export(logRecords: [logRecord])
5049

5150
// TODO: Use protobuf to verify that we have received the correct Log records
52-
XCTAssertNoThrow(try testServer.receiveHead())
51+
XCTAssertNoThrow(try testServer.receiveHeadAndVerify { head in
52+
let otelVersion = Headers.getUserAgentHeader()
53+
XCTAssertTrue(head.headers.contains(name: Constants.HTTP.userAgent))
54+
XCTAssertEqual(otelVersion, head.headers.first(name: Constants.HTTP.userAgent))
55+
})
5356
XCTAssertNoThrow(try testServer.receiveBodyAndVerify() { body in
5457
var contentsBuffer = ByteBuffer(buffer: body)
5558
let contents = contentsBuffer.readString(length: contentsBuffer.readableBytes)!

Tests/ExportersTests/OpenTelemetryProtocol/OtlpHttpMetricsExporterTest.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ class OtlpHttpMetricsExporterTest: XCTestCase {
5555
}
5656
XCTAssertEqual(result, MetricExporterResultCode.success)
5757

58-
XCTAssertNoThrow(try testServer.receiveHead())
58+
XCTAssertNoThrow(try testServer.receiveHeadAndVerify { head in
59+
let otelVersion = Headers.getUserAgentHeader()
60+
XCTAssertTrue(head.headers.contains(name: Constants.HTTP.userAgent))
61+
XCTAssertEqual(otelVersion, head.headers.first(name: Constants.HTTP.userAgent))
62+
})
5963
XCTAssertNoThrow(try testServer.receiveBodyAndVerify() { body in
6064
var contentsBuffer = ByteBuffer(buffer: body)
6165
let contents = contentsBuffer.readString(length: contentsBuffer.readableBytes)!

Tests/ExportersTests/OpenTelemetryProtocol/OtlpHttpTraceExporterTests.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class OtlpHttpTraceExporterTests: XCTestCase {
2525
override func tearDown() {
2626
XCTAssertNoThrow(try testServer.stop())
2727
XCTAssertNoThrow(try group.syncShutdownGracefully())
28+
2829
}
2930

3031
// This is a somewhat hacky solution to verifying that the spans got across correctly. It simply looks for the metric
@@ -41,7 +42,11 @@ class OtlpHttpTraceExporterTests: XCTestCase {
4142
spans.append(generateFakeSpan(endpointName: endpointName2))
4243
let _ = exporter.export(spans: spans)
4344

44-
XCTAssertNoThrow(try testServer.receiveHead())
45+
XCTAssertNoThrow(try testServer.receiveHeadAndVerify { head in
46+
let otelVersion = Headers.getUserAgentHeader()
47+
XCTAssertTrue(head.headers.contains(name: Constants.HTTP.userAgent))
48+
XCTAssertEqual(otelVersion, head.headers.first(name: Constants.HTTP.userAgent))
49+
})
4550
XCTAssertNoThrow(try testServer.receiveBodyAndVerify() { body in
4651
var contentsBuffer = ByteBuffer(buffer: body)
4752
let contents = contentsBuffer.readString(length: contentsBuffer.readableBytes)!

Tests/ExportersTests/OpenTelemetryProtocol/OtlpMetricExporterTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class OtlpMetricExproterTests: XCTestCase {
6161
func testConfigHeadersIsNil_whenDefaultInitCalled() throws {
6262
let exporter = OtlpMetricExporter(channel: channel)
6363
XCTAssertNil(exporter.config.headers)
64+
65+
verifyUserAgentIsSet(exporter: exporter)
6466
}
6567

6668
func testConfigHeadersAreSet_whenInitCalledWithCustomConfig() throws {
@@ -70,12 +72,16 @@ class OtlpMetricExproterTests: XCTestCase {
7072
XCTAssertEqual(exporter.config.headers?[0].0, "FOO")
7173
XCTAssertEqual(exporter.config.headers?[0].1, "BAR")
7274
XCTAssertEqual("BAR", exporter.callOptions?.customMetadata.first(name: "FOO"))
75+
76+
verifyUserAgentIsSet(exporter: exporter)
7377
}
7478

7579
func testConfigHeadersAreSet_whenInitCalledWithExplicitHeaders() throws {
7680
let exporter = OtlpMetricExporter(channel: channel, envVarHeaders: [("FOO", "BAR")])
7781
XCTAssertNil(exporter.config.headers)
7882
XCTAssertEqual("BAR", exporter.callOptions?.customMetadata.first(name: "FOO"))
83+
84+
verifyUserAgentIsSet(exporter: exporter)
7985
}
8086

8187
func testGaugeExport() {
@@ -167,6 +173,18 @@ class OtlpMetricExproterTests: XCTestCase {
167173
metric.data.append(data)
168174
return metric
169175
}
176+
177+
func verifyUserAgentIsSet(exporter: OtlpMetricExporter) {
178+
if let callOptions = exporter.callOptions {
179+
let customMetadata = callOptions.customMetadata
180+
let userAgent = Headers.getUserAgentHeader()
181+
if customMetadata.contains(name: Constants.HTTP.userAgent) && customMetadata.first(name: Constants.HTTP.userAgent) == userAgent {
182+
return
183+
}
184+
}
185+
XCTFail("User-Agent header was not set correctly")
186+
}
187+
170188
}
171189

172190
class FakeMetricCollector: Opentelemetry_Proto_Collector_Metrics_V1_MetricsServiceProvider {

0 commit comments

Comments
 (0)