diff --git a/Sources/TracingOpenTelemetrySemanticConventions/SpanAttributes+URLSemantics.swift b/Sources/TracingOpenTelemetrySemanticConventions/SpanAttributes+URLSemantics.swift new file mode 100644 index 0000000..a4f4a23 --- /dev/null +++ b/Sources/TracingOpenTelemetrySemanticConventions/SpanAttributes+URLSemantics.swift @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Distributed Tracing open source project +// +// Copyright (c) 2023 Apple Inc. and the Swift Distributed Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift Distributed Tracing project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Tracing + +extension SpanAttributes { + /// URL attributes. + /// + /// OpenTelemetry Spec: [URL attributes](https://opentelemetry.io/docs/specs/semconv/attributes-registry/url/) + public var url: URLAttributes { + get { + .init(attributes: self) + } + set { + self = newValue.attributes + } + } +} + +/// URL attributes. +/// +/// OpenTelemetry Spec: [URL attributes](https://opentelemetry.io/docs/specs/semconv/attributes-registry/url/) +@dynamicMemberLookup +public struct URLAttributes: SpanAttributeNamespace { + public var attributes: SpanAttributes + + public init(attributes: SpanAttributes) { + self.attributes = attributes + } + + public struct NestedSpanAttributes: NestedSpanAttributesProtocol { + public init() {} + + /// Domain extracted from the url.full, such as “opentelemetry.io”. + public var domain: Key { "url.domain" } + + /// The file extension extracted from the url.full, excluding the leading dot. + public var `extension`: Key { "url.extension" } + + /// The URI fragment component + public var fragment: Key { "url.fragment" } + + /// Absolute URL describing a network resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986) + public var full: Key { "url.full" } + + /// Unmodified original URL as seen in the event source + public var original: Key { "url.original" } + + /// The URI path component + public var path: Key { "url.path" } + + /// Port extracted from the url.full + public var port: Key { "url.port" } + + /// The URI query component + public var query: Key { "url.query" } + + /// The highest registered url domain, stripped of the subdomain + public var registeredDomain: Key { "url.registered_domain" } + + /// The URI scheme component identifying the used protocol + public var scheme: Key { "url.scheme" } + + /// The subdomain portion of a fully qualified domain name includes all of the names except the + /// host name under the registered\_domain. In a partially qualified domain, or if the qualification + /// level of the full name cannot be determined, subdomain contains all of the names below the + /// registered domain + public var subdomain: Key { "url.subdomain" } + + /// The low-cardinality template of an absolute path reference + public var template: Key { "url.template" } + + /// The effective top level domain (eTLD), also known as the domain suffix, is the last part of the + /// domain name. For example, the top level domain for example.com is com + public var topLevelDomain: Key { "url.top_level_domain" } + } +} diff --git a/Tests/TracingOpenTelemetrySemanticConventionsTests/URLSemanticsTests.swift b/Tests/TracingOpenTelemetrySemanticConventionsTests/URLSemanticsTests.swift new file mode 100644 index 0000000..2f10310 --- /dev/null +++ b/Tests/TracingOpenTelemetrySemanticConventionsTests/URLSemanticsTests.swift @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift Distributed Tracing open source project +// +// Copyright (c) 2023 Apple Inc. and the Swift Distributed Tracing project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of Swift Distributed Tracing project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +import Tracing +import TracingOpenTelemetrySemanticConventions +import XCTest + +final class URLSemanticsTests: XCTestCase { + func test_url() { + var attributes = SpanAttributes() + + attributes.url.domain = "www.foo.bar" + attributes.url.`extension` = "png" + attributes.url.fragment = "SemConv" + attributes.url.full = "https://www.foo.bar/search?q=OpenTelemetry#SemConv" + attributes.url.original = "https://www.foo.bar/search?q=OpenTelemetry#SemConv" + attributes.url.path = "/search" + attributes.url.port = 443 + attributes.url.query = "q=OpenTelemetry" + attributes.url.registeredDomain = "example.com" + attributes.url.scheme = "https" + attributes.url.subdomain = "east" + attributes.url.template = "/users/{id}" + attributes.url.topLevelDomain = "co.uk" + + XCTAssertSpanAttributesEqual(attributes, [ + "url.domain": "www.foo.bar", + "url.extension": "png", + "url.fragment": "SemConv", + "url.full": "https://www.foo.bar/search?q=OpenTelemetry#SemConv", + "url.original": "https://www.foo.bar/search?q=OpenTelemetry#SemConv", + "url.path": "/search", + "url.port": 443, + "url.query": "q=OpenTelemetry", + "url.registered_domain": "example.com", + "url.scheme": "https", + "url.subdomain": "east", + "url.template": "/users/{id}", + "url.top_level_domain": "co.uk", + ]) + } +}