Skip to content

[SVLS-4422] Support for metrics with timestamps when the Extension is present #480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 9, 2024
Merged
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
8 changes: 2 additions & 6 deletions datadog_lambda/api.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os
import logging
import base64
from datadog_lambda.extension import should_use_extension

logger = logging.getLogger(__name__)
KMS_ENCRYPTION_CONTEXT_KEY = "LambdaFunctionName"
Expand Down Expand Up @@ -48,13 +47,10 @@ def decrypt_kms_api_key(kms_client, ciphertext):


def init_api():
if (
not should_use_extension
and not os.environ.get("DD_FLUSH_TO_LOG", "").lower() == "true"
):
if not os.environ.get("DD_FLUSH_TO_LOG", "").lower() == "true":
# Make sure that this package would always be lazy-loaded/outside from the critical path
# since underlying packages are quite heavy to load
# and useless when the extension is present
# and useless with the extension unless sending metrics with timestamps
from datadog import api

if not api._api_key:
Expand Down
26 changes: 23 additions & 3 deletions datadog_lambda/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@

from datadog_lambda.extension import should_use_extension
from datadog_lambda.tags import get_enhanced_metrics_tags, dd_lambda_layer_tag
from datadog_lambda.api import init_api

logger = logging.getLogger(__name__)

lambda_stats = None
extension_thread_stats = None

init_api()
flush_in_thread = os.environ.get("DD_FLUSH_IN_THREAD", "").lower() == "true"

if should_use_extension:
from datadog_lambda.statsd_writer import StatsDWriter
Expand All @@ -28,8 +28,9 @@
# end of invocation. To make metrics submitted from a long-running Lambda
# function available sooner, consider using the Datadog Lambda extension.
from datadog_lambda.thread_stats_writer import ThreadStatsWriter
from datadog_lambda.api import init_api

flush_in_thread = os.environ.get("DD_FLUSH_IN_THREAD", "").lower() == "true"
init_api()
lambda_stats = ThreadStatsWriter(flush_in_thread)

enhanced_metrics_enabled = (
Expand Down Expand Up @@ -57,6 +58,22 @@ def lambda_metric(metric_name, value, timestamp=None, tags=None, force_async=Fal
tags = [] if tags is None else list(tags)
tags.append(dd_lambda_layer_tag)

if should_use_extension and timestamp is not None:
# The extension does not support timestamps for distributions so we create a
# a thread stats writer to submit metrics with timestamps to the API
global extension_thread_stats
if extension_thread_stats is None:
from datadog_lambda.thread_stats_writer import ThreadStatsWriter
from datadog_lambda.api import init_api

init_api()
extension_thread_stats = ThreadStatsWriter(flush_in_thread)

extension_thread_stats.distribution(
metric_name, value, tags=tags, timestamp=timestamp
)
return

if should_use_extension:
logger.debug(
"Sending metric %s value %s to Datadog via extension", metric_name, value
Expand Down Expand Up @@ -94,6 +111,9 @@ def write_metric_point_to_stdout(metric_name, value, timestamp=None, tags=[]):
def flush_stats():
lambda_stats.flush()

if extension_thread_stats is not None:
extension_thread_stats.flush()


def submit_enhanced_metric(metric_name, lambda_context):
"""Submits the enhanced metric with the given name
Expand Down
12 changes: 12 additions & 0 deletions tests/test_metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ def test_lambda_metric_flush_to_log_with_extension(self):
)
del os.environ["DD_FLUSH_TO_LOG"]

@patch("datadog_lambda.metric.should_use_extension", True)
def test_lambda_metric_timestamp_with_extension(self):
patcher = patch("datadog_lambda.metric.extension_thread_stats")
self.mock_metric_extension_thread_stats = patcher.start()
self.addCleanup(patcher.stop)

lambda_metric("test_timestamp", 1, 123)
self.mock_metric_lambda_stats.distribution.assert_not_called()
self.mock_metric_extension_thread_stats.distribution.assert_called_with(
"test_timestamp", 1, timestamp=123, tags=[dd_lambda_layer_tag]
)

def test_lambda_metric_flush_to_log(self):
os.environ["DD_FLUSH_TO_LOG"] = "True"

Expand Down
Loading