Skip to content

Commit e21061a

Browse files
committed
test: ensure child metrics retain parent namespace/subsystem/unit
Signed-off-by: hazel-shen <mail@hazel.style>
1 parent 622d045 commit e21061a

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

prometheus_client/metrics.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ def __init__(self: T,
109109
registry: Optional[CollectorRegistry] = REGISTRY,
110110
_labelvalues: Optional[Sequence[str]] = None,
111111
) -> None:
112+
113+
self._original_name = name
114+
self._namespace = namespace
115+
self._subsystem = subsystem
112116
self._name = _build_full_name(self._type, name, namespace, subsystem, unit)
113117
self._labelnames = _validate_labelnames(self, labelnames)
114118
self._labelvalues = tuple(_labelvalues or ())
@@ -177,18 +181,22 @@ def labels(self: T, *labelvalues: Any, **labelkwargs: Any) -> T:
177181
with self._lock:
178182
if labelvalues not in self._metrics:
179183

180-
child_kwargs = dict(self._kwargs) if self._kwargs else {}
184+
original_name = getattr(self, '_original_name', self._name)
185+
namespace = getattr(self, '_namespace', '')
186+
subsystem = getattr(self, '_subsystem', '')
187+
unit = getattr(self, '_unit', '')
181188

189+
child_kwargs = dict(self._kwargs) if self._kwargs else {}
182190
for k in ('namespace', 'subsystem', 'unit'):
183191
child_kwargs.pop(k, None)
184192

185193
self._metrics[labelvalues] = self.__class__(
186-
self._name,
194+
original_name,
187195
documentation=self._documentation,
188196
labelnames=self._labelnames,
189-
namespace="",
190-
subsystem="",
191-
unit="",
197+
namespace=namespace,
198+
subsystem=subsystem,
199+
unit=unit,
192200
_labelvalues=labelvalues,
193201
**child_kwargs
194202
)

tests/test_multiprocess.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,45 @@ def __init__(
467467
f"found double-built name(s): {[n for n in all_names if n.startswith(bad_prefix)]}"
468468
)
469469

470+
def test_child_preserves_parent_context_for_subclasses(self):
471+
"""
472+
Ensure child metrics preserve parent's namespace/subsystem/unit information
473+
so that subclasses can correctly use these parameters in their logic.
474+
"""
475+
class ContextAwareCounter(Counter):
476+
def __init__(self,
477+
name,
478+
documentation,
479+
labelnames=(),
480+
namespace="",
481+
subsystem="",
482+
unit="",
483+
**kwargs):
484+
self.context = {
485+
'namespace': namespace,
486+
'subsystem': subsystem,
487+
'unit': unit
488+
}
489+
super().__init__(name, documentation,
490+
labelnames=labelnames,
491+
namespace=namespace,
492+
subsystem=subsystem,
493+
unit=unit,
494+
**kwargs)
495+
496+
parent = ContextAwareCounter('m', 'help',
497+
labelnames=['status'],
498+
namespace='prod',
499+
subsystem='api',
500+
unit='seconds',
501+
registry=None)
502+
503+
child = parent.labels(status='200')
504+
505+
# Verify that child retains parent's context
506+
self.assertEqual(child.context['namespace'], 'prod')
507+
self.assertEqual(child.context['subsystem'], 'api')
508+
self.assertEqual(child.context['unit'], 'seconds')
470509

471510

472511
class TestMmapedDict(unittest.TestCase):

0 commit comments

Comments
 (0)