Skip to content

feat(config): add pull metric reader support to declarative config#5216

Open
MikeGoldsmith wants to merge 7 commits into
open-telemetry:mainfrom
MikeGoldsmith:mike/config-pull-metric-reader
Open

feat(config): add pull metric reader support to declarative config#5216
MikeGoldsmith wants to merge 7 commits into
open-telemetry:mainfrom
MikeGoldsmith:mike/config-pull-metric-reader

Conversation

@MikeGoldsmith
Copy link
Copy Markdown
Member

Description

Adds pull metric reader support to declarative file configuration, including Prometheus metric reader via the prometheus_development config field.

Previously, _create_metric_reader() raised ConfigurationError for any pull reader config. Now it dispatches to new factory functions that handle both the built-in Prometheus reader and plugin-based pull readers.

How it works

Prometheus (prometheus_development):

  • Dynamically imports PrometheusMetricReader and start_http_server from opentelemetry-exporter-prometheus (same try/except pattern as OTLP exporters)
  • Maps config fields: without_target_info_developmentdisable_target_info, host/portstart_http_server()
  • Warns for unsupported fields: without_scope_info, with_resource_constant_labels

Plugin pull readers:

  • Unknown exporter names in additional_properties are loaded via load_entry_point("opentelemetry_pull_metric_exporter", name)(**(config or {}))

Not yet supported (warnings logged):

Design note

Pull "exporters" like Prometheus are combined reader+exporter objects — PrometheusMetricReader IS a MetricReader. The _create_pull_metric_exporter() function returns a MetricReader, matching the config schema's terminology while reflecting the SDK's class hierarchy.

Example config

meter_provider:
  readers:
    - pull:
        exporter:
          prometheus_development:
            host: "0.0.0.0"
            port: 9090
            without_target_info_development: true

Tests

8 new tests covering: prometheus creation with config, defaults, missing package, no exporter, plugin loading, plugin not found, producers warning, cardinality_limits warning.

Closes #5073

Implements PullMetricReader and PullMetricExporter support in
declarative file configuration:

- _create_prometheus_metric_reader() — dynamically imports
  PrometheusMetricReader, maps config fields (host, port,
  without_target_info_development), and starts HTTP server
- _create_pull_metric_exporter() — dispatches to prometheus or
  loads plugin readers via opentelemetry_pull_metric_exporter
  entry point group
- _create_pull_metric_reader() — handles producers (warns, open-telemetry#5074)
  and cardinality_limits (warns), delegates to exporter factory

producers and cardinality_limits log warnings as not yet supported.

Assisted-by: Claude Opus 4.6
@MikeGoldsmith MikeGoldsmith requested a review from a team as a code owner May 15, 2026 12:54
@MikeGoldsmith MikeGoldsmith moved this to Ready for merge in Python PR digest May 15, 2026
@MikeGoldsmith MikeGoldsmith moved this from Ready for merge to Ready for review in Python PR digest May 15, 2026
Remove redundant 'or False' from bool() conversion.

Assisted-by: Claude Opus 4.6
Add provider assertions so test methods use self, satisfying
pylint's no-self-use check.

Assisted-by: Claude Opus 4.6
Comment thread opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_meter_provider.py Outdated
Comment thread opentelemetry-sdk/tests/_configuration/test_meter_provider.py
@MikeGoldsmith MikeGoldsmith moved this from Ready for review to Approved PRs in Python PR digest May 18, 2026
- Add PrometheusMetricExporterConfig type annotation to
  _create_prometheus_metric_reader config parameter
- Assert entry_points is called with the correct group name
  (opentelemetry_pull_metric_exporter) in plugin loading test

Assisted-by: Claude Opus 4.6
start_http_server,
)
except ImportError as exc:
raise ConfigurationError(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No need to add this into this PR, but it might be nice to define an exception specifically for dependency errors, e.g.

class MissingDependencyError(ConfigurationError):
    """Raised when an optional dependency is not installed."""

    def __init__(
        self,
        package: str,
        feature: str | None = None,
        install_name: str | None = None,
        extras: str | None = None,
    ) -> None:
        self.package = package
        self.feature = feature
        self.install_name = install_name or package
        self.extras = extras

        if extras:
            install_cmd = f"pip install '{self.install_name}[{extras}]'"
        else:
            install_cmd = f"pip install {self.install_name}"

        if feature:
            message = (
                f"{feature} requires '{package}'. "
                f"Install it with: {install_cmd}"
            )
        else:
            message = (
                f"'{package}' is required but not installed. "
                f"Install it with: {install_cmd}"
            )

        super().__init__(message)

@herin049
Copy link
Copy Markdown
Contributor

Looks like lint is failing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Approved PRs

Development

Successfully merging this pull request may close these issues.

feat(config): add metric producer support to declarative config

2 participants