Skip to content

Commit 3e2ff07

Browse files
committed
Added metrics for UWSGIStorage
1 parent d70a2e5 commit 3e2ff07

File tree

9 files changed

+229
-170
lines changed

9 files changed

+229
-170
lines changed

conftest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,8 @@ def measure_time():
3535
@pytest.fixture()
3636
def iterations():
3737
return 500
38+
39+
40+
@pytest.fixture()
41+
def num_workers():
42+
return 10

pyprometheus/contrib/uwsgi_features.py

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from contextlib import contextmanager
2020
from logging import getLogger
2121
from pyprometheus.const import TYPES
22-
from pyprometheus.metrics import Gauge
22+
from pyprometheus.metrics import Gauge, Counter
2323
from pyprometheus.storage import BaseStorage, LocalMemoryStorage
2424

2525

@@ -37,7 +37,7 @@
3737
class InvalidUWSGISharedareaPagesize(Exception):
3838
pass
3939

40-
logger = getLogger('pyprometheus.uwsgi_features')
40+
logger = getLogger("pyprometheus.uwsgi_features")
4141

4242

4343
class UWSGICollector(object):
@@ -122,7 +122,7 @@ def get_workers_samples(self, workers):
122122
for worker in workers:
123123
labels = self._labels + (("id", worker["id"]),)
124124
metric.add_sample(labels, metric.build_sample(labels,
125-
( (TYPES.GAUGE, metric.name, "", self._labels + (("id", worker["id"]),), worker[name]), )))
125+
( (TYPES.GAUGE, metric.name, "", labels, worker[name]), )))
126126

127127
yield metric
128128

@@ -163,18 +163,65 @@ class UWSGIStorage(BaseStorage):
163163
SIGN_POSITION = 4
164164
AREA_SIZE_POSITION = 0
165165

166-
def __init__(self, sharedarea_id=SHAREDAREA_ID):
166+
def __init__(self, sharedarea_id=SHAREDAREA_ID, namespace="", stats=False, labels={}):
167167
self._sharedarea_id = sharedarea_id
168168
self._used = None
169169
# Changed every time then keys added
170170
self._sign = None
171171
self._positions = {}
172172
self._rlocked = False
173173
self._wlocked = False
174-
self._m = uwsgi.sharedarea_memoryview(self._sharedarea_id)
175174
self._keys_cache = {}
175+
self._namespace = namespace
176+
self._stats = stats
177+
self._labels = tuple(sorted(labels.items(), key=lambda x: x[0]))
178+
179+
self._m = uwsgi.sharedarea_memoryview(self._sharedarea_id)
180+
176181
self.init_memory()
177182

183+
self._collectors = self.declare_metrics()
184+
185+
@property
186+
def uid(self):
187+
return "uwsgi-storage:{0}".format(self._namespace)
188+
189+
@property
190+
def text_export_header(self):
191+
return "# {0} stats metrics".format(self.__class__.__name__)
192+
193+
def metric_name(self, name):
194+
"""Make metric name with namespace
195+
196+
:param name:
197+
"""
198+
return ":".join([self._namespace, name])
199+
200+
def declare_metrics(self):
201+
return {
202+
"memory_sync": Counter(self.metric_name("memory_read"), "UWSGI shared memory syncs", ("sharedarea", ) + self._labels),
203+
"memory_size": Gauge(self.metric_name("memory_size"), "UWSGI shared memory size", ("sharedarea", ) + self._labels),
204+
"num_keys": Gauge(self.metric_name("num_keys"), "UWSGI num_keys", ("sharedarea", ) + self._labels)
205+
}
206+
207+
def collect(self):
208+
labels = self._labels + (("sharedarea", self._sharedarea_id), )
209+
# metric = self._collectors["memory_sync"]
210+
# metric.add_sample(labels, metric.build_sample(labels, ( (TYPES.GAUGE, metric.name, "", labels, ) ))
211+
212+
# yield metric
213+
metric = self._collectors["memory_size"]
214+
215+
metric.add_sample(labels, metric.build_sample(labels, ( (TYPES.GAUGE, metric.name, "", labels, self.get_area_size()), )))
216+
217+
yield metric
218+
219+
metric = self._collectors["num_keys"]
220+
metric.add_sample(labels, metric.build_sample(labels, ( (TYPES.GAUGE, metric.name, "", labels, len(self._positions)), )))
221+
222+
yield metric
223+
224+
178225
@property
179226
def m(self):
180227
return self._m
@@ -263,7 +310,6 @@ def read_memory(self):
263310
self._sign = self.get_area_sign()
264311
self._positions.clear()
265312

266-
267313
while pos < self._used + self.AREA_SIZE_POSITION:
268314

269315
key_size, (key, key_value), positions = self.read_item(pos)

