Skip to content

Commit de4c1f8

Browse files
authored
Merge branch 'main' into jordan.gonzalez/gitlab/secrets-from-kv
2 parents 908aced + 354a074 commit de4c1f8

28 files changed

+493
-44
lines changed

.github/workflows/system_tests.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ on:
77
pull_request:
88
branches:
99
- "**"
10+
schedule:
11+
- cron: '00 03 * * *'
1012

1113
jobs:
1214
build:
@@ -27,12 +29,15 @@ jobs:
2729
needs:
2830
- build
2931
uses: DataDog/system-tests/.github/workflows/system-tests.yml@main
30-
secrets: inherit
32+
secrets:
33+
DD_API_KEY: ${{ secrets.DD_API_KEY }}
34+
TEST_OPTIMIZATION_API_KEY: ${{ secrets.TEST_OPTIMIZATION_API_KEY }}
3135
permissions:
3236
contents: read
3337
packages: write
3438
with:
3539
library: python_lambda
3640
binaries_artifact: binaries
37-
scenarios_groups: appsec
41+
scenarios_groups: tracer_release
3842
skip_empty_scenarios: true
43+
push_to_test_optimization: true

Dockerfile

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,34 @@ ENV PATH=/root/.cargo/bin:$PATH
2525

2626
# Install datadog_lambda and dependencies from local
2727
COPY . .
28+
2829
RUN pip install --no-cache-dir . -t ./python/lib/$runtime/site-packages
2930

