@@ -15,9 +15,13 @@ Gauge is a metric that represents a single numerical value that can arbitrarily
15
15
A Gauge is typically used for measured values like temperatures or current memory usage,
16
16
but also \"counts\" that can go up and down, like the number of running processes.
17
17
18
+ It can take the value of undefined when the value is not known.
19
+ In that case, increments and decrements will not be possible
20
+ and explicitly setting to a new value will be necessary.
21
+
18
22
Example use cases for Gauges:
19
23
20
- * Inprogress requests
24
+ * In-progress requests
21
25
* Number of items in a queue
22
26
* Free memory
23
27
* Total memory
@@ -95,6 +99,8 @@ track_checked_out_sockets(CheckoutFun) ->
95
99
-behaviour (prometheus_metric ).
96
100
-behaviour (prometheus_collector ).
97
101
102
+ % % Records will be triplets `{Key, ISum, FSum}`
103
+ % % where `IGauge` are integer gauges, and `FGauge` are float gauges
98
104
-define (TABLE , ? PROMETHEUS_GAUGE_TABLE ).
99
105
-define (IGAUGE_POS , 2 ).
100
106
-define (FGAUGE_POS , 3 ).
@@ -183,23 +189,33 @@ Raises:
183
189
Registry :: prometheus_registry :registry (),
184
190
Name :: prometheus_metric :name (),
185
191
LabelValues :: prometheus_metric :labels (),
186
- Value :: number ().
187
- set (Registry , Name , LabelValues , Value ) ->
188
- Update =
189
- case Value of
190
- _ when is_number (Value ) ->
191
- [{? IGAUGE_POS , 0 }, {? FGAUGE_POS , Value }];
192
- undefined ->
193
- [{? IGAUGE_POS , undefined }, {? FGAUGE_POS , undefined }];
194
- _ ->
195
- erlang :error ({invalid_value , Value , " set accepts only numbers and 'undefined'" })
196
- end ,
192
+ Value :: undefined | number ().
193
+ set (Registry , Name , LabelValues , Value ) when is_integer (Value ) ->
194
+ Update = [{? IGAUGE_POS , Value }, {? FGAUGE_POS , 0 }],
197
195
case ets :update_element (? TABLE , {Registry , Name , LabelValues }, Update ) of
198
196
false ->
199
- insert_metric (Registry , Name , LabelValues , Value , fun set /4 );
197
+ insert_metric_int (Registry , Name , LabelValues , Value , fun set /4 );
200
198
true ->
201
199
ok
202
- end .
200
+ end ;
201
+ set (Registry , Name , LabelValues , Value ) when is_float (Value ) ->
202
+ Update = [{? IGAUGE_POS , 0 }, {? FGAUGE_POS , Value }],
203
+ case ets :update_element (? TABLE , {Registry , Name , LabelValues }, Update ) of
204
+ false ->
205
+ insert_metric_float (Registry , Name , LabelValues , Value , fun set /4 );
206
+ true ->
207
+ ok
208
+ end ;
209
+ set (Registry , Name , LabelValues , undefined ) ->
210
+ Update = [{? IGAUGE_POS , undefined }, {? FGAUGE_POS , undefined }],
211
+ case ets :update_element (? TABLE , {Registry , Name , LabelValues }, Update ) of
212
+ false ->
213
+ insert_metric_undefined (Registry , Name , LabelValues , undefined , fun set /4 );
214
+ true ->
215
+ ok
216
+ end ;
217
+ set (_ , _ , _ , Value ) ->
218
+ erlang :error ({invalid_value , Value , " set accepts only numbers and 'undefined'" }).
203
219
204
220
? DOC (#{equiv => inc (default , Name , [], 1 )}).
205
221
-spec inc (prometheus_metric :name ()) -> ok .
@@ -236,19 +252,21 @@ Raises:
236
252
LabelValues :: prometheus_metric :labels (),
237
253
Value :: number ().
238
254
inc (Registry , Name , LabelValues , Value ) when is_integer (Value ) ->
255
+ Key = key (Registry , Name , LabelValues ),
256
+ Spec = {? IGAUGE_POS , Value },
239
257
try
240
- ets :update_counter (? TABLE , { Registry , Name , LabelValues }, { ? IGAUGE_POS , Value } )
258
+ ets :update_counter (? TABLE , Key , Spec )
241
259
catch
242
260
error :badarg ->
243
- maybe_insert_metric_for_inc (Registry , Name , LabelValues , Value )
261
+ maybe_insert_metric_for_inc_int (Registry , Name , LabelValues , Value )
244
262
end ,
245
263
ok ;
246
- inc (Registry , Name , LabelValues , Value ) when is_number (Value ) ->
264
+ inc (Registry , Name , LabelValues , Value ) when is_float (Value ) ->
247
265
Key = key (Registry , Name , LabelValues ),
248
- Spec = [{{Key , '$1' , '$2' }, [], [{{{Key }, '$1' , {'+' , '$2' , Value }}}]}],
266
+ Spec = [{{Key , '$1' , '$2' }, [{ is_integer , '$1' } ], [{{{Key }, '$1' , {'+' , '$2' , Value }}}]}],
249
267
case ets :select_replace (? TABLE , Spec ) of
250
268
0 ->
251
- insert_metric (Registry , Name , LabelValues , Value , fun inc / 4 );
269
+ maybe_insert_metric_for_inc_float (Registry , Name , LabelValues , Value );
252
270
1 ->
253
271
ok
254
272
end ;
@@ -522,20 +540,40 @@ collect_metrics(Name, {CLabels, Labels, Registry, DU}) ->
522
540
key (Registry , Name , LabelValues ) ->
523
541
{Registry , Name , LabelValues }.
524
542
525
- maybe_insert_metric_for_inc (Registry , Name , LabelValues , Value ) ->
543
+ maybe_insert_metric_for_inc_int (Registry , Name , LabelValues , Value ) ->
544
+ case ets :lookup (? TABLE , {Registry , Name , LabelValues }) of
545
+ [{_Key , undefined , undefined }] ->
546
+ erlang :error ({invalid_operation , 'inc/dec' , " Can't inc/dec undefined" });
547
+ _ ->
548
+ insert_metric_int (Registry , Name , LabelValues , Value , fun inc /4 )
549
+ end .
550
+
551
+ maybe_insert_metric_for_inc_float (Registry , Name , LabelValues , Value ) ->
526
552
case ets :lookup (? TABLE , {Registry , Name , LabelValues }) of
527
553
[{_Key , undefined , undefined }] ->
528
554
erlang :error ({invalid_operation , 'inc/dec' , " Can't inc/dec undefined" });
529
555
_ ->
530
- insert_metric (Registry , Name , LabelValues , Value , fun inc /4 )
556
+ insert_metric_float (Registry , Name , LabelValues , Value , fun inc /4 )
531
557
end .
532
558
533
559
deregister_select (Registry , Name ) ->
534
560
[{{{Registry , Name , '_' }, '_' , '_' }, [], [true ]}].
535
561
536
- insert_metric (Registry , Name , LabelValues , Value , ConflictCB ) ->
562
+ insert_metric_int (Registry , Name , LabelValues , Value , ConflictCB ) ->
563
+ Counter = {key (Registry , Name , LabelValues ), Value , 0 },
564
+ insert_metric (Registry , Name , LabelValues , Value , ConflictCB , Counter ).
565
+
566
+ insert_metric_float (Registry , Name , LabelValues , Value , ConflictCB ) ->
567
+ Counter = {key (Registry , Name , LabelValues ), 0 , Value },
568
+ insert_metric (Registry , Name , LabelValues , Value , ConflictCB , Counter ).
569
+
570
+ insert_metric_undefined (Registry , Name , LabelValues , Value , ConflictCB ) ->
571
+ Counter = {key (Registry , Name , LabelValues ), undefined , undefined },
572
+ insert_metric (Registry , Name , LabelValues , Value , ConflictCB , Counter ).
573
+
574
+ insert_metric (Registry , Name , LabelValues , Value , ConflictCB , Counter ) ->
537
575
prometheus_metric :check_mf_exists (? TABLE , Registry , Name , LabelValues ),
538
- case ets :insert_new (? TABLE , {{ Registry , Name , LabelValues }, 0 , Value } ) of
576
+ case ets :insert_new (? TABLE , Counter ) of
539
577
% % some sneaky process already inserted
540
578
false ->
541
579
ConflictCB (Registry , Name , LabelValues , Value );
@@ -546,7 +584,7 @@ insert_metric(Registry, Name, LabelValues, Value, ConflictCB) ->
546
584
load_all_values (Registry , Name ) ->
547
585
ets :match (? TABLE , {{Registry , Name , '$1' }, '$2' , '$3' }).
548
586
549
- sum (_IValue , undefined ) ->
587
+ sum (undefined , _FValue ) ->
550
588
undefined ;
551
589
sum (IValue , FValue ) ->
552
590
IValue + FValue .
0 commit comments