From 35b98cb59327ea76ffa062c3032d4f6e394ec48c Mon Sep 17 00:00:00 2001 From: Alnour Ribault Date: Mon, 25 May 2026 21:56:15 +0200 Subject: [PATCH] feat(telemetry): forward provider_kwargs to MeterProvider in setup_meter setup_meter previously hard-coded the MeterProvider construction to only accept resource and metric_readers, forcing users who needed views, exemplar_filter, or shutdown_on_exit to bypass the helper entirely and reconstruct the provider from scratch. This change accepts arbitrary keyword arguments and forwards them, exposing the full MeterProvider surface without changing existing behavior. Resolves: #843 --- src/strands/telemetry/config.py | 37 +++++++++++++++++++++++--- tests/strands/telemetry/test_config.py | 19 +++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/strands/telemetry/config.py b/src/strands/telemetry/config.py index 93225335d8..f2122dcded 100644 --- a/src/strands/telemetry/config.py +++ b/src/strands/telemetry/config.py @@ -171,9 +171,36 @@ def setup_otlp_exporter(self, **kwargs: Any) -> "StrandsTelemetry": return self def setup_meter( - self, enable_console_exporter: bool = False, enable_otlp_exporter: bool = False + self, + enable_console_exporter: bool = False, + enable_otlp_exporter: bool = False, + **provider_kwargs: Any, ) -> "StrandsTelemetry": - """Initialize the OpenTelemetry Meter.""" + """Initialize the OpenTelemetry Meter. + + Args: + enable_console_exporter: When True, attach a console metrics exporter. + enable_otlp_exporter: When True, attach an OTLP metrics exporter. + **provider_kwargs: Optional keyword arguments passed directly to + OpenTelemetry's MeterProvider initializer (e.g., views, + shutdown_on_exit). Note that resource and metric_readers are + managed by this method and cannot be overridden via this + parameter. + + Returns: + self: Enables method chaining. + + Example: + Drop high-cardinality attributes (e.g. tool_use_id, event_loop_cycle_id) + from tool metrics by passing a View through to the underlying MeterProvider: + + >>> from opentelemetry.sdk.metrics.view import View + >>> StrandsTelemetry().setup_meter( + ... enable_otlp_exporter=True, + ... views=[View(instrument_name="strands.tool.*", + ... attribute_keys={"tool_name"})], + ... ) + """ logger.info("Initializing meter") metrics_readers = [] try: @@ -190,7 +217,11 @@ def setup_meter( except Exception as e: logger.exception("error=<%s> | Failed to configure OTLP metrics exporter", e) - self.meter_provider = metrics_sdk.MeterProvider(resource=self.resource, metric_readers=metrics_readers) + self.meter_provider = metrics_sdk.MeterProvider( + resource=self.resource, + metric_readers=metrics_readers, + **provider_kwargs, + ) # Set as global tracer provider metrics_api.set_meter_provider(self.meter_provider) diff --git a/tests/strands/telemetry/test_config.py b/tests/strands/telemetry/test_config.py index cc08c295c0..3ee865c090 100644 --- a/tests/strands/telemetry/test_config.py +++ b/tests/strands/telemetry/test_config.py @@ -163,6 +163,25 @@ def test_setup_meter_with_console_and_otlp_exporter( mock_metrics_api.set_meter_provider.assert_called_once() +def test_setup_meter_forwards_provider_kwargs( + mock_resource, + mock_reader, + mock_metrics_api, + mock_meter_provider, +): + """Test that arbitrary kwargs are forwarded to MeterProvider.""" + sentinel_views = [mock.MagicMock()] + + telemetry = StrandsTelemetry() + telemetry.setup_meter(views=sentinel_views) + + mock_meter_provider.assert_called_once_with( + resource=mock_resource.return_value, + metric_readers=[], + views=sentinel_views, + ) + + def test_setup_console_exporter(mock_resource, mock_tracer_provider, mock_console_exporter, mock_simple_processor): """Test add console exporter"""