Skip to content

Commit

Permalink
Merge pull request #2 from Yasumoto/master
Browse files Browse the repository at this point in the history
Fixup tests since we're now all async
  • Loading branch information
MrLotU authored Apr 16, 2019
2 parents ce55dcb + 20e7fc7 commit c5b2773
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 105 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: generic
os: osx
osx_image: xcode10.1
osx_image: xcode10.2
script:
- swift build
- swift test
- swift test -Xswiftc -DDEBUG
38 changes: 27 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![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)
[![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)

# SwiftPrometheus, Prometheus client for Swift

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

```swift
let counter = Prometheus.shared.createCounter(forType: Int.self, named: "my_counter")
let prom = PrometheusClient()

let counter = prom.createCounter(forType: Int.self, named: "my_counter")
counter.inc() // Increment by 1
counter.inc(12) // Increment by given value
```
Expand All @@ -23,7 +25,9 @@ counter.inc(12) // Increment by given value
Gauges can go up and down

```swift
let gauge = Prometheus.shared.createGauge(forType: Int.self, named: "my_gauge")
let prom = PrometheusClient()

let gauge = prom.createGauge(forType: Int.self, named: "my_gauge")
gauge.inc() // Increment by 1
gauge.dec(19) // Decrement by given value
gauge.set(12) // Set to a given value
Expand All @@ -34,7 +38,9 @@ gauge.set(12) // Set to a given value
Histograms track the size and number of events in buckets. This allows for aggregatable calculation of quantiles.

```swift
let histogram = Prometheus.shared.createHistogram(forType: Double.self, named: "my_histogram")
let prom = PrometheusClient()

let histogram = prom.createHistogram(forType: Double.self, named: "my_histogram")
histogram.observe(4.7) // Observe the given value
```

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

```swift
let summary = Prometheus.shared.createSummary(forType: Double.self, named: "my_summary")
let prom = PrometheusClient()

let summary = prom.createSummary(forType: Double.self, named: "my_summary")
summary.observe(4.7) // Observe the given value
```

Expand All @@ -64,7 +72,9 @@ struct MyInfoStruct: MetricLabels {
}
}

let info = Prometheus.shared.createInfo(named: "my_info", helpText: "Just some info", labelType: MyInfoStruct.self)
let prom = PrometheusClient()

let info = prom.createInfo(named: "my_info", helpText: "Just some info", labelType: MyInfoStruct.self)

info.info(MyInfoStruct("def"))
```
Expand All @@ -78,19 +88,25 @@ struct RouteLabels: MetricLabels {
var route: String = "*"
}

let counter = Prometheus.shared.createCounter(forType: Int.self, named: "my_counter", helpText: "Just a counter", withLabelType: RouteLabels.self)
let prom = PrometheusClient()

let counter = prom.createCounter(forType: Int.self, named: "my_counter", helpText: "Just a counter", withLabelType: RouteLabels.self)

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

# Exporting

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
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

This could look something like this:
```swift
router.get("/metrics") { request -> String in
return Prometheus.shared.getMetrics()
router.get("/metrics") { request -> Future<String> in
let promise = req.eventLoop.newPromise(String.self)
prom.getMetrics {
promise.succeed(result: $0)
}
return promise.futureResult
}
```
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.
Expand All @@ -99,6 +115,6 @@ Here, I used [Vapor](https://github.com/vapor/vapor) syntax, but this will work

All contributions are most welcome!

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!
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!

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.)
72 changes: 37 additions & 35 deletions Sources/Prometheus/MetricTypes/Gauge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
/// - help: Helpt text of the Gauge
/// - initialValue: Initial value to set the Gauge to
/// - p: Prometheus instance that created this Gauge
///
internal init(_ name: String, _ help: String? = nil, _ initialValue: NumType = 0, _ p: PrometheusClient) {
self.name = name
self.help = help
Expand All @@ -39,8 +40,9 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa

/// Gets the metric string for this Gauge
///
/// - Returns:
/// Newline seperated Prometheus formatted metric string
/// - Parameters:
/// - done: Callback passing a newline separated Prometheus-formatted metric string
///
public func getMetric(_ done: @escaping (String) -> Void) {
prometheusQueue.async(flags: .barrier) {
var output = [String]()
Expand All @@ -49,7 +51,7 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
output.append("# HELP \(self.name) \(help)")
}
output.append("# TYPE \(self.name) \(self._type)")

output.append("\(self.name) \(self.value)")

self.metrics.forEach { (labels, value) in
Expand All @@ -67,15 +69,15 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
/// - amount: Amount to set the gauge to
/// - labels: Labels to attach to the value
///
public func set(_ amount: NumType, _ labels: Labels? = nil, _ done: @escaping (NumType) -> Void = { _ in }) {
public func set(_ amount: NumType, _ labels: Labels? = nil, _ done: @escaping () -> Void = { }) {
prometheusQueue.async(flags: .barrier) {
if let labels = labels {
self.metrics[labels] = amount
done(amount)
} else {
self.value = amount
done(self.value)
}
if let labels = labels {
self.metrics[labels] = amount
done()
} else {
self.value = amount
done()
}
}
}

Expand All @@ -84,49 +86,50 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
/// - Parameters:
/// - amount: Amount to increment the Gauge with
/// - labels: Labels to attach to the value
/// - done: Completion handler
///
public func inc(_ amount: NumType, _ labels: Labels? = nil, _ done: @escaping (NumType) -> Void = { _ in }) {
prometheusQueue.async(flags: .barrier) {
if let labels = labels {
var val = self.metrics[labels] ?? self.initialValue
val += amount
self.metrics[labels] = val
done(val)
} else {
self.value += amount
done(self.value)
}
if let labels = labels {
var val = self.metrics[labels] ?? self.initialValue
val += amount
self.metrics[labels] = val
done(val)
} else {
self.value += amount
done(self.value)
}
}
}

/// Increments the Gauge
///
/// - Parameters:
/// - labels: Labels to attach to the value
/// - done: Completion handler
///
public func inc(_ labels: Labels? = nil, _ done: @escaping (NumType) -> Void = { _ in }) {
self.inc(1, labels) {
done($0)
}
self.inc(1, labels, done)
}

/// Decrements the Gauge
///
/// - Parameters:
/// - amount: Amount to decrement the Gauge with
/// - labels: Labels to attach to the value
/// - done: Completion handler
///
public func dec(_ amount: NumType, _ labels: Labels? = nil, _ done: @escaping (NumType) -> Void = { _ in }) {
prometheusQueue.async(flags: .barrier) {
if let labels = labels {
var val = self.metrics[labels] ?? self.initialValue
val -= amount
self.metrics[labels] = val
done(val)
} else {
self.value -= amount
done(self.value)
}
if let labels = labels {
var val = self.metrics[labels] ?? self.initialValue
val -= amount
self.metrics[labels] = val
done(val)
} else {
self.value -= amount
done(self.value)
}
}
}

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

/// Gets the value of the Gauge
Expand All @@ -147,6 +148,7 @@ public class Gauge<NumType: Numeric, Labels: MetricLabels>: Metric, PrometheusHa
/// - labels: Labels to get the value for
///
/// - Returns: The value of the Gauge attached to the provided labels
///
public func get(_ labels: Labels? = nil) -> NumType {
if let labels = labels {
return self.metrics[labels] ?? initialValue
Expand Down
32 changes: 19 additions & 13 deletions Sources/Prometheus/MetricTypes/Histogram.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ extension HistogramLabels {
}
}

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

/// Gets the metric string for this Histogram
///
/// - Returns:
/// Newline seperated Prometheus formatted metric string
/// - Parameters:
/// - done: Newline separated Prometheus-formatted metric string
public func getMetric(_ done: @escaping (String) -> Void) {
prometheusQueue.async(flags: .barrier) {
var output = [String]()
Expand Down Expand Up @@ -123,20 +123,26 @@ public class Histogram<NumType: DoubleRepresentable, Labels: HistogramLabels>: M
/// - Parameters:
/// - value: Value to observe
/// - labels: Labels to attach to the observed value
public func observe(_ value: NumType, _ labels: Labels? = nil) {
/// - done: Completion handler
public func observe(_ value: NumType, _ labels: Labels? = nil, _ done: @escaping () -> Void = { }) {
prometheusQueue.async(flags: .barrier) {
if let labels = labels, type(of: labels) != type(of: EmptySummaryLabels()) {
let his = self.prometheus.getOrCreateHistogram(with: labels, for: self)
his.observe(value)
let completion: () -> Void = {
self.total.inc(value)

for (i, bound) in self.upperBounds.enumerated() {
if bound >= value.doubleValue {
self.buckets[i].inc()
break
}
}
done()
}
self.total.inc(value)

for (i, bound) in self.upperBounds.enumerated() {
if bound >= value.doubleValue {
self.buckets[i].inc()
return
}
if let labels = labels, type(of: labels) != type(of: EmptySummaryLabels()) {
let his = self.prometheus.getOrCreateHistogram(with: labels, for: self)
return his.observe(value, nil, completion)
}
return completion()
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions Sources/Prometheus/MetricTypes/Info.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ public class Info<Labels: MetricLabels>: Metric, PrometheusHandled {

/// Gets the metric string for this Info
///
/// - Returns:
/// Newline seperated Prometheus formatted metric string
/// - Parameters:
/// - done: Callback passing a newline separated Prometheus-formatted metric string
///
public func getMetric(_ done: @escaping (String) -> Void) {
prometheusQueue.async(flags: .barrier) {
var output = [String]()
Expand Down
30 changes: 21 additions & 9 deletions Sources/Prometheus/MetricTypes/Summary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ public class Summary<NumType: DoubleRepresentable, Labels: SummaryLabels>: Metri

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

Expand Down Expand Up @@ -109,7 +111,7 @@ public class Summary<NumType: DoubleRepresentable, Labels: SummaryLabels>: Metri
}

self.labels.quantile = ""

done(output.joined(separator: "\n"))
}
}
Expand All @@ -119,15 +121,25 @@ public class Summary<NumType: DoubleRepresentable, Labels: SummaryLabels>: Metri
/// - Parameters:
/// - value: Value to observe
/// - labels: Labels to attach to the observed value
public func observe(_ value: NumType, _ labels: Labels? = nil) {
/// - done: Completion handler
///
public func observe(_ value: NumType, _ labels: Labels? = nil, _ done: @escaping () -> Void = { }) {
prometheusQueue.async(flags: .barrier) {
func completion() {
self.count.inc(1)
self.sum.inc(value)
self.values.append(value)
done()
}

if let labels = labels, type(of: labels) != type(of: EmptySummaryLabels()) {
let sum = self.prometheus.getOrCreateSummary(withLabels: labels, forSummary: self)
sum.observe(value)
sum.observe(value) {
completion()
}
} else {
completion()
}
self.count.inc(1)
self.sum.inc(value)
self.values.append(value)
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions Sources/Prometheus/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ public protocol DoubleRepresentable: Numeric {
/// Numbers that convert to other types
public protocol ConvertibleNumberType: DoubleRepresentable {}
public extension ConvertibleNumberType {
public var floatValue: Float {get {return Float(doubleValue)}}
public var intValue: Int {get {return lrint(doubleValue)}}
public var CGFloatValue: CGFloat {get {return CGFloat(doubleValue)}}
var floatValue: Float {get {return Float(doubleValue)}}
var intValue: Int {get {return lrint(doubleValue)}}
var CGFloatValue: CGFloat {get {return CGFloat(doubleValue)}}
}

/// Double Representable Conformance
Expand Down
Loading

0 comments on commit c5b2773

Please sign in to comment.