11import re
22import time
3- from . meters import Counter , Histogram , Meter , Timer , Gauge , CallbackGauge , SimpleGauge , BaseMetric
3+ from typing import Dict
44
5+ from .meters import BaseMetric , CallbackGauge , Counter , Event , Gauge , Histogram , Meter , \
6+ SimpleGauge , Timer
57
6- class MetricsRegistry (object ):
78
9+ class MetricsRegistry (object ):
810 """
911 A single interface used to gather metrics on a service. It keeps track of
1012 all the relevant Counters, Meters, Histograms, and Timers. It does not have
@@ -21,6 +23,7 @@ def __init__(self, clock=time):
2123 self ._counters = {}
2224 self ._histograms = {}
2325 self ._gauges = {}
26+ self ._events = {}
2427 self ._clock = clock
2528
2629 def add (self , key , metric , tags = None ):
@@ -42,6 +45,7 @@ def add(self, key, metric, tags=None):
4245 (Gauge , self ._gauges ),
4346 (Timer , self ._timers ),
4447 (Counter , self ._counters ),
48+ (Event , self ._events ),
4549 )
4650 for cls , registry in class_map :
4751 if isinstance (metric , cls ):
@@ -144,11 +148,28 @@ def timer(self, key, tags=None):
144148 )
145149 return self ._timers [metric_key ]
146150
151+ def event (self , key : str , tags : Dict [str , str ] = None ) -> Event :
152+ """
153+ Gets an event reporter based on key and tags
154+ :param key: The metric name / measurement name
155+ :param tags: Tags to attach to the metric
156+ :return: Event object you can add readings to
157+ """
158+ metric_key = BaseMetric (key , tags )
159+ if metric_key not in self ._events :
160+ self ._events [metric_key ] = Event (
161+ clock = self ._clock ,
162+ key = key ,
163+ tags = tags
164+ )
165+ return self ._events [metric_key ]
166+
147167 def clear (self ):
148168 self ._meters .clear ()
149169 self ._counters .clear ()
150170 self ._gauges .clear ()
151171 self ._timers .clear ()
172+ self ._events .clear ()
152173 self ._histograms .clear ()
153174
154175 def _get_counter_metrics (self , metric_key ):
@@ -196,6 +217,19 @@ def _get_meter_metrics(self, metric_key):
196217 return res
197218 return {}
198219
220+ def _get_event_metrics (self , metric_key ):
221+ if metric_key in self ._events :
222+ _event = self ._events [metric_key ]
223+ points = _event .get_events ()
224+
225+ if points :
226+ res = {
227+ "events" : points
228+ }
229+
230+ return res
231+ return {}
232+
199233 def _get_timer_metrics (self , metric_key ):
200234 if metric_key in self ._timers :
201235 timer = self ._timers [metric_key ]
@@ -237,11 +271,12 @@ def get_metrics(self, key, tags=None):
237271 def _get_metrics_by_metric_key (self , metric_key ):
238272 metrics = {}
239273 for getter in (
240- self ._get_counter_metrics ,
241- self ._get_histogram_metrics ,
242- self ._get_meter_metrics ,
243- self ._get_timer_metrics ,
244- self ._get_gauge_metrics ,
274+ self ._get_counter_metrics ,
275+ self ._get_histogram_metrics ,
276+ self ._get_meter_metrics ,
277+ self ._get_timer_metrics ,
278+ self ._get_gauge_metrics ,
279+ self ._get_event_metrics ,
245280 ):
246281 metrics .update (getter (metric_key ))
247282 return metrics
@@ -257,11 +292,12 @@ def dump_metrics(self, key_is_metric=False):
257292 """
258293 metrics = {}
259294 for metric_type in (
260- self ._counters ,
261- self ._histograms ,
262- self ._meters ,
263- self ._timers ,
264- self ._gauges ,
295+ self ._counters ,
296+ self ._histograms ,
297+ self ._meters ,
298+ self ._timers ,
299+ self ._gauges ,
300+ self ._events ,
265301 ):
266302 for metric_key in metric_type .keys ():
267303 if key_is_metric :
@@ -271,12 +307,15 @@ def dump_metrics(self, key_is_metric=False):
271307
272308 metrics [key ] = self ._get_metrics_by_metric_key (metric_key )
273309
310+ # Don't repeat events, that's the whole point of events
311+ for _event in self ._events .values ():
312+ _event .clear ()
313+
274314 return metrics
275315
276316
277317# TODO make sure tags are supported properly
278318class RegexRegistry (MetricsRegistry ):
279-
280319 """
281320 A single interface used to gather metrics on a service. This class uses a regex to combine
282321 measures that match a pattern. For example, if you have a REST API, instead of defining
@@ -348,6 +387,10 @@ def timer(key, tags=None):
348387 return _global_registry .timer (key , tags )
349388
350389
390+ def event (key , tags = None ):
391+ return _global_registry .event (key , tags )
392+
393+
351394def gauge (key , gauge = None , tags = None ):
352395 return _global_registry .gauge (key = key , gauge = gauge , tags = tags )
353396
0 commit comments