Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#674] Made the registry restriction handle newly added metrics. #675

Merged
merged 2 commits into from
Jul 1, 2021
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
9 changes: 9 additions & 0 deletions prometheus_client/metrics_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ def __repr__(self):
self.samples,
)

def _restricted_metric(self, names):
"""Build a snapshot of a metric with samples restricted to a given set of names."""
samples = [s for s in self.samples if s[0] in names]
if samples:
m = Metric(self.name, self.documentation, self.type)
m.samples = samples
return m
return None


class UnknownMetricFamily(Metric):
"""A single unknown metric and its samples.
Expand Down
35 changes: 13 additions & 22 deletions prometheus_client/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,28 +94,7 @@ def restricted_registry(self, names):

Experimental."""
names = set(names)
collectors = set()
metrics = []
with self._lock:
if 'target_info' in names and self._target_info:
metrics.append(self._target_info_metric())
names.remove('target_info')
for name in names:
if name in self._names_to_collectors:
collectors.add(self._names_to_collectors[name])
for collector in collectors:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this code has caused a serious performance regression. The whole point of this feature is not to collect from collectors that aren't needed, so that it's very cheap to access just one or two collectors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, thank you for the context.

@pavel-lexyr perhaps let's approach this by improving the documentation, would you be willing to open a PR to change this back but with more complete documentation?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to undo the whole change (even though it is a behaviour change as to when it binds), but the collector lookup is important.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed your concerns in #680. Let me know if you find the implementation agreeable.

for metric in collector.collect():
samples = [s for s in metric.samples if s[0] in names]
if samples:
m = Metric(metric.name, metric.documentation, metric.type)
m.samples = samples
metrics.append(m)

class RestrictedRegistry(object):
def collect(self):
return metrics

return RestrictedRegistry()
return RestrictedRegistry(names, self)

def set_target_info(self, labels):
with self._lock:
Expand Down Expand Up @@ -150,4 +129,16 @@ def get_sample_value(self, name, labels=None):
return None


class RestrictedRegistry(object):
def __init__(self, names, registry):
self._name_set = set(names)
self._registry = registry

def collect(self):
for metric in self._registry.collect():
m = metric._restricted_metric(self._name_set)
if m:
yield m


REGISTRY = CollectorRegistry(auto_describe=True)
18 changes: 15 additions & 3 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,19 @@ def test_restricted_registry(self):

m = Metric('s', 'help', 'summary')
m.samples = [Sample('s_sum', {}, 7)]
self.assertEqual([m], registry.restricted_registry(['s_sum']).collect())
self.assertEqual([m], list(registry.restricted_registry(['s_sum']).collect()))

def test_restricted_registry_adds_new_metrics(self):
registry = CollectorRegistry()
Counter('c_total', 'help', registry=registry)

restricted_registry = registry.restricted_registry(['s_sum'])

Summary('s', 'help', registry=registry).observe(7)
m = Metric('s', 'help', 'summary')
m.samples = [Sample('s_sum', {}, 7)]

self.assertEqual([m], list(restricted_registry.collect()))

def test_target_info_injected(self):
registry = CollectorRegistry(target_info={'foo': 'bar'})
Expand All @@ -820,11 +832,11 @@ def test_target_info_restricted_registry(self):

m = Metric('s', 'help', 'summary')
m.samples = [Sample('s_sum', {}, 7)]
self.assertEqual([m], registry.restricted_registry(['s_sum']).collect())
self.assertEqual([m], list(registry.restricted_registry(['s_sum']).collect()))

m = Metric('target', 'Target metadata', 'info')
m.samples = [Sample('target_info', {'foo': 'bar'}, 1)]
self.assertEqual([m], registry.restricted_registry(['target_info']).collect())
self.assertEqual([m], list(registry.restricted_registry(['target_info']).collect()))


if __name__ == '__main__':
Expand Down