Skip to content

Commit a94f4d1

Browse files
committed
customize Starlette Instrumentor middleware to exclude noisy receive and send spans
1 parent f5770d9 commit a94f4d1

File tree

3 files changed

+51
-4
lines changed

3 files changed

+51
-4
lines changed

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_instrumentation_patch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def apply_instrumentation_patches() -> None:
6767
from amazon.opentelemetry.distro.patches._starlette_patches import _apply_starlette_instrumentation_patches
6868

6969
# Starlette auto-instrumentation v0.54b includes a strict dependency version check
70-
# This restriction was removed in v1.34.0/0.55b0. Applying temporary patch for Genesis launch
70+
# This restriction was removed in v1.34.0/0.55b0. Applying temporary patch for Bedrock AgentCore launch
7171
# TODO: Remove patch after syncing with upstream v1.34.0 or later
7272
_apply_starlette_instrumentation_patches()
7373

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_starlette_patches.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from logging import Logger, getLogger
55
from typing import Collection
66

7+
from amazon.opentelemetry.distro._utils import AGENT_OBSERVABILITY_ENABLED
8+
79
_logger: Logger = getLogger(__name__)
810

911

@@ -18,6 +20,7 @@ def _apply_starlette_instrumentation_patches() -> None:
1820
"""
1921
try:
2022
# pylint: disable=import-outside-toplevel
23+
from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
2124
from opentelemetry.instrumentation.starlette import StarletteInstrumentor
2225

2326
# Patch starlette dependencies version check
@@ -28,6 +31,21 @@ def patched_instrumentation_dependencies(self) -> Collection[str]:
2831
# Apply the patch
2932
StarletteInstrumentor.instrumentation_dependencies = patched_instrumentation_dependencies
3033

34+
# Patch to exclude http recieve/send ASGI event spans, this Middleware instrumentation is injected
35+
# internally by Starlette Instrumentor, see:
36+
# https://github.com/open-telemetry/opentelemetry-python-contrib/blob/51da0a766e5d3cbc746189e10c9573163198cfcd/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py#L573
37+
if AGENT_OBSERVABILITY_ENABLED:
38+
original_init = OpenTelemetryMiddleware.__init__
39+
40+
def patched_init(self, app, **kwargs):
41+
original_init(self, app, **kwargs)
42+
if hasattr(self, "exclude_receive_span"):
43+
self.exclude_receive_span = True
44+
if hasattr(self, "exclude_send_span"):
45+
self.exclude_send_span = True
46+
47+
OpenTelemetryMiddleware.__init__ = patched_init
48+
3149
_logger.debug("Successfully patched Starlette instrumentation_dependencies method")
3250
except Exception as exc: # pylint: disable=broad-except
3351
_logger.warning("Failed to apply Starlette instrumentation patches: %s", exc)

aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/patches/test_starlette_patches.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,36 @@
99
class TestStarlettePatch(TestCase):
1010
"""Test the Starlette instrumentation patches."""
1111

12+
@patch("amazon.opentelemetry.distro.patches._starlette_patches.AGENT_OBSERVABILITY_ENABLED", True)
1213
@patch("amazon.opentelemetry.distro.patches._starlette_patches._logger")
1314
def test_starlette_patch_applied_successfully(self, mock_logger):
1415
"""Test that the Starlette instrumentation patch is applied successfully."""
1516
# Create a mock StarletteInstrumentor class
1617
mock_instrumentor_class = MagicMock()
1718
mock_instrumentor_class.__name__ = "StarletteInstrumentor"
1819

19-
# Create a mock module
20+
class MockMiddleware:
21+
def __init__(self, app, **kwargs):
22+
pass
23+
24+
mock_middleware_class = MockMiddleware
25+
original_init = mock_middleware_class.__init__
26+
27+
# Create mock modules
2028
mock_starlette_module = MagicMock()
2129
mock_starlette_module.StarletteInstrumentor = mock_instrumentor_class
2230

23-
# Mock the import
24-
with patch.dict("sys.modules", {"opentelemetry.instrumentation.starlette": mock_starlette_module}):
31+
mock_asgi_module = MagicMock()
32+
mock_asgi_module.OpenTelemetryMiddleware = mock_middleware_class
33+
34+
# Mock the imports
35+
with patch.dict(
36+
"sys.modules",
37+
{
38+
"opentelemetry.instrumentation.starlette": mock_starlette_module,
39+
"opentelemetry.instrumentation.asgi": mock_asgi_module,
40+
},
41+
):
2542
# Apply the patch
2643
_apply_starlette_instrumentation_patches()
2744

@@ -33,6 +50,18 @@ def test_starlette_patch_applied_successfully(self, mock_logger):
3350
result = mock_instrumentor_class.instrumentation_dependencies(mock_instance)
3451
self.assertEqual(result, ("starlette >= 0.13",))
3552

53+
self.assertNotEqual(mock_middleware_class.__init__, original_init)
54+
55+
# Test middleware patching sets exclude flags
56+
mock_middleware_instance = MagicMock()
57+
mock_middleware_instance.exclude_receive_span = False
58+
mock_middleware_instance.exclude_send_span = False
59+
60+
mock_middleware_class.__init__(mock_middleware_instance, "app")
61+
62+
self.assertTrue(mock_middleware_instance.exclude_receive_span)
63+
self.assertTrue(mock_middleware_instance.exclude_send_span)
64+
3665
# Verify logging
3766
mock_logger.debug.assert_called_once_with(
3867
"Successfully patched Starlette instrumentation_dependencies method"

0 commit comments

Comments
 (0)