pyprometheus/metrics.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def text_export_header(self):
9191
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
9292
# TYPE go_gc_duration_seconds summary
9393
"""
94-
return '\n'.join(["# HELP {name} {doc}",
94+
return "\n".join(["# HELP {name} {doc}",
9595
"# TYPE {name} {metric_type}"]).format(
9696
name=self.name,
9797
doc=self.doc,
@@ -100,7 +100,7 @@ def text_export_header(self):
100100
def build_samples(self, items):
101101
"""Build samples from objects
102102
103-
[((2, 'metric_gauge_name', '', (('label1', 'value3'), ('label2', 'value4'))), 5.0)]
103+
[((2, "metric_gauge_name", "", (("label1", "value3"), ("label2", "value4"))), 5.0)]
104104
"""
105105
for label_values, data in items:
106106
self.add_sample(label_values, self.build_sample(label_values, data))
@@ -135,16 +135,16 @@ class Gauge(BaseMetric):
135135

136136
value_class = GaugeValue
137137

138-
PARENT_METHODS = set(('inc', 'dec', 'set', 'get', 'track_inprogress',
139-
'set_to_current_time', 'time', 'value'))
138+
PARENT_METHODS = set(("inc", "dec", "set", "get", "track_inprogress",
139+
"set_to_current_time", "time", "value"))
140140

141141

142142
class Counter(BaseMetric):
143143
TYPE = "counter"
144144

145145
value_class = CounterValue
146146

147-
PARENT_METHODS = set(('inc', 'get', 'value'))
147+
PARENT_METHODS = set(("inc", "get", "value"))
148148

149149

150150
class Summary(BaseMetric):
@@ -154,9 +154,9 @@ class Summary(BaseMetric):
154154

155155
value_class = SummaryValue
156156

157-
NOT_ALLOWED_LABELS = set('quantile')
157+
NOT_ALLOWED_LABELS = set("quantile")
158158

159-
PARENT_METHODS = set(('observe', 'value', 'time'))
159+
PARENT_METHODS = set(("observe", "value", "time"))
160160

161161
def __init__(self, name, doc, labels=[], quantiles=False, registry=None):
162162
self._quantiles = list(sorted(quantiles)) if quantiles else []
@@ -168,21 +168,21 @@ def quantiles(self):
168168

169169
def build_sample(self, label_values, data):
170170
subtypes = {
171-
'sum': None,
172-
'count': None,
173-
'quantiles': [] if isinstance(self._quantiles, (list, tuple)) else None
171+
"sum": None,
172+
"count": None,
173+
"quantiles": [] if isinstance(self._quantiles, (list, tuple)) else None
174174
}
175175

176176
for meta, value in data:
177177
value_class = self.value_class.SUBTYPES[meta[2]]
178178

179179
if meta[0] == TYPES.SUMMARY_SUM:
180-
subtypes['sum'] = value_class(self, label_values=label_values, value=value)
180+
subtypes["sum"] = value_class(self, label_values=label_values, value=value)
181181
elif meta[0] == TYPES.SUMMARY_COUNTER:
182-
subtypes['count'] = value_class(self, label_values=label_values, value=value)
182+
subtypes["count"] = value_class(self, label_values=label_values, value=value)
183183
elif meta[0] == TYPES.SUMMARY_QUANTILE:
184-
quantile = dict(meta[3])['quantile']
185-
subtypes['quantiles'].append(
184+
quantile = dict(meta[3])["quantile"]
185+
subtypes["quantiles"].append(
186186
value_class(self, label_values=label_values, quantile=quantile, value=value))
187187

188188
return self.value_class(self, label_values=label_values, value=subtypes)
@@ -192,13 +192,13 @@ class Histogram(BaseMetric):
192192
TYPE = "histogram"
193193

194194
DEFAULT_BUCKETS = (0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5,
195-
0.75, 1.0, 2.5, 5.0, 7.5, 10.0, float('inf'))
195+
0.75, 1.0, 2.5, 5.0, 7.5, 10.0, float("inf"))
196196

197-
NOT_ALLOWED_LABELS = set('le')
197+
NOT_ALLOWED_LABELS = set("le")
198198

199199
value_class = HistogramValue
200200

201-
PARENT_METHODS = set(('observe', 'value', 'time'))
201+
PARENT_METHODS = set(("observe", "value", "time"))
202202

203203
def __init__(self, name, doc, labels=[], buckets=DEFAULT_BUCKETS, registry=None):
204204
self._buckets = list(sorted(buckets)) if buckets else []
@@ -211,21 +211,21 @@ def buckets(self):
211211

212212
def build_sample(self, label_values, data):
213213
subtypes = {
214-
'sum': None,
215-
'count': None,
216-
'buckets': [] if isinstance(self._buckets, (list, tuple)) else None
214+
"sum": None,
215+
"count": None,
216+
"buckets": [] if isinstance(self._buckets, (list, tuple)) else None
217217
}
218218

219219
for meta, value in data:
220220
value_class = self.value_class.SUBTYPES[meta[2]]
221221

222222
if meta[0] == TYPES.HISTOGRAM_SUM:
223-
subtypes['sum'] = value_class(self, label_values=label_values, value=value)
223+
subtypes["sum"] = value_class(self, label_values=label_values, value=value)
224224
elif meta[0] == TYPES.HISTOGRAM_COUNTER:
225-
subtypes['count'] = value_class(self, label_values=label_values, value=value)
225+
subtypes["count"] = value_class(self, label_values=label_values, value=value)
226226
elif meta[0] == TYPES.HISTOGRAM_BUCKET:
227-
bucket = dict(meta[3])['bucket']
228-
subtypes['buckets'].append(
227+
bucket = dict(meta[3])["bucket"]
228+
subtypes["buckets"].append(
229229
value_class(self, label_values=label_values, bucket=bucket, value=value))
230230

231231
return self.value_class(self, label_values=label_values, value=subtypes)

0 commit comments

Comments
 (0)