8000 Implement PR feedback · DataDog/datadog-lambda-python@281e791 · GitHub
[go: up one dir, main page]

Skip to content

Commit 281e791

Browse files
committed
Implement PR feedback
1 parent 47a622b commit 281e791

File tree

9 files changed

+90
-71
lines changed

9 files changed

+90
-71
lines changed

datadog_lambda/constants.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ class XraySubsegment(object):
2626
NAMESPACE = "datadog"
2727

2828

29-
# Source of datadog context
30-
class Source(object):
29+
# TraceContextSource of datadog context. The DD_MERGE_XRAY_TRACES
30+
# feature uses this to determine when to use X-Ray as the parent
31+
# trace.
32+
class TraceContextSource(object):
3133
XRAY = "xray"
3234
EVENT = "event"
3335
DDTRACE = "ddtrace"

datadog_lambda/tracing.py

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,14 @@
1313
SamplingPriority,
1414
TraceHeader,
1515
XraySubsegment,
16-
Source,
16+
TraceContextSource,
1717
)
1818
from ddtrace import tracer, patch
1919

2020
logger = logging.getLogger(__name__)
2121

2222
dd_trace_context = {}
23-
dd_native_tracing_enabled = (
24-
os.environ.get("DD_TRACE_ENABLED", "false").lower() == "true"
25-
)
23+
dd_tracing_enabled = os.environ.get("DD_TRACE_ENABLED", "false").lower() == "true"
2624

2725

2826
def _convert_xray_trace_id(xray_trace_id):
@@ -59,22 +57,23 @@ def _get_xray_trace_context():
5957
"trace-id": _convert_xray_trace_id(xray_trace_entity.trace_id),
6058
"parent-id": _convert_xray_entity_id(xray_trace_entity.id),
6159
"sampling-priority": _convert_xray_sampling(xray_trace_entity.sampled),
62-
"source": Source.XRAY,
60+
"source": TraceContextSource.XRAY,
6361
}
6462

6563

66-
def _get_dd_trace_native_context():
64+
def _get_dd_trace_py_context():
6765
span = tracer.current_span()
6866
if not span:
6967
return None
7068

7169
parent_id = span.context.span_id
7270
trace_id = span.context.trace_id
71+
sampling_priority = span.context.sampling_priority
7372
return {
7473
"parent-id": str(parent_id),
7574
"trace-id": str(trace_id),
76-
"sampling-priority": SamplingPriority.AUTO_KEEP,
77-
"source": Source.DDTRACE,
75+
"sampling-priority": str(sampling_priority),
76+
"source": TraceContextSource.DDTRACE,
7877
}
7978

8079

@@ -116,7 +115,7 @@ def extract_dd_trace_context(event):
116115