3031
# Remove botocore (40MB) to reduce package size. aws-xray-sdk
3132
# installs it, while it's already provided by the Lambda Runtime.
3233
RUN rm -rf ./python/lib/$runtime/site-packages/botocore*
3334
RUN rm -rf ./python/lib/$runtime/site-packages/setuptools
3435
RUN rm -rf ./python/lib/$runtime/site-packages/jsonschema/tests
35-
RUN rm -f ./python/lib/$runtime/site-packages/ddtrace/appsec/_iast/_ast/iastpatch*.so
36-
RUN rm -rf ./python/lib/$runtime/site-packages/ddtrace/appsec/_iast/_taint_tracking/_vendor
37-
RUN rm -f ./python/lib/$runtime/site-packages/ddtrace/appsec/_iast/_taint_tracking/*.so
38-
RUN rm -f ./python/lib/$runtime/site-packages/ddtrace/appsec/_iast/_stacktrace*.so
36+
RUN rm -rf ./python/lib/$runtime/site-packages/ddtrace/appsec/_iast
37+
# CI Visibility paths/integrations
38+
RUN rm -rf \
39+
./python/lib/$runtime/site-packages/ddtrace/contrib/coverage/ \
40+
./python/lib/$runtime/site-packages/ddtrace/contrib/pytest/ \
41+
./python/lib/$runtime/site-packages/ddtrace/contrib/pytest_bdd/ \
42+
./python/lib/$runtime/site-packages/ddtrace/contrib/pytest_benchmark/ \
43+
./python/lib/$runtime/site-packages/ddtrace/contrib/selenium/ \
44+
./python/lib/$runtime/site-packages/ddtrace/contrib/unittest/ \
45+
./python/lib/$runtime/site-packages/ddtrace/ext/ci_visibility \
46+
./python/lib/$runtime/site-packages/ddtrace/ext/test_visibility \
47+
./python/lib/$runtime/site-packages/ddtrace/internal/ci_visibility \
48+
./python/lib/$runtime/site-packages/ddtrace/internal/coverage \
49+
./python/lib/$runtime/site-packages/ddtrace/internal/test_visibility \
50+
./python/lib/$runtime/site-packages/ddtrace/testing/
51+
52+
# Dogshell
53+
RUN rm -rf ./python/lib/$runtime/site-packages/datadog/dogshell
54+
RUN rm -rf ./python/lib/$runtime/site-packages/bin/dog*
55+
3956
# remove *.dist-info directories except any entry_points.txt files and METADATA files required for Appsec Software Composition Analysis
4057
RUN find ./python/lib/$runtime/site-packages/*.dist-info \
4158
-type f \
@@ -49,7 +66,8 @@ RUN rm -rf \
4966
./python/lib/$runtime/site-packages/urllib3* \
5067
./python/lib/$runtime/site-packages/certifi* \
5168
./python/lib/$runtime/site-packages/idna* \
52-
./python/lib/$runtime/site-packages/charset_normalizer*
69+
./python/lib/$runtime/site-packages/charset_normalizer* \
70+
./python/lib/$runtime/site-packages/*__mypyc*.so # from charset_normalizer
5371

5472
# Precompile all .pyc files and remove .py files. This speeds up load time.
5573
# Compile with optimization level 2 (-OO) and PYTHONNODEBUGRANGES=1 to redtce
@@ -58,10 +76,18 @@ RUN rm -rf \
5876
# https://docs.python.org/3.11/using/cmdline.html#cmdoption-O
5977
# https://docs.python.org/3/using/cmdline.html#envvar-PYTHONNODEBUGRANGES
6078
RUN PYTHONNODEBUGRANGES=1 python -OO -m compileall -b ./python/lib/$runtime/site-packages
61-
# remove all .py files except ddtrace/contrib/*/patch.py which are necessary
62-
# for ddtrace.patch to discover instrumationation packages.
63-
RUN find ./python/lib/$runtime/site-packages -name \*.py | grep -v ddtrace/contrib | xargs rm -rf
64-
RUN find ./python/lib/$runtime/site-packages/ddtrace/contrib -name \*.py | grep -v patch.py | xargs rm -rf
79+
# remove all .py files
80+
# DEV: ddtrace>=4.7.0rc3 checks for .pyc files in addition to .py files for instrumentation
81+
# discovery (DataDog/dd-trace-py#17196), so we can safely remove all .py files.
82+
# For older versions, we need to keep patch.py files for instrumentation discovery.
83+
RUN pip install --quiet packaging && \
84+
DDTRACE_VERSION=$(grep "^Version:" ./python/lib/$runtime/site-packages/ddtrace-*.dist-info/METADATA | awk '{print $2}') && \
85+
if python -c "from packaging.version import Version; exit(0 if Version('$DDTRACE_VERSION') >= Version('4.7.0rc3') else 1)"; then \
86+
find ./python/lib/$runtime/site-packages -name \*.py | xargs rm -rf; \
87+
else \
88+
find ./python/lib/$runtime/site-packages -name \*.py | grep -v ddtrace/contrib | xargs rm -rf && \
89+
find ./python/lib/$runtime/site-packages/ddtrace/contrib -name \*.py | grep -v patch.py | xargs rm -rf; \
90+
fi
6591
RUN find ./python/lib/$runtime/site-packages -name __pycache__ -type d -exec rm -r {} \+
6692

6793
# When building ddtrace from branch, remove extra source files. These are
@@ -72,6 +98,7 @@ RUN find ./python/lib/$runtime/site-packages/ddtrace -name \*.cc -delete
7298
RUN find ./python/lib/$runtime/site-packages/ddtrace -name \*.h -delete
7399
RUN find ./python/lib/$runtime/site-packages/ddtrace -name \*.hpp -delete
74100
RUN find ./python/lib/$runtime/site-packages/ddtrace -name \*.pyx -delete
101+
RUN find ./python/lib/$runtime/site-packages/ddtrace -name \*.pyi -delete
75102

76103
# Strip debug symbols and symbols that are not needed for relocation
77104
# processing using strip --strip-unneeded for all .so files. This is to

datadog_lambda/config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ def _reset(self):
141141
"enabled" if config.fips_mode_enabled else "not enabled",
142142
)
143143

144+
# disable css to prevent double counting in lambda
145+
os.environ["DD_TRACE_STATS_COMPUTATION_ENABLED"] = "false"
146+
147+
# unset css aliases to ensure it is disabled
148+
if "DD_TRACE_COMPUTE_STATS" in os.environ:
149+
del os.environ["DD_TRACE_COMPUTE_STATS"]
144150

