Skip to content

Commit 47d4b26

Browse files
joeyzhao2018claude
andcommitted
fix: use DD_SERVICE for cold start spans instead of hardcoded aws.lambda
Cold start spans (aws.lambda.load, aws.lambda.import) were always created with service="aws.lambda". Use DD_SERVICE when set, falling back to aws.lambda otherwise, so they land in the same service as the function span. This matches what the Lambda extension already does by rewriting aws.lambda spans to DD_SERVICE (datadog-lambda-extension#471), and follows the same change made for the function span in #635. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent c50f73b commit 47d4b26

2 files changed

Lines changed: 58 additions & 2 deletions

File tree

‎datadog_lambda/cold_start.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def start_span(self, span_type, resource, start_time_ns):
248248
) # reactivate required after each finish() call
249249
self.need_to_reactivate_context = False
250250
span_kwargs = {
251-
"service": "aws.lambda",
251+
"service": config.service or "aws.lambda",
252252
"resource": resource,
253253
"span_type": span_type,
254254
}

‎tests/test_cold_start.py‎

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import unittest
44

55
from sys import modules, meta_path
6-
from unittest.mock import MagicMock
6+
from unittest.mock import MagicMock, patch
77

88
import datadog_lambda.cold_start as cold_start
99
import datadog_lambda.wrapper as wrapper
@@ -162,6 +162,7 @@ class TestColdStartTracer(unittest.TestCase):
162162
def setUp(self) -> None:
163163
mock_tracer = MagicMock()
164164
self.output_spans = []
165+
self.output_services = []
165166
self.shared_mock_span = MagicMock()
166167
self.shared_mock_span.current_spans = []
167168
self.finish_call_count = 0
@@ -176,6 +177,7 @@ def _finish(finish_time_s):
176177
def _trace(*args, **kwargs):
177178
module_name = kwargs["resource"]
178179
self.shared_mock_span.current_spans.append(module_name)
180+
self.output_services.append(kwargs["service"])
179181
return self.shared_mock_span
180182

181183
mock_tracer.trace = _trace
@@ -286,6 +288,20 @@ def test_trace_ignore_libs(self):
286288
self.mock_activate.assert_called_once_with(self.mock_trace_ctx)
287289
self.assertEqual(self.output_spans, ["node_0", "unittest_cold_start"])
288290

291+
@patch("datadog_lambda.config.Config.service", "my-dd-service")
292+
def test_trace_uses_dd_service(self):
293+
node_0 = cold_start.ImportNode("node_0", None, self.first_node_start_time_ns)
294+
node_0.end_time_ns = self.first_node_start_time_ns + self.test_time_unit
295+
self.cold_start_tracer.trace([node_0])
296+
self.assertEqual(self.output_services, ["my-dd-service", "my-dd-service"])
297+
298+
@patch("datadog_lambda.config.Config.service", None)
299+
def test_trace_falls_back_to_aws_lambda_service(self):
300+
node_0 = cold_start.ImportNode("node_0", None, self.first_node_start_time_ns)
301+
node_0.end_time_ns = self.first_node_start_time_ns + self.test_time_unit
302+
self.cold_start_tracer.trace([node_0])
303+
self.assertEqual(self.output_services, ["aws.lambda", "aws.lambda"])
304+
289305

290306
def test_lazy_loaded_package_imports(monkeypatch):
291307
spans = []
@@ -325,3 +341,43 @@ def handler(event, context):
325341
assert import_span.trace_id == function_span.trace_id
326342
assert load_span is not None
327343
assert load_span.trace_id == function_span.trace_id
344+
345+
346+
def test_cold_start_spans_use_dd_service(monkeypatch):
347+
spans = []
348+
349+
def finish(span):
350+
spans.append(span)
351+
352+
monkeypatch.setattr(wrapper.tracer, "_on_span_finish", finish)
353+
monkeypatch.setattr(wrapper, "is_new_sandbox", lambda: True)
354+
monkeypatch.setattr("datadog_lambda.config.Config.trace_enabled", True)
355+
monkeypatch.setattr("datadog_lambda.config.Config.service", "my-dd-service")
356+
monkeypatch.setenv(
357+
"DD_COLD_START_TRACE_SKIP_LIB", "ddtrace.contrib.logging,datadog_lambda.wrapper"
358+
)
359+
monkeypatch.setenv("DD_MIN_COLD_START_DURATION", "0")
360+
# ensure the import below is not served from the module cache
361+
monkeypatch.delitem(modules, "colorsys", raising=False)
362+
363+
@wrapper.datadog_lambda_wrapper
364+
def handler(event, context):
365+
import colorsys # noqa: F401
366+
367+
handler({}, get_mock_context())
368+
369+
function_span = import_span = load_span = None
370+
for span in spans:
371+
if span.resource == "colorsys":
372+
import_span = span
373+
elif span.name == "aws.lambda":
374+
function_span = span
375+
elif span.name == "aws.lambda.load":
376+
load_span = span
377+
378+
assert function_span is not None
379+
assert import_span is not None
380+
assert load_span is not None
381+
assert function_span.service == "my-dd-service"
382+
assert import_span.service == "my-dd-service"
383+
assert load_span.service == "my-dd-service"

0 commit comments

Comments
 (0)