diff --git a/CHANGELOG.md b/CHANGELOG.md index 46f42fd58b..bf61ce8925 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.7.0-0.26b0...HEAD) +### Added + +- `opentelemetry-instrumentation-aws-lambda` Adds support for configurable flush timeout via `OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT` property. ([#825](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/825)) + ### Fixed - `opentelemetry-exporter-richconsole` Fixed attribute error on parentless spans. diff --git a/instrumentation/opentelemetry-instrumentation-aws-lambda/src/opentelemetry/instrumentation/aws_lambda/__init__.py b/instrumentation/opentelemetry-instrumentation-aws-lambda/src/opentelemetry/instrumentation/aws_lambda/__init__.py index 2df4359a65..951f27dd44 100644 --- a/instrumentation/opentelemetry-instrumentation-aws-lambda/src/opentelemetry/instrumentation/aws_lambda/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aws-lambda/src/opentelemetry/instrumentation/aws_lambda/__init__.py @@ -97,6 +97,9 @@ def custom_event_context_extractor(lambda_event): _HANDLER = "_HANDLER" _X_AMZN_TRACE_ID = "_X_AMZN_TRACE_ID" ORIG_HANDLER = "ORIG_HANDLER" +OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT = ( + "OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT" +) def _default_event_context_extractor(lambda_event: Any) -> Context: @@ -167,6 +170,7 @@ def _determine_parent_context( def _instrument( wrapped_module_name, wrapped_function_name, + flush_timeout, event_context_extractor: Callable[[Any], Context], tracer_provider: TracerProvider = None, ): @@ -222,7 +226,7 @@ def _instrumented_lambda_handler_call( # NOTE: `force_flush` before function quit in case of Lambda freeze. # Assumes we are using the OpenTelemetry SDK implementation of the # `TracerProvider`. - _tracer_provider.force_flush() + _tracer_provider.force_flush(flush_timeout) except Exception: # pylint: disable=broad-except logger.error( "TracerProvider was missing `force_flush` method. This is necessary in case of a Lambda freeze and would exist in the OTel SDK implementation." @@ -262,9 +266,22 @@ def _instrument(self, **kwargs): self._wrapped_function_name, ) = lambda_handler.rsplit(".", 1) + flush_timeout_env = os.environ.get( + OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT, "" + ) + flush_timeout = 30000 + try: + flush_timeout = int(flush_timeout_env) + except ValueError: + logger.warning( + "Could not convert OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT value %s to int", + flush_timeout_env, + ) + _instrument( self._wrapped_module_name, self._wrapped_function_name, + flush_timeout, event_context_extractor=kwargs.get( "event_context_extractor", _default_event_context_extractor ), diff --git a/instrumentation/opentelemetry-instrumentation-aws-lambda/tests/test_aws_lambda_instrumentation_manual.py b/instrumentation/opentelemetry-instrumentation-aws-lambda/tests/test_aws_lambda_instrumentation_manual.py index 270925e2f1..c2d7d71689 100644 --- a/instrumentation/opentelemetry-instrumentation-aws-lambda/tests/test_aws_lambda_instrumentation_manual.py +++ b/instrumentation/opentelemetry-instrumentation-aws-lambda/tests/test_aws_lambda_instrumentation_manual.py @@ -19,6 +19,7 @@ from opentelemetry.instrumentation.aws_lambda import ( _HANDLER, _X_AMZN_TRACE_ID, + OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT, AwsLambdaInstrumentor, ) from opentelemetry.propagate import get_global_textmap @@ -246,3 +247,30 @@ def custom_event_context_extractor(lambda_event): self.assertTrue(parent_context.is_remote) test_env_patch.stop() + + def test_lambda_no_error_with_invalid_flush_timeout(self): + + test_env_patch = mock.patch.dict( + "os.environ", + { + **os.environ, + # NOT Active Tracing + _X_AMZN_TRACE_ID: MOCK_XRAY_TRACE_CONTEXT_NOT_SAMPLED, + # NOT using the X-Ray Propagator + OTEL_PROPAGATORS: "tracecontext", + OTEL_INSTRUMENTATION_AWS_LAMBDA_FLUSH_TIMEOUT: "invalid-timeout-string", + }, + ) + test_env_patch.start() + + AwsLambdaInstrumentor().instrument() + + mock_execute_lambda() + + spans = self.memory_exporter.get_finished_spans() + + assert spans + + self.assertEqual(len(spans), 1) + + test_env_patch.stop() diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py index 91af787c28..9cdc7e682c 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -58,7 +58,6 @@ def __call__(self, request): response = self.get_response(request) return self.process_response(request, response) - else: # Django versions 1.x can use `settings.MIDDLEWARE_CLASSES` and expect # old-style middlewares, which are created by inheriting from diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py index 473a0fb3c0..f5d31d920b 100644 --- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=E0611 + from sys import modules from unittest.mock import Mock, patch diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware_asgi.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware_asgi.py index 3d8d557bcc..ecc3172e8b 100644 --- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware_asgi.py +++ b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware_asgi.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=E0611 + from sys import modules from unittest.mock import Mock, patch