145151
if (
146152
"DD_INSTRUMENTATION_TELEMETRY_ENABLED" not in os.environ

datadog_lambda/durable.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Unless explicitly stated otherwise all files in this repository are licensed
2+
# under the Apache License Version 2.0.
3+
# This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
# Copyright 2019 Datadog, Inc.
5+
import logging
6+
import re
7+
8+
logger = logging.getLogger(__name__)
9+
10+
11+
def _parse_durable_execution_arn(arn):
12+
"""
13+
Parses a DurableExecutionArn to extract execution name and ID.
14+
ARN format:
15+
arn:aws:lambda:{region}:{account}:function:{func}:{version}/durable-execution/{name}/{id}
16+
Returns (execution_name, execution_id) or None if parsing fails.
17+
"""
18+
match = re.search(r"/durable-execution/([^/]+)/([^/]+)$", arn)
19+
if not match:
20+
return None
21+
execution_name, execution_id = match.group(1), match.group(2)
22+
if not execution_name or not execution_id:
23+
return None
24+
return execution_name, execution_id
25+
26+
27+
def extract_durable_function_tags(event):
28+
"""
29+
Extracts durable function tags from the Lambda event payload.
30+
Returns a dict with durable function tags, or an empty dict if the event
31+
is not a durable function invocation.
32+
"""
33+
if not isinstance(event, dict):
34+
return {}
35+
36+
durable_execution_arn = event.get("DurableExecutionArn")
37+
if not isinstance(durable_execution_arn, str):
38+
return {}
39+
40+
parsed = _parse_durable_execution_arn(durable_execution_arn)
41+
if not parsed:
42+
logger.error("Failed to parse DurableExecutionArn: %s", durable_execution_arn)
43+
return {}
44+
45+
execution_name, execution_id = parsed
46+
return {
47+
"aws_lambda.durable_function.execution_name": execution_name,
48+
"aws_lambda.durable_function.execution_id": execution_id,
49+
}
50+
51+
52+
VALID_DURABLE_STATUSES = {"SUCCEEDED", "FAILED", "STOPPED", "TIMED_OUT"}
53+
54+
55+
def extract_durable_execution_status(response, event):
56+
if not isinstance(event, dict) or "DurableExecutionArn" not in event:
57+
return None
58+
if not isinstance(response, dict):
59+
return None
60+
status = response.get("Status")
61+
if status not in VALID_DURABLE_STATUSES:
62+
return None
63+
return status

datadog_lambda/tracing.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,7 @@ def create_function_execution_span(
14491449
trace_context_source,
14501450
merge_xray_traces,
14511451
trigger_tags,
1452+
durable_function_tags=None,
14521453
parent_span=None,
14531454
span_pointers=None,
14541455
):
@@ -1459,6 +1460,7 @@ def create_function_execution_span(
14591460
function_arn = ":".join(tk[0:7]) if len(tk) > 7 else function_arn
14601461
function_version = tk[7] if len(tk) > 7 else "$LATEST"
14611462
tags = {
1463+
"span.kind": "server",
14621464
"cold_start": str(is_cold_start).lower(),
14631465
"function_arn": function_arn,
14641466
"function_version": function_version,
@@ -1477,6 +1479,8 @@ def create_function_execution_span(
14771479
if trace_context_source == TraceContextSource.XRAY and merge_xray_traces:
14781480
tags["_dd.parent_source"] = trace_context_source
14791481
tags.update(trigger_tags)
1482+
if durable_function_tags:
1483+
tags.update(durable_function_tags)
14801484
tracer.set_tags(_dd_origin)
14811485
# Determine service name based on config and env var
14821486
if config.service:

datadog_lambda/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "8.123.0.dev0"
1+
__version__ = "8.124.0.dev0"

datadog_lambda/wrapper.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
tracer,
4343
propagator,
4444
)
45+
from datadog_lambda.durable import (
46+
extract_durable_function_tags,
47+
extract_durable_execution_status,
48+
)
4549
from datadog_lambda.trigger import (
4650
extract_trigger_tags,
4751
extract_http_status_code_tag,
@@ -152,7 +156,7 @@ def __init__(self, func):
152156
if config.trace_extractor:
153157
extractor_parts = config.trace_extractor.rsplit(".", 1)
154158
if len(extractor_parts) == 2:
155-
(mod_name, extractor_name) = extractor_parts
159+
mod_name, extractor_name = extractor_parts
156160
modified_extractor_name = modify_module_name(mod_name)
157161
extractor_module = import_module(modified_extractor_name)
158162
self.trace_extractor = getattr(extractor_module, extractor_name)
@@ -243,6 +247,7 @@ def _before(self, event, context):
243247
submit_invocations_metric(context)
244248

245249
self.trigger_tags = extract_trigger_tags(event, context)
250+
self.durable_function_tags = extract_durable_function_tags(event)
246251
# Extract Datadog trace context and source from incoming requests
247252
dd_context, trace_context_source, event_source = extract_dd_trace_context(
248253
event,
@@ -280,6 +285,7 @@ def _before(self, event, context):
280285
trace_context_source=trace_context_source,
281286
merge_xray_traces=config.merge_xray_traces,
282287
trigger_tags=self.trigger_tags,
288+
durable_function_tags=self.durable_function_tags,
283289
parent_span=self.inferred_span,
284290
span_pointers=calculate_span_pointers(event_source, event),
285291
)
@@ -289,7 +295,7 @@ def _before(self, event, context):
289295
else:
290296
set_correlation_ids()
291297
if config.profiling_enabled and profiler and is_new_sandbox():
292-
self.prof.start(stop_on_exit=False, profile_children=True)
298+
self.prof.start()
293299
logger.debug("datadog_lambda_wrapper _before() done")
294300
except Exception as e:
295301
logger.error(format_err_with_traceback(e))
@@ -302,6 +308,16 @@ def _after(self, event, context):
302308

303309
status_code = extract_http_status_code_tag(self.trigger_tags, self.response)
304310

311+
# Skip creating cold start spans in managed instances mode
312+
# In managed instances, the tracer library handles cold start independently
313+
should_trace_cold_start = (
314+
config.cold_start_tracing
315+
and is_new_sandbox()
316+
and not is_managed_instances_mode()
317+
)
318+
if should_trace_cold_start:
319+
trace_ctx = tracer.current_trace_context()
320+
305321
if self.span:
306322
if config.appsec_enabled and not self.blocking_response:
307323
asm_start_response(
@@ -327,6 +343,13 @@ def _after(self, event, context):
327343
if status_code:
328344
self.span.set_tag("http.status_code", status_code)
329345

346+
durable_status = extract_durable_execution_status(self.response, event)
347+
if durable_status:
348+
self.span.set_tag(
349+
"aws_lambda.durable_function.execution_status",
350+
durable_status,
351+
)
352+
330353
self.span.finish()
331354

332355
if status_code:
@@ -339,15 +362,6 @@ def _after(self, event, context):
339362
create_dd_dummy_metadata_subsegment(
340363
self.trigger_tags, XraySubsegment.LAMBDA_FUNCTION_TAGS_KEY
341364
)
342-
# Skip creating cold start spans in managed instances mode
343-
# In managed instances, the tracer library handles cold start independently
344-
should_trace_cold_start = (
345-
config.cold_start_tracing
346-
and is_new_sandbox()
347-
and not is_managed_instances_mode()
348-
)
349-
if should_trace_cold_start:
350-
trace_ctx = tracer.current_trace_context()
351365

352366
if self.inferred_span:
353367
if status_code:

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "datadog_lambda"
3-
version = "8.123.0.dev0"
3+
version = "8.124.0.dev0"
44
description = "The Datadog AWS Lambda Library"
55
authors = ["Datadog, Inc. <dev@datadoghq.com>"]
66
license = "Apache-2.0"
@@ -31,7 +31,7 @@ datadog = ">=0.51.0,<1.0.0"
3131
wrapt = "^1.11.2"
3232
ddtrace = [
3333
{version = ">=3.19.1,<4", python = ">=3.8,<3.10"},
34-
{version = ">=4.1.1,<5", python = ">=3.10"}
34+
{version = ">=4.1.1,<5,!=4.6.*", python = ">=3.10"}
3535
]
3636
ujson = ">=5.9.0"
3737
botocore = { version = "^1.34.0", optional = true }

0 commit comments

Comments
 (0)