redis/redis-py · error · RuntimeError

Metrics are enabled but no global MeterProvider is…

Error message

Metrics are enabled but no global MeterProvider is configured.

Set up OpenTelemetry before initializing redis-py observability:

  from opentelemetry import metrics
  from opentelemetry.sdk.metrics import MeterProvider
  from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
  from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter

  # Create exporter
  exporter = OTLPMetricExporter(
      endpoint='http://localhost:4318/v1/metrics'
  )

  # Create reader
  reader = PeriodicExportingMetricReader(
      exporter=exporter,
      export_interval_millis=10000
  )

  # Create and set global provider
  provider = MeterProvider(metric_readers=[reader])
  metrics.set_meter_provider(provider)

  # Now initialize redis-py observability
  from redis.observability import get_observability_instance, OTelConfig
  otel = get_observability_instance()
  otel.init(OTelConfig(enable_metrics=True))

What it means

Raised as RuntimeError by OTelProviderManager.get_meter_provider() (redis/observability/providers.py:90) when metrics are enabled and the SDK is importable, but the global MeterProvider is still the OpenTelemetry default NoOpMeterProvider. redis-py deliberately uses the application-owned global provider (see module docstring) rather than installing its own, so if nothing has called metrics.set_meter_provider(...) the manager refuses to silently no-op and raises with a copy-pasteable setup recipe.

Solutions

  1. Set a real global MeterProvider BEFORE initializing redis-py observability, exactly as the embedded recipe shows: build an OTLPMetricExporter, wrap it in a PeriodicExportingMetricReader, construct MeterProvider(metric_readers=[reader]), then metrics.set_meter_provider(provider).
  2. Reorder application startup so the OTel SDK/provider setup runs before get_observability_instance().init(...).
  3. If you only want local/no-op metrics, disable metrics by passing OTelConfig(enabled_telemetry=[]) (or TelemetryOption(0)) so get_meter_provider() returns None before the NoOp check.
  4. Confirm your provider is not a NoOpMeterProvider via `isinstance(metrics.get_meter_provider(), NoOpMeterProvider)` returns False after setup.

Example fix

# before - metrics enabled, provider never set
from redis.observability import get_observability_instance, OTelConfig
otel = get_observability_instance()
otel.init(OTelConfig(enable_metrics=True))  # first command -> providers.py:90 RuntimeError

# after - set global provider first
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
reader = PeriodicExportingMetricReader(
    exporter=OTLPMetricExporter(endpoint='http://localhost:4318/v1/metrics'),
    export_interval_millis=10000,
)
metrics.set_meter_provider(MeterProvider(metric_readers=[reader]))
otel.init(OTelConfig(enable_metrics=True))
Defensive patterns

Strategy: validation

Validate before calling

from opentelemetry import metrics
from opentelemetry.metrics import NoOpMeterProvider

def real_provider_is_set():
    return not isinstance(metrics.get_meter_provider(), NoOpMeterProvider)

# set the provider, then verify, before initializing redis-py observability
metrics.set_meter_provider(MeterProvider(metric_readers=[reader]))
assert real_provider_is_set(), 'global MeterProvider still NoOp'
otel.init(OTelConfig(enable_metrics=True))

Try / catch

try:
    otel.init(OTelConfig(enable_metrics=True))
except RuntimeError as e:
    if 'no global MeterProvider' in str(e):
        logging.error('Set a global MeterProvider before enabling redis-py metrics')
    else:
        raise

Prevention

When it happens

Trigger: Calling otel.init(OTelConfig(enable_metrics=True)) and then a Redis operation without ever having called metrics.set_meter_provider(MeterProvider(metric_readers=[...])) first. The check is `isinstance(self._meter_provider, NoOpMeterProvider)` — so any real provider set before init avoids this, while an unset global defaults to NoOp and trips it.

Common situations: App initializes redis-py observability at import time but defers OTel SDK setup to a later app hook that runs after the first Redis command; a framework integration (e.g. FastAPI/Django startup) sets the provider in a different lifecycle stage than the one that constructs the Redis client; test code that enables metrics without wiring a provider; ordering bug where set_meter_provider runs after otel.init's first get_meter_provider().

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/99546dc6b9f2d380. Report an issue: GitHub.

Appendix: source

Thrown at redis/observability/providers.py:90

            return None

        # Lazy import - only import OTel when metrics are enabled
        try:
            from opentelemetry import metrics
            from opentelemetry.metrics import NoOpMeterProvider
        except ImportError:
            raise ImportError(
                "OpenTelemetry is not installed. Install it with:\n"
                "  pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http"
            )

        # Get the global MeterProvider
        if self._meter_provider is None:
            self._meter_provider = metrics.get_meter_provider()

            # Check if it's a real provider (not NoOp)
            if isinstance(self._meter_provider, NoOpMeterProvider):
                raise RuntimeError(
                    "Metrics are enabled but no global MeterProvider is configured.\n"
                    "\n"
                    "Set up OpenTelemetry before initializing redis-py observability:\n"
                    "\n"
                    "  from opentelemetry import metrics\n"
                    "  from opentelemetry.sdk.metrics import MeterProvider\n"
                    "  from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader\n"
                    "  from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter\n"
                    "\n"
                    "  # Create exporter\n"
                    "  exporter = OTLPMetricExporter(\n"
                    "      endpoint='http://localhost:4318/v1/metrics'\n"
                    "  )\n"
                    "\n"
                    "  # Create reader\n"
                    "  reader = PeriodicExportingMetricReader(\n"
                    "      exporter=exporter,\n"
                    "      export_interval_millis=10000\n"

View on GitHub (pinned to 6a6b581b48)