You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
add "meter" - a new type of metric and metric handler (#123)
motivation: seperate gauge from recorder in a backwards compatible way
changes:
* add new meter and meter handler pair
* add increment and decrement to meter handler
* add default implementation based on recorder for backwards compatibility
* add and adjust tests
Copy file name to clipboardExpand all lines: README.md
+63-26Lines changed: 63 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -98,16 +98,22 @@ The API supports four metric types:
98
98
counter.increment(by: 100)
99
99
```
100
100
101
-
`Recorder`: A recorder collects observations within a time window (usually things like response sizes) and *can* provide aggregated information about the data sample, for example count, sum, min, max and various quantiles.
101
+
`Gauge`: A Gauge is a metric that represents a single numerical value that can arbitrarily go up and down. Gauges are typically used for measured values like temperatures or current memory usage, but also "counts" that can go up and down, like the number of active threads. Gauges are modeled as a `Recorder` with a sample size of 1 that does not perform any aggregation.
102
102
103
103
```swift
104
-
recorder.record(100)
104
+
gauge.record(100)
105
105
```
106
106
107
-
`Gauge`: A Gauge is a metric that represents a single numerical value that can arbitrarily go up and down. Gauges are typically used for measured values like temperatures or current memory usage, but also "counts" that can go up and down, like the number of active threads. Gauges are modeled as a `Recorder` with a sample size of 1 that does not perform any aggregation.
107
+
`Meter`: A Meter is similar to `Gauge` - a metric that represents a single numerical value that can arbitrarily go up and down. Meters are typically used for measured values like temperatures or current memory usage, but also "counts" that can go up and down, like the number of active threads. Unlike `Gauge`, `Meter` also supports atomic incerements and decerements.
108
108
109
109
```swift
110
-
gauge.record(100)
110
+
meter.record(100)
111
+
```
112
+
113
+
`Recorder`: A recorder collects observations within a time window (usually things like response sizes) and *can* provide aggregated information about the data sample, for example count, sum, min, max and various quantiles.
114
+
115
+
```swift
116
+
recorder.record(100)
111
117
```
112
118
113
119
`Timer`: A timer collects observations within a time window (usually things like request duration) and provides aggregated information about the data sample, for example min, max and various quantiles. It is similar to a `Recorder` but specialized for values that represent durations.
@@ -120,7 +126,7 @@ timer.recordMilliseconds(100)
120
126
121
127
Note: Unless you need to implement a custom metrics backend, everything in this section is likely not relevant, so please feel free to skip.
122
128
123
-
As seen above, each constructor for `Counter`, `Timer`, `Recorder` and `Gauge` provides a metric object. This uncertainty obscures the selected metrics backend calling these constructors by design. _Each application_ can select and configure its desired backend. The application sets up the metrics backend it wishes to use. Configuring the metrics backend is straightforward:
129
+
As seen above, each constructor for `Counter`, `Gauge`, `Meter`, `Recorder` and `Timer` provides a metric object. This uncertainty obscures the selected metrics backend calling these constructors by design. _Each application_ can select and configure its desired backend. The application sets up the metrics backend it wishes to use. Configuring the metrics backend is straightforward:
124
130
125
131
```swift
126
132
let metricsImplementation =MyFavoriteMetricsImplementation()
@@ -134,10 +140,12 @@ Given the above, an implementation of a metric backend needs to conform to `prot
@@ -154,11 +162,14 @@ public protocol CounterHandler: AnyObject {
154
162
}
155
163
```
156
164
157
-
**Timer**
165
+
**Meter**
158
166
159
167
```swift
160
-
publicprotocolTimerHandler: AnyObject{
161
-
funcrecordNanoseconds(_duration: Int64)
168
+
publicprotocolMeterHandler: AnyObject{
169
+
funcset(_value: Int64)
170
+
funcset(_value: Double)
171
+
funcincrement(by: Double)
172
+
funcdecrement(by: Double)
162
173
}
163
174
```
164
175
@@ -171,9 +182,17 @@ public protocol RecorderHandler: AnyObject {
171
182
}
172
183
```
173
184
185
+
**Timer**
186
+
187
+
```swift
188
+
publicprotocolTimerHandler: AnyObject{
189
+
funcrecordNanoseconds(_duration: Int64)
190
+
}
191
+
```
192
+
174
193
#### Dealing with Overflows
175
194
176
-
Implementaton of metric objects that deal with integers, like `Counter` and `Timer` should be careful with overflow. The expected behavior is to cap at `.max`, and never crash the program due to overflow . For example:
195
+
Implementation of metric objects that deal with integers, like `Counter` and `Timer` should be careful with overflow. The expected behavior is to cap at `.max`, and never crash the program due to overflow . For example:
177
196
178
197
```swift
179
198
classExampleCounter: CounterHandler {
@@ -201,9 +220,12 @@ class SimpleMetricsLibrary: MetricsFactory {
0 commit comments