Skip to content

Commit

Permalink
Flush meter provider at end of lambda function handler
Browse files Browse the repository at this point in the history
Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
  • Loading branch information
Aneurysm9 committed Jan 31, 2023
1 parent bbe7578 commit 107e89d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#1553](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1553))
- `opentelemetry/sdk/extension/aws` Implement [`aws.ecs.*`](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/cloud_provider/aws/ecs.md) and [`aws.logs.*`](https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/cloud_provider/aws/logs/) resource attributes in the `AwsEcsResourceDetector` detector when the ECS Metadata v4 is available
([#1212](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1212))
- `opentelemetry-instrumentation-aws-lambda` Flush `MeterProvider` at end of function invocation.
([#TBD](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/tbd))

### Fixed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def lambda_handler(event, context):
The `instrument` method accepts the following keyword args:
tracer_provider (TracerProvider) - an optional tracer provider
meter_provider (MeterProvider) - an optional meter provider
event_context_extractor (Callable) - a function that returns an OTel Trace
Context given the Lambda Event the AWS Lambda was invoked with
this function signature is: def event_context_extractor(lambda_event: Any) -> Context
Expand All @@ -68,6 +69,7 @@ def custom_event_context_extractor(lambda_event):

import logging
import os
import time
from importlib import import_module
from typing import Any, Callable, Collection
from urllib.parse import urlencode
Expand All @@ -79,6 +81,10 @@ def custom_event_context_extractor(lambda_event):
from opentelemetry.instrumentation.aws_lambda.version import __version__
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.instrumentation.utils import unwrap
from opentelemetry.metrics import (
MeterProvider,
get_meter_provider,
)
from opentelemetry.propagate import get_global_textmap
from opentelemetry.propagators.aws.aws_xray_propagator import (
TRACE_HEADER_KEY,
Expand Down Expand Up @@ -274,6 +280,7 @@ def _instrument(
event_context_extractor: Callable[[Any], Context],
tracer_provider: TracerProvider = None,
disable_aws_context_propagation: bool = False,
meter_provider: MeterProvider = None,
):
def _instrumented_lambda_handler_call(
call_wrapped, instance, args, kwargs
Expand Down Expand Up @@ -352,6 +359,7 @@ def _instrumented_lambda_handler_call(
result.get("statusCode"),
)

now = time.time()
_tracer_provider = tracer_provider or get_tracer_provider()
try:
# NOTE: `force_flush` before function quit in case of Lambda freeze.
Expand All @@ -363,6 +371,19 @@ def _instrumented_lambda_handler_call(
"TracerProvider was missing `force_flush` method. This is necessary in case of a Lambda freeze and would exist in the OTel SDK implementation."
)

rem = flush_timeout - (time.time()-now)*1000
if rem > 0:
_meter_provider = meter_provider or get_meter_provider()
try:
# NOTE: `force_flush` before function quit in case of Lambda freeze.
# Assumes we are using the OpenTelemetry SDK implementation of the
# `MeterProvider`.
_meter_provider.force_flush(rem)
except Exception: # pylint: disable=broad-except
logger.error(
"MeterProvider was missing `force_flush` method. This is necessary in case of a Lambda freeze and would exist in the OTel SDK implementation."
)

return result

wrap_function_wrapper(
Expand All @@ -385,6 +406,7 @@ def _instrument(self, **kwargs):
Args:
**kwargs: Optional arguments
``tracer_provider``: a TracerProvider, defaults to global
``meter_provider``: a MeterProvider, defaults to global
``event_context_extractor``: a method which takes the Lambda
Event as input and extracts an OTel Context from it. By default,
the context is extracted from the HTTP headers of an API Gateway
Expand Down Expand Up @@ -432,6 +454,7 @@ def _instrument(self, **kwargs):
),
tracer_provider=kwargs.get("tracer_provider"),
disable_aws_context_propagation=disable_aws_context_propagation,
meter_provider=kwargs.get("meter_provider"),
)

def _uninstrument(self, **kwargs):
Expand Down

0 comments on commit 107e89d

Please sign in to comment.