-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathOpenTelemetry+Extensions.swift
More file actions
145 lines (118 loc) · 5.67 KB
/
Copy pathOpenTelemetry+Extensions.swift
File metadata and controls
145 lines (118 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2020-Present Datadog, Inc.
*/
import Foundation
import OpenTelemetryApi
import OpenTelemetrySdk
// MARK: - Resource accessors
/// Typed accessors over the OTel semantic-convention attribute keys we care
/// about. The encoders read service / version / environment / SDK info from
/// `SpanData.resource` instead of carrying them on the exporter's own struct.
public extension Resource {
var applicationName: String? {
get { attributes[SemanticConventions.Service.name.rawValue]?.description }
set { attributes[SemanticConventions.Service.name.rawValue] = newValue.map { .string($0) } }
}
var applicationVersion: String? {
get { attributes[SemanticConventions.Service.version.rawValue]?.description }
set { attributes[SemanticConventions.Service.version.rawValue] = newValue.map { .string($0) } }
}
var service: String? {
get { attributes[SemanticConventions.Service.namespace.rawValue]?.description }
set { attributes[SemanticConventions.Service.namespace.rawValue] = newValue.map { .string($0) } }
}
var sdkName: String? {
get { attributes[SemanticConventions.Telemetry.sdkName.rawValue]?.description }
set { attributes[SemanticConventions.Telemetry.sdkName.rawValue] = newValue.map { .string($0) } }
}
var sdkLanguage: String? {
get { attributes[SemanticConventions.Telemetry.sdkLanguage.rawValue]?.description }
set { attributes[SemanticConventions.Telemetry.sdkLanguage.rawValue] = newValue.map { .string($0) } }
}
var sdkVersion: String? {
get { attributes[SemanticConventions.Telemetry.sdkVersion.rawValue]?.description }
set { attributes[SemanticConventions.Telemetry.sdkVersion.rawValue] = newValue.map { .string($0) } }
}
var environment: String? {
get { attributes[SemanticConventions.Deployment.environmentName.rawValue]?.description }
set { attributes[SemanticConventions.Deployment.environmentName.rawValue] = newValue.map { .string($0) } }
}
/// Datadog telemetry namespace for `generate-metrics` series (gauge / count /
/// summary) produced by a meter provider. Used by the metric exporter as the
/// per-series namespace override.
var telemetryMetricNamespace: TelemetryMetric.Namespace? {
get { (attributes["dd.telemetry.metric.namespace"]?.description).flatMap(TelemetryMetric.Namespace.init(rawValue:)) }
set { attributes["dd.telemetry.metric.namespace"] = newValue.map { .string($0.rawValue) } }
}
/// Datadog telemetry namespace for `distributions` series (histograms) produced
/// by a meter provider. Used by the metric exporter as the per-series namespace
/// override. Kept separate from `telemetryMetricNamespace` because the two
/// payload types accept different namespace value sets.
var telemetryDistributionNamespace: TelemetryDistribution.Namespace? {
get { (attributes["dd.telemetry.distribution.namespace"]?.description).flatMap(TelemetryDistribution.Namespace.init(rawValue:)) }
set { attributes["dd.telemetry.distribution.namespace"] = newValue.map { .string($0.rawValue) } }
}
}
// MARK: - Test-attribute accessors on SpanData / AttributeValue dictionaries
public extension SpanData {
var testSessionId: SpanId? { attributes.testSessionId }
var testSuiteId: SpanId? { attributes.testSuiteId }
var testModuleId: SpanId? { attributes.testModuleId }
}
public extension Dictionary where Key == String, Value == AttributeValue {
var testSessionId: SpanId? {
get { decodeSpanIdAttribute("test_session_id") }
set { self["test_session_id"] = newValue.map { .string($0.hexString) } }
}
var testSuiteId: SpanId? {
get { decodeSpanIdAttribute("test_suite_id") }
set { self["test_suite_id"] = newValue.map { .string($0.hexString) } }
}
var testModuleId: SpanId? {
get { decodeSpanIdAttribute("test_module_id") }
set { self["test_module_id"] = newValue.map { .string($0.hexString) } }
}
var type: String? {
get { self["type"]?.description }
set { self["type"] = newValue.map { .string($0) } }
}
var resource: String? {
get { self["resource"]?.description }
set { self["resource"] = newValue.map { .string($0) } }
}
var itrCorrelationId: String? {
get { self["itr_correlation_id"]?.description }
set { self["itr_correlation_id"] = newValue.map { .string($0) } }
}
private func decodeSpanIdAttribute(_ key: String) -> SpanId? {
guard let raw = self[key]?.description else { return nil }
let id = SpanId(fromHexString: raw)
return id == .invalid ? nil : id
}
}
// MARK: - SpanExporterResultCode / ExportResult combinators
/// Lets call sites do `code1 && code2 && code3` without unpacking each
/// `success` case manually. Used to combine flush results across the
/// per-feature sub-exporters.
internal protocol ResultCodeCompatible {
var isSuccess: Bool { get }
}
extension ResultCodeCompatible {
static func && (lhs: Self, rhs: ResultCodeCompatible) -> Bool {
lhs.isSuccess && rhs.isSuccess
}
static func && (lhs: Bool, rhs: Self) -> Bool {
lhs && rhs.isSuccess
}
static func && (lhs: Self, rhs: Bool) -> Bool {
lhs.isSuccess && rhs
}
}
extension SpanExporterResultCode: ResultCodeCompatible {
var isSuccess: Bool { self == .success }
}
extension ExportResult: ResultCodeCompatible {
var isSuccess: Bool { self == .success }
}