Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public struct EnvironmentContextPropagator: TextMapPropagator {
* EnvironmentMappingSetter adapts a `Setter` to normalize propagation keys to environment variable format.
*
* Normalization rules per OpenTelemetry specification:
* - Replaces an empty key name with a single underscore (`_`)
* - Converts keys to uppercase (e.g., "traceparent" → "TRACEPARENT")
* - Replaces all non-alphanumeric characters (except underscore) with underscores
* (e.g., "x-b3-traceid" → "X_B3_TRACEID")
Expand Down Expand Up @@ -72,6 +73,7 @@ public struct EnvironmentMappingSetter: Setter {
* (e.g. `"traceparent"` instead of `"TRACEPARENT"`) are silently ignored.
*
* Normalization rules:
* - Replaces an empty key name with a single underscore (`_`)
* - Converts the requested key to uppercase (e.g., `"traceparent"` → `"TRACEPARENT"`)
* - Replaces every character that is not an ASCII letter, digit, or underscore with `_`
* (e.g., `"x-b3-traceid"` → `"X_B3_TRACEID"`)
Expand Down Expand Up @@ -100,10 +102,15 @@ public struct EnvironmentMappingGetter: Getter {
}

/// Normalizes a key to environment-variable format:
/// - Replaces an empty key name with a single underscore (`_`)
/// - Uppercases ASCII letters (`a–z` → `A–Z`)
/// - Replaces every character that is not an ASCII letter, digit, or underscore with `_`
/// - Prefixes the result with `_` if it would otherwise start with an ASCII digit
private func normalizeKeyForEnvironment(_ key: String) -> String {
if key.isEmpty {
return "_"
}

var result = ""
result.reserveCapacity(key.utf8.count + 1)
// An env-var name must not start with a digit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ class EnvironmentContextPropagatorTests: XCTestCase {
XCTAssertEqual(carrier, ["_FOO": "v"])
}

func testEmptyStringProducesEmptyString() {
func testEmptyStringNormalizesToUnderscore() {
var carrier = [String: String]()
setter.set(carrier: &carrier, key: "", value: "v")
XCTAssertEqual(carrier, ["": "v"])
XCTAssertEqual(carrier, ["_": "v"])
}

func testOnlySpecialCharacters() {
Expand All @@ -134,4 +134,9 @@ class EnvironmentContextPropagatorTests: XCTestCase {
let carrier = ["TRACEPARENT": "value"]
XCTAssertNil(getter.get(carrier: carrier, key: "tracestate"))
}

func testGetterEmptyKeyNormalizesToUnderscore() {
let carrier = ["_": "value"]
XCTAssertEqual(getter.get(carrier: carrier, key: ""), ["value"])
}
}
Loading