Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions src/strands/telemetry/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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)
Expand Down
19 changes: 19 additions & 0 deletions tests/strands/telemetry/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""

Expand Down