Skip to content

Commit c5b2773

Browse files
authored
Merge pull request swift-server#2 from Yasumoto/master
Fixup tests since we're now all async
2 parents ce55dcb + 20e7fc7 commit c5b2773

File tree

8 files changed

+229
-105
lines changed

8 files changed

+229
-105
lines changed

.travis.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
language: generic
22
os: osx
3-
osx_image: xcode10.1
3+
osx_image: xcode10.2
44
script:
55
- swift build
6-
- swift test
6+
- swift test -Xswiftc -DDEBUG

README.md

+27-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[![Build Status](https://travis-ci.com/MrLotU/SwiftPrometheus.svg?branch=master)](https://travis-ci.com/MrLotU/SwiftPrometheus) [![Swift 4.2](https://img.shields.io/badge/swift-4.2-orange.svg?style=flat)](http://swift.org)
1+
[![Build Status](https://travis-ci.com/MrLotU/SwiftPrometheus.svg?branch=master)](https://travis-ci.com/MrLotU/SwiftPrometheus) [![Swift 5.0](https://img.shields.io/badge/swift-5.0-orange.svg?style=flat)](http://swift.org)
22

33
# SwiftPrometheus, Prometheus client for Swift
44

@@ -13,7 +13,9 @@ For examples, see [main.swift](./Sources/PrometheusExample/main.swift)
1313
Counters go up, and reset when the process restarts.
1414

1515
```swift
16-
let counter = Prometheus.shared.createCounter(forType: Int.self, named: "my_counter")
16+
let prom = PrometheusClient()
17+
18+
let counter = prom.createCounter(forType: Int.self, named: "my_counter")
1719
counter.inc() // Increment by 1
1820
counter.inc(12) // Increment by given value
1921
```
@@ -23,7 +25,9 @@ counter.inc(12) // Increment by given value
2325
Gauges can go up and down
2426

2527
```swift
26-
let gauge = Prometheus.shared.createGauge(forType: Int.self, named: "my_gauge")
28+
let prom = PrometheusClient()
29+
30+
let gauge = prom.createGauge(forType: Int.self, named: "my_gauge")
2731
gauge.inc() // Increment by 1
2832
gauge.dec(19) // Decrement by given value
2933
gauge.set(12) // Set to a given value
@@ -34,7 +38,9 @@ gauge.set(12) // Set to a given value
3438
Histograms track the size and number of events in buckets. This allows for aggregatable calculation of quantiles.
3539

3640
```swift
37-
let histogram = Prometheus.shared.createHistogram(forType: Double.self, named: "my_histogram")
41+
let prom = PrometheusClient()
42+
43+
let histogram = prom.createHistogram(forType: Double.self, named: "my_histogram")
3844
histogram.observe(4.7) // Observe the given value
3945
```
4046

@@ -43,7 +49,9 @@ histogram.observe(4.7) // Observe the given value
4349
Summaries track the size and number of events
4450

4551
```swift
46-
let summary = Prometheus.shared.createSummary(forType: Double.self, named: "my_summary")
52+
let prom = PrometheusClient()
53+
54+
let summary = prom.createSummary(forType: Double.self, named: "my_summary")
4755
summary.observe(4.7) // Observe the given value
4856
```
4957

@@ -64,7 +72,9 @@ struct MyInfoStruct: MetricLabels {
6472
}
6573
}
6674

67-
let info = Prometheus.shared.createInfo(named: "my_info", helpText: "Just some info", labelType: MyInfoStruct.self)
75+
let prom = PrometheusClient()
76+
77+
let info = prom.createInfo(named: "my_info", helpText: "Just some info", labelType: MyInfoStruct.self)
6878

6979
info.info(MyInfoStruct("def"))
7080
```
@@ -78,19 +88,25 @@ struct RouteLabels: MetricLabels {
7888
var route: String = "*"
7989
}
8090

81-
let counter = Prometheus.shared.createCounter(forType: Int.self, named: "my_counter", helpText: "Just a counter", withLabelType: RouteLabels.self)
91+
let prom = PrometheusClient()
92+
93+
let counter = prom.createCounter(forType: Int.self, named: "my_counter", helpText: "Just a counter", withLabelType: RouteLabels.self)
8294

8395
counter.inc(12, .init(route: "/"))
8496
```
8597

8698
# Exporting
8799

88-
To keep SwiftPrometheus as clean and leight weitght as possible, there is no way of exporting metrics to Prometheus. All you can do is get a formatted string that Prometheus can use, so you can integrate it in your own Serverside Swift application
100+
To keep SwiftPrometheus as clean and lightweight as possible, there is no way of exporting metrics directly to Prometheus. Instead, retrieve a formatted string that Prometheus can use, so you can integrate it in your own Serverside Swift application
89101

90102
This could look something like this:
91103
```swift
92-
router.get("/metrics") { request -> String in
93-
return Prometheus.shared.getMetrics()
104+
router.get("/metrics") { request -> Future<String> in
105+
let promise = req.eventLoop.newPromise(String.self)
106+
prom.getMetrics {
107+
promise.succeed(result: $0)
108+
}
109+
return promise.futureResult
94110
}
95111
```
96112
Here, I used [Vapor](https://github.com/vapor/vapor) syntax, but this will work with any web framework, since it's just returning a plain String.
@@ -99,6 +115,6 @@ Here, I used [Vapor](https://github.com/vapor/vapor) syntax, but this will work
99115

100116
All contributions are most welcome!
101117

102-
If you think of some crazy cool new feature that should be included, please [create an issue](https://github.com/MrLotU/SwiftPrometheus/issues/new/choose). Or, if you want to implement it yourself, [fork this repo](https://github.com/MrLotU/SwiftPrometheus/fork) and submit a PR!
118+
If you think of some cool new feature that should be included, please [create an issue](https://github.com/MrLotU/SwiftPrometheus/issues/new/choose). Or, if you want to implement it yourself, [fork this repo](https://github.com/MrLotU/SwiftPrometheus/fork) and submit a PR!
103119

104120
If you find a bug or have issues, please [create an issue](https://github.com/MrLotU/SwiftPrometheus/issues/new/choose) explaining your problems. Please include as much information as possible, so it's easier for me to reproduce (Framework, OS, Swift version, terminal output, etc.)

Sources/Prometheus/MetricTypes/Gauge.swift

+37-35
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
2929
/// - help: Helpt text of the Gauge
3030
/// - initialValue: Initial value to set the Gauge to
3131
/// - p: Prometheus instance that created this Gauge
32+
///
3233
internal init(_ name: String, _ help: String? = nil, _ initialValue: NumType = 0, _ p: PrometheusClient) {
3334
self.name = name
3435
self.help = help
@@ -39,8 +40,9 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
3940

4041
/// Gets the metric string for this Gauge
4142
///
42-
/// - Returns:
43-
/// Newline seperated Prometheus formatted metric string
43+
/// - Parameters:
44+
/// - done: Callback passing a newline separated Prometheus-formatted metric string
45+
///
4446
public func getMetric(_ done: @escaping (String) -> Void) {
4547
prometheusQueue.async(flags: .barrier) {
4648
var output = [String]()
@@ -49,7 +51,7 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
4951
output.append("# HELP \(self.name) \(help)")
5052
}
5153
output.append("# TYPE \(self.name) \(self._type)")
52-
54+
5355
output.append("\(self.name) \(self.value)")
5456

5557
self.metrics.forEach { (labels, value) in
@@ -67,15 +69,15 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
6769
/// - amount: Amount to set the gauge to
6870
/// - labels: Labels to attach to the value
6971
///
70-
public func set(_ amount: NumType, _ labels: Labels? = nil, _ done: @escaping (NumType) -> Void = { _ in }) {
72+
public func set(_ amount: NumType, _ labels: Labels? = nil, _ done: @escaping () -> Void = { }) {
7173
prometheusQueue.async(flags: .barrier) {
72-
if let labels = labels {
73-
self.metrics[labels] = amount
74-
done(amount)
75-
} else {
76-
self.value = amount
77-
done(self.value)
78-
}
74+
if let labels = labels {
75+
self.metrics[labels] = amount
76+
done()
77+
} else {
78+
self.value = amount
79+
done()
80+
}
7981
}
8082
}
8183

@@ -84,49 +86,50 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
8486
/// - Parameters:
8587
/// - amount: Amount to increment the Gauge with
8688
/// - labels: Labels to attach to the value
89+
/// - done: Completion handler
8790
///
8891
public func inc(_ amount: NumType, _ labels: Labels? = nil, _ done: @escaping (NumType) -> Void = { _ in }) {
8992
prometheusQueue.async(flags: .barrier) {
90-
if let labels = labels {
91-
var val = self.metrics[labels] ?? self.initialValue
92-
val += amount
93-
self.metrics[labels] = val
94-
done(val)
95-
} else {
96-
self.value += amount
97-
done(self.value)
98-
}
93+
if let labels = labels {
94+
var val = self.metrics[labels] ?? self.initialValue
95+
val += amount
96+
self.metrics[labels] = val
97+
done(val)
98+
} else {
99+
self.value += amount
100+
done(self.value)
101+
}
99102
}
100103
}
101104

102105
/// Increments the Gauge
103106
///
104107
/// - Parameters:
105108
/// - labels: Labels to attach to the value
109+
/// - done: Completion handler
106110
///
107111
public func inc(_ labels: Labels? = nil, _ done: @escaping (NumType) -> Void = { _ in }) {
108-
self.inc(1, labels) {
109-
done($0)
110-
}
112+
self.inc(1, labels, done)
111113
}
112114

113115
/// Decrements the Gauge
114116
///
115117
/// - Parameters:
116118
/// - amount: Amount to decrement the Gauge with
117119
/// - labels: Labels to attach to the value
120+
/// - done: Completion handler
118121
///
119122
public func dec(_ amount: NumType, _ labels: Labels? = nil, _ done: @escaping (NumType) -> Void = { _ in }) {
120123
prometheusQueue.async(flags: .barrier) {
121-
if let labels = labels {
122-
var val = self.metrics[labels] ?? self.initialValue
123-
val -= amount
124-
self.metrics[labels] = val
125-
done(val)
126-
} else {
127-
self.value -= amount
128-
done(self.value)
129-
}
124+
if let labels = labels {
125+
var val = self.metrics[labels] ?? self.initialValue
126+
val -= amount
127+
self.metrics[labels] = val
128+
done(val)
129+
} else {
130+
self.value -= amount
131+
done(self.value)
132+
}
130133
}
131134
}
132135

@@ -136,9 +139,7 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
136139
/// - labels: Labels to attach to the value
137140
///
138141
public func dec(_ labels: Labels? = nil, _ done: @escaping (NumType) -> Void = { _ in }) {
139-
self.dec(1, labels) {
140-
done($0)
141-
}
142+
self.dec(1, labels, done)
142143
}
143144

144145
/// Gets the value of the Gauge
@@ -147,6 +148,7 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
147148
/// - labels: Labels to get the value for
148149
///
149150
/// - Returns: The value of the Gauge attached to the provided labels
151+
///
150152
public func get(_ labels: Labels? = nil) -> NumType {
151153
if let labels = labels {
152154
return self.metrics[labels] ?? initialValue

Sources/Prometheus/MetricTypes/Histogram.swift

+19-13
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ extension HistogramLabels {
1414
}
1515
}
1616

17-
/// Prometheus Counter metric
17+
/// Prometheus Histogram metric
1818
///
1919
/// See https://prometheus.io/docs/concepts/metric_types/#Histogram
2020
public class Histogram<NumType: DoubleRepresentable, Labels: HistogramLabels>: Metric, PrometheusHandled {
@@ -71,8 +71,8 @@ public class Histogram<NumType: DoubleRepresentable, Labels: HistogramLabels>: M
7171

7272
/// Gets the metric string for this Histogram
7373
///
74-
/// - Returns:
75-
/// Newline seperated Prometheus formatted metric string
74+
/// - Parameters:
75+
/// - done: Newline separated Prometheus-formatted metric string
7676
public func getMetric(_ done: @escaping (String) -> Void) {
7777
prometheusQueue.async(flags: .barrier) {
7878
var output = [String]()
@@ -123,20 +123,26 @@ public class Histogram<NumType: DoubleRepresentable, Labels: HistogramLabels>: M
123123
/// - Parameters:
124124
/// - value: Value to observe
125125
/// - labels: Labels to attach to the observed value
126-
public func observe(_ value: NumType, _ labels: Labels? = nil) {
126+
/// - done: Completion handler
127+
public func observe(_ value: NumType, _ labels: Labels? = nil, _ done: @escaping () -> Void = { }) {
127128
prometheusQueue.async(flags: .barrier) {
128-
if let labels = labels, type(of: labels) != type(of: EmptySummaryLabels()) {
129-
let his = self.prometheus.getOrCreateHistogram(with: labels, for: self)
130-
his.observe(value)
129+
let completion: () -> Void = {
130+
self.total.inc(value)
131+
132+
for (i, bound) in self.upperBounds.enumerated() {
133+
if bound >= value.doubleValue {
134+
self.buckets[i].inc()
135+
break
136+
}
137+
}
138+
done()
131139
}
132-
self.total.inc(value)
133140

134-
for (i, bound) in self.upperBounds.enumerated() {
135-
if bound >= value.doubleValue {
136-
self.buckets[i].inc()
137-
return
138-
}
141+
if let labels = labels, type(of: labels) != type(of: EmptySummaryLabels()) {
142+
let his = self.prometheus.getOrCreateHistogram(with: labels, for: self)
143+
return his.observe(value, nil, completion)
139144
}
145+
return completion()
140146
}
141147
}
142148
}

Sources/Prometheus/MetricTypes/Info.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ public class Info<Labels: MetricLabels>: Metric, PrometheusHandled {
3939

4040
/// Gets the metric string for this Info
4141
///
42-
/// - Returns:
43-
/// Newline seperated Prometheus formatted metric string
42+
/// - Parameters:
43+
/// - done: Callback passing a newline separated Prometheus-formatted metric string
44+
///
4445
public func getMetric(_ done: @escaping (String) -> Void) {
4546
prometheusQueue.async(flags: .barrier) {
4647
var output = [String]()

Sources/Prometheus/MetricTypes/Summary.swift

+21-9
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,11 @@ public class Summary<NumType: DoubleRepresentable, Labels: SummaryLabels>: Metri
7272

7373
/// Gets the metric string for this Summary
7474
///
75-
/// - Returns:
76-
/// Newline seperated Prometheus formatted metric string
77-
public func getMetric(_ done: @escaping (String) -> Void) {
75+
/// - Parameters:
76+
/// - done: Completion handler
77+
/// - metric: String value in prom-format
78+
///
79+
public func getMetric(_ done: @escaping (_ metric: String) -> Void) {
7880
prometheusQueue.async(flags: .barrier) {
7981
var output = [String]()
8082

@@ -109,7 +111,7 @@ public class Summary<NumType: DoubleRepresentable, Labels: SummaryLabels>: Metri
109111
}
110112

111113
self.labels.quantile = ""
112-
114+
113115
done(output.joined(separator: "\n"))
114116
}
115117
}
@@ -119,15 +121,25 @@ public class Summary<NumType: DoubleRepresentable, Labels: SummaryLabels>: Metri
119121
/// - Parameters:
120122
/// - value: Value to observe
121123
/// - labels: Labels to attach to the observed value
122-
public func observe(_ value: NumType, _ labels: Labels? = nil) {
124+
/// - done: Completion handler
125+
///
126+
public func observe(_ value: NumType, _ labels: Labels? = nil, _ done: @escaping () -> Void = { }) {
123127
prometheusQueue.async(flags: .barrier) {
128+
func completion() {
129+
self.count.inc(1)
130+
self.sum.inc(value)
131+
self.values.append(value)
132+
done()
133+
}
134+
124135
if let labels = labels, type(of: labels) != type(of: EmptySummaryLabels()) {
125136
let sum = self.prometheus.getOrCreateSummary(withLabels: labels, forSummary: self)
126-
sum.observe(value)
137+
sum.observe(value) {
138+
completion()
139+
}
140+
} else {
141+
completion()
127142
}
128-
self.count.inc(1)
129-
self.sum.inc(value)
130-
self.values.append(value)
131143
}
132144
}
133145
}

Sources/Prometheus/Utils.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ public protocol DoubleRepresentable: Numeric {
6262
/// Numbers that convert to other types
6363
public protocol ConvertibleNumberType: DoubleRepresentable {}
6464
public extension ConvertibleNumberType {
65-
public var floatValue: Float {get {return Float(doubleValue)}}
66-
public var intValue: Int {get {return lrint(doubleValue)}}
67-
public var CGFloatValue: CGFloat {get {return CGFloat(doubleValue)}}
65+
var floatValue: Float {get {return Float(doubleValue)}}
66+
var intValue: Int {get {return lrint(doubleValue)}}
67+
var CGFloatValue: CGFloat {get {return CGFloat(doubleValue)}}
6868
}
6969

7070
/// Double Representable Conformance

0 commit comments

Comments
 (0)