@@ -6,7 +6,30 @@ import Foundation
66import OpenTelemetryApi
77import OpenTelemetrySdk
88
9- public struct MetricsAdapter {
9+ public enum MetricsAdapter {
10+ public static func toProtoResourceMetrics( stableMetricData: [ StableMetricData ] ) -> [ Opentelemetry_Proto_Metrics_V1_ResourceMetrics ] {
11+ let resourceAndScopeMap = groupByResouceAndScope ( stableMetricData: stableMetricData)
12+
13+ var resourceMetrics = [ Opentelemetry_Proto_Metrics_V1_ResourceMetrics] ( )
14+ resourceAndScopeMap. forEach { resMap in
15+ var instrumentationScopeMetrics = [ Opentelemetry_Proto_Metrics_V1_ScopeMetrics] ( )
16+ resMap. value. forEach { instScope in
17+ var protoInst = Opentelemetry_Proto_Metrics_V1_ScopeMetrics ( )
18+ protoInst. scope =
19+ CommonAdapter . toProtoInstrumentationScope ( instrumentationScopeInfo: instScope. key)
20+ instScope. value. forEach {
21+ protoInst. metrics. append ( $0)
22+ }
23+ instrumentationScopeMetrics. append ( protoInst)
24+ }
25+ var resourceMetric = Opentelemetry_Proto_Metrics_V1_ResourceMetrics ( )
26+ resourceMetric. resource = ResourceAdapter . toProtoResource ( resource: resMap. key)
27+ resourceMetric. scopeMetrics. append ( contentsOf: instrumentationScopeMetrics)
28+ resourceMetrics. append ( resourceMetric)
29+ }
30+ return resourceMetrics
31+ }
32+
1033 public static func toProtoResourceMetrics( metricDataList: [ Metric ] ) -> [ Opentelemetry_Proto_Metrics_V1_ResourceMetrics ] {
1134 let resourceAndScopeMap = groupByResouceAndScope ( metricDataList: metricDataList)
1235 var resourceMetrics = [ Opentelemetry_Proto_Metrics_V1_ResourceMetrics] ( )
@@ -15,7 +38,7 @@ public struct MetricsAdapter {
1538 var instrumentationScopeMetrics = [ Opentelemetry_Proto_Metrics_V1_ScopeMetrics] ( )
1639 resMap. value. forEach { instScope in
1740 var protoInst =
18- Opentelemetry_Proto_Metrics_V1_ScopeMetrics ( )
41+ Opentelemetry_Proto_Metrics_V1_ScopeMetrics ( )
1942 protoInst. scope =
2043 CommonAdapter . toProtoInstrumentationScope ( instrumentationScopeInfo: instScope. key)
2144 instScope. value. forEach {
@@ -32,6 +55,17 @@ public struct MetricsAdapter {
3255 return resourceMetrics
3356 }
3457
58+ private static func groupByResouceAndScope( stableMetricData: [ StableMetricData ] ) -> [ Resource : [ InstrumentationScopeInfo : [ Opentelemetry_Proto_Metrics_V1_Metric ] ] ] {
59+ var results = [ Resource: [ InstrumentationScopeInfo: [ Opentelemetry_Proto_Metrics_V1_Metric] ] ] ( )
60+
61+ stableMetricData. forEach {
62+ if let metric = toProtoMetric ( stableMetric: $0) {
63+ results [ $0. resource, default: [ InstrumentationScopeInfo: [ Opentelemetry_Proto_Metrics_V1_Metric] ] ( ) ] [ $0. instrumentationScopeInfo, default: [ Opentelemetry_Proto_Metrics_V1_Metric] ( ) ] . append ( metric)
64+ }
65+ }
66+ return results
67+ }
68+
3569 private static func groupByResouceAndScope( metricDataList: [ Metric ] ) -> [ Resource : [ InstrumentationScopeInfo : [ Opentelemetry_Proto_Metrics_V1_Metric ] ] ] {
3670 var results = [ Resource: [ InstrumentationScopeInfo: [ Opentelemetry_Proto_Metrics_V1_Metric] ] ] ( )
3771
@@ -45,6 +79,151 @@ public struct MetricsAdapter {
4579 return results
4680 }
4781
82+ public static func toProtoMetric( stableMetric: StableMetricData ) -> Opentelemetry_Proto_Metrics_V1_Metric ? {
83+ var protoMetric = Opentelemetry_Proto_Metrics_V1_Metric ( )
84+ protoMetric. name = stableMetric. name
85+ protoMetric. unit = stableMetric. unit
86+ protoMetric. description_p = stableMetric. description
87+ if stableMetric. data. points. isEmpty { return nil }
88+
89+ stableMetric. data. points. forEach {
90+ switch stableMetric. type {
91+ case . LongGauge:
92+ guard let gaugeData = $0 as? LongPointData else {
93+ break
94+ }
95+ var protoDataPoint = Opentelemetry_Proto_Metrics_V1_NumberDataPoint ( )
96+ injectPointData ( protoNumberPoint: & protoDataPoint, pointData: gaugeData)
97+ protoDataPoint. value = . asInt( Int64 ( gaugeData. value) )
98+ protoMetric. gauge. dataPoints. append ( protoDataPoint)
99+ case . LongSum:
100+ guard let gaugeData = $0 as? LongPointData else {
101+ break
102+ }
103+ var protoDataPoint = Opentelemetry_Proto_Metrics_V1_NumberDataPoint ( )
104+ injectPointData ( protoNumberPoint: & protoDataPoint, pointData: gaugeData)
105+ protoDataPoint. value = . asInt( Int64 ( gaugeData. value) )
106+ protoMetric. sum. aggregationTemporality = . cumulative
107+ protoMetric. sum. dataPoints. append ( protoDataPoint)
108+ case . DoubleGauge:
109+ guard let gaugeData = $0 as? DoublePointData else {
110+ break
111+ }
112+ var protoDataPoint = Opentelemetry_Proto_Metrics_V1_NumberDataPoint ( )
113+ injectPointData ( protoNumberPoint: & protoDataPoint, pointData: gaugeData)
114+ protoDataPoint. value = . asDouble( gaugeData. value)
115+ protoMetric. gauge. dataPoints. append ( protoDataPoint)
116+ case . DoubleSum:
117+ guard let gaugeData = $0 as? DoublePointData else {
118+ break
119+ }
120+ var protoDataPoint = Opentelemetry_Proto_Metrics_V1_NumberDataPoint ( )
121+ injectPointData ( protoNumberPoint: & protoDataPoint, pointData: gaugeData)
122+ protoDataPoint. value = . asDouble( gaugeData. value)
123+ protoMetric. sum. aggregationTemporality = . cumulative
124+ protoMetric. sum. dataPoints. append ( protoDataPoint)
125+ case . Summary:
126+ guard let summaryData = $0 as? SummaryPointData else {
127+ break
128+ }
129+ var protoDataPoint = Opentelemetry_Proto_Metrics_V1_SummaryDataPoint ( )
130+ injectPointData ( protoSummaryPoint: & protoDataPoint, pointData: summaryData)
131+ protoDataPoint. sum = summaryData. sum
132+ protoDataPoint. count = summaryData. count
133+ summaryData. values. forEach {
134+ var quantile = Opentelemetry_Proto_Metrics_V1_SummaryDataPoint . ValueAtQuantile ( )
135+ quantile. quantile = $0. quantile ( )
136+ quantile. value = $0. value ( )
137+ protoDataPoint. quantileValues. append ( quantile)
138+ }
139+ protoMetric. summary. dataPoints. append ( protoDataPoint)
140+ case . Histogram:
141+ guard let histogramData = $0 as? HistogramPointData else {
142+ break
143+ }
144+ var protoDataPoint = Opentelemetry_Proto_Metrics_V1_HistogramDataPoint ( )
145+ injectPointData ( protoHistogramPoint: & protoDataPoint, pointData: histogramData)
146+ protoDataPoint. sum = Double ( histogramData. sum)
147+ protoDataPoint. count = UInt64 ( histogramData. count)
148+ protoDataPoint. explicitBounds = histogramData. boundaries. map { Double ( $0) }
149+ protoDataPoint. bucketCounts = histogramData. counts. map { UInt64 ( $0) }
150+ protoMetric. histogram. aggregationTemporality = . cumulative
151+ protoMetric. histogram. dataPoints. append ( protoDataPoint)
152+ case . ExponentialHistogram:
153+ // TODO: implement
154+ break
155+ }
156+ }
157+ return protoMetric
158+ }
159+
160+ static func injectPointData( protoHistogramPoint protoPoint: inout Opentelemetry_Proto_Metrics_V1_HistogramDataPoint , pointData: PointData ) {
161+ protoPoint. timeUnixNano = pointData. endEpochNanos
162+ protoPoint. startTimeUnixNano = pointData. startEpochNanos
163+
164+ pointData. attributes. forEach {
165+ protoPoint. attributes. append ( CommonAdapter . toProtoAttribute ( key: $0. key, attributeValue: $0. value) )
166+ }
167+
168+ pointData. exemplars. forEach {
169+ var protoExemplar = Opentelemetry_Proto_Metrics_V1_Exemplar ( )
170+ protoExemplar. timeUnixNano = $0. epochNanos
171+
172+ $0. filteredAttributes. forEach {
173+ protoExemplar. filteredAttributes. append ( CommonAdapter . toProtoAttribute ( key: $0. key, attributeValue: $0. value) )
174+ }
175+ if let spanContext = $0. spanContext {
176+ protoExemplar. spanID = TraceProtoUtils . toProtoSpanId ( spanId: spanContext. spanId)
177+ protoExemplar. traceID = TraceProtoUtils . toProtoTraceId ( traceId: spanContext. traceId)
178+ }
179+ }
180+ }
181+
182+ static func injectPointData( protoSummaryPoint protoPoint: inout Opentelemetry_Proto_Metrics_V1_SummaryDataPoint , pointData: PointData ) {
183+ protoPoint. timeUnixNano = pointData. endEpochNanos
184+ protoPoint. startTimeUnixNano = pointData. startEpochNanos
185+
186+ pointData. attributes. forEach {
187+ protoPoint. attributes. append ( CommonAdapter . toProtoAttribute ( key: $0. key, attributeValue: $0. value) )
188+ }
189+
190+ pointData. exemplars. forEach {
191+ var protoExemplar = Opentelemetry_Proto_Metrics_V1_Exemplar ( )
192+ protoExemplar. timeUnixNano = $0. epochNanos
193+
194+ $0. filteredAttributes. forEach {
195+ protoExemplar. filteredAttributes. append ( CommonAdapter . toProtoAttribute ( key: $0. key, attributeValue: $0. value) )
196+ }
197+ if let spanContext = $0. spanContext {
198+ protoExemplar. spanID = TraceProtoUtils . toProtoSpanId ( spanId: spanContext. spanId)
199+ protoExemplar. traceID = TraceProtoUtils . toProtoTraceId ( traceId: spanContext. traceId)
200+ }
201+ }
202+ }
203+
204+ static func injectPointData( protoNumberPoint protoPoint: inout Opentelemetry_Proto_Metrics_V1_NumberDataPoint , pointData: PointData ) {
205+ protoPoint. timeUnixNano = pointData. endEpochNanos
206+ protoPoint. startTimeUnixNano = pointData. startEpochNanos
207+
208+ pointData. attributes. forEach {
209+ protoPoint. attributes. append ( CommonAdapter . toProtoAttribute ( key: $0. key, attributeValue: $0. value) )
210+ }
211+
212+ pointData. exemplars. forEach {
213+ var protoExemplar = Opentelemetry_Proto_Metrics_V1_Exemplar ( )
214+ protoExemplar. timeUnixNano = $0. epochNanos
215+
216+ $0. filteredAttributes. forEach {
217+ protoExemplar. filteredAttributes. append ( CommonAdapter . toProtoAttribute ( key: $0. key, attributeValue: $0. value) )
218+ }
219+ if let spanContext = $0. spanContext {
220+ protoExemplar. spanID = TraceProtoUtils . toProtoSpanId ( spanId: spanContext. spanId)
221+ protoExemplar. traceID = TraceProtoUtils . toProtoTraceId ( traceId: spanContext. traceId)
222+ }
223+ protoPoint. exemplars. append ( protoExemplar)
224+ }
225+ }
226+
48227 public static func toProtoMetric( metric: Metric ) -> Opentelemetry_Proto_Metrics_V1_Metric ? {
49228 var protoMetric = Opentelemetry_Proto_Metrics_V1_Metric ( )
50229 protoMetric. name = metric. name
@@ -179,14 +358,14 @@ public struct MetricsAdapter {
179358 protoDataPoint. timeUnixNano = histogramData. timestamp. timeIntervalSince1970. toNanoseconds
180359 protoDataPoint. explicitBounds = histogramData. buckets. boundaries. map { Double ( $0) }
181360 protoDataPoint. bucketCounts = histogramData. buckets. counts. map { UInt64 ( $0) }
182-
361+
183362 histogramData. labels. forEach {
184363 var kvp = Opentelemetry_Proto_Common_V1_KeyValue ( )
185364 kvp. key = $0. key
186365 kvp. value. stringValue = $0. value
187366 protoDataPoint. attributes. append ( kvp)
188367 }
189-
368+
190369 protoMetric. histogram. aggregationTemporality = . cumulative
191370 protoMetric. histogram. dataPoints. append ( protoDataPoint)
192371 case . doubleHistogram:
@@ -200,14 +379,14 @@ public struct MetricsAdapter {
200379 protoDataPoint. timeUnixNano = histogramData. timestamp. timeIntervalSince1970. toNanoseconds
201380 protoDataPoint. explicitBounds = histogramData. buckets. boundaries. map { Double ( $0) }
202381 protoDataPoint. bucketCounts = histogramData. buckets. counts. map { UInt64 ( $0) }
203-
382+
204383 histogramData. labels. forEach {
205384 var kvp = Opentelemetry_Proto_Common_V1_KeyValue ( )
206385 kvp. key = $0. key
207386 kvp. value. stringValue = $0. value
208387 protoDataPoint. attributes. append ( kvp)
209388 }
210-
389+
211390 protoMetric. histogram. aggregationTemporality = . cumulative
212391 protoMetric. histogram. dataPoints. append ( protoDataPoint)
213392 }
0 commit comments