117116
subsegment.put_metadata(XraySubsegment.KEY, metadata, XraySubsegment.NAMESPACE)
118117
dd_trace_context = metadata.copy()
119-
dd_trace_context["source"] = Source.EVENT
118+
dd_trace_context["source"] = TraceContextSource.EVENT
120119
xray_recorder.end_subsegment()
121120
else:
122121
# AWS Lambda runtime caches global variables between invocations,
@@ -132,35 +131,38 @@ def get_dd_trace_context():
132131
133132
If the Lambda function is invoked by a Datadog-traced service, a Datadog
134133
trace context may already exist, and it should be used. Otherwise, use the
135-
current X-Ray trace entity.
134+
current X-Ray trace entity, or the dd-trace-py context if DD_TRACE_ENABLED is true.
136135
137136
Most of widely-used HTTP clients are patched to inject the context
138137
automatically, but this function can be used to manually inject the trace
139138
context to an outgoing request.
140139
"""
141140
global dd_trace_context
142141

143-
if dd_native_tracing_enabled:
144-
native_trace_context = _get_dd_trace_native_context()
145-
if native_trace_context is not None:
146-
logger.info("get_dd_trace_context using dd-trace context")
147-
return _context_obj_to_headers(native_trace_context)
142+
context = None
143+
xray_context = None
148144

149145
try:
150-
trace_headers = _context_obj_to_headers(dd_trace_context)
151146
xray_context = _get_xray_trace_context() # xray (sub)segment
152-
if xray_context and not trace_headers:
153-
return _context_obj_to_headers(xray_context)
154-
if xray_context and trace_headers:
155-
trace_headers[TraceHeader.PARENT_ID] = xray_context["parent-id"]
156-
return trace_headers
157147
except Exception as e:
158148
logger.debug(
159149
"get_dd_trace_context couldn't read from segment from x-ray, with error %s"
160150
% e
161151
)
162152

163-
return {}
153+
if xray_context and not dd_trace_context:
154+
context = xray_context
155+
elif xray_context and dd_trace_context:
156+
context = dd_trace_context.copy()
157+
context["parent-id"] = xray_context["parent-id"]
158+
159+
if dd_tracing_enabled:
160+
dd_trace_py_context = _get_dd_trace_py_context()
161+
if dd_trace_py_context is not None:
162+
logger.debug("get_dd_trace_context using dd-trace context")
163+
context = dd_trace_py_context
164+
165+
return _context_obj_to_headers(context) if context is not None else {}
164166

165167

166168
def set_correlation_ids():
@@ -174,7 +176,7 @@ def set_correlation_ids():
174176
if not is_lambda_context():
175177
logger.debug("set_correlation_ids is only supported in LambdaContext")
176178
return
177-
if dd_native_tracing_enabled:
179+
if dd_tracing_enabled:
178180
logger.debug("using ddtrace implementation for spans")
179181
return
180182

datadog_lambda/wrapper.py

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
extract_dd_trace_context,
1919
inject_correlation_ids,
2020
get_dd_trace_context,
21-
dd_native_tracing_enabled,
21+
dd_tracing_enabled,
2222
set_correlation_ids,
2323
)
24-
from datadog_lambda.constants import Source
24+
from datadog_lambda.constants import TraceContextSource
2525
from ddtrace import tracer
2626
from ddtrace.propagation.http import HTTPPropagator
2727

@@ -97,8 +97,10 @@ def __init__(self, func):
9797
if self.logs_injection:
9898
inject_correlation_ids()
9999

100-
# Patch HTTP clients to propagate Datadog trace context
101-
patch_all()
100+
if not dd_tracing_enabled:
101+
# When using dd_trace_py it will patch all the http clients for us,
102+
# Patch HTTP clients to propagate Datadog trace context
103+
patch_all()
102104
logger.debug("datadog_lambda_wrapper initialized")
103105
except Exception:
104106
traceback.print_exc()
@@ -121,31 +123,10 @@ def _before(self, event, context):
121123
submit_invocations_metric(context)
122124
# Extract Datadog trace context from incoming requests
123125
dd_context = extract_dd_trace_context(event)
124-
span_context = None
125-
if dd_context["source"] == Source.EVENT or self.merge_xray_traces:
126-
headers = get_dd_trace_context()
127-
span_context = self.propagator.extract(headers)
128-
129-
tags = {}
130-
if context:
131-
tags = {
132-
"cold_start": is_cold_start(),
133-
"function_arn": context.invoked_function_arn,
134-
"request_id": context.aws_request_id,
135-
"resource_names": context.function_name,
136-
}
137-
args = {
138-
"service": self.function_name,
139-
"resource": self.handler_name,
140-
"span_type": "serverless",
141-
"child_of": span_context,
142-
}
143126

144127
self.span = None
145-
if dd_native_tracing_enabled:
146-
self.span = tracer.start_span("aws.lambda", **args)
147-
if self.span:
148-
self.span.set_tags(tags)
128+
if dd_tracing_enabled:
129+
self.span = self._create_dd_trace_py_span(context, dd_context)
149130
else:
150131
set_correlation_ids()
151132

@@ -163,5 +144,33 @@ def _after(self, event, context):
163144
except Exception:
164145
traceback.print_exc()
165146

147+
def _create_dd_trace_py_span(self, context, trace_context):
148+
span_context = None
149+
if (
150+
trace_context["source"] == TraceContextSource.EVENT
151+
or self.merge_xray_traces
152+
):
153+
headers = get_dd_trace_context()
154+
span_context = self.propagator.extract(headers)
155+
156+
tags = {}
157+
if context:
158+
tags = {
159+
"cold_start": is_cold_start(),
160+
"function_arn": context.invoked_function_arn,
161+
"request_id": context.aws_request_id,
162+
"resource_names": context.function_name,
163+
}
164+
args = {
165+
"service": self.function_name,
166+
"resource": self.handler_name,
167+
"span_type": "serverless",
168+
"child_of": span_context,
169+
}
170+
span = tracer.start_span("aws.lambda", **args)
171+
if span:
172+
span.set_tags(tags)
173+
return span
174+
166175

167176
datadog_lambda_wrapper = _LambdaDecorator

scripts/run_integration_tests.sh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,15 @@ for handler_name in "${LAMBDA_HANDLERS[@]}"; do
116116
# Strip API key from logged requests
117117
sed -E "s/(api_key=|'api_key': ')[a-z0-9\.\-]+/\1XXXX/g" |
118118
# Normalize minor package version so that these snapshots aren't broken on version bumps
119-
sed -E "s/(dd_lambda_layer:datadog-python[0-9]+_2\.)[0-9]+\.0/\1XX\.0/g"
119+
sed -E "s/(dd_lambda_layer:datadog-python[0-9]+_2\.)[0-9]+\.0/\1XX\.0/g" |
120+
# Strip out trace/span/parent/timestamps
121+
sed -E "s/(\"trace_id\"\: \")[A-Z0-9\.\-]+/\1XXXX/g" |
122+
sed -E "s/(\"span_id\"\: \")[A-Z0-9\.\-]+/\1XXXX/g" |
123+
sed -E "s/(\"parent_id\"\: \")[A-Z0-9\.\-]+/\1XXXX/g" |
124+
sed -E "s/(\"request_id\"\: \")[a-z0-9\.\-]+/\1XXXX/g" |
125+
sed -E "s/(\"duration\"\: )[0-9\.\-]+/\1XXXX/g" |
126+
sed -E "s/(\"start\"\: )[0-9\.\-]+/\1XXXX/g" |
127+
sed -E "s/(\"system\.pid\"\: )[0-9\.\-]+/\1XXXX/g"
120128
)
121129

122130
if [ ! -f $function_snapshot_path ]; then

tests/integration/snapshots/logs/http-requests_python27.log

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ START RequestId: XXXX Version: $LATEST
22
{"e": XXXX, "m": "aws.lambda.enhanced.invocations", "t": ["region:us-east-1", "account_id:XXXX", "functionname:integration-tester-dev-http-requests_python27", "cold_start:true", "memorysize:1024", "runtime:python2.7", "dd_lambda_layer:datadog-python27_2.XX.0"], "v": 1}
33
HTTP GET https://ip-ranges.datadoghq.com/ Headers: ["x-datadog-parent-id:XXXX", "x-datadog-sampling-priority:2", "x-datadog-trace-id:XXXX"] Data: {}
44
HTTP GET https://ip-ranges.datadoghq.eu/ Headers: ["x-datadog-parent-id:XXXX", "x-datadog-sampling-priority:2", "x-datadog-trace-id:XXXX"] Data: {}
5-
{"traces": [[{"resource": "http_requests.handle", "name": "aws.lambda", "service": "integration-tester-dev-http-requests_python27", "start": 1585077483318449000, "trace_id": "06C0653FC881D935", "metrics": {"_sampling_priority_v1": 1, "system.pid": 1, "_dd.agent_psr": 1.0}, "parent_id": "0000000000000000", "meta": {"function_arn": "arn:aws:lambda:us-east-1:601427279990:function:integration-tester-dev-http-requests_python27", "request_id": "da026ab0-1d6c-4980-9720-1b4bdd843314", "cold_start": "True", "resource_names": "integration-tester-dev-http-requests_python27"}, "error": 0, "duration": 389814000, "type": "serverless", "span_id": "3DA8AA128268BFA1"}]]}
5+
{"traces": [[{"resource": "http_requests.handle", "name": "aws.lambda", "service": "integration-tester-dev-http-requests_python27", "start": XXXX, "trace_id": "XXXX", "metrics": {"_sampling_priority_v1": 1, "system.pid": XXXX, "_dd.agent_psr": 1.0}, "parent_id": "XXXX", "meta": {"function_arn": "arn:aws:lambda:us-east-1:601427279990:function:integration-tester-dev-http-requests_python27", "request_id": "XXXX", "cold_start": "True", "resource_names": "integration-tester-dev-http-requests_python27"}, "error": 0, "duration": XXXX, "type": "serverless", "span_id": "XXXX"}]]}
66
HTTP POST https://api.datadoghq.com/api/v1/distribution_points Headers: ["Content-Type:application/json", "x-datadog-parent-id:XXXX", "x-datadog-sampling-priority:2", "x-datadog-trace-id:XXXX"] Data: {"series": [{"tags": ["team:serverless", "role:hello", "dd_lambda_layer:datadog-python27_2.XX.0"], "metric": "hello.dog", "interval": 10, "host": null, "points": [[XXXX, [1.0]]], "device": null, "type": "distribution"}, {"tags": ["test:integration", "role:hello", "dd_lambda_layer:datadog-python27_2.XX.0"], "metric": "tests.integration.count", "interval": 10, "host": null, "points": [[XXXX, [21.0]]], "device": null, "type": "distribution"}]}
77
END RequestId: XXXX
88
REPORT RequestId: XXXX Duration: XXXX ms Billed Duration: XXXX ms Memory Size: 1024 MB Max Memory Used: XXXX MB Init Duration: XXXX ms
@@ -11,7 +11,7 @@ START RequestId: XXXX Version: $LATEST
1111
{"e": XXXX, "m": "aws.lambda.enhanced.invocations", "t": ["region:us-east-1", "account_id:XXXX", "functionname:integration-tester-dev-http-requests_python27", "cold_start:false", "memorysize:1024", "runtime:python2.7", "dd_lambda_layer:datadog-python27_2.XX.0"], "v": 1}
1212
HTTP GET https://ip-ranges.datadoghq.com/ Headers: ["x-datadog-parent-id:XXXX", "x-datadog-sampling-priority:2", "x-datadog-trace-id:XXXX"] Data: {}
1313
HTTP GET https://ip-ranges.datadoghq.eu/ Headers: ["x-datadog-parent-id:XXXX", "x-datadog-sampling-priority:2", "x-datadog-trace-id:XXXX"] Data: {}
14-
{"traces": [[{"resource": "http_requests.handle", "name": "aws.lambda", "service": "integration-tester-dev-http-requests_python27", "start": 1585077485080991000, "trace_id": "6BDE1FAE35B84C6C", "metrics": {"_sampling_priority_v1": 1, "system.pid": 1, "_dd.agent_psr": 1.0}, "parent_id": "0000000000000000", "meta": {"function_arn": "arn:aws:lambda:us-east-1:601427279990:function:integration-tester-dev-http-requests_python27", "request_id": "f1b1655b-ce14-4540-bf54-8e128af7b8ab", "cold_start": "False", "resource_names": "integration-tester-dev-http-requests_python27"}, "error": 0, "duration": 80971000, "type": "serverless", "span_id": "393ECB596ED13F61"}]]}
14+
{"traces": [[{"resource": "http_requests.handle", "name": "aws.lambda", "service": "integration-tester-dev-http-requests_python27", "start": XXXX, "trace_id": "XXXX", "metrics": {"_sampling_priority_v1": 1, "system.pid": XXXX, "_dd.agent_psr": 1.0}, "parent_id": "XXXX", "meta": {"function_arn": "arn:aws:lambda:us-east-1:601427279990:function:integration-tester-dev-http-requests_python27", "request_id": "XXXX", "cold_start": "False", "resource_names": "integration-tester-dev-http-requests_python27"}, "error": 0, "duration": XXXX, "type": "serverless", "span_id": "XXXX"}]]}
1515
HTTP POST https://api.datadoghq.com/api/v1/distribution_points Headers: ["Content-Type:application/json", "x-datadog-parent-id:XXXX", "x-datadog-sampling-priority:2", "x-datadog-trace-id:XXXX"] Data: {"series": [{"tags": ["team:serverless", "role:hello", "dd_lambda_layer:datadog-python27_2.XX.0"], "metric": "hello.dog", "interval": 10, "host": null, "points": [[XXXX, [1.0]]], "device": null, "type": "distribution"}, {"tags": ["test:integration", "role:hello", "dd_lambda_layer:datadog-python27_2.XX.0"], "metric": "tests.integration.count", "interval": 10, "host": null, "points": [[XXXX, [21.0]]], "device": null, "type": "distribution"}]}
1616
END RequestId: XXXX
1717
REPORT RequestId: XXXX Duration: XXXX ms Billed Duration: XXXX ms Memory Size: 1024 MB Max Memory Used: XXXX MB
@@ -20,7 +20,7 @@ START RequestId: XXXX Version: $LATEST
2020
{"e": XXXX, "m": "aws.lambda.enhanced.invocations", "t": ["region:us-east-1", "account_id:XXXX", "functionname:integration-tester-dev-http-requests_python27", "cold_start:false", "memorysize:1024", "runtime:python2.7", "dd_lambda_layer:datadog-python27_2.XX.0"], "v": 1}
2121
HTTP GET https://ip-ranges.datadoghq.com/ Headers: ["x-datadog-parent-id:XXXX", "x-datadog-sampling-priority:2", "x-datadog-trace-id:XXXX"] Data: {}
2222
HTTP GET https://ip-ranges.datadoghq.eu/ Headers: ["x-datadog-parent-id:XXXX", "x-datadog-sampling-priority:2", "x-datadog-trace-id:XXXX"] Data: {}
23-
{"traces": [[{"resource": "http_requests.handle", "name": "aws.lambda", "service": "integration-tester-dev-http-requests_python27", "start": 1585077486596975000, "trace_id": "0A7F7B686FDCC310", "metrics": {"_sampling_priority_v1": 1, "system.pid": 1, "_dd.agent_psr": 1.0}, "parent_id": "0000000000000000", "meta": {"function_arn": "arn:aws:lambda:us-east-1:601427279990:function:integration-tester-dev-http-requests_python27", "request_id": "6f90344e-1fa5-48cb-8933-d7f523868746", "cold_start": "False", "resource_names": "integration-tester-dev-http-requests_python27"}, "error": 0, "duration": 100314000, "type": "serverless", "span_id": "58E9AB1D40B41342"}]]}
23+
{"traces": [[{"resource": "http_requests.handle", "name": "aws.lambda", "service": "integration-tester-dev-http-requests_python27", "start": XXXX, "trace_id": "XXXX", "metrics": {"_sampling_priority_v1": 1, "system.pid": XXXX, "_dd.agent_psr": 1.0}, "parent_id": "XXXX", "meta": {"function_arn": "arn:aws:lambda:us-east-1:601427279990:function:integration-tester-dev-http-requests_python27", "request_id": "XXXX", "cold_start": "False", "resource_names": "integration-tester-dev-http-requests_python27"}, "error": 0, "duration": XXXX, "type": "serverless", "span_id": "XXXX"}]]}
2424
HTTP POST https://api.datadoghq.com/api/v1/distribution_points Headers: ["Content-Type:application/json", "x-datadog-parent-id:XXXX", "x-datadog-sampling-priority:2", "x-datadog-trace-id:XXXX"] Data: {"series": [{"tags": ["team:serverless", "role:hello", "dd_lambda_layer:datadog-python27_2.XX.0"], "metric": "hello.dog", "interval": 10, "host": null, "points": [[XXXX, [1.0]]], "device": null, "type": "distribution"}, {"tags": ["test:integration", "role:hello", "dd_lambda_layer:datadog-python27_2.XX.0"], "metric": "tests.integration.count", "interval": 10, "host": null, "points": [[XXXX, [21.0]]], "device": null, "type": "distribution"}]}
2525
END RequestId: XXXX
2626
REPORT RequestId: XXXX Duration: XXXX ms Billed Duration: XXXX ms Memory Size: 1024 MB Max Memory Used: XXXX MB

0 commit comments

Comments
 (0)
0