Skip to content

Commit 79a7ff7

Browse files
author
Ignacio Bonafonte
authored
Merge pull request #192 from bryce-b/gauge-measurement
Gauge measurement
2 parents 4ba525a + 88033cc commit 79a7ff7

File tree

16 files changed

+393
-40
lines changed

16 files changed

+393
-40
lines changed

Sources/Exporters/DatadogExporter/Metrics/MetricUtils.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ internal struct MetricUtils: Encodable {
2222
/// getType maps a metric into a Datadog type
2323
static func getType(metric: Metric) -> String {
2424
switch metric.aggregationType {
25-
case .doubleSum, .intSum:
26-
return countType
27-
case .doubleSummary, .intSummary:
28-
return gaugeType
25+
case .doubleSum, .intSum:
26+
return countType
27+
case .doubleSummary, .intSummary, .intGauge, .doubleGauge:
28+
return gaugeType
2929
}
3030
}
3131

Sources/Exporters/DatadogExporter/Metrics/MetricsExporter.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal class MetricsExporter {
2222
throw ExporterError(description: "Metrics Exporter need an api key")
2323
}
2424

25-
self.configuration = config
25+
configuration = config
2626

2727
let filesOrchestrator = FilesOrchestrator(
2828
directory: try Directory(withSubdirectoryPath: metricsDirectory),
@@ -76,18 +76,18 @@ internal class MetricsExporter {
7676
let labels = metricData.labels
7777
tags.append(contentsOf: MetricUtils.getTags(labels: labels))
7878
switch metric.aggregationType {
79-
case .doubleSum:
80-
let sum = metricData as! SumData<Double>
81-
return DDMetricPoint(timestamp: metricData.timestamp, value: sum.sum)
82-
case .intSum:
83-
let sum = metricData as! SumData<Int>
84-
return DDMetricPoint(timestamp: metricData.timestamp, value: Double(sum.sum))
85-
case .doubleSummary:
86-
let summary = metricData as! SummaryData<Double>
87-
return DDMetricPoint(timestamp: metricData.timestamp, value: summary.sum)
88-
case .intSummary:
89-
let summary = metricData as! SummaryData<Int>
90-
return DDMetricPoint(timestamp: metricData.timestamp, value: Double(summary.sum))
79+
case .doubleSum:
80+
let sum = metricData as! SumData<Double>
81+
return DDMetricPoint(timestamp: metricData.timestamp, value: sum.sum)
82+
case .intSum:
83+
let sum = metricData as! SumData<Int>
84+
return DDMetricPoint(timestamp: metricData.timestamp, value: Double(sum.sum))
85+
case .doubleSummary, .doubleGauge:
86+
let summary = metricData as! SummaryData<Double>
87+
return DDMetricPoint(timestamp: metricData.timestamp, value: summary.sum)
88+
case .intSummary, .intGauge:
89+
let summary = metricData as! SummaryData<Int>
90+
return DDMetricPoint(timestamp: metricData.timestamp, value: Double(summary.sum))
9191
}
9292
}
9393

Sources/Exporters/OpenTelemetryProtocol/metric/MetricsAdapter.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,49 @@ struct MetricsAdapter {
5050

5151
metric.data.forEach {
5252
switch metric.aggregationType {
53+
case .doubleGauge:
54+
guard let gaugeData = $0 as? SumData<Double> else {
55+
break
56+
}
57+
var protoDataPoint = Opentelemetry_Proto_Metrics_V1_DoubleDataPoint()
58+
protoDataPoint.timeUnixNano = gaugeData.timestamp.timeIntervalSince1970.toNanoseconds
59+
protoDataPoint.startTimeUnixNano = gaugeData.startTimestamp.timeIntervalSince1970.toNanoseconds
60+
protoDataPoint.value = gaugeData.sum
61+
gaugeData.labels.forEach {
62+
var kvp = Opentelemetry_Proto_Common_V1_StringKeyValue()
63+
kvp.key = $0.key
64+
kvp.value = $0.value
65+
protoDataPoint.labels.append(kvp)
66+
}
67+
68+
protoMetric.doubleGauge.dataPoints.append(protoDataPoint)
69+
case .intGauge:
70+
guard let gaugeData = $0 as? SumData<Int> else {
71+
break
72+
}
73+
74+
var protoDataPoint = Opentelemetry_Proto_Metrics_V1_IntDataPoint()
75+
76+
protoDataPoint.value = Int64(gaugeData.sum)
77+
protoDataPoint.timeUnixNano = gaugeData.timestamp.timeIntervalSince1970.toNanoseconds
78+
protoDataPoint.startTimeUnixNano = gaugeData.startTimestamp.timeIntervalSince1970.toNanoseconds
79+
gaugeData.labels.forEach {
80+
var kvp = Opentelemetry_Proto_Common_V1_StringKeyValue()
81+
kvp.key = $0.key
82+
kvp.value = $0.value
83+
protoDataPoint.labels.append(kvp)
84+
}
85+
86+
protoMetric.intGauge.dataPoints.append(protoDataPoint)
5387
case .doubleSum:
5488
guard let sumData = $0 as? SumData<Double> else {
5589
break
5690
}
5791

5892
var protoDataPoint = Opentelemetry_Proto_Metrics_V1_DoubleDataPoint()
5993
protoDataPoint.value = sumData.sum
94+
protoDataPoint.timeUnixNano = sumData.timestamp.timeIntervalSince1970.toNanoseconds
95+
protoDataPoint.startTimeUnixNano = sumData.startTimestamp.timeIntervalSince1970.toNanoseconds
6096
sumData.labels.forEach {
6197
var kvp = Opentelemetry_Proto_Common_V1_StringKeyValue()
6298
kvp.key = $0.key
@@ -91,6 +127,8 @@ struct MetricsAdapter {
91127
}
92128
var protoDataPoint = Opentelemetry_Proto_Metrics_V1_IntDataPoint()
93129
protoDataPoint.value = Int64(sumData.sum)
130+
protoDataPoint.timeUnixNano = sumData.timestamp.timeIntervalSince1970.toNanoseconds
131+
protoDataPoint.startTimeUnixNano = sumData.startTimestamp.timeIntervalSince1970.toNanoseconds
94132
sumData.labels.forEach {
95133
var kvp = Opentelemetry_Proto_Common_V1_StringKeyValue()
96134
kvp.key = $0.key

Sources/Exporters/Prometheus/PrometheusExporterExtensions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import Foundation
77
import OpenTelemetrySdk
88

9-
public struct PrometheusExporterExtensions {
9+
public enum PrometheusExporterExtensions {
1010
static let prometheusCounterType = "counter"
1111
static let prometheusSummaryType = "summary"
1212
static let prometheusSummarySumPostFix = "_sum"
@@ -31,14 +31,14 @@ public struct PrometheusExporterExtensions {
3131
case .intSum:
3232
let sum = metricData as! SumData<Int>
3333
output += PrometheusExporterExtensions.writeSum(prometheusMetric: prometheusMetric, timeStamp: now, labels: labels, doubleValue: Double(sum.sum))
34-
case .doubleSummary:
34+
case .doubleSummary, .doubleGauge:
3535
let summary = metricData as! SummaryData<Double>
3636
let count = summary.count
3737
let sum = summary.sum
3838
let min = summary.min
3939
let max = summary.max
4040
output += PrometheusExporterExtensions.writeSummary(prometheusMetric: prometheusMetric, timeStamp: now, labels: labels, metricName: metric.name, sum: sum, count: count, min: min, max: max)
41-
case .intSummary:
41+
case .intSummary, .intGauge:
4242
let summary = metricData as! SummaryData<Int>
4343
let count = summary.count
4444
let sum = summary.sum

Sources/OpenTelemetryApi/Metrics/Meter.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,20 @@ public protocol Meter {
5151
/// - Returns:The observer instance.
5252
func createDoubleObserver(name: String, absolute: Bool, callback: @escaping (DoubleObserverMetric) -> Void) -> DoubleObserverMetric
5353

54+
/// Creates Double Observable Gauge with given name.
55+
/// - Parameters:
56+
/// - name: The name of the gauge.
57+
/// - callback: The callback to be called to observe metric value.
58+
/// - Returns:The gauge instance.
59+
func createIntObservableGauge(name: String, callback: @escaping (IntObserverMetric) -> Void) -> IntObserverMetric
60+
61+
/// Creates Int Observable Gauge with given name.
62+
/// - Parameters:
63+
/// - name: The name of the gauge.
64+
/// - callback: The callback to be called to observe metric value.
65+
/// - Returns:The gauge instance.
66+
func createDoubleObservableGauge(name: String, callback: @escaping (DoubleObserverMetric) -> Void) -> DoubleObserverMetric
67+
5468
/// Constructs or retrieves the LabelSet from the given dictionary.
5569
/// - Parameters:
5670
/// - labels: dictionary with key-value pairs.

Sources/OpenTelemetryApi/Metrics/ProxyMeter.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ public struct ProxyMeter: Meter {
2929
return realMeter?.createDoubleMeasure(name: name, absolute: absolute) ?? AnyMeasureMetric<Double>(NoopMeasureMetric<Double>())
3030
}
3131

32+
public func createIntObservableGauge(name: String, callback: @escaping (IntObserverMetric) -> Void) -> IntObserverMetric {
33+
return realMeter?.createIntObservableGauge(name: name, callback: callback) ?? NoopIntObserverMetric()
34+
}
35+
36+
public func createDoubleObservableGauge(name: String, callback: @escaping (DoubleObserverMetric) -> Void) -> DoubleObserverMetric {
37+
return realMeter?.createDoubleObservableGauge(name: name, callback: callback) ?? NoopDoubleObserverMetric()
38+
}
39+
3240
public func createIntObserver(name: String, absolute: Bool, callback: @escaping (IntObserverMetric) -> Void) -> IntObserverMetric {
3341
return realMeter?.createIntObserver(name: name, absolute: absolute, callback: callback) ?? NoopIntObserverMetric()
3442
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
8+
public class MaxValueAggregator<T: SignedNumeric & Comparable>: Aggregator<T> {
9+
var value: T = 0
10+
var pointCheck: T = 0
11+
12+
private let lock = Lock()
13+
14+
override public func update(value: T) {
15+
lock.withLockVoid {
16+
if value > self.value {
17+
self.value = value
18+
}
19+
}
20+
}
21+
22+
override public func checkpoint() {
23+
lock.withLockVoid {
24+
super.checkpoint()
25+
self.pointCheck = self.value
26+
self.value = 0
27+
}
28+
}
29+
30+
override public func toMetricData() -> MetricData {
31+
return SumData<T>(startTimestamp: lastStart, timestamp: lastEnd, sum: pointCheck)
32+
}
33+
34+
override public func getAggregationType() -> AggregationType {
35+
if T.self == Double.Type.self {
36+
return .doubleGauge
37+
} else {
38+
return .intGauge
39+
}
40+
}
41+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
import OpenTelemetryApi
8+
9+
struct DoubleObservableGaugeHandle: DoubleObserverMetricHandle {
10+
public private(set) var aggregator = MaxValueAggregator<Double>()
11+
12+
func observe(value: Double) {
13+
aggregator.update(value: value)
14+
}
15+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import Foundation
7+
import OpenTelemetryApi
8+
9+
class DoubleObservableGaugeSdk: DoubleObserverMetric {
10+
public private(set) var observerHandles = [LabelSet: DoubleObservableGaugeHandle]()
11+
let name: String
12+
var callback: (DoubleObserverMetric) -> Void
13+
14+
init(measurementName: String, callback: @escaping (DoubleObserverMetric) -> Void) {
15+
name = measurementName
16+
self.callback = callback
17+
}
18+
19+
func observe(value: Double, labels: [String: String]) {
20+
observe(value: value, labelset: LabelSet(labels: labels))
21+
}
22+
23+
func observe(value: Double, labelset: LabelSet) {
24+
var boundInstrument = observerHandles[labelset]
25+
if boundInstrument == nil {
26+
boundInstrument = DoubleObservableGaugeHandle()
27+
observerHandles[labelset] = boundInstrument
28+
}
29+
boundInstrument?.observe(value: value)
30+
}
31+
32+
func invokeCallback() {
33+
callback(self)
34+
}
35+
}

Sources/OpenTelemetrySdk/Metrics/Export/AggregationType.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import Foundation
77

88
public enum AggregationType {
9+
case intGauge
10+
case doubleGauge
911
case doubleSum
1012
case intSum
1113
case doubleSummary

0 commit comments

Comments
 (0)