Skip to content

feat(telemetry): check the exact record shape against a golden record - #160

Merged
hln33 merged 1 commit into
mainfrom
feat/telemetry-exact-record-shape
Oct 24, 2026
Merged

hln33 merged 1 commit into
mainfrom
feat/telemetry-exact-record-shape

Conversation

@hln33

@hln33 hln33 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Stack #162: main → this PR → #150. #144 has merged as f04647b. This PR adds one commit on top of main.

Closes #153.

Problem

The validator checked only the keys a requirement listed. So it accepted an extra key at any level, an operations array next to operationsByName, truncation markers, a different key order, count: 1.0 for 1, a result on an operation summary, and timestamps with 0, 3, 6, or 9 fraction digits. Each of these is a difference between SDKs that the suite exists to detect.

Change

entry.record is now the complete expected record.

  • At every mapping level the record must carry exactly the listed keys, in the listed order. An unlisted key is an error. The same keys in a different order is an error.
  • A number matches only a number of the same JSON type. 1.0 does not match 1.
  • The identity fields come from six placeholders bound from the execution ARN: EXECUTION_ARN (bound by core), EXECUTION_NAME, FUNCTION_NAME, FUNCTION_QUALIFIER, REGION, ACCOUNT_ID. A requirement that binds one of these names under Variables fails with a collision error.
  • forbid_fields and operations_by_name are removed. The closed key set covers both. operationsByName sits inside record at its position.

telemetry-1.yaml lists the 16 top-level keys and the 9 operation-summary keys in the order the JS CloudWatch Logs exporter writes them (buildRecord in aws-durable-execution-sdk-js-telemetry-exporter/src/index.ts). Timestamps must have exactly three fraction digits and a Z suffix. Every SDK writes this fixed-width form, so text order equals time order in CloudWatch Logs Insights and DynamoDB.

Why a golden record in YAML, not JSON Schema

JSON Schema cannot express key order. It treats 1.0 and 1 as the same integer. It admits an unlisted key unless additionalProperties: false is written at every level. The existing YAML expectation language already has regex and placeholder rules. So the golden record reuses that language, and the validator gains the closed-mapping and key-order checks.

Expected first result per SDK

A failure on a real difference is the intended result. It is what #153 asks the suite to detect.

Known limitation

Key order is checked inside input and output too. Go's encoding/json sorts map keys. So a Go record with a multi-key payload would fail the order check. telemetry-1 uses single-key payloads, so this has no effect today.

Validation

  • hatch run test:all: 703 passed (telemetry package: 264, up from 199).
  • hatch run types:check, hatch fmt --check, hatch run yaml:lint, hatch run dist:build + dist:check: pass.
  • Cloud e2e, JS in test AWS account, 2026-10-23: telemetry-1 PASSED. 1 record fetched, 0 malformed, 0 errors. The fetched record has the 16 keys in the golden order, an integer durationMs, and three-digit timestamp fractions.
  • Negative check in test AWS account: record replayed through the validator after six single-field mutations (drop operationsByName, add truncated, move recordType last, durationMs: 896.0, six-digit emittedAt fraction, wrong accountId). Each produces exactly one error.

@hln33
hln33 deployed to ai-pr-review-runtime October 23, 2026 20:14 — with GitHub Actions Active
Base automatically changed from feat/telemetry-conformance-suite-42b525b to main October 23, 2026 20:26
@hln33
hln33 force-pushed the feat/telemetry-exact-record-shape branch from ec67e69 to cd4178e Compare October 23, 2026 20:35
@hln33
hln33 added this pull request to stack #162 October 23, 2026 20:40
@hln33
hln33 force-pushed the feat/telemetry-exact-record-shape branch from cd4178e to faa0491 Compare October 23, 2026 21:00
@hln33
hln33 deployed to ai-pr-review-runtime October 23, 2026 21:28 — with GitHub Actions Active
@hln33
hln33 force-pushed the feat/telemetry-exact-record-shape branch from faa0491 to e1c42e9 Compare October 23, 2026 22:03
@hln33
hln33 deployed to ai-pr-review-runtime October 23, 2026 22:18 — with GitHub Actions Active
@github-actions

This comment has been minimized.

@hln33
hln33 marked this pull request as draft October 23, 2026 22:51
@hln33
hln33 force-pushed the feat/telemetry-exact-record-shape branch from e1c42e9 to e0c0ea0 Compare October 23, 2026 23:05
@hln33
hln33 marked this pull request as ready for review October 24, 2026 00:07
@hln33
hln33 deployed to ai-pr-review-runtime October 24, 2026 00:07 — with GitHub Actions Active
The validator checked only the keys a requirement listed. So it accepted an
extra key at any level, an `operations` array next to `operationsByName`,
truncation markers, a different key order, `count: 1.0` for `1`, a `result`
on an operation summary, and timestamps with 0, 3, 6, or 9 fraction digits.
Each of these is a difference between SDKs that the suite exists to detect.

`entry.record` is now the complete expected record. At every mapping level
the record must carry exactly the listed keys, in the listed order. A number
matches only a number of the same JSON type. The identity fields come from
six placeholders bound from the execution ARN: EXECUTION_ARN (bound by
core), EXECUTION_NAME, FUNCTION_NAME, FUNCTION_QUALIFIER, REGION, ACCOUNT_ID.
`forbid_fields` and `operations_by_name` are removed; the closed key set
covers both, and `operationsByName` sits inside `record` at its position.

telemetry-1 lists the 16 top-level keys and 9 summary keys in the order the
JS CloudWatch Logs exporter writes them. Timestamps must have exactly three
fraction digits and a Z suffix, the fixed-width form every SDK writes, so
that text order equals time order in CloudWatch Logs Insights and DynamoDB.

Closes #153
@hln33
hln33 force-pushed the feat/telemetry-exact-record-shape branch from e0c0ea0 to 2795446 Compare October 24, 2026 00:07
@hln33
hln33 deployed to ai-pr-review-runtime October 24, 2026 00:08 — with GitHub Actions Active
@github-actions

Copy link
Copy Markdown
Contributor

Codex AI review

One prior P2 finding remains confirmed (deferred); no additional findings. Tests and cloud validation were not run under the read-only review constraints.

Suppressed repeats

  • arf_v1_b36phov4p2kokt6d5txgoulfjv — deferred (maintainer verdict)

Reviewed commit 279544636ed81a7121040c9aedd7fee76db53529. Workflow run

@ParidelPooya ParidelPooya left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approving. The validator now compares entry.record as a closed mapping at every level, checks key order, compares numbers by JSON type, and pins timestamps to YYYY-MM-DDTHH:MM:SS.sssZ.

I re-ran the mutation probe from the #144 review against this branch and against main. Every case this PR targets is now rejected:

  • extra keys at the top level, in input, and in an operation summary;
  • operations[] next to operationsByName;
  • truncation markers, and a summary result;
  • any key-order change;
  • 1.0 in place of 1;
  • timestamps with 0, 1, 6, or 9 fraction digits.

The golden record matches what the JS exporter writes: buildRecord, then withOperationsByName. Python main passes, in a local run of its real CloudWatchLogsExporter with a fake logs client. Java main fails on one point: OperationSummary.toWireMap() writes the summary keys in a different order from JS. That is a Java SDK bug, which this suite now catches as intended.

Non-blocking

  1. The timestamp pattern accepts a trailing newline and non-ASCII digits. The validator compiles the pattern with default flags and calls search. In Python, $ also matches before a final \n, so 2026-01-01T00:00:01.000Z\n passes. In a Python 3 str pattern, \d matches any Unicode decimal digit, so the same timestamp written in Arabic-Indic digits passes. The README says any other suffix fails, so the README claim is false as written. No SDK writes either form today. The fix is one line in telemetry-1.yaml: use [0-9] for \d and \Z for $. Then add both values to test_telemetry_1_rejects_other_timestamp_formats.

  2. Fields are not checked against each other. The golden record checks each field alone. So these pass: endTime before startTime, emittedAt before startTime, durationMs different from endTime - startTime, minDurationMs greater than maxDurationMs, and a date with month 13. This can hide a real difference between SDKs:

    • JS computes durationMs from the written millisecond timestamps.
    • Python computes it from the untruncated times.
    • With an execution start of 00:00:00.000999, Python main wrote a durationMs 1 ms smaller than the difference of its written timestamps.

    I did not verify whether Lambda delivers start times with sub-millisecond precision. A small post-check in validate_record would cover all five cases.

  3. A duplicated key in the message passes. json.loads keeps the last value at the position of the first key. So {"status":"FAILED", ..., "status":"SUCCEEDED"} validates as SUCCEEDED, with the correct key order. No SDK writes duplicate keys today. Rejecting them takes one object_pairs_hook in parse_record. That event would then count as malformed.

  4. The reserved EXECUTION_ARN placeholder is not protected. The Codex finding on extension.py:126 is correct. Core overwrites EXECUTION_ARN, so Variables: {EXECUTION_ARN: ...} is accepted without an error. The other five names fail with the collision error, as intended. Deferring the fix to #165 is reasonable, because the cause is in core.

  5. The README should state the payload key-order limitation. The PR body says that Go's encoding/json sorts map keys, so a multi-key payload from Go would fail the order check. The README says only that input and output keys are checked in the listed order. A requirement author reads the README, not the PR body. So please copy the limitation into the README "What is asserted" section. Whether user payload key order is part of the contract is a team decision. Today the suite says it is.

  6. The PR body names a stack PR that does not exist. It says "Stack #162: main → this PR → #150". #162 does not exist in this repo. #150 is the PR based on this branch.

Not covered yet

These are outside this PR's scope. I list them so the remaining parity work stays visible.

  • One scenario. Only a successful execution with one step is checked. None of these appear in a checked record:
    • a failure, so the error shape {name, message, cause?} is not checked;
    • retries, waits, and on-change RUNNING records;
    • truncation markers;
    • repeated operation names;
    • opted-in operation results;
    • child contexts and full-tree.
  • One exporter. Only CloudWatchLogsExporter is checked. LambdaLogExporter records arrive inside a log envelope, and the parser drops them.
  • One language with a handler and a cloud run. Only JS has both. The reusable workflow is in #150. Python and Java main have no telemetry conformance handler yet. Go was not checked.

@hln33
hln33 merged commit 0906c78 into main Oct 24, 2026
23 checks passed
@hln33
hln33 deleted the feat/telemetry-exact-record-shape branch October 24, 2026 01:06

This branch was successfully deployed

1 active deployment
ai-pr-review-runtime — 27954463 Deployed Oct 24, 2026 by hln33 via ai-pr-review / Codex review / Generate Codex review #849
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.

[Feature]: Telemetry suite: check the exact record shape

2 participants