8000 Add target_info to registries (#453) · lweith/client_python@7ced8d3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7ced8d3

Browse files
authored
Add target_info to registries (prometheus#453)
This allows target labels as needed by push-based systems to be provided, in a way that doesn't mess up Prometheus's own top-down pull based approach to SD. Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
1 parent 8601873 commit 7ced8d3

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

prometheus_client/registry.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ class CollectorRegistry(object):
1212
exposition formats.
1313
"""
1414

15-
def __init__(self, auto_describe=False):
15+
def __init__(self, auto_describe=False, target_info=None):
1616
self._collector_to_names = {}
1717
self._names_to_collectors = {}
1818
self._auto_describe = auto_describe
1919
self._lock = Lock()
20+
self._target_info = {}
21+
self.set_target_info(target_info)
2022

2123
def register(self, collector):
2224
"""Add a collector to the registry."""
@@ -69,8 +71,13 @@ def _get_names(self, collector):
6971
def collect(self):
7072
"""Yields metrics from the collectors in the registry."""
7173
collectors = None
74+
ti = None
7275
with self._lock:
7376
collectors = copy.copy(self._collector_to_names)
77+
if self._target_info:
78+
ti = self._target_info_metric()
79+
if ti:
80+
yield ti
7481
for collector in collectors:
7582
for metric in collector.collect():
7683
yield metric
@@ -87,11 +94,14 @@ def restricted_registry(self, names):
8794
Experimental."""
8895
names = set(names)
8996
collectors = set()
97+
metrics = []
9098
with self._lock:
99+
if 'target_info' in names and self._target_info:
100+
metrics.append(self._target_info_metric())
101+
names.remove('target_info')
91102
for name in names:
92103
if name in self._names_to_collectors:
93104
collectors.add(self._names_to_collectors[name])
94-
metrics = []
95105
for collector in collectors:
96106
for metric in collector.collect():
97107
samples = [s for s in metric.samples if s[0] in names]
@@ -106,6 +116,25 @@ def collect(self):
106116

107117
return RestrictedRegistry()
108118

119+
def set_target_info(self, labels):
120+
with self._lock:
121+
if labels:
122+
if not self._target_info and 'target_info' in self._names_to_collectors:
123+
raise ValueError('CollectorRegistry already contains a target_info metric')
124+
self._names_to_collectors['target_info'] = None
125+
elif self._target_info:
126+
self._names_to_collectors.pop('target_info', None)
127+
self._target_info = labels
128+
129+
def get_target_info(self):
130+
with self._lock:
131+
return self._target_info
132+
133+
def _target_info_metric(self):
134+
m = Metric('target', 'Target metadata', 'info')
135+
m.add_sample('target_info', self._target_info, 1)
136+
return m
137+
109138
def get_sample_value(self, name, labels=None):
110139
"""Returns the sample value, or None if not found.
111140

tests/test_core.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,9 @@ def test_duplicate_metrics_raises(self):
696696
# The name of the histogram itself isn't taken.
697697
Gauge('h', 'help', registry=registry)
698698

699+
Info('i', 'help', registry=registry)
700+
self.assertRaises(ValueError, Gauge, 'i_info', 'help', registry=registry)
701+
699702
def test_unregister_works(self):
700703
registry = CollectorRegistry()
701704
s = Summary('s', 'help', registry=registry)
@@ -728,6 +731,34 @@ def test_restricted_registry(self):
728731
m.samples = [Sample('s_sum', {}, 7)]
729732
self.assertEquals([m], registry.restricted_registry(['s_sum']).collect())
730733

734+
def test_target_info_injected(self):
735+
registry = CollectorRegistry(target_info={'foo': 'bar'})
736+
self.assertEqual(1, registry.get_sample_value('target_info', {'foo': 'bar'}))
737+
738+
def test_target_info_duplicate_detected(self):
739+
registry = CollectorRegistry(target_info={'foo': 'bar'})
740+
self.assertRaises(ValueError, Info, 'target', 'help', registry=registry)
741+
742+
registry.set_target_info({})
743+
i = Info('target', 'help', registry=registry)
744+
registry.set_target_info({})
745+
self.assertRaises(ValueError, Info, 'target', 'help', registry=registry)
746+
self.assertRaises(ValueError, registry.set_target_info, {'foo': 'bar'})
747+
registry.unregister(i)
748+
registry.set_target_info({'foo': 'bar'})
749+
750+
def test_target_info_restricted_registry(self):
751+
registry = CollectorRegistry(target_info={'foo': 'bar'})
752+
Summary('s', 'help', registry=registry).observe(7)
753+
754+
m = Metric('s', 'help', 'summary')
755+
m.samples = [Sample('s_sum', {}, 7)]
756+
self.assertEquals([m], registry.restricted_registry(['s_sum']).collect())
757+
758+
m = Metric('target', 'Target metadata', 'info')
759+
m.samples = [Sample('target_info', {'foo': 'bar'}, 1)]
760+
self.assertEquals([m], registry.restricted_registry(['target_info']).collect())
761+
731762

732763
if __name__ == '__main__':
733764
unittest.main()

0 commit comments

Comments
 (0)
0