Skip to content

Commit ae4505f

Browse files
jchrostek-ddclaude
andcommitted
feat: add durable_function_execution_status tag to aws.lambda span
When using AWS Lambda Durable Execution SDK, extract the execution status from the handler response and add it as a tag to the aws.lambda span. The tag captures the Status field from durable function responses: - SUCCEEDED: Execution completed successfully - FAILED: Execution failed - PENDING: Execution is still in progress The tag is only added when: 1. The event contains a DurableExecutionArn (indicates durable invocation) 2. The response is a dict with a valid Status field 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0f4c059 commit ae4505f

File tree

3 files changed

+101
-1
lines changed

3 files changed

+101
-1
lines changed

datadog_lambda/durable.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,30 @@ def extract_durable_function_tags(event):
4747
"durable_function_execution_name": execution_name,
4848
"durable_function_execution_id": execution_id,
4949
}
50+
51+
52+
VALID_DURABLE_STATUSES = {"SUCCEEDED", "FAILED", "PENDING"}
53+
54+
55+
def extract_durable_function_status_tag(response, event):
56+
"""
57+
Extract durable function execution status from handler response.
58+
59+
Returns a dict with the status tag if:
60+
- The event indicates a durable function invocation (has DurableExecutionArn)
61+
- The response is a dict with a valid Status field
62+
63+
Returns empty dict otherwise.
64+
"""
65+
# Only add status tag for durable function invocations
66+
if not isinstance(event, dict) or "DurableExecutionArn" not in event:
67+
return {}
68+
69+
if not isinstance(response, dict):
70+
return {}
71+
72+
status = response.get("Status")
73+
if status not in VALID_DURABLE_STATUSES:
74+
return {}
75+
76+
return {"durable_function_execution_status": status}

datadog_lambda/wrapper.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@
4242
tracer,
4343
propagator,
4444
)
45-
from datadog_lambda.durable import extract_durable_function_tags
45+
from datadog_lambda.durable import (
46+
extract_durable_function_tags,
47+
extract_durable_function_status_tag,
48+
)
4649
from datadog_lambda.trigger import (
4750
extract_trigger_tags,
4851
extract_http_status_code_tag,
@@ -340,6 +343,13 @@ def _after(self, event, context):
340343
if status_code:
341344
self.span.set_tag("http.status_code", status_code)
342345

346+
# Extract and set durable function execution status
347+
durable_status_tags = extract_durable_function_status_tag(
348+
self.response, event
349+
)
350+
for tag_name, tag_value in durable_status_tags.items():
351+
self.span.set_tag(tag_name, tag_value)
352+
343353
self.span.finish()
344354

345355
if status_code:

tests/test_durable.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from datadog_lambda.durable import (
88
_parse_durable_execution_arn,
99
extract_durable_function_tags,
10+
extract_durable_function_status_tag,
1011
)
1112

1213

@@ -89,3 +90,65 @@ def test_returns_empty_dict_when_durable_execution_arn_cannot_be_parsed(self):
8990
def test_returns_empty_dict_when_event_is_empty(self):
9091
result = extract_durable_function_tags({})
9192
self.assertEqual(result, {})
93+
94+
95+
class TestExtractDurableFunctionStatusTag(unittest.TestCase):
96+
def test_succeeded_status(self):
97+
event = {"DurableExecutionArn": "arn:aws:states:us-east-1:123456789012:..."}
98+
response = {"Status": "SUCCEEDED", "Result": "some-result"}
99+
result = extract_durable_function_status_tag(response, event)
100+
self.assertEqual(result, {"durable_function_execution_status": "SUCCEEDED"})
101+
102+
def test_failed_status(self):
103+
event = {"DurableExecutionArn": "arn:aws:states:us-east-1:123456789012:..."}
104+
response = {"Status": "FAILED", "Error": "some-error"}
105+
result = extract_durable_function_status_tag(response, event)
106+
self.assertEqual(result, {"durable_function_execution_status": "FAILED"})
107+
108+
def test_pending_status(self):
109+
event = {"DurableExecutionArn": "arn:aws:states:us-east-1:123456789012:..."}
110+
response = {"Status": "PENDING"}
111+
result = extract_durable_function_status_tag(response, event)
112+
self.assertEqual(result, {"durable_function_execution_status": "PENDING"})
113+
114+
def test_non_durable_event_returns_empty(self):
115+
event = {"key": "value"} # No DurableExecutionArn
116+
response = {"Status": "SUCCEEDED"}
117+
result = extract_durable_function_status_tag(response, event)
118+
self.assertEqual(result, {})
119+
120+
def test_non_dict_response_returns_empty(self):
121+
event = {"DurableExecutionArn": "arn:aws:states:us-east-1:123456789012:..."}
122+
response = "string response"
123+
result = extract_durable_function_status_tag(response, event)
124+
self.assertEqual(result, {})
125+
126+
def test_missing_status_returns_empty(self):
127+
event = {"DurableExecutionArn": "arn:aws:states:us-east-1:123456789012:..."}
128+
response = {"Result": "some-result"} # No Status field
129+
result = extract_durable_function_status_tag(response, event)
130+
self.assertEqual(result, {})
131+
132+
def test_invalid_status_returns_empty(self):
133+
event = {"DurableExecutionArn": "arn:aws:states:us-east-1:123456789012:..."}
134+
response = {"Status": "INVALID"}
135+
result = extract_durable_function_status_tag(response, event)
136+
self.assertEqual(result, {})
137+
138+
def test_non_dict_event_returns_empty(self):
139+
event = "not-a-dict"
140+
response = {"Status": "SUCCEEDED"}
141+
result = extract_durable_function_status_tag(response, event)
142+
self.assertEqual(result, {})
143+
144+
def test_none_event_returns_empty(self):
145+
event = None
146+
response = {"Status": "SUCCEEDED"}
147+
result = extract_durable_function_status_tag(response, event)
148+
self.assertEqual(result, {})
149+
150+
def test_none_response_returns_empty(self):
151+
event = {"DurableExecutionArn": "arn:aws:states:us-east-1:123456789012:..."}
152+
response = None
153+
result = extract_durable_function_status_tag(response, event)
154+
self.assertEqual(result, {})

0 commit comments

Comments
 (0)