Skip to content
This repository was archived by the owner on Jul 11, 2025. It is now read-only.

Commit a095f31

Browse files
authored
Add OTel semantic network span attributes (#13)
1 parent ff3b3b8 commit a095f31

File tree

3 files changed

+326
-0
lines changed

3 files changed

+326
-0
lines changed

Package.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import PackageDescription
33

44
let package = Package(
55
name: "swift-distributed-tracing-extras",
6+
platforms: [
7+
.macOS(.v10_13),
8+
.iOS(.v11),
9+
],
610
products: [
711
.library(name: "OpenTelemetrySemanticConventions", targets: ["OpenTelemetrySemanticConventions"]),
812
],
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Distributed Tracing open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift Distributed Tracing project
6+
// authors
7+
// Licensed under Apache License v2.0
8+
//
9+
// See LICENSE.txt for license information
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Tracing
16+
17+
extension SpanAttributes {
18+
/// General network connection attributes.
19+
///
20+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#general-network-connection-attributes)
21+
public var network: NetworkAttributes {
22+
get {
23+
.init(attributes: self)
24+
}
25+
set {
26+
self = newValue.attributes
27+
}
28+
}
29+
}
30+
31+
/// General network connection attributes.
32+
///
33+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#general-network-connection-attributes)
34+
@dynamicMemberLookup
35+
public struct NetworkAttributes: SpanAttributeNamespace {
36+
public var attributes: SpanAttributes
37+
38+
public init(attributes: SpanAttributes) {
39+
self.attributes = attributes
40+
}
41+
42+
public struct NestedSpanAttributes: NestedSpanAttributesProtocol {
43+
public init() {}
44+
45+
/// Transport protocol used.
46+
public var transport: Key<Transport> { "net.transport" }
47+
}
48+
49+
/// Possible values for the `network.transport` span attribute.
50+
///
51+
/// OpenTelemetry Spec: [Network transport attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#network-transport-attributes)
52+
public struct Transport: RawRepresentable, SpanAttributeConvertible {
53+
public let rawValue: String
54+
55+
public init(rawValue: String) {
56+
self.rawValue = rawValue
57+
}
58+
59+
/// `ip_tcp`.
60+
public static let ipTCP = Transport(rawValue: "ip_tcp")
61+
62+
/// `ip_udp`.
63+
public static let ipUDP = Transport(rawValue: "ip_udp")
64+
65+
/// Another IP-based protocol.
66+
public static let ip = Transport(rawValue: "ip")
67+
68+
/// Unix Domain socket.
69+
public static let unix = Transport(rawValue: "unix")
70+
71+
/// Named or anonymous pipe.
72+
public static let pipe = Transport(rawValue: "pipe")
73+
74+
/// In-process communication.
75+
///
76+
/// Signals that there is only in-process communication not using a "real" network protocol in cases where network
77+
/// attributes would normally be expected. Usually all other network attributes can be left out in that case.
78+
public static let inProcess = Transport(rawValue: "inproc")
79+
80+
/// Something else (non IP-based).
81+
public static let other = Transport(rawValue: "other")
82+
83+
public func toSpanAttribute() -> SpanAttribute {
84+
.string(rawValue)
85+
}
86+
}
87+
88+
// MARK: - Network Peer Attributes
89+
90+
/// Network peer attributes.
91+
///
92+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#network-transport-attributes)
93+
public var peer: NetworkPeerAttributes {
94+
get {
95+
.init(attributes: self.attributes)
96+
}
97+
set {
98+
self.attributes = newValue.attributes
99+
}
100+
}
101+
102+
/// Network peer attributes.
103+
///
104+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#network-transport-attributes)
105+
public struct NetworkPeerAttributes: SpanAttributeNamespace {
106+
public var attributes: SpanAttributes
107+
108+
public init(attributes: SpanAttributes) {
109+
self.attributes = attributes
110+
}
111+
112+
public struct NestedSpanAttributes: NestedSpanAttributesProtocol {
113+
public init() {}
114+
115+
/// Remote address of the peer (dotted decimal for IPv4 or [RFC 5952](https://tools.ietf.org/html/rfc5952) for IPv6),
116+
/// e.g. `127.0.0.1`.
117+
public var ip: Key<String> { "net.peer.ip" }
118+
119+
/// Remote port number, e.g. `443`.
120+
public var port: Key<Int> { "net.peer.port" }
121+
122+
/// Remote hostname or similar. E.g. `example.com`.
123+
///
124+
/// - Warning: The peer name SHOULD NOT be set if capturing it would require an extra DNS lookup.
125+
public var name: Key<String> { "net.peer.name" }
126+
}
127+
}
128+
129+
// MARK: - Network Host Attributes
130+
131+
/// Network host attributes.
132+
///
133+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#network-transport-attributes)
134+
public var host: NetworkHostAttributes {
135+
get {
136+
.init(attributes: self.attributes)
137+
}
138+
set {
139+
self.attributes = newValue.attributes
140+
}
141+
}
142+
143+
/// Network host attributes.
144+
///
145+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#network-transport-attributes)
146+
public struct NetworkHostAttributes: SpanAttributeNamespace {
147+
public var attributes: SpanAttributes
148+
149+
public init(attributes: SpanAttributes) {
150+
self.attributes = attributes
151+
}
152+
153+
public struct NestedSpanAttributes: NestedSpanAttributesProtocol {
154+
public init() {}
155+
156+
/// Remote address of the host (dotted decimal for IPv4 or [RFC 5952](https://tools.ietf.org/html/rfc5952) for IPv6),
157+
/// useful in case of a multi-IP host. E.g. `192.168.0.1`.
158+
public var ip: Key<String> { "net.host.ip" }
159+
160+
/// Host port number, e.g. `35555`.
161+
public var port: Key<Int> { "net.host.port" }
162+
163+
/// Local hostname or similar. E.g. `localhost`.
164+
///
165+
/// - Warning: The peer name SHOULD NOT be set if capturing it would require an extra DNS lookup.
166+
public var name: Key<String> { "net.host.name" }
167+
}
168+
169+
/// Network host connection attributes.
170+
///
171+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#network-transport-attributes)
172+
public var connection: ConnectionAttributes {
173+
get {
174+
.init(attributes: self.attributes)
175+
}
176+
set {
177+
self.attributes = newValue.attributes
178+
}
179+
}
180+
181+
/// Network host connection attributes.
182+
///
183+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#network-transport-attributes)
184+
public struct ConnectionAttributes: SpanAttributeNamespace {
185+
public var attributes: SpanAttributes
186+
187+
public init(attributes: SpanAttributes) {
188+
self.attributes = attributes
189+
}
190+
191+
public struct NestedSpanAttributes: NestedSpanAttributesProtocol {
192+
public init() {}
193+
194+
/// The internet connection type currently being used by the host. E.g. `wifi`.
195+
public var type: Key<String> { "net.host.connection.type" }
196+
197+
/// This describes more details regarding the ``type``.
198+
/// It may be the type of cell technology connection, but it could be used for describing details about a wifi connection. E.g. `LTE`.
199+
public var subtype: Key<String> { "net.host.connection.subtype" }
200+
}
201+
}
202+
203+
/// Network host carrier attributes.
204+
///
205+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#network-transport-attributes)
206+
public var carrier: CarrierAttributes {
207+
get {
208+
.init(attributes: self.attributes)
209+
}
210+
set {
211+
self.attributes = newValue.attributes
212+
}
213+
}
214+
215+
/// Network host carrier attributes.
216+
///
217+
/// OpenTelemetry Spec: [General network connection attributes](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.11.0/specification/trace/semantic_conventions/span-general.md#network-transport-attributes)
218+
public struct CarrierAttributes: SpanAttributeNamespace {
219+
public var attributes: SpanAttributes
220+
221+
public init(attributes: SpanAttributes) {
222+
self.attributes = attributes
223+
}
224+
225+
public struct NestedSpanAttributes: NestedSpanAttributesProtocol {
226+
public init() {}
227+
228+
/// The name of the mobile carrier.
229+
public var name: Key<String> { "net.host.carrier.name" }
230+
231+
/// The mobile carrier country code. E.g. `310`.
232+
public var mcc: Key<String> { "net.host.carrier.mcc" }
233+
234+
/// The mobile carrier network code. E.g. `001`.
235+
public var mnc: Key<String> { "net.host.carrier.mnc" }
236+
237+
/// The `ISO 3166-1 alpha-2` 2-character country code associated with the mobile carrier network. E.g. `DE`.
238+
public var icc: Key<String> { "net.host.carrier.icc" }
239+
}
240+
}
241+
}
242+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift Distributed Tracing open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift Distributed Tracing project
6+
// authors
7+
// Licensed under Apache License v2.0
8+
//
9+
// See LICENSE.txt for license information
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import OpenTelemetrySemanticConventions
16+
import Tracing
17+
import XCTest
18+
19+
final class NetworkSemanticsTests: XCTestCase {
20+
func test_networkNamespace() {
21+
var attributes = SpanAttributes()
22+
23+
attributes.network.transport = .ipTCP
24+
XCTAssertEqual(attributes["net.transport"]?.toSpanAttribute(), "ip_tcp")
25+
26+
attributes.network.transport = .ipUDP
27+
XCTAssertEqual(attributes["net.transport"]?.toSpanAttribute(), "ip_udp")
28+
29+
attributes.network.transport = .ip
30+
XCTAssertEqual(attributes["net.transport"]?.toSpanAttribute(), "ip")
31+
32+
attributes.network.transport = .unix
33+
XCTAssertEqual(attributes["net.transport"]?.toSpanAttribute(), "unix")
34+
35+
attributes.network.transport = .pipe
36+
XCTAssertEqual(attributes["net.transport"]?.toSpanAttribute(), "pipe")
37+
38+
attributes.network.transport = .inProcess
39+
XCTAssertEqual(attributes["net.transport"]?.toSpanAttribute(), "inproc")
40+
41+
attributes.network.transport = .other
42+
XCTAssertEqual(attributes["net.transport"]?.toSpanAttribute(), "other")
43+
44+
attributes.network.peer.ip = "127.0.0.1"
45+
XCTAssertEqual(attributes["net.peer.ip"]?.toSpanAttribute(), "127.0.0.1")
46+
47+
attributes.network.peer.port = 80
48+
XCTAssertEqual(attributes["net.peer.port"]?.toSpanAttribute(), 80)
49+
50+
attributes.network.peer.name = "swift.org"
51+
XCTAssertEqual(attributes["net.peer.name"]?.toSpanAttribute(), "swift.org")
52+
53+
attributes.network.host.ip = "127.0.0.1"
54+
XCTAssertEqual(attributes["net.host.ip"]?.toSpanAttribute(), "127.0.0.1")
55+
56+
attributes.network.host.port = 35555
57+
XCTAssertEqual(attributes["net.host.port"]?.toSpanAttribute(), 35555)
58+
59+
attributes.network.host.name = "localhost"
60+
XCTAssertEqual(attributes["net.host.name"]?.toSpanAttribute(), "localhost")
61+
62+
attributes.network.host.connection.type = "wifi"
63+
XCTAssertEqual(attributes["net.host.connection.type"]?.toSpanAttribute(), "wifi")
64+
65+
attributes.network.host.connection.subtype = "LTE"
66+
XCTAssertEqual(attributes["net.host.connection.subtype"]?.toSpanAttribute(), "LTE")
67+
68+
attributes.network.host.carrier.name = "42"
69+
XCTAssertEqual(attributes["net.host.carrier.name"]?.toSpanAttribute(), "42")
70+
71+
attributes.network.host.carrier.mcc = "42"
72+
XCTAssertEqual(attributes["net.host.carrier.mcc"]?.toSpanAttribute(), "42")
73+
74+
attributes.network.host.carrier.mnc = "42"
75+
XCTAssertEqual(attributes["net.host.carrier.mnc"]?.toSpanAttribute(), "42")
76+
77+
attributes.network.host.carrier.icc = "DE"
78+
XCTAssertEqual(attributes["net.host.carrier.icc"]?.toSpanAttribute(), "DE")
79+
}
80+
}

0 commit comments

Comments
 (0)