35
35
_unpack_integer = struct .Struct (b'i' ).unpack_from
36
36
_unpack_double = struct .Struct (b'd' ).unpack_from
37
37
38
- Sample = namedtuple ('Sample' , ['name' , 'labels' , 'value' , 'timestamp' , 'exemplar' ])
39
- # Value can be an int or a float.
40
38
# Timestamp and exemplar are optional.
39
+ # Value can be an int or a float.
40
+ # Timestamp can be a float containing a unixtime in seconds,
41
+ # or a Timestamp object.
42
+ Sample = namedtuple ('Sample' , ['name' , 'labels' , 'value' , 'timestamp' , 'exemplar' ])
41
43
Sample .__new__ .__defaults__ = (None , None )
42
44
45
+
46
+ class Timestamp (object ):
47
+ '''A nanosecond-resolution timestamp.'''
48
+ def __init__ (self , sec , nsec ):
49
+ if nsec < 0 or nsec >= 1e9 :
50
+ raise ValueError ("Invalid value for nanoseconds in Timestamp: {}" .format (nsec ))
51
+ self .sec = int (sec )
52
+ self .nsec = int (nsec )
53
+
54
+ def __str__ (self ):
55
+ return "{0}.{1:09d}" .format (self .sec , self .nsec )
56
+
57
+ def __float__ (self ):
58
+ return float (self .sec ) + float (self .nsec ) / 1e9
59
+
60
+
43
61
class CollectorRegistry (object ):
44
62
'''Metric collector registry.
45
63
@@ -60,7 +78,7 @@ def register(self, collector):
60
78
duplicates = set (self ._names_to_collectors ).intersection (names )
61
79
if duplicates :
62
80
raise ValueError (
63
- 'Duplicated timeseries in CollectorRegistry: {}' .format (
81
+ 'Duplicated timeseries in CollectorRegistry: {0 }' .format (
64
82
duplicates ))
65
83
for name in names :
66
84
self ._names_to_collectors [name ] = collector
@@ -179,19 +197,24 @@ def __init__(self, name, documentation, typ, unit=''):
179
197
if typ not in _METRIC_TYPES :
180
198
raise ValueError ('Invalid metric type: ' + typ )
181
199
self .type = typ
200
+ if unit :
201
+ if not name .endswith ('_' + unit ):
202
+ raise ValueError ('Metric name does not end with unit: ' + name )
203
+ self .unit = unit
182
204
self .samples = []
183
205
184
- def add_sample (self , name , labels , value ):
206
+ def add_sample (self , name , labels , value , timestamp = None ):
185
207
'''Add a sample to the metric.
186
208
187
209
Internal-only, do not use.'''
188
- self .samples .append (Sample (name , labels , value ))
210
+ self .samples .append (Sample (name , labels , value , timestamp ))
189
211
190
212
def __eq__ (self , other ):
191
213
return (isinstance (other , Metric ) and
192
214
self .name == other .name and
193
215
self .documentation == other .documentation and
194
216
self .type == other .type and
217
+ self .unit == other .unit and
195
218
self .samples == other .samples )
196
219
197
220
def __repr__ (self ):
0 commit comments