datadog_lambda 5.92.0__py3-none-any.whl → 5.94.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- datadog_lambda/__init__.py +2 -6
- datadog_lambda/cold_start.py +6 -2
- datadog_lambda/extension.py +2 -4
- datadog_lambda/handler.py +18 -3
- datadog_lambda/metric.py +14 -18
- datadog_lambda/patch.py +3 -3
- datadog_lambda/tag_object.py +4 -4
- datadog_lambda/tags.py +21 -48
- datadog_lambda/tracing.py +201 -182
- datadog_lambda/trigger.py +39 -35
- datadog_lambda/version.py +1 -0
- datadog_lambda/wrapper.py +6 -5
- datadog_lambda/xray.py +45 -34
- datadog_lambda-5.94.0.dist-info/LICENSE-3rdparty.csv +13 -0
- {datadog_lambda-5.92.0.dist-info → datadog_lambda-5.94.0.dist-info}/METADATA +3 -3
- datadog_lambda-5.94.0.dist-info/RECORD +27 -0
- datadog_lambda-5.92.0.dist-info/LICENSE-3rdparty.csv +0 -3
- datadog_lambda-5.92.0.dist-info/RECORD +0 -26
- {datadog_lambda-5.92.0.dist-info → datadog_lambda-5.94.0.dist-info}/LICENSE +0 -0
- {datadog_lambda-5.92.0.dist-info → datadog_lambda-5.94.0.dist-info}/NOTICE +0 -0
- {datadog_lambda-5.92.0.dist-info → datadog_lambda-5.94.0.dist-info}/WHEEL +0 -0
datadog_lambda/__init__.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from datadog_lambda.cold_start import initialize_cold_start_tracing
|
|
2
|
-
from datadog_lambda.logger import initialize_logging
|
|
3
2
|
import os
|
|
4
3
|
|
|
5
4
|
|
|
@@ -13,11 +12,8 @@ initialize_cold_start_tracing()
|
|
|
13
12
|
|
|
14
13
|
# The minor version corresponds to the Lambda layer version.
|
|
15
14
|
# E.g.,, version 0.5.0 gets packaged into layer version 5.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
except ModuleNotFoundError:
|
|
19
|
-
import importlib_metadata
|
|
15
|
+
from datadog_lambda.version import __version__ # noqa: E402 F401
|
|
16
|
+
from datadog_lambda.logger import initialize_logging # noqa: E402
|
|
20
17
|
|
|
21
|
-
__version__ = importlib_metadata.version(__name__)
|
|
22
18
|
|
|
23
19
|
initialize_logging(__name__)
|
datadog_lambda/cold_start.py
CHANGED
|
@@ -50,12 +50,16 @@ def is_new_sandbox():
|
|
|
50
50
|
|
|
51
51
|
def get_cold_start_tag():
|
|
52
52
|
"""Returns the cold start tag to be used in metrics"""
|
|
53
|
-
return "cold_start:
|
|
53
|
+
return "cold_start:true" if _cold_start else "cold_start:false"
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
def get_proactive_init_tag():
|
|
57
57
|
"""Returns the proactive init tag to be used in metrics"""
|
|
58
|
-
return
|
|
58
|
+
return (
|
|
59
|
+
"proactive_initialization:true"
|
|
60
|
+
if _proactive_initialization
|
|
61
|
+
else "proactive_initialization:false"
|
|
62
|
+
)
|
|
59
63
|
|
|
60
64
|
|
|
61
65
|
class ImportNode(object):
|
datadog_lambda/extension.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
|
|
2
|
+
import os
|
|
3
3
|
|
|
4
4
|
AGENT_URL = "http://127.0.0.1:8124"
|
|
5
5
|
FLUSH_PATH = "/lambda/flush"
|
|
@@ -9,9 +9,7 @@ logger = logging.getLogger(__name__)
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def is_extension_present():
|
|
12
|
-
|
|
13
|
-
return True
|
|
14
|
-
return False
|
|
12
|
+
return os.path.exists(EXTENSION_PATH)
|
|
15
13
|
|
|
16
14
|
|
|
17
15
|
def flush_extension():
|
datadog_lambda/handler.py
CHANGED
|
@@ -7,6 +7,9 @@ from __future__ import absolute_import
|
|
|
7
7
|
from importlib import import_module
|
|
8
8
|
|
|
9
9
|
import os
|
|
10
|
+
from time import time_ns
|
|
11
|
+
|
|
12
|
+
from datadog_lambda.tracing import emit_telemetry_on_exception_outside_of_handler
|
|
10
13
|
from datadog_lambda.wrapper import datadog_lambda_wrapper
|
|
11
14
|
from datadog_lambda.module_name import modify_module_name
|
|
12
15
|
|
|
@@ -22,10 +25,22 @@ if path is None:
|
|
|
22
25
|
)
|
|
23
26
|
parts = path.rsplit(".", 1)
|
|
24
27
|
if len(parts) != 2:
|
|
25
|
-
raise HandlerError("Value
|
|
28
|
+
raise HandlerError(f"Value {path} for DD_LAMBDA_HANDLER has invalid format.")
|
|
26
29
|
|
|
27
30
|
|
|
28
31
|
(mod_name, handler_name) = parts
|
|
29
32
|
modified_mod_name = modify_module_name(mod_name)
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
handler_load_start_time_ns = time_ns()
|
|
36
|
+
handler_module = import_module(modified_mod_name)
|
|
37
|
+
handler_func = getattr(handler_module, handler_name)
|
|
38
|
+
except Exception as e:
|
|
39
|
+
emit_telemetry_on_exception_outside_of_handler(
|
|
40
|
+
e,
|
|
41
|
+
modified_mod_name,
|
|
42
|
+
handler_load_start_time_ns,
|
|
43
|
+
)
|
|
44
|
+
raise
|
|
45
|
+
|
|
46
|
+
handler = datadog_lambda_wrapper(handler_func)
|
datadog_lambda/metric.py
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
# Copyright 2019 Datadog, Inc.
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
|
-
import json
|
|
8
7
|
import time
|
|
9
8
|
import logging
|
|
9
|
+
import ujson as json
|
|
10
10
|
|
|
11
11
|
from datadog_lambda.extension import should_use_extension
|
|
12
|
-
from datadog_lambda.tags import get_enhanced_metrics_tags,
|
|
12
|
+
from datadog_lambda.tags import get_enhanced_metrics_tags, dd_lambda_layer_tag
|
|
13
13
|
from datadog_lambda.api import init_api
|
|
14
14
|
|
|
15
15
|
logger = logging.getLogger(__name__)
|
|
@@ -32,6 +32,10 @@ else:
|
|
|
32
32
|
flush_in_thread = os.environ.get("DD_FLUSH_IN_THREAD", "").lower() == "true"
|
|
33
33
|
lambda_stats = ThreadStatsWriter(flush_in_thread)
|
|
34
34
|
|
|
35
|
+
enhanced_metrics_enabled = (
|
|
36
|
+
os.environ.get("DD_ENHANCED_METRICS", "true").lower() == "true"
|
|
37
|
+
)
|
|
38
|
+
|
|
35
39
|
|
|
36
40
|
def lambda_metric(metric_name, value, timestamp=None, tags=None, force_async=False):
|
|
37
41
|
"""
|
|
@@ -50,7 +54,8 @@ def lambda_metric(metric_name, value, timestamp=None, tags=None, force_async=Fal
|
|
|
50
54
|
and always use the layer to send metrics to the extension
|
|
51
55
|
"""
|
|
52
56
|
flush_to_logs = os.environ.get("DD_FLUSH_TO_LOG", "").lower() == "true"
|
|
53
|
-
tags =
|
|
57
|
+
tags = [] if tags is None else list(tags)
|
|
58
|
+
tags.append(dd_lambda_layer_tag)
|
|
54
59
|
|
|
55
60
|
if should_use_extension:
|
|
56
61
|
logger.debug(
|
|
@@ -80,7 +85,8 @@ def write_metric_point_to_stdout(metric_name, value, timestamp=None, tags=[]):
|
|
|
80
85
|
"v": value,
|
|
81
86
|
"e": timestamp or int(time.time()),
|
|
82
87
|
"t": tags,
|
|
83
|
-
}
|
|
88
|
+
},
|
|
89
|
+
escape_forward_slashes=False,
|
|
84
90
|
)
|
|
85
91
|
)
|
|
86
92
|
|
|
@@ -89,24 +95,14 @@ def flush_stats():
|
|
|
89
95
|
lambda_stats.flush()
|
|
90
96
|
|
|
91
97
|
|
|
92
|
-
def are_enhanced_metrics_enabled():
|
|
93
|
-
"""Check env var to find if enhanced metrics should be submitted
|
|
94
|
-
|
|
95
|
-
Returns:
|
|
96
|
-
boolean for whether enhanced metrics are enabled
|
|
97
|
-
"""
|
|
98
|
-
# DD_ENHANCED_METRICS defaults to true
|
|
99
|
-
return os.environ.get("DD_ENHANCED_METRICS", "true").lower() == "true"
|
|
100
|
-
|
|
101
|
-
|
|
102
98
|
def submit_enhanced_metric(metric_name, lambda_context):
|
|
103
99
|
"""Submits the enhanced metric with the given name
|
|
104
100
|
|
|
105
101
|
Args:
|
|
106
102
|
metric_name (str): metric name w/o enhanced prefix i.e. "invocations" or "errors"
|
|
107
|
-
lambda_context (
|
|
103
|
+
lambda_context (object): Lambda context dict passed to the function by AWS
|
|
108
104
|
"""
|
|
109
|
-
if not
|
|
105
|
+
if not enhanced_metrics_enabled:
|
|
110
106
|
logger.debug(
|
|
111
107
|
"Not submitting enhanced metric %s because enhanced metrics are disabled",
|
|
112
108
|
metric_name,
|
|
@@ -122,7 +118,7 @@ def submit_invocations_metric(lambda_context):
|
|
|
122
118
|
"""Increment aws.lambda.enhanced.invocations by 1, applying runtime, layer, and cold_start tags
|
|
123
119
|
|
|
124
120
|
Args:
|
|
125
|
-
lambda_context (
|
|
121
|
+
lambda_context (object): Lambda context dict passed to the function by AWS
|
|
126
122
|
"""
|
|
127
123
|
submit_enhanced_metric("invocations", lambda_context)
|
|
128
124
|
|
|
@@ -131,6 +127,6 @@ def submit_errors_metric(lambda_context):
|
|
|
131
127
|
"""Increment aws.lambda.enhanced.errors by 1, applying runtime, layer, and cold_start tags
|
|
132
128
|
|
|
133
129
|
Args:
|
|
134
|
-
lambda_context (
|
|
130
|
+
lambda_context (object): Lambda context dict passed to the function by AWS
|
|
135
131
|
"""
|
|
136
132
|
submit_enhanced_metric("errors", lambda_context)
|
datadog_lambda/patch.py
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
# This product includes software developed at Datadog (https://www.datadoghq.com/).
|
|
4
4
|
# Copyright 2019 Datadog, Inc.
|
|
5
5
|
|
|
6
|
-
import json
|
|
7
6
|
import os
|
|
8
7
|
import sys
|
|
9
8
|
import logging
|
|
10
9
|
import zlib
|
|
10
|
+
import ujson as json
|
|
11
11
|
|
|
12
12
|
from wrapt import wrap_function_wrapper as wrap
|
|
13
13
|
from wrapt.importer import when_imported
|
|
@@ -144,14 +144,14 @@ def _print_request_string(request):
|
|
|
144
144
|
data = zlib.decompress(data)
|
|
145
145
|
data_dict = json.loads(data)
|
|
146
146
|
data_dict.get("series", []).sort(key=lambda series: series.get("metric"))
|
|
147
|
-
sorted_data = json.dumps(data_dict)
|
|
147
|
+
sorted_data = json.dumps(data_dict, escape_forward_slashes=False)
|
|
148
148
|
|
|
149
149
|
# Sort headers to prevent any differences in ordering
|
|
150
150
|
headers = request.headers or {}
|
|
151
151
|
sorted_headers = sorted(
|
|
152
152
|
"{}:{}".format(key, value) for key, value in headers.items()
|
|
153
153
|
)
|
|
154
|
-
sorted_header_str = json.dumps(sorted_headers)
|
|
154
|
+
sorted_header_str = json.dumps(sorted_headers, escape_forward_slashes=False)
|
|
155
155
|
print(
|
|
156
156
|
"HTTP {} {} Headers: {} Data: {}".format(
|
|
157
157
|
method, url, sorted_header_str, sorted_data
|
datadog_lambda/tag_object.py
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
# Copyright 2021 Datadog, Inc.
|
|
5
5
|
|
|
6
6
|
from decimal import Decimal
|
|
7
|
-
import json
|
|
8
7
|
import logging
|
|
8
|
+
import ujson as json
|
|
9
9
|
|
|
10
10
|
redactable_keys = ["authorization", "x-authorization", "password", "token"]
|
|
11
11
|
max_depth = 10
|
|
@@ -30,17 +30,17 @@ def tag_object(span, key, obj, depth=0):
|
|
|
30
30
|
return span.set_tag(key, str(obj))
|
|
31
31
|
if isinstance(obj, list):
|
|
32
32
|
for k, v in enumerate(obj):
|
|
33
|
-
formatted_key = "{}.{}"
|
|
33
|
+
formatted_key = f"{key}.{k}"
|
|
34
34
|
tag_object(span, formatted_key, v, depth)
|
|
35
35
|
return
|
|
36
36
|
if hasattr(obj, "items"):
|
|
37
37
|
for k, v in obj.items():
|
|
38
|
-
formatted_key = "{}.{}"
|
|
38
|
+
formatted_key = f"{key}.{k}"
|
|
39
39
|
tag_object(span, formatted_key, v, depth)
|
|
40
40
|
return
|
|
41
41
|
if hasattr(obj, "to_dict"):
|
|
42
42
|
for k, v in obj.to_dict().items():
|
|
43
|
-
formatted_key = "{}.{}"
|
|
43
|
+
formatted_key = f"{key}.{k}"
|
|
44
44
|
tag_object(span, formatted_key, v, depth)
|
|
45
45
|
return
|
|
46
46
|
try:
|
datadog_lambda/tags.py
CHANGED
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
|
|
3
|
-
from platform import python_version_tuple
|
|
4
|
-
|
|
5
3
|
from datadog_lambda import __version__
|
|
6
4
|
from datadog_lambda.cold_start import get_cold_start_tag
|
|
7
5
|
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
runtime = "python{}{}".format(sys.version_info[0], sys.version_info[1])
|
|
14
|
-
return "dd_lambda_layer:datadog-{}_{}".format(runtime, __version__)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def tag_dd_lambda_layer(tags):
|
|
18
|
-
"""
|
|
19
|
-
Used by lambda_metric to insert the dd_lambda_layer tag
|
|
20
|
-
"""
|
|
21
|
-
dd_lambda_layer_tag = _format_dd_lambda_layer_tag()
|
|
22
|
-
if tags:
|
|
23
|
-
return tags + [dd_lambda_layer_tag]
|
|
24
|
-
else:
|
|
25
|
-
return [dd_lambda_layer_tag]
|
|
7
|
+
_major, _minor = sys.version_info[0], sys.version_info[1]
|
|
8
|
+
dd_lambda_layer_tag = f"dd_lambda_layer:datadog-python{_major}{_minor}_{__version__}"
|
|
9
|
+
runtime_tag = f"runtime:python{_major}.{_minor}"
|
|
10
|
+
library_version_tag = f"datadog_lambda:v{__version__}"
|
|
26
11
|
|
|
27
12
|
|
|
28
13
|
def parse_lambda_tags_from_arn(lambda_context):
|
|
@@ -32,64 +17,52 @@ def parse_lambda_tags_from_arn(lambda_context):
|
|
|
32
17
|
ex: lambda_context.arn = arn:aws:lambda:us-east-1:123597598159:function:my-lambda:1
|
|
33
18
|
"""
|
|
34
19
|
# Set up flag for extra testing to distinguish between a version or alias
|
|
35
|
-
|
|
20
|
+
has_alias = False
|
|
36
21
|
# Cap the number of times to spli
|
|
37
22
|
split_arn = lambda_context.invoked_function_arn.split(":")
|
|
38
23
|
|
|
39
24
|
if len(split_arn) > 7:
|
|
40
|
-
|
|
25
|
+
has_alias = True
|
|
41
26
|
_, _, _, region, account_id, _, function_name, alias = split_arn
|
|
42
27
|
else:
|
|
43
28
|
_, _, _, region, account_id, _, function_name = split_arn
|
|
44
29
|
|
|
45
30
|
# Add the standard tags to a list
|
|
46
31
|
tags = [
|
|
47
|
-
"region:{}"
|
|
48
|
-
"account_id:{}"
|
|
49
|
-
"functionname:{}"
|
|
32
|
+
f"region:{region}",
|
|
33
|
+
f"account_id:{account_id}",
|
|
34
|
+
f"functionname:{function_name}",
|
|
50
35
|
]
|
|
51
36
|
|
|
52
37
|
# Check if we have a version or alias
|
|
53
|
-
if
|
|
38
|
+
if has_alias:
|
|
54
39
|
# If $Latest, drop the $ for datadog tag convention. A lambda alias can't start with $
|
|
55
40
|
if alias.startswith("$"):
|
|
56
41
|
alias = alias[1:]
|
|
57
42
|
# Versions are numeric. Aliases need the executed version tag
|
|
58
43
|
elif not check_if_number(alias):
|
|
59
|
-
tags.append("executedversion:{
|
|
44
|
+
tags.append(f"executedversion:{lambda_context.function_version}")
|
|
60
45
|
# create resource tag with function name and alias/version
|
|
61
|
-
resource = "resource:{}:{}"
|
|
46
|
+
resource = f"resource:{function_name}:{alias}"
|
|
62
47
|
else:
|
|
63
48
|
# Resource is only the function name otherwise
|
|
64
|
-
resource = "resource:{}"
|
|
49
|
+
resource = f"resource:{function_name}"
|
|
65
50
|
|
|
66
51
|
tags.append(resource)
|
|
67
52
|
|
|
68
53
|
return tags
|
|
69
54
|
|
|
70
55
|
|
|
71
|
-
def get_runtime_tag():
|
|
72
|
-
"""Get the runtime tag from the current Python version"""
|
|
73
|
-
major_version, minor_version, _ = python_version_tuple()
|
|
74
|
-
|
|
75
|
-
return "runtime:python{major}.{minor}".format(
|
|
76
|
-
major=major_version, minor=minor_version
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def get_library_version_tag():
|
|
81
|
-
"""Get datadog lambda library tag"""
|
|
82
|
-
return "datadog_lambda:v{}".format(__version__)
|
|
83
|
-
|
|
84
|
-
|
|
85
56
|
def get_enhanced_metrics_tags(lambda_context):
|
|
86
57
|
"""Get the list of tags to apply to enhanced metrics"""
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
58
|
+
tags = []
|
|
59
|
+
if lambda_context:
|
|
60
|
+
tags = parse_lambda_tags_from_arn(lambda_context)
|
|
61
|
+
tags.append(f"memorysize:{lambda_context.memory_limit_in_mb}")
|
|
62
|
+
tags.append(get_cold_start_tag())
|
|
63
|
+
tags.append(runtime_tag)
|
|
64
|
+
tags.append(library_version_tag)
|
|
65
|
+
return tags
|
|
93
66
|
|
|
94
67
|
|
|
95
68
|
def check_if_number(alias):
|