Skip to content

fix(multiprocess): avoid double-building child metric names (#1035) - #1146

Merged
csmarchbanks merged 2 commits into
prometheus:masterfrom
hazel-shen:fix/multiprocess-child-name-double-build-1035
Nov 17, 2025
Merged

fix(multiprocess): avoid double-building child metric names (#1035)#1146
csmarchbanks merged 2 commits into
prometheus:masterfrom
hazel-shen:fix/multiprocess-child-name-double-build-1035

Conversation

@hazel-shen

@hazel-shenhazel-shen commented Nov 14, 2025

Copy link
Copy Markdown
Contributor

Description

Fixes #1035

Child metrics created via labels() could rebuild their full names when using metric subclasses with default namespace/subsystem/unit, especially in multiprocess mode, producing double-prefixed names.

Problem

With a subclass like:

classCustomCounter(Counter):
def__init__(self, name, documentation, labelnames=(),
namespace='mydefaultnamespace',
subsystem='mydefaultsubsystem',
unit='defaultunit',
**kwargs):
super().__init__(name, documentation, labelnames=labelnames,
namespace=namespace, subsystem=subsystem,
unit=unit, **kwargs)

and an instance:

c=CustomCounter(
name='m',
documentation='help',
labelnames=('status', 'method'),
namespace='mynamespace',
subsystem='mysubsystem',
unit='seconds',
)

multiprocess mode could export child metrics with double-prefixed names like:

mydefaultnamespace_mydefaultsubsystem_mynamespace_mysubsystem_m_seconds_total

instead of the correct:

mynamespace_mysubsystem_m_seconds_total

This happened because the already-built full name was passed to the child metric constructor, which then applied namespace/subsystem/unit transformations a second time.

Solution

  • In MetricWrapperBase.__init__, store original constructor arguments:

    self._original_name=nameself._namespace=namespaceself._subsystem=subsystemself._unit=unit
  • In MetricWrapperBase.labels(), use stored values when creating child metrics:

    original_name=getattr(self, '_original_name', self._name)
    namespace=getattr(self, '_namespace', '')
    subsystem=getattr(self, '_subsystem', '')
    unit=getattr(self, '_unit', '')
    self._metrics[labelvalues] =self.__class__(
    original_name,
    namespace=namespace,
    subsystem=subsystem,
    unit=unit,
    ...
    )

This ensures the full name is built exactly once, making single-process and multiprocess exports consistent.

Testing

  • All existing tests pass
  • Verified correct name construction in multiprocess mode
  • Verified subclass compatibility (child metrics preserve parent context)
  • Backward compatible via getattr() fallbacks

Breaking Changes

None (internal-only change to MetricWrapperBase)

@hazel-shen
hazel-shenforce-pushed the fix/multiprocess-child-name-double-build-1035 branch from 7bef223 to 11f2793CompareNovember 14, 2025 11:23
@hazel-shen
hazel-shenforce-pushed the fix/multiprocess-child-name-double-build-1035 branch 2 times, most recently from 2c01fe2 to e21061aCompareNovember 14, 2025 11:30
Signed-off-by: hazel-shen <mail@hazel.style>
@hazel-shen
hazel-shenforce-pushed the fix/multiprocess-child-name-double-build-1035 branch from e21061a to d0cf1fcCompareNovember 14, 2025 11:40

@csmarchbankscsmarchbanks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

@csmarchbanks
csmarchbanks merged commit e8f8bae into prometheus:masterNov 17, 2025
12 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@hazel-shen@csmarchbanks