Skip to content

fix: [SVLS-9168] fix operation_attempt on replay operations#18520

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 5 commits into
mainfrom
yiming.luo/durable-replay-attempt-offbyone
Jun 10, 2026
Merged

fix: [SVLS-9168] fix operation_attempt on replay operations#18520
gh-worker-dd-mergequeue-cf854d[bot] merged 5 commits into
mainfrom
yiming.luo/durable-replay-attempt-offbyone

Conversation

@lym953

@lym953 lym953 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Problem

The value of aws.durable.operation_attempt span attribute is off by 1 for replays.

For example, if an operation fails for the first attempt, succeeds on the first retry, then replays, the three spans should have:

  1. operation_attempt == 0, replayed == false.
  2. operation_attempt == 1, replayed == false.
  3. operation_attempt == 1, replayed == true. The operation_attempt should be the same as the that of the last span because the replay just loads the result from the last successful attempt.

However, right now the last span has operation_attempt == 2.

This PR

If the operation is succeeded, i.e. it's a replay, then subtract operation_attempt by 1.

Testing

image

The result is correct from the UI. See the "replay" and "attempt" value for the order_process_payment operations.

… replay

The aws.durable.operation_attempt metric was off by one for replayed
operations. _traced_process reads step_details.attempt at two different
points in the checkpoint lifecycle:

- pending/retry checkpoint (fresh execution): the value is the count of
  prior failed attempts, which already equals the 0-indexed index of the
  attempt about to run.
- succeeded checkpoint (read on a replay): the value is the 1-indexed
  number of the attempt that ultimately succeeded (1 for a first-try
  success).

This made the same operation report attempt=0 on its fresh execution but
attempt=1 on a later replay. Normalize the succeeded read by subtracting
1 so both agree on the documented 0-indexed convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@lym953 lym953 added the changelog/no-changelog A changelog entry is not required for this PR. label Jun 8, 2026
@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Pipelines  Tests

Fix all issues with BitsAI

⚠️ Warnings

🚦 9 Pipeline jobs failed

Changelog | Validate changelog   View in Datadog   GitHub Actions

DataDog/apm-reliability/dd-trace-py | build linux serverless: [amd64, cp315-cp315, v113741238-d2b8243-manylinux2014_x86_64, 1]   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-py | build linux serverless: [amd64, cp315-cp315, v113741491-d2b8243-musllinux_1_2_x86_64, 1]   View in Datadog   GitLab

View all 9 failed jobs.

ℹ️ Info

No other issues found (see more)

🧪 All tests passed
❄️ No new flaky tests detected

🔄 Datadog auto-retried 1 job - 1 passed on retry View in Datadog

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 8562a6e | Docs | Datadog PR Page | Give us feedback!

@cit-pr-commenter-54b7da

cit-pr-commenter-54b7da Bot commented Jun 8, 2026

Copy link
Copy Markdown

Codeowners resolved as

ddtrace/contrib/internal/aws_durable_execution_sdk_python/patch.py      @DataDog/apm-core-python @DataDog/apm-idm-python
releasenotes/notes/aws-durable-operation-attempt-replay-ebfaf94dd19318de.yaml  @DataDog/apm-python
tests/contrib/aws_durable_execution_sdk_python/test_aws_durable_execution_sdk_python.py  @DataDog/apm-core-python @DataDog/apm-idm-python

On a succeeded checkpoint the stored attempt is the 1-indexed number of
the attempt that succeeded, which is always >= 1, so attempt - 1 is
always >= 0 and the max(0, ...) floor can never fire. Removing it keeps
the normalization honest and avoids silently masking a future invariant
break.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@lym953 lym953 changed the title fix(aws_durable_execution_sdk_python): normalize operation_attempt on replay [SVLS-9168] fix: fix operation_attempt on replay operations Jun 8, 2026
step_details.attempt is server-maintained; the SDK only reads it. Note
that the succeeded-checkpoint 1-indexing is observed behavior pinned by
the unit test, not an SDK guarantee. Also condense the comment.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@lym953
lym953 requested review from a team and joeyzhao2018 June 8, 2026 19:42
@lym953 lym953 changed the title [SVLS-9168] fix: fix operation_attempt on replay operations fix: [SVLS-9168] fix operation_attempt on replay operations Jun 8, 2026
@lym953
lym953 marked this pull request as ready for review June 8, 2026 19:43
@lym953
lym953 requested review from a team as code owners June 8, 2026 19:43
@lym953
lym953 requested review from juanjux and quinna-h June 8, 2026 19:43

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: db0c145006

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread ddtrace/contrib/internal/aws_durable_execution_sdk_python/patch.py Outdated

@emmettbutler emmettbutler left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change looks reasonable enough. Please add a release note.

Comment thread ddtrace/contrib/internal/aws_durable_execution_sdk_python/patch.py Outdated
lym953 and others added 2 commits June 9, 2026 18:41
…t attempt=0 on replay

Defensively clamp the replayed operation_attempt so a succeeded checkpoint
whose StepDetails lacks "Attempt" (StepDetails.from_dict defaults it to 0)
cannot emit a nonsensical operation_attempt = -1. We have not observed
attempt == 0 on success; every SDK success path increments via
OperationAction.SUCCEED or the wait_for_condition +1.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…n_attempt replay fix

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@lym953
lym953 requested a review from a team as a code owner June 9, 2026 22:45
@lym953 lym953 removed the changelog/no-changelog A changelog entry is not required for this PR. label Jun 9, 2026
@lym953

lym953 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Added a release note

@lym953
lym953 requested a review from emmettbutler June 9, 2026 22:48
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot merged commit 25fb0fd into main Jun 10, 2026
501 of 505 checks passed
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot deleted the yiming.luo/durable-replay-attempt-offbyone branch June 10, 2026 17:04
vlad-scherbich pushed a commit that referenced this pull request Jun 10, 2026
# Problem
The value of `aws.durable.operation_attempt` span attribute is off by 1 for replays.

For example, if an operation fails for the first attempt, succeeds on the first retry, then replays, the three spans should have:
1. operation_attempt == 0, replayed == false.
2. operation_attempt == 1, replayed == false.
3. operation_attempt == 1, replayed == true. The operation_attempt should be the same as the that of the last span because the replay just loads the result from the last successful attempt.

However, right now the last span has `operation_attempt == 2`.

# This PR
If the operation is succeeded, i.e. it's a replay, then subtract operation_attempt by 1.

# Testing
<img width="712" height="523" alt="image" src="https://github.com/user-attachments/assets/401f72a1-527f-4672-8189-db590eff5cf4" />

The result is correct from the UI. See the "replay" and "attempt" value for the `order_process_payment` operations.

Co-authored-by: yiming.luo <[email protected]>
brettlangdon pushed a commit that referenced this pull request Jun 11, 2026
# Problem
The value of `aws.durable.operation_attempt` span attribute is off by 1 for replays.

For example, if an operation fails for the first attempt, succeeds on the first retry, then replays, the three spans should have:
1. operation_attempt == 0, replayed == false.
2. operation_attempt == 1, replayed == false.
3. operation_attempt == 1, replayed == true. The operation_attempt should be the same as the that of the last span because the replay just loads the result from the last successful attempt.

However, right now the last span has `operation_attempt == 2`.

# This PR
If the operation is succeeded, i.e. it's a replay, then subtract operation_attempt by 1.

# Testing
<img width="712" height="523" alt="image" src="https://github.com/user-attachments/assets/401f72a1-527f-4672-8189-db590eff5cf4" />

The result is correct from the UI. See the "replay" and "attempt" value for the `order_process_payment` operations.

Co-authored-by: yiming.luo <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants