Skip to content

Commit 0766491

Browse files
authored
Merge branch 'main' into dependabot/pip/contract-tests/images/applications/django/django-5.0.13
2 parents 81d705a + 8632951 commit 0766491

File tree

10 files changed

+193
-11
lines changed

10 files changed

+193
-11
lines changed

.github/workflows/daily_scan.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ jobs:
6666
if: always()
6767
run: |
6868
gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 259A55407DD6C00299E6607EFFDE55BE73A2D1ED
69-
VERSION=$(curl -s https://jeremylong.github.io/DependencyCheck/current.txt)
70-
curl -Ls "https://github.com/jeremylong/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip" --output dependency-check.zip
71-
curl -Ls "https://github.com/jeremylong/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip.asc" --output dependency-check.zip.asc
69+
VERSION=$(curl -s https://jeremylong.github.io/DependencyCheck/current.txt | head -n1 | cut -d' ' -f1)
70+
curl -Ls "https://github.com/dependency-check/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip" --output dependency-check.zip
71+
curl -Ls "https://github.com/dependency-check/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip.asc" --output dependency-check.zip.asc
7272
gpg --verify dependency-check.zip.asc
7373
unzip dependency-check.zip
7474
./dependency-check/bin/dependency-check.sh --enableExperimental --suppression .github/dependency-check-suppressions.xml --failOnCVSS 0 --nvdApiKey ${{ env.NVD_API_KEY_NVD_API_KEY }} -s aws-opentelemetry-distro/

.github/workflows/release-lambda.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,13 @@ jobs:
212212
layer_arns.tf layer.zip
213213
echo Removing release_notes.md ...
214214
rm -f release_notes.md
215-
- name: Upload layer.zip to SDK Release Notes (tagged with latest)
215+
- name: Upload layer.zip and SHA-256 checksum to SDK Release Notes (tagged with latest)
216216
env:
217217
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
218218
run: |
219219
LATEST_SDK_VERSION=$(gh release list --repo "aws-observability/aws-otel-python-instrumentation" --json tagName,isLatest -q 'map(select(.isLatest==true)) | .[0].tagName')
220-
gh release upload "$LATEST_SDK_VERSION" layer.zip --repo "aws-observability/aws-otel-python-instrumentation" --clobber
220+
# Generate SHA-256 checksum for layer.zip
221+
shasum -a 256 layer.zip > layer.zip.sha256
222+
# Upload layer.zip and its checksum to the latest SDK release note
223+
gh release upload "$LATEST_SDK_VERSION" layer.zip layer.zip.sha256 --repo "aws-observability/aws-otel-python-instrumentation" --clobber
221224
echo "✅ layer.zip successfully uploaded to $LATEST_SDK_VERSION in the upstream repo!"

.github/workflows/release-udp-exporter.yml

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ on:
77
description: 'Version number for deployment e.g. 0.1.0'
88
required: true
99
type: string
10+
env:
11+
AWS_DEFAULT_REGION: us-east-1
12+
ARTIFACT_NAME: aws_otel_otlp_udp_exporter-${{ github.event.inputs.version }}-py3-none-any.whl
13+
14+
permissions:
15+
id-token: write
16+
contents: write
1017

1118
jobs:
1219
build-test-publish:
@@ -74,4 +81,37 @@ jobs:
7481
exit 1
7582
fi
7683
77-
# TODO: Steps to publish to PyPI
84+
- name: Configure AWS credentials for PyPI secrets
85+
uses: aws-actions/configure-aws-credentials@v4
86+
with:
87+
role-to-assume: ${{ secrets.AWS_ROLE_ARN_SECRETS_MANAGER }}
88+
aws-region: ${{ env.AWS_DEFAULT_REGION }}
89+
90+
- name: Get PyPI secrets
91+
uses: aws-actions/aws-secretsmanager-get-secrets@v1
92+
id: pypi_secrets
93+
with:
94+
secret-ids: |
95+
PROD_PYPI_TOKEN,${{ secrets.PYPI_PROD_TOKEN_SECRET_ARN }}
96+
TEST_PYPI_TOKEN,${{ secrets.PYPI_TEST_TOKEN_SECRET_ARN }}
97+
parse-json-secrets: true
98+
99+
- name: Install twine
100+
run: pip install twine
101+
102+
# The step below publishes to testpypi in order to catch any issues
103+
# with the package configuration that would cause a failure to upload to PyPI.
104+
- name: Publish to TestPyPI
105+
env:
106+
TWINE_USERNAME: '__token__'
107+
TWINE_PASSWORD: ${{ env.TEST_PYPI_TOKEN_API_TOKEN }}
108+
run: |
109+
twine upload --repository testpypi --skip-existing --verbose exporters/aws-otel-otlp-udp-exporter/dist/${{ env.ARTIFACT_NAME }}
110+
111+
# Publish to prod PyPI
112+
- name: Publish to PyPI
113+
env:
114+
TWINE_USERNAME: '__token__'
115+
TWINE_PASSWORD: ${{ env.PROD_PYPI_TOKEN_API_TOKEN }}
116+
run: |
117+
twine upload --skip-existing --verbose exporters/aws-otel-otlp-udp-exporter/dist/${{ env.ARTIFACT_NAME }}

.github/workflows/release_build.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,14 +133,16 @@ jobs:
133133
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
134134
run: |
135135
# Download layer.zip from existing latest tagged SDK release note
136-
LATEST_SDK_VERSION=$(gh release list --repo "aws-observability/aws-otel-java-instrumentation" --json tagName,isLatest -q 'map(select(.isLatest==true)) | .[0].tagName')
136+
LATEST_SDK_VERSION=$(gh release list --repo "aws-observability/aws-otel-python-instrumentation" --json tagName,isLatest -q 'map(select(.isLatest==true)) | .[0].tagName')
137137
mkdir -p layer_artifact
138-
gh release download "$LATEST_SDK_VERSION" --repo "aws-observability/aws-otel-java-instrumentation" --pattern "layer.zip" --dir layer_artifact
138+
gh release download "$LATEST_SDK_VERSION" --repo "aws-observability/aws-otel-python-instrumentation" --pattern "layer.zip" --dir layer_artifact
139+
shasum -a 256 layer_artifact/layer.zip > layer_artifact/layer.zip.sha256
139140
140141
gh release create --target "$GITHUB_REF_NAME" \
141142
--title "Release v${{ github.event.inputs.version }}" \
142143
--draft \
143144
"v${{ github.event.inputs.version }}" \
144145
dist/${{ env.ARTIFACT_NAME }} \
145146
${{ env.ARTIFACT_NAME }}.sha256 \
146-
layer_artifact/layer.zip
147+
layer_artifact/layer.zip \
148+
layer_artifact/layer.zip.sha256

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/_aws_attribute_keys.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
AWS_SDK_DESCENDANT: str = "aws.sdk.descendant"
1414
AWS_CONSUMER_PARENT_SPAN_KIND: str = "aws.consumer.parent.span.kind"
1515
AWS_TRACE_FLAG_SAMPLED: str = "aws.trace.flag.sampled"
16+
AWS_TRACE_LAMBDA_FLAG_MULTIPLE_SERVER: str = "aws.trace.lambda.multiple-server"
1617
AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER: str = "aws.remote.resource.cfn.primary.identifier"
1718

1819
# AWS_#_NAME attributes are not supported in python as they are not part of the Semantic Conventions.

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/_aws_span_processing_util.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ def get_ingress_operation(__, span: ReadableSpan) -> str:
5757
with the first API path parameter" if the default span name is None, UnknownOperation or http.method value.
5858
"""
5959
operation: str = span.name
60-
if _AWS_LAMBDA_FUNCTION_NAME in os.environ:
60+
scope = getattr(span, "instrumentation_scope", None)
61+
if _AWS_LAMBDA_FUNCTION_NAME in os.environ and scope.name != "opentelemetry.instrumentation.flask":
6162
operation = os.environ.get(_AWS_LAMBDA_FUNCTION_NAME) + "/FunctionHandler"
6263
elif should_use_internal_operation(span):
6364
operation = INTERNAL_OPERATION
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
from typing import Optional
4+
5+
from typing_extensions import override
6+
7+
from amazon.opentelemetry.distro._aws_attribute_keys import AWS_TRACE_LAMBDA_FLAG_MULTIPLE_SERVER
8+
from opentelemetry.context import Context, get_value
9+
from opentelemetry.sdk.trace import ReadableSpan, Span, SpanProcessor
10+
from opentelemetry.trace import SpanKind
11+
from opentelemetry.trace.propagation import _SPAN_KEY
12+
13+
14+
class AwsLambdaSpanProcessor(SpanProcessor):
15+
def __init__(self, instrumentation_names=None):
16+
self.instrumentation_names = set(instrumentation_names or ["opentelemetry.instrumentation.flask"])
17+
18+
@override
19+
def on_start(self, span: Span, parent_context: Optional[Context] = None) -> None:
20+
21+
scope = getattr(span, "instrumentation_scope", None)
22+
if scope.name in self.instrumentation_names:
23+
parent_span = get_value(_SPAN_KEY, context=parent_context)
24+
25+
if parent_span is None:
26+
return
27+
28+
parent_scope = getattr(parent_span, "instrumentation_scope", None)
29+
if parent_scope.name == "opentelemetry.instrumentation.aws_lambda":
30+
span._kind = SpanKind.SERVER
31+
parent_span.set_attribute(AWS_TRACE_LAMBDA_FLAG_MULTIPLE_SERVER, True)
32+
33+
return
34+
35+
# pylint: disable=no-self-use
36+
@override
37+
def on_end(self, span: ReadableSpan) -> None:
38+
return
39+
40+
@override
41+
def shutdown(self) -> None:
42+
self.force_flush()
43+
44+
# pylint: disable=no-self-use
45+
@override
46+
def force_flush(self, timeout_millis: int = None) -> bool:
47+
return True

aws-opentelemetry-distro/src/amazon/opentelemetry/distro/aws_opentelemetry_configurator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
AttributePropagatingSpanProcessorBuilder,
1717
)
1818
from amazon.opentelemetry.distro.aws_batch_unsampled_span_processor import BatchUnsampledSpanProcessor
19+
from amazon.opentelemetry.distro.aws_lambda_span_processor import AwsLambdaSpanProcessor
1920
from amazon.opentelemetry.distro.aws_metric_attributes_span_exporter_builder import (
2021
AwsMetricAttributesSpanExporterBuilder,
2122
)
@@ -343,6 +344,7 @@ def _customize_span_processors(provider: TracerProvider, resource: Resource) ->
343344
# Export 100% spans and not export Application-Signals metrics if on Lambda.
344345
if _is_lambda_environment():
345346
_export_unsampled_span_for_lambda(provider, resource)
347+
provider.add_span_processor(AwsLambdaSpanProcessor())
346348
return
347349

348350
# Construct meterProvider
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
from unittest import TestCase
4+
from unittest.mock import MagicMock, patch
5+
6+
from amazon.opentelemetry.distro._aws_attribute_keys import AWS_TRACE_LAMBDA_FLAG_MULTIPLE_SERVER
7+
from amazon.opentelemetry.distro.aws_lambda_span_processor import AwsLambdaSpanProcessor
8+
from opentelemetry.context import Context, set_value
9+
from opentelemetry.trace import Span, SpanContext, SpanKind
10+
from opentelemetry.trace.propagation import _SPAN_KEY
11+
12+
13+
class TestAwsLambdaSpanProcessor(TestCase):
14+
15+
def setUp(self):
16+
self.processor = AwsLambdaSpanProcessor()
17+
self.lambda_span: Span = MagicMock()
18+
self.lambda_span.instrumentation_scope.name = "opentelemetry.instrumentation.aws_lambda"
19+
self.lambda_span.kind = SpanKind.SERVER
20+
21+
self.lambda_span_context: SpanContext = MagicMock()
22+
self.lambda_span_context.trace_id = "ABC"
23+
self.lambda_span_context.span_id = "lambda_id"
24+
25+
self.lambda_context: Context = set_value(_SPAN_KEY, self.lambda_span)
26+
27+
self.lambda_span.get_span_context.return_value = self.lambda_span_context
28+
self.processor.on_start(self.lambda_span)
29+
30+
def tearDown(self):
31+
self.processor.on_end(self.lambda_span)
32+
self.processor.shutdown()
33+
34+
@patch("opentelemetry.sdk.trace.Span")
35+
def test_lambda_span_multiple_server_flag_internal_api(self, mock_span_class):
36+
37+
flask_span = mock_span_class.return_value
38+
flask_span.instrumentation_scope.name = "opentelemetry.instrumentation.flask"
39+
flask_span.kind = SpanKind.INTERNAL
40+
flask_span.parent = self.lambda_span_context
41+
42+
self.processor.on_start(flask_span, self.lambda_context)
43+
44+
self.assertEqual(flask_span._kind, SpanKind.SERVER)
45+
self.assertIn(AWS_TRACE_LAMBDA_FLAG_MULTIPLE_SERVER, self.lambda_span.set_attribute.call_args_list[0][0][0])
46+
47+
self.processor.on_end(flask_span)
48+
self.processor.on_end(self.lambda_span)
49+
50+
self.processor.shutdown()
51+
52+
@patch("opentelemetry.sdk.trace.Span")
53+
def test_lambda_span_multiple_server_flag_server_api(self, mock_span_class):
54+
55+
flask_span = mock_span_class.return_value
56+
flask_span.instrumentation_scope.name = "opentelemetry.instrumentation.flask"
57+
flask_span.kind = SpanKind.SERVER
58+
flask_span.parent = self.lambda_span_context
59+
60+
self.processor.on_start(flask_span, self.lambda_context)
61+
62+
self.assertEqual(flask_span.kind, SpanKind.SERVER)
63+
self.assertIn(AWS_TRACE_LAMBDA_FLAG_MULTIPLE_SERVER, self.lambda_span.set_attribute.call_args_list[0][0][0])
64+
65+
self.processor.on_end(flask_span)
66+
self.processor.on_end(self.lambda_span)
67+
68+
self.processor.shutdown()
69+
70+
@patch("opentelemetry.sdk.trace.Span")
71+
def test_lambda_span_single_server_span(self, mock_span_class):
72+
73+
flask_span = mock_span_class.return_value
74+
flask_span.instrumentation_scope.name = "opentelemetry.instrumentation.http"
75+
flask_span.kind = SpanKind.CLIENT
76+
flask_span.parent = self.lambda_span_context
77+
78+
self.processor.on_start(flask_span, self.lambda_context)
79+
80+
self.assertEqual(flask_span.kind, SpanKind.CLIENT)
81+
flask_span.set_attribute.assert_not_called()
82+
83+
self.processor.on_end(flask_span)
84+
self.processor.on_end(self.lambda_span)
85+
86+
self.processor.shutdown()

aws-opentelemetry-distro/tests/amazon/opentelemetry/distro/test_aws_opentelementry_configurator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ def test_customize_span_processors_lambda(self):
318318
os.environ.setdefault("OTEL_AWS_APPLICATION_SIGNALS_ENABLED", "True")
319319
os.environ.setdefault("AWS_LAMBDA_FUNCTION_NAME", "myLambdaFunc")
320320
_customize_span_processors(mock_tracer_provider, Resource.get_empty())
321-
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 2)
321+
self.assertEqual(mock_tracer_provider.add_span_processor.call_count, 3)
322322
first_processor: SpanProcessor = mock_tracer_provider.add_span_processor.call_args_list[0].args[0]
323323
self.assertIsInstance(first_processor, AttributePropagatingSpanProcessor)
324324
second_processor: SpanProcessor = mock_tracer_provider.add_span_processor.call_args_list[1].args[0]

0 commit comments

Comments
 (0)