Skip to content

Commit ff6b456

Browse files
committed
feat(plugin)!: add execution_start_time to invocation info
1 parent 82985ca commit ff6b456

5 files changed

Lines changed: 18 additions & 27 deletions

File tree

packages/aws-durable-execution-sdk-python-otel/src/aws_durable_execution_sdk_python_otel/plugin.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ def on_invocation_start(self, info: InvocationStartInfo) -> None:
320320
logger.debug("Durable invocation started: %s", info)
321321
self._execution_arn = info.execution_arn or ""
322322
self._extracted_context = self._context_extractor(info)
323-
self._id_generator.set_trace_id(self._execution_arn, info.start_time)
323+
self._id_generator.set_trace_id(self._execution_arn, info.execution_start_time)
324324

325325
self._start_span(
326326
operation_id=None,
@@ -331,16 +331,15 @@ def on_invocation_start(self, info: InvocationStartInfo) -> None:
331331
def on_invocation_end(self, info: InvocationEndInfo) -> None:
332332
"""Called at the end of each invocation. Ends the invocation span and flushes."""
333333
logger.debug("Durable invocation ended: %s", info)
334-
end_time = info.end_time
335334
# end all pending spans
336335
with self._operation_spans_lock:
337336
operation_ids = list(self._operation_spans.keys())
338337
for operation_id in operation_ids:
339338
if operation_id:
340-
self._end_span(operation_id, end_time)
339+
self._end_span(operation_id)
341340

342341
# end the invocation span
343-
self._end_span(None, end_time)
342+
self._end_span(None)
344343

345344
# Clear all per-invocation state to prevent leaks across warm Lambda reuses
346345
self._execution_arn = ""

packages/aws-durable-execution-sdk-python-otel/tests/test_log_filter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def _invocation_start_info() -> InvocationStartInfo:
4949
return InvocationStartInfo(
5050
request_id="request-1",
5151
execution_arn=EXECUTION_ARN,
52-
start_time=START_TIME,
52+
execution_start_time=START_TIME,
5353
is_first_invocation=True,
5454
)
5555

packages/aws-durable-execution-sdk-python-otel/tests/test_plugin.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def _invocation_start_info() -> InvocationStartInfo:
7070
return InvocationStartInfo(
7171
request_id="request-1",
7272
execution_arn=EXECUTION_ARN,
73-
start_time=START_TIME,
73+
execution_start_time=START_TIME,
7474
is_first_invocation=True,
7575
)
7676

@@ -80,10 +80,9 @@ def _invocation_end_info() -> InvocationEndInfo:
8080
return InvocationEndInfo(
8181
request_id="request-1",
8282
execution_arn=EXECUTION_ARN,
83-
start_time=START_TIME,
83+
execution_start_time=START_TIME,
8484
is_first_invocation=True,
8585
status=InvocationStatus.SUCCEEDED,
86-
end_time=END_TIME,
8786
error=None,
8887
)
8988

packages/aws-durable-execution-sdk-python/src/aws_durable_execution_sdk_python/plugin.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ def from_start_info(
161161
class InvocationInfo:
162162
request_id: str | None
163163
execution_arn: str | None
164-
start_time: datetime.datetime | None
165164
is_first_invocation: bool
165+
execution_start_time: datetime.datetime | None = None
166166

167167

168168
@dataclass(frozen=True)
@@ -172,9 +172,8 @@ class InvocationStartInfo(InvocationInfo):
172172

173173
@dataclass(frozen=True)
174174
class InvocationEndInfo(InvocationInfo):
175-
status: InvocationStatus
176-
end_time: datetime.datetime | None
177-
error: ErrorObject | None
175+
status: InvocationStatus | None = None
176+
error: ErrorObject | None = None
178177

179178
@classmethod
180179
def from_durable_execution_invocation_output(
@@ -185,10 +184,9 @@ def from_durable_execution_invocation_output(
185184
return InvocationEndInfo(
186185
request_id=invocation_start_info.request_id,
187186
execution_arn=invocation_start_info.execution_arn,
188-
start_time=invocation_start_info.start_time,
189187
is_first_invocation=invocation_start_info.is_first_invocation,
188+
execution_start_time=invocation_start_info.execution_start_time,
190189
status=output.status,
191-
end_time=datetime.datetime.now(datetime.UTC),
192190
error=output.error,
193191
)
194192

@@ -325,16 +323,11 @@ def on_invocation_start(
325323
lambda_context: LambdaContext | None,
326324
) -> None:
327325
aws_request_id = lambda_context.aws_request_id if lambda_context else None
328-
invocation_start_time = (
329-
datetime.datetime.now(datetime.UTC)
330-
if is_first_invocation
331-
else execution_start_time
332-
)
333326
self._invocation_status = InvocationStartInfo(
334327
execution_arn=execution_arn,
335328
request_id=aws_request_id,
336329
is_first_invocation=is_first_invocation,
337-
start_time=invocation_start_time,
330+
execution_start_time=execution_start_time,
338331
)
339332
self.execute_plugins(self._invocation_status, sync=True)
340333

packages/aws-durable-execution-sdk-python/tests/plugin_test.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,16 @@
6868
INVOCATION_START_INFO = InvocationStartInfo(
6969
request_id="req-1",
7070
execution_arn="arn:aws:lambda:us-east-1:123:durable:abc",
71-
start_time=START_TS,
71+
execution_start_time=START_TS,
7272
is_first_invocation=True,
7373
)
7474
INVOCATION_END_INFO = InvocationEndInfo(
7575
request_id="req-1",
7676
execution_arn="arn:test",
77-
start_time=START_TS,
77+
execution_start_time=START_TS,
7878
status=InvocationStatus.FAILED,
7979
error=ERROR,
8080
is_first_invocation=False,
81-
end_time=END_TS,
8281
)
8382

8483
USER_FUNCTION_START_INFO = UserFunctionStartInfo(
@@ -137,17 +136,16 @@ def test_invocation_start_info(self):
137136
INVOCATION_START_INFO.execution_arn,
138137
"arn:aws:lambda:us-east-1:123:durable:abc",
139138
)
140-
self.assertEqual(INVOCATION_START_INFO.start_time, START_TS)
139+
self.assertEqual(INVOCATION_START_INFO.execution_start_time, START_TS)
141140
self.assertTrue(INVOCATION_START_INFO.is_first_invocation)
142141

143142
def test_invocation_end_info(self):
144143
self.assertEqual(INVOCATION_END_INFO.request_id, "req-1")
145144
self.assertEqual(INVOCATION_END_INFO.execution_arn, "arn:test")
146-
self.assertEqual(INVOCATION_END_INFO.start_time, START_TS)
145+
self.assertEqual(INVOCATION_END_INFO.execution_start_time, START_TS)
147146
self.assertFalse(INVOCATION_END_INFO.is_first_invocation)
148147
self.assertEqual(INVOCATION_END_INFO.status, InvocationStatus.FAILED)
149148
self.assertEqual(INVOCATION_END_INFO.error.message, "boom")
150-
self.assertEqual(INVOCATION_END_INFO.end_time, END_TS)
151149

152150
def test_user_function_start_info(self):
153151
self.assertEqual(USER_FUNCTION_START_INFO.operation_id, "op-1")
@@ -408,7 +406,9 @@ def test_first_invocation_fires_invocation_start(self):
408406
self.assertEqual(
409407
LAMBDA_CTX.aws_request_id, self.executor._invocation_status.request_id
410408
)
411-
self.assertEqual(START_TS, self.executor._invocation_status.start_time)
409+
self.assertEqual(
410+
START_TS, self.executor._invocation_status.execution_start_time
411+
)
412412
self.assertFalse(self.executor._invocation_status.is_first_invocation)
413413

414414
self.assertIsNone(self.executor._invocation_status)

0 commit comments

Comments
 (0)