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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#3743](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3743))
- Add `rstcheck` to pre-commit to stop introducing invalid RST
([#3777](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3777))
- `opentelemetry-instrumentation-botocore`: botocore: Add AWS_LAMBDA_RESOURCE_MAPPING_ID Semantic Convention Support for AWS Lambda SDK
([#3800](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3800))
- `opentelemetry-exporter-credential-provider-gcp`: create this package which provides support for supplying your machine's Application Default
Credentials (https://cloud.google.com/docs/authentication/application-default-credentials) to the OTLP Exporters created automatically by OpenTelemetry Python's auto instrumentation. These credentials authorize OTLP traces to be sent to `telemetry.googleapis.com`. [#3766](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3766).
- `opentelemetry-instrumentation-psycopg`: Add missing parameter `capture_parameters` to instrumentor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@
_AwsSdkCallContext,
_AwsSdkExtension,
_BotocoreInstrumentorContext,
_BotoResultT,
)
from opentelemetry.propagate import inject
from opentelemetry.semconv._incubating.attributes.aws_attributes import (
AWS_LAMBDA_RESOURCE_MAPPING_ID,
)
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.trace.span import Span

Expand Down Expand Up @@ -71,9 +75,13 @@ def extract_attributes(
@classmethod
def _parse_function_name(cls, call_context: _AwsSdkCallContext):
function_name_or_arn = call_context.params.get("FunctionName")
if function_name_or_arn is None:
return None
matches = cls.ARN_LAMBDA_PATTERN.match(function_name_or_arn)
function_name = matches.group(1)
return function_name_or_arn if function_name is None else function_name
if matches:
function_name = matches.group(1)
return function_name if function_name else function_name_or_arn
return function_name_or_arn

@classmethod
def before_service_call(cls, call_context: _AwsSdkCallContext, span: Span):
Expand Down Expand Up @@ -115,6 +123,10 @@ def __init__(self, call_context: _AwsSdkCallContext):
self._op = _OPERATION_MAPPING.get(call_context.operation)

def extract_attributes(self, attributes: _AttributeMapT):
resource_mapping_id = self._call_context.params.get("UUID")
if resource_mapping_id:
attributes[AWS_LAMBDA_RESOURCE_MAPPING_ID] = resource_mapping_id

if self._op is None:
return

Expand All @@ -127,3 +139,15 @@ def before_service_call(
return

self._op.before_service_call(self._call_context, span)

def on_success(
self,
span: Span,
result: _BotoResultT,
instrumentor_context: _BotocoreInstrumentorContext,
):
resource_mapping_id = result.get("UUID")
if resource_mapping_id:
span.set_attribute(
AWS_LAMBDA_RESOURCE_MAPPING_ID, resource_mapping_id
)
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
_LambdaExtension,
)
from opentelemetry.propagate import get_global_textmap, set_global_textmap
from opentelemetry.semconv._incubating.attributes.aws_attributes import (
AWS_LAMBDA_RESOURCE_MAPPING_ID,
)
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.test.mock_textmap import MockTextMapPropagator
from opentelemetry.test.test_base import TestBase
Expand Down Expand Up @@ -126,6 +129,18 @@ def _create_lambda_function(self, function_name: str, function_code: str):
Publish=True,
)

def _create_sqs_queue_and_get_arn(self) -> str:
"""Helper method to create SQS queue and return ARN"""
session = botocore.session.get_session()
session.set_credentials(
access_key="access-key", secret_key="secret-key"
)
sqs_client = session.create_client("sqs", region_name=self.region)
sqs_client.create_queue(
QueueName="MyTestQueue.fifo", Attributes={"FifoQueue": "true"}
)
return f"arn:aws:sqs:{self.region}:123456789012:MyTestQueue.fifo"

@mark.skip(reason="Docker error, unblocking builds for now.")
@mark.skipif(
sys.platform == "win32",
Expand Down Expand Up @@ -185,3 +200,82 @@ def test_invoke_parse_arn(self):
self.assertEqual(
function_name, attributes[SpanAttributes.FAAS_INVOKED_NAME]
)

@mock_aws
def test_get_function(self):
function_name = "lambda-function-name-foo"
self._create_lambda_function(
function_name, return_headers_lambda_str()
)

self.memory_exporter.clear()
self.client.get_function(FunctionName=function_name)
spans = self.memory_exporter.get_finished_spans()
self.assertEqual(1, len(spans))
span = spans[0]
self.assertEqual(
"GetFunction", span.attributes[SpanAttributes.RPC_METHOD]
)

self.assertIsNone(span.attributes.get(AWS_LAMBDA_RESOURCE_MAPPING_ID))

@mock_aws
def test_create_event_source_mapping(self):
function_name = "MyLambdaFnFoo"
self._create_lambda_function(
function_name, return_headers_lambda_str()
)

queue_arn = self._create_sqs_queue_and_get_arn()
self.memory_exporter.clear()
response = self.client.create_event_source_mapping(
EventSourceArn=queue_arn, FunctionName=function_name, BatchSize=10
)
expected_uuid = response["UUID"]
self.assertIsNotNone(expected_uuid)
self.assertTrue(expected_uuid)

spans = self.memory_exporter.get_finished_spans()
self.assertEqual(1, len(spans))
span = spans[0]
self.assertEqual(
"CreateEventSourceMapping",
span.attributes[SpanAttributes.RPC_METHOD],
)

uuid = span.attributes.get(AWS_LAMBDA_RESOURCE_MAPPING_ID)
self.assertIsNotNone(uuid)
self.assertEqual(expected_uuid, uuid)

@mock_aws
def test_get_event_source_mapping(self):
function_name = "MyLambdaFnBar"
self._create_lambda_function(
function_name, return_headers_lambda_str()
)

queue_arn = self._create_sqs_queue_and_get_arn()

# Create event source mapping first
create_response = self.client.create_event_source_mapping(
EventSourceArn=queue_arn, FunctionName=function_name, BatchSize=10
)
mapping_uuid = create_response["UUID"]

self.memory_exporter.clear()
response = self.client.get_event_source_mapping(UUID=mapping_uuid)
expected_uuid = response["UUID"]
self.assertIsNotNone(expected_uuid)
self.assertTrue(expected_uuid)

spans = self.memory_exporter.get_finished_spans()
self.assertEqual(1, len(spans))
span = spans[0]
self.assertEqual(
"GetEventSourceMapping",
span.attributes[SpanAttributes.RPC_METHOD],
)

uuid = span.attributes.get(AWS_LAMBDA_RESOURCE_MAPPING_ID)
self.assertIsNotNone(uuid)
self.assertEqual(expected_uuid, uuid)