2121from pyprometheus .const import TYPES
2222from pyprometheus .metrics import Gauge , Counter
2323from pyprometheus .storage import BaseStorage , LocalMemoryStorage
24-
24+ from pyprometheus import compat
2525
2626try :
2727 import uwsgi
@@ -45,7 +45,9 @@ class UWSGICollector(object):
4545 """
4646 def __init__ (self , namespace , labels = {}):
4747 self ._namespace = namespace
48+
4849 self ._labels = tuple (sorted (labels .items (), key = lambda x : x [0 ]))
50+ self ._labels_names = tuple (label [0 ] for label in self ._labels )
4951 self ._collectors = self .declare_metrics ()
5052
5153 @property
@@ -70,29 +72,30 @@ def metric_name(self, name):
7072 return ":" .join ([self ._namespace , name ])
7173
7274 def declare_metrics (self ):
75+
7376 return {
74- "memory" : Gauge (self .metric_name ("uwsgi_memory_bytes" ), "UWSGI memory usage in bytes" , ("type" ,) + self ._labels ),
75- "processes" : Gauge (self .metric_name ("processes_total" ), "Number of UWSGI processes" , self ._labels ),
76- "worker_status" : Gauge (self .metric_name ("worker_status_totla" ), "Current workers status" , self ._labels ),
77- "total_requests" : Gauge (self .metric_name ("requests_total" ), "Total processed request" , self ._labels ),
78- "buffer_size" : Gauge (self .metric_name ("buffer_size_bytes" ), "UWSGI buffer size in bytes" , self ._labels ),
79- "started_on" : Gauge (self .metric_name ("started_on" ), "UWSGI started on timestamp" , self ._labels ),
80- "cores" : Gauge (self .metric_name ("cores" ), "system cores" , self ._labels ),
81-
82-
83- "process:respawn_count" : Gauge (self .metric_name ("process:respawn_count" ), "Process respawn count" , ("id" , ) + self ._labels ),
84- "process:last_spawn" : Gauge (self .metric_name ("process:last_spawn" ), "Process last spawn" , ("id" , ) + self ._labels ),
85- "process:signals" : Gauge (self .metric_name ("process:signals" ), "Process signals total" , ("id" , ) + self ._labels ),
86- "process:avg_rt" : Gauge (self .metric_name ("process:avg_rt" ), "Process average response time" , ("id" , ) + self ._labels ),
87- "process:tx" : Gauge (self .metric_name ("process:tx" ), "Process transmitted data" , ("id" ,) + self ._labels ),
88-
89- "process:status" : Gauge (self .metric_name ("process:status" ), "Process status" , ("id" , "status" ) + self ._labels ),
90- "process:running_time" : Gauge (self .metric_name ("process:running_time" ), "Process running time" , ("id" , ) + self ._labels ),
91- "process:exceptions" : Gauge (self .metric_name ("process:exceptions" ), "Process exceptions" , ("id" , ) + self ._labels ),
92- "process:requests" : Gauge (self .metric_name ("process:requests" ), "Process requests" , ("id" , ) + self ._labels ),
93- "process:delta_requests" : Gauge (self .metric_name ("process:delta_requests" ), "Process delta_requests" , ("id" , ) + self ._labels ),
94- "process:rss" : Gauge (self .metric_name ("process:rss" ), "Process rss memory" , ("id" , ) + self ._labels ),
95- "process:vsz" : Gauge (self .metric_name ("process:vzs" ), "Process vsz address space" , ("id" , ) + self ._labels ),
77+ "memory" : Gauge (self .metric_name ("uwsgi_memory_bytes" ), "UWSGI memory usage in bytes" , ("type" ,) + self ._labels_names ),
78+ "processes" : Gauge (self .metric_name ("processes_total" ), "Number of UWSGI processes" , self ._labels_names ),
79+ "worker_status" : Gauge (self .metric_name ("worker_status_totla" ), "Current workers status" , self ._labels_names ),
80+ "total_requests" : Gauge (self .metric_name ("requests_total" ), "Total processed request" , self ._labels_names ),
81+ "buffer_size" : Gauge (self .metric_name ("buffer_size_bytes" ), "UWSGI buffer size in bytes" , self ._labels_names ),
82+ "started_on" : Gauge (self .metric_name ("started_on" ), "UWSGI started on timestamp" , self ._labels_names ),
83+ "cores" : Gauge (self .metric_name ("cores" ), "system cores" , self ._labels_names ),
84+
85+
86+ "process:respawn_count" : Gauge (self .metric_name ("process:respawn_count" ), "Process respawn count" , ("id" , ) + self ._labels_names ),
87+ "process:last_spawn" : Gauge (self .metric_name ("process:last_spawn" ), "Process last spawn" , ("id" , ) + self ._labels_names ),
88+ "process:signals" : Gauge (self .metric_name ("process:signals" ), "Process signals total" , ("id" , ) + self ._labels_names ),
89+ "process:avg_rt" : Gauge (self .metric_name ("process:avg_rt" ), "Process average response time" , ("id" , ) + self ._labels_names ),
90+ "process:tx" : Gauge (self .metric_name ("process:tx" ), "Process transmitted data" , ("id" ,) + self ._labels_names ),
91+
92+ "process:status" : Gauge (self .metric_name ("process:status" ), "Process status" , ("id" , "status" ) + self ._labels_names ),
93+ "process:running_time" : Gauge (self .metric_name ("process:running_time" ), "Process running time" , ("id" , ) + self ._labels_names ),
94+ "process:exceptions" : Gauge (self .metric_name ("process:exceptions" ), "Process exceptions" , ("id" , ) + self ._labels_names ),
95+ "process:requests" : Gauge (self .metric_name ("process:requests" ), "Process requests" , ("id" , ) + self ._labels_names ),
96+ "process:delta_requests" : Gauge (self .metric_name ("process:delta_requests" ), "Process delta_requests" , ("id" , ) + self ._labels_names ),
97+ "process:rss" : Gauge (self .metric_name ("process:rss" ), "Process rss memory" , ("id" , ) + self ._labels_names ),
98+ "process:vsz" : Gauge (self .metric_name ("process:vzs" ), "Process vsz address space" , ("id" , ) + self ._labels_names ),
9699 }
97100
98101 def collect (self ):
@@ -108,7 +111,6 @@ def collect(self):
108111 for x in self .get_workers_samples (uwsgi .workers ()):
109112 yield x
110113
111-
112114 def get_workers_samples (self , workers ):
113115 """Read worker stats and create samples
114116
@@ -122,15 +124,15 @@ def get_workers_samples(self, workers):
122124 for worker in workers :
123125 labels = self ._labels + (("id" , worker ["id" ]),)
124126 metric .add_sample (labels , metric .build_sample (labels ,
125- ( (TYPES .GAUGE , metric .name , "" , labels , worker [name ]), )))
127+ ( (TYPES .GAUGE , metric .name , "" , labels , worker [name ]), ))) # noqa
126128
127129 yield metric
128130
129131 metric = self ._collectors ["process:status" ]
130132 for worker in workers :
131133 labels = self ._labels + (("id" , worker ["id" ]), ("status" , worker ["status" ]))
132134 metric .add_sample (labels , metric .build_sample (labels ,
133- ( (TYPES .GAUGE , metric .name , "" , self ._labels + (("id" , worker ["id" ]), ("status" , worker ["status" ])), 1 ), )))
135+ ( (TYPES .GAUGE , metric .name , "" , self ._labels + (("id" , worker ["id" ]), ("status" , worker ["status" ])), 1 ), ))) # noqa
134136
135137 yield metric
136138
@@ -141,15 +143,15 @@ def get_sample(self, name, value):
141143 :param value:
142144 """
143145 metric = self ._collectors [name ]
144- return metric .build_samples ([(self ._labels , ( (TYPES .GAUGE , metric .name , "" , self ._labels , float (value )), ))])
146+ return metric .build_samples ([(self ._labels , ( (TYPES .GAUGE , metric .name , "" , self ._labels , float (value )), ))]) # noqa
145147
146148 def get_memory_samples (self ):
147149 """Get memory usage samples
148150 """
149151 metric = self ._collectors ["memory" ]
150152 return metric .build_samples (
151- [(self ._labels + (("type" , "rss" ),), ( (TYPES .GAUGE , metric .name , "" , self ._labels + (("type" , "rss" ),), uwsgi .mem ()[0 ]), )),
152- (self ._labels + (("type" , "vsz" ),), ( (TYPES .GAUGE , metric .name , "" , self ._labels + (("type" , "vsz" ),), uwsgi .mem ()[1 ]), ))])
153+ [(self ._labels + (("type" , "rss" ),), ( (TYPES .GAUGE , metric .name , "" , self ._labels + (("type" , "rss" ),), uwsgi .mem ()[0 ]), )), # noqa
154+ (self ._labels + (("type" , "vsz" ),), ( (TYPES .GAUGE , metric .name , "" , self ._labels + (("type" , "vsz" ),), uwsgi .mem ()[1 ]), ))]) # noqa
153155
154156
155157class UWSGIStorage (BaseStorage ):
@@ -199,7 +201,6 @@ def metric_name(self, name):
199201 """
200202 return ":" .join ([self ._namespace , name ])
201203
202-
203204 @staticmethod
204205 def get_unique_id ():
205206 try :
@@ -221,7 +222,7 @@ def declare_metrics(self):
221222 def collect (self ):
222223 labels = self ._labels + (("sharedarea" , self ._sharedarea_id ), ("id" , self .get_unique_id ()))
223224 metric = self ._collectors ["memory_sync" ]
224- metric .add_sample (labels , metric .build_sample (labels , ( (TYPES .GAUGE , metric .name , "" , labels , self ._syncs ), )))
225+ metric .add_sample (labels , metric .build_sample (labels , ( (TYPES .GAUGE , metric .name , "" , labels , self ._syncs ), ))) # noqa
225226
226227 yield metric
227228
@@ -230,16 +231,15 @@ def collect(self):
230231 # yield metric
231232 metric = self ._collectors ["memory_size" ]
232233
233- metric .add_sample (labels , metric .build_sample (labels , ( (TYPES .GAUGE , metric .name , "" , labels , self .get_area_size ()), )))
234+ metric .add_sample (labels , metric .build_sample (labels , ( (TYPES .GAUGE , metric .name , "" , labels , self .get_area_size ()), ))) # noqa
234235
235236 yield metric
236237
237238 metric = self ._collectors ["num_keys" ]
238- metric .add_sample (labels , metric .build_sample (labels , ( (TYPES .GAUGE , metric .name , "" , labels , len (self ._positions )), )))
239+ metric .add_sample (labels , metric .build_sample (labels , ( (TYPES .GAUGE , metric .name , "" , labels , len (self ._positions )), ))) # noqa
239240
240241 yield metric
241242
242-
243243 @property
244244 def m (self ):
245245 return self ._m
@@ -279,12 +279,12 @@ def get_area_size_with_lock(self):
279279 return self .get_area_size ()
280280
281281 def get_slice (self , start , size ):
282- return slice (start , start + size )
282+ return slice (start , start + size )
283283
284284 def get_area_size (self ):
285285 """Read area size from uwsgi
286286 """
287- return struct .unpack (b"i" , self .m [self .get_slice (self .AREA_SIZE_POSITION , self .AREA_SIZE_SIZE )])[0 ]
287+ return struct .unpack (b"i" , self .m [self .get_slice (self .AREA_SIZE_POSITION , self .AREA_SIZE_SIZE )]. tobytes () )[0 ]
288288
289289 def init_area_size (self ):
290290 return self .update_area_size (self .AREA_SIZE_SIZE )
@@ -298,7 +298,6 @@ def update_area_sign(self):
298298 self ._sign = os .urandom (self .SIGN_SIZE )
299299 self .m [self .get_slice (self .SIGN_POSITION , self .SIGN_SIZE )] = self ._sign
300300
301-
302301 def get_area_sign (self ):
303302 """Get current area sign from memory
304303 """
@@ -353,21 +352,25 @@ def get_string_padding(self, key):
353352 http://stackoverflow.com/questions/11642210/computing-padding-required-for-n-byte-alignment
354353 :param key: encoded string
355354 """
356- #return (4 - (len(key) % 4)) % 4
355+ return (4 - (len (key ) % 4 )) % 4
356+
357+ # return (8 - (len(key) + 4) % 4)
357358
358- return (8 - (len (key ) + 4 ) % 8 )
359+ def get_string_padded_len (self , key ):
360+ padding = self .get_string_padding (key )
361+ return len (key ) + padding
359362
360363 def get_key_size (self , key ):
361364 """Calculate how many memory need key
362365 :param key: key string
363366 """
364- return len (self .serialize_key (key )) + self .KEY_SIZE_SIZE + self .KEY_VALUE_SIZE
365-
367+ return self .get_string_padded_len (self .serialize_key (key )) + self .KEY_SIZE_SIZE + self .KEY_VALUE_SIZE
366368
367369 def get_binary_string (self , key , value ):
368- item_template = "=i{0}sd" .format (len (key )).encode ()
370+ padded_string_len = self .get_string_padded_len (key )
371+ item_template = "=i{0}sd" .format (padded_string_len ).encode ()
369372
370- return struct .pack (item_template , len ( key ), key , value )
373+ return struct .pack (item_template , padded_string_len , compat . b ( key ) , value )
371374
372375 def init_key (self , key , init_value = 0.0 ):
373376 """Initialize memory for key
@@ -393,24 +396,23 @@ def read_key_string(self, position, size):
393396 :param position: int offset for key string
394397 :param size: int key size in bytes to read
395398 """
396- key_string_bytes = self .m [self .get_slice (position , size )]
397- return struct .unpack (b"{0}s" .format (size ), key_string_bytes )[0 ]
398-
399+ key_string_bytes = self .m [self .get_slice (position , size )].tobytes ()
400+ return struct .unpack (compat .b ("{0}s" .format (size )), key_string_bytes )[0 ].strip (compat .b ("\x00 " ))
399401
400402 def read_key_value (self , position ):
401403 """Read float value of position
402404
403405 :param position: int offset for key value float
404406 """
405- key_value_bytes = self .m [self .get_slice (position , self .KEY_VALUE_SIZE )]
407+ key_value_bytes = self .m [self .get_slice (position , self .KEY_VALUE_SIZE )]. tobytes ()
406408 return struct .unpack (b"d" , key_value_bytes )[0 ]
407409
408410 def read_key_size (self , position ):
409411 """Read key size from position
410412
411413 :param position: int offset for 4-byte key size
412414 """
413- key_size_bytes = self .m [self .get_slice (position , self .KEY_SIZE_SIZE )]
415+ key_size_bytes = self .m [self .get_slice (position , self .KEY_SIZE_SIZE )]. tobytes ()
414416 return struct .unpack (b"i" , key_size_bytes )[0 ]
415417
416418 def write_key_value (self , position , value ):
@@ -558,7 +560,7 @@ def __len__(self):
558560
559561 def clear (self ):
560562 for x in xrange (self .AREA_SIZE_SIZE + self .AREA_SIZE_SIZE ):
561- self .m [x ] = " \x00 "
563+ self .m [x ] = compat . PAD_SYMBOL
562564
563565 self ._positions .clear ()
564566
0 commit comments