From 1fb67a7b86251229bce91dad2530893618469ffe Mon Sep 17 00:00:00 2001 From: Lei Wang <66336933+wangzlei@users.noreply.github.com> Date: Mon, 15 Sep 2025 16:56:47 -0700 Subject: [PATCH 1/3] Merge main to release/v0.12.x for v0.12.1 releasing (#467) *Issue #, if available:* *Description of changes:* By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. --------- Co-authored-by: Eric Zhang Co-authored-by: github-actions Co-authored-by: Eric Zhang Co-authored-by: Steve Liu --- .github/workflows/daily-scan.yml | 4 +- .github/workflows/release-build.yml | 18 ++++ .../distro/patches/_instrumentation_patch.py | 2 +- .../distro/patches/_starlette_patches.py | 22 +++++ .../amazon/opentelemetry/distro/version.py | 2 +- .../distro/patches/test_starlette_patches.py | 82 +++++++++++++------ 6 files changed, 101 insertions(+), 29 deletions(-) diff --git a/.github/workflows/daily-scan.yml b/.github/workflows/daily-scan.yml index da6a3b392..79d826202 100644 --- a/.github/workflows/daily-scan.yml +++ b/.github/workflows/daily-scan.yml @@ -95,7 +95,7 @@ jobs: id: high_scan uses: ./.github/actions/image_scan with: - image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.11.0" + image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.12.0" severity: 'CRITICAL,HIGH' logout: 'false' @@ -104,7 +104,7 @@ jobs: id: low_scan uses: ./.github/actions/image_scan with: - image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.11.0" + image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.12.0" severity: 'MEDIUM,LOW,UNKNOWN' logout: 'false' diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index e3c8fcf29..6d818c0e7 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -28,6 +28,24 @@ jobs: - name: Checkout Repo @ SHA - ${{ github.sha }} uses: actions/checkout@v4 + - name: Check main build status + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + WORKFLOW_ID=$(gh api repos/${{ github.repository }}/actions/workflows --jq '.workflows[] | select(.name=="Python Instrumentation Main Build") | .id') + LATEST_RUN=$(gh api repos/${{ github.repository }}/actions/workflows/$WORKFLOW_ID/runs --jq '[.workflow_runs[] | select(.head_branch=="${{ github.ref_name }}")] | sort_by(.created_at) | .[-1] | {conclusion, status}') + STATUS=$(echo "$LATEST_RUN" | jq -r '.status') + CONCLUSION=$(echo "$LATEST_RUN" | jq -r '.conclusion') + + if [ "$STATUS" = "in_progress" ] || [ "$STATUS" = "queued" ]; then + echo "Main build is still running (status: $STATUS). Cannot proceed with release." + exit 1 + elif [ "$CONCLUSION" != "success" ]; then + echo "Latest main build on branch ${{ github.ref_name }} conclusion: $CONCLUSION" + exit 1 + fi + echo "Main build succeeded, proceeding with release" + - name: Build Wheel and Image Files uses: ./.github/actions/artifacts_build with: diff --git a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_instrumentation_patch.py b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_instrumentation_patch.py index df066bca2..7cc5611f7 100644 --- a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_instrumentation_patch.py +++ b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_instrumentation_patch.py @@ -67,7 +67,7 @@ def apply_instrumentation_patches() -> None: from amazon.opentelemetry.distro.patches._starlette_patches import _apply_starlette_instrumentation_patches # Starlette auto-instrumentation v0.54b includes a strict dependency version check - # This restriction was removed in v1.34.0/0.55b0. Applying temporary patch for Genesis launch + # This restriction was removed in v1.34.0/0.55b0. Applying temporary patch for Bedrock AgentCore launch # TODO: Remove patch after syncing with upstream v1.34.0 or later _apply_starlette_instrumentation_patches() diff --git a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_starlette_patches.py b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_starlette_patches.py index b3bcd624b..385fb0b59 100644 --- a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_starlette_patches.py +++ b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/patches/_starlette_patches.py @@ -4,6 +4,8 @@ from logging import Logger, getLogger from typing import Collection +from amazon.opentelemetry.distro._utils import is_agent_observability_enabled + _logger: Logger = getLogger(__name__) @@ -18,6 +20,7 @@ def _apply_starlette_instrumentation_patches() -> None: """ try: # pylint: disable=import-outside-toplevel + from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware from opentelemetry.instrumentation.starlette import StarletteInstrumentor # Patch starlette dependencies version check @@ -28,6 +31,25 @@ def patched_instrumentation_dependencies(self) -> Collection[str]: # Apply the patch StarletteInstrumentor.instrumentation_dependencies = patched_instrumentation_dependencies + # pylint: disable=line-too-long + # Patch to exclude http receive/send ASGI event spans from Bedrock AgentCore, + # this Middleware instrumentation is injected internally by Starlette Instrumentor, see: + # https://github.com/open-telemetry/opentelemetry-python-contrib/blob/51da0a766e5d3cbc746189e10c9573163198cfcd/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py#L573 + # + # Issue for tracking a feature to customize this setting within Starlette: + # https://github.com/open-telemetry/opentelemetry-python-contrib/issues/3725 + if is_agent_observability_enabled(): + original_init = OpenTelemetryMiddleware.__init__ + + def patched_init(self, app, **kwargs): + original_init(self, app, **kwargs) + if hasattr(self, "exclude_receive_span"): + self.exclude_receive_span = True + if hasattr(self, "exclude_send_span"): + self.exclude_send_span = True + + OpenTelemetryMiddleware.__init__ = patched_init + _logger.debug("Successfully patched Starlette instrumentation_dependencies method") except Exception as exc: # pylint: disable=broad-except _logger.warning("Failed to apply Starlette instrumentation patches: %s", exc) diff --git a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py index 9a19a2e07..07665e687 100644 --- a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py +++ b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py @@ -1,4 +1,4 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -__version__ = "0.12.0" +__version__ = "0.12.0.dev0" diff --git a/aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/patches/test_starlette_patches.py b/aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/patches/test_starlette_patches.py index e0bbf4270..3de5f0bde 100644 --- a/aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/patches/test_starlette_patches.py +++ b/aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/patches/test_starlette_patches.py @@ -12,31 +12,63 @@ class TestStarlettePatch(TestCase): @patch("amazon.opentelemetry.distro.patches._starlette_patches._logger") def test_starlette_patch_applied_successfully(self, mock_logger): """Test that the Starlette instrumentation patch is applied successfully.""" - # Create a mock StarletteInstrumentor class - mock_instrumentor_class = MagicMock() - mock_instrumentor_class.__name__ = "StarletteInstrumentor" - - # Create a mock module - mock_starlette_module = MagicMock() - mock_starlette_module.StarletteInstrumentor = mock_instrumentor_class - - # Mock the import - with patch.dict("sys.modules", {"opentelemetry.instrumentation.starlette": mock_starlette_module}): - # Apply the patch - _apply_starlette_instrumentation_patches() - - # Verify the instrumentation_dependencies method was replaced - self.assertTrue(hasattr(mock_instrumentor_class, "instrumentation_dependencies")) - - # Test the patched method returns the expected value - mock_instance = MagicMock() - result = mock_instrumentor_class.instrumentation_dependencies(mock_instance) - self.assertEqual(result, ("starlette >= 0.13",)) - - # Verify logging - mock_logger.debug.assert_called_once_with( - "Successfully patched Starlette instrumentation_dependencies method" - ) + for agent_enabled in [True, False]: + with self.subTest(agent_enabled=agent_enabled): + with patch.dict("os.environ", {"AGENT_OBSERVABILITY_ENABLED": "true" if agent_enabled else "false"}): + # Create a mock StarletteInstrumentor class + mock_instrumentor_class = MagicMock() + mock_instrumentor_class.__name__ = "StarletteInstrumentor" + + def create_middleware_class(): + class MockMiddleware: + def __init__(self, app, **kwargs): + pass + + return MockMiddleware + + mock_middleware_class = create_middleware_class() + + mock_starlette_module = MagicMock() + mock_starlette_module.StarletteInstrumentor = mock_instrumentor_class + + mock_asgi_module = MagicMock() + mock_asgi_module.OpenTelemetryMiddleware = mock_middleware_class + + with patch.dict( + "sys.modules", + { + "opentelemetry.instrumentation.starlette": mock_starlette_module, + "opentelemetry.instrumentation.asgi": mock_asgi_module, + }, + ): + # Apply the patch + _apply_starlette_instrumentation_patches() + + # Verify the instrumentation_dependencies method was replaced + self.assertTrue(hasattr(mock_instrumentor_class, "instrumentation_dependencies")) + + # Test the patched method returns the expected value + mock_instance = MagicMock() + result = mock_instrumentor_class.instrumentation_dependencies(mock_instance) + self.assertEqual(result, ("starlette >= 0.13",)) + + mock_middleware_instance = MagicMock() + mock_middleware_instance.exclude_receive_span = False + mock_middleware_instance.exclude_send_span = False + mock_middleware_class.__init__(mock_middleware_instance, "app") + + # Test middleware patching sets exclude flags + if agent_enabled: + self.assertTrue(mock_middleware_instance.exclude_receive_span) + self.assertTrue(mock_middleware_instance.exclude_send_span) + else: + self.assertFalse(mock_middleware_instance.exclude_receive_span) + self.assertFalse(mock_middleware_instance.exclude_send_span) + + # Verify logging + mock_logger.debug.assert_called_with( + "Successfully patched Starlette instrumentation_dependencies method" + ) @patch("amazon.opentelemetry.distro.patches._starlette_patches._logger") def test_starlette_patch_handles_import_error(self, mock_logger): From 606f6293097d8ae53b8089aed5e48a226089b08d Mon Sep 17 00:00:00 2001 From: aws-application-signals-bot <167233089+aws-application-signals-bot@users.noreply.github.com> Date: Mon, 15 Sep 2025 21:20:37 -0700 Subject: [PATCH 2/3] Pre-release: Update version to 0.12.1 (#466) This PR updates the version to 0.12.1. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. Co-authored-by: github-actions Co-authored-by: Lei Wang <66336933+wangzlei@users.noreply.github.com> --- .../src/amazon/opentelemetry/distro/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py index 07665e687..86d023d09 100644 --- a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py +++ b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py @@ -1,4 +1,4 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -__version__ = "0.12.0.dev0" +__version__ = "0.12.1" From de0dd2e16be5ac91f8479f3eb0f1beb0ca63e0b4 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 16 Sep 2025 20:17:22 +0000 Subject: [PATCH 3/3] Prepare main for next development cycle: Update version to 0.12.1.dev0 --- .github/workflows/daily-scan.yml | 4 ++-- CHANGELOG.md | 13 +++++++++++++ .../src/amazon/opentelemetry/distro/version.py | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.github/workflows/daily-scan.yml b/.github/workflows/daily-scan.yml index 79d826202..f269cd386 100644 --- a/.github/workflows/daily-scan.yml +++ b/.github/workflows/daily-scan.yml @@ -95,7 +95,7 @@ jobs: id: high_scan uses: ./.github/actions/image_scan with: - image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.12.0" + image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.12.1" severity: 'CRITICAL,HIGH' logout: 'false' @@ -104,7 +104,7 @@ jobs: id: low_scan uses: ./.github/actions/image_scan with: - image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.12.0" + image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.12.1" severity: 'MEDIUM,LOW,UNKNOWN' logout: 'false' diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..d39093671 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +> **Note:** This CHANGELOG was created starting from version 0.12.0. Earlier changes are not documented here. + +For any change that affects end users of this package, please add an entry under the **Unreleased** section. Briefly summarize the change and provide the link to the PR. Example: +- add GenAI attribute support for Amazon Bedrock models + ([#300](https://github.com/aws-observability/aws-otel-python-instrumentation/pull/300)) + +If your change does not need a CHANGELOG entry, add the "skip changelog" label to your PR. + +## Unreleased diff --git a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py index 86d023d09..05dff4918 100644 --- a/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py +++ b/aws-opentelemetry-distro/src/amazon/opentelemetry/distro/version.py @@ -1,4 +1,4 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 -__version__ = "0.12.1" +__version__ = "0.12.1.dev0"