Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Features
- Four types of metric are supported: Counter, Gauge, Summary(without quantiles) and Histogram.
- InMemoryStorage (do not use it for multiprocessing apps)
- UWSGI storage - share metrics between processes
- UWAGI flush storage - sync metrics with uwsgi sharedarea by flush call
- time decorator
- time context manager

Expand Down
13 changes: 12 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,21 @@ def project_root():
def run_around_tests():
m = uwsgi.sharedarea_memoryview(0)
for x in xrange(len(m)):
m[x] = '\x00'
m[x] = "\x00"

yield


@pytest.fixture
def measure_time():
return measure_time_manager


@pytest.fixture()
def iterations():
return 500


@pytest.fixture()
def num_workers():
return 10
223 changes: 162 additions & 61 deletions pyprometheus/contrib/uwsgi_features.py

Large diffs are not rendered by default.

56 changes: 24 additions & 32 deletions pyprometheus/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@
:github: http://github.com/Lispython/pyprometheus
"""



from pyprometheus.const import TYPES
from pyprometheus.values import (MetricValue, GaugeValue,
CounterValue, SummaryValue,
HistogramValue)

class BaseMetric(object):

value_class = MetricValue
Expand Down Expand Up @@ -94,7 +91,7 @@ def text_export_header(self):
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
"""
return '\n'.join(["# HELP {name} {doc}",
return "\n".join(["# HELP {name} {doc}",
"# TYPE {name} {metric_type}"]).format(
name=self.name,
doc=self.doc,
Expand All @@ -103,7 +100,7 @@ def text_export_header(self):
def build_samples(self, items):
"""Build samples from objects

[((2, 'metric_gauge_name', '', (('label1', 'value3'), ('label2', 'value4'))), 5.0)]
[((2, "metric_gauge_name", "", (("label1", "value3"), ("label2", "value4"))), 5.0)]
"""
for label_values, data in items:
self.add_sample(label_values, self.build_sample(label_values, data))
Expand Down Expand Up @@ -132,27 +129,22 @@ def __getattr__(self, name):
# return super(BaseMetric, self).__getattr__(name)






class Gauge(BaseMetric):

TYPE = "gauge"

value_class = GaugeValue

PARENT_METHODS = set(('inc', 'dec', 'set', 'get', 'track_inprogress',
'set_to_current_time', 'time', 'value'))

PARENT_METHODS = set(("inc", "dec", "set", "get", "track_inprogress",
"set_to_current_time", "time", "value"))


class Counter(BaseMetric):
TYPE = "counter"

value_class = CounterValue

PARENT_METHODS = set(('inc', 'get', 'value'))
PARENT_METHODS = set(("inc", "get", "value"))


class Summary(BaseMetric):
Expand All @@ -162,9 +154,9 @@ class Summary(BaseMetric):

value_class = SummaryValue

NOT_ALLOWED_LABELS = set('quantile')
NOT_ALLOWED_LABELS = set("quantile")

PARENT_METHODS = set(('observe', 'value', 'time'))
PARENT_METHODS = set(("observe", "value", "time"))

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

def build_sample(self, label_values, data):
subtypes = {
'sum': None,
'count': None,
'quantiles': [] if isinstance(self._quantiles, (list, tuple)) else None
"sum": None,
"count": None,
"quantiles": [] if isinstance(self._quantiles, (list, tuple)) else None
}

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

if meta[0] == TYPES.SUMMARY_SUM:
subtypes['sum'] = value_class(self, label_values=label_values, value=value)
subtypes["sum"] = value_class(self, label_values=label_values, value=value)
elif meta[0] == TYPES.SUMMARY_COUNTER:
subtypes['count'] = value_class(self, label_values=label_values, value=value)
subtypes["count"] = value_class(self, label_values=label_values, value=value)
elif meta[0] == TYPES.SUMMARY_QUANTILE:
quantile = dict(meta[3])['quantile']
subtypes['quantiles'].append(
quantile = dict(meta[3])["quantile"]
subtypes["quantiles"].append(
value_class(self, label_values=label_values, quantile=quantile, value=value))

return self.value_class(self, label_values=label_values, value=subtypes)
Expand All @@ -200,13 +192,13 @@ class Histogram(BaseMetric):
TYPE = "histogram"

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

NOT_ALLOWED_LABELS = set('le')
NOT_ALLOWED_LABELS = set("le")

value_class = HistogramValue

PARENT_METHODS = set(('observe', 'value', 'time'))
PARENT_METHODS = set(("observe", "value", "time"))

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

def build_sample(self, label_values, data):
subtypes = {
'sum': None,
'count': None,
'buckets': [] if isinstance(self._buckets, (list, tuple)) else None
"sum": None,
"count": None,
"buckets": [] if isinstance(self._buckets, (list, tuple)) else None
}

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

if meta[0] == TYPES.HISTOGRAM_SUM:
subtypes['sum'] = value_class(self, label_values=label_values, value=value)
subtypes["sum"] = value_class(self, label_values=label_values, value=value)
elif meta[0] == TYPES.HISTOGRAM_COUNTER:
subtypes['count'] = value_class(self, label_values=label_values, value=value)
subtypes["count"] = value_class(self, label_values=label_values, value=value)
elif meta[0] == TYPES.HISTOGRAM_BUCKET:
bucket = dict(meta[3])['bucket']
subtypes['buckets'].append(
bucket = dict(meta[3])["bucket"]
subtypes["buckets"].append(
value_class(self, label_values=label_values, bucket=bucket, value=value))

return self.value_class(self, label_values=label_values, value=subtypes)
2 changes: 0 additions & 2 deletions pyprometheus/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,9 @@ def label_group(self, value):
class LocalMemoryStorage(BaseStorage):

def __init__(self):
self._storage = defaultdict(lambda: defaultdict(lambda: defaultdict(float)))
self._storage = defaultdict(float)
self._lock = Lock()


def inc_value(self, key, value):
with self._lock:
self._storage[key] += value
Expand Down
Loading