Skip to content

feat: add Workflow Insight plugin - #661

Draft
wangyb-A wants to merge 4 commits into
mainfrom
workflow-insight-plugin
Draft

feat: add Workflow Insight plugin#661
wangyb-A wants to merge 4 commits into
mainfrom
workflow-insight-plugin

Conversation

@wangyb-A

Copy link
Copy Markdown
Contributor

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Issue Link, if available

N/A. Workflow Insight conformance requirements are being reviewed in aws/aws-durable-execution-conformance-tests#73.

Description

Adds the preview Workflow Insight plugin as a new insight-plugin Maven module.

The plugin emits schema-versioned execution records from the existing Java plugin hooks and matches the JavaScript Workflow Insight contract. It includes:

  • deterministic per-execution sampling and on-complete, on-failure, and on-change emission modes
  • execution input/output transforms, operation filtering, error controls, and result opt-in transforms
  • top-level and full-tree operation detail
  • operations-array and operationsByName record shapes
  • per-exporter record-size truncation
  • Lambda log, Amazon S3, and CloudWatch Logs exporters
  • exporter failure isolation and flushing

The implementation uses the invocation operation snapshots, execution payloads, errors, attempts, and serialized operation results already exposed by the Java plugin API. No core hook changes are required.

Demo/Screenshots

No UI change. insight-plugin/README.md contains a usage example. The draft conformance PR linked above contains Java handlers for all 18 Workflow Insight requirements.

Checklist

  • I have filled out every section of the PR template
  • I have thoroughly tested this change

Testing

Unit Tests

Yes. The module adds 35 tests covering record construction, sampling, emission modes, replay/suspension state, operation filtering, result transforms, aggregation, truncation, exporter requests, failure isolation, and flush behavior.

mvn -q -pl insight-plugin -am test
mvn -q -pl insight-plugin -am clean verify

Both pass.

The full repository reactor also passes:

mvn -q clean verify

Integration Tests

Yes. WorkflowInsightPluginTest exercises the plugin through LocalDurableTestRunner.

The draft Workflow Insight conformance suite was also run against deployed Java 21 Lambda functions in us-west-2:

  • S3 operations-array leg: 18 passed, 0 failed
  • CloudWatch operationsByName leg: 18 passed, 0 failed

Sink-specific assertions were capability-gated and exercised by the complementary leg.

Examples

The module README includes configuration and exporter usage. Customer-facing conformance handlers are in aws/aws-durable-execution-conformance-tests#73 rather than this repository, following the repository's conformance-test ownership rule.

@wangyb-A
wangyb-A force-pushed the workflow-insight-plugin branch from 5d83fc9 to 9cb8201 Compare August 28, 2026 18:06
@wangyb-A
wangyb-A marked this pull request as ready for review August 28, 2026 18:38
@wangyb-A
wangyb-A requested a review from a team August 28, 2026 18:38
@wangyb-A
wangyb-A deployed to ai-pr-review-runtime August 28, 2026 18:38 — with GitHub Actions Active
@wangyb-A
wangyb-A had a problem deploying to ai-pr-review-runtime August 28, 2026 18:40 — with GitHub Actions Failure
@wangyb-A
wangyb-A deployed to ai-pr-review-runtime August 28, 2026 18:40 — with GitHub Actions Active
Comment thread pom.xml
<module>sdk-testing</module>
<module>sdk-integration-tests</module>
<module>otel-plugin</module>
<module>insight-plugin</module>

This comment was marked as outdated.

*/
@Deprecated
public final class Json {
static final ObjectMapper MAPPER = new ObjectMapper();

This comment was marked as outdated.

Comment on lines +181 to +182
exporter.export(shaped);
exporter.flush();

This comment was marked as outdated.

if (operations == null) {
return out;
}
for (OperationChangeItemInfo item : operations.values()) {

This comment was marked as outdated.

Comment on lines +328 to +329
private static ErrorInfo toErrorInfo(Throwable t) {
return new ErrorInfo(t.getClass().getSimpleName(), t.getMessage());

This comment was marked as outdated.

Comment on lines +315 to +316
if (!include || value == null) {
return null;

This comment was marked as outdated.

Comment on lines +43 to +44
public List<OperationRecord> operations() {
return operations;

This comment was marked as outdated.

return false;
}
long unsigned = fnv1a32(executionArn) & 0xffffffffL;
return (double) unsigned / 0xffffffffL < rate;

This comment was marked as outdated.

@github-actions

This comment has been minimized.

@zhongkechen

Copy link
Copy Markdown
Contributor

Use /ai review command to trigger AI review workflows for draft PRs

@wangyb-A
wangyb-A marked this pull request as draft August 28, 2026 19:22
@wangyb-A
wangyb-A force-pushed the workflow-insight-plugin branch from d90f91f to bdbd88f Compare August 28, 2026 21:00
@wangyb-A

Copy link
Copy Markdown
Contributor Author

/ai review

if (state == null || !state.sampledIn) {
return;
}
emit(buildRecord(

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.

Codex AI review · Finding arf_v1_xryomwjxrzqt3z55wozggpsrsl

[P2] Keep ON_CHANGE exports off checkpoint processing

onOperationChange runs synchronously while checkpoint coordination is still active. This call performs S3/CloudWatch I/O and flush() inline for every change, so a slow exporter stalls subsequent checkpoints and can cause invocation timeouts. Queue immutable snapshots here and drain/flush them asynchronously, awaiting completion from onInvocationEnd; add a delayed-exporter test proving this hook returns promptly.

if (!state.sampledIn) {
return;
}
state.cachedInput = info.executionInput();

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.

Codex AI review · Finding arf_v1_cyyzil3ide53kqls24cwcz3cts

[P2] Snapshot execution input before user code can mutate it

executionInput() is the same mutable object passed to the handler. Caching its reference lets handler mutations rewrite later insight records; in ON_CHANGE mode, a mutating input transform can even alter the object before the handler runs. Create and cache a detached snapshot before applying transforms, use it for every emission including invocation end, and test both handler and transform mutations.

Comment on lines +173 to +174
if (isTerminal) {
byArn.remove(info.durableExecutionArn());

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.

Codex AI review · Finding arf_v1_qh6xoafzze3z3ccgrbppucmunr

[P2] Do not retain suspended executions indefinitely

A PENDING/RETRYING execution may resume in another Lambda environment, so this warm container may never observe its terminal event and byArn grows without bound—even when sampling is disabled. Each new invocation already supplies the stable execution start time and input. Remove state on every invocation end and recreate it at the next start, or use a bounded expiry strategy; test a paired suspend/resume lifecycle.

* is applied (omit on throw so a failing redactor never leaks the raw value); otherwise include as-is.
*/
static Object applyDataContent(Object value, boolean include, Function<Object, Object> transform) {
if (!include || value == null) {

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.

Codex AI review · Finding arf_v1_oirdg3rnpdnwvpldafyiqrnncz

[P2] Preserve included JSON null values

This conflates an enabled value that is actually null with content disabled by configuration. A successful handler returning null therefore emits no output field despite output inclusion defaulting to true. Track field presence separately or use an explicit JSON-null sentinel, omitting only unavailable/disabled content; add null input/output tests.

// own class/message would lose the original checkpointed failure identity. When the checkpointed ErrorObject is
// present, derive name/message from its errorType/errorMessage, falling back to the throwable's own fields for
// any value the ErrorObject leaves null.
if (t instanceof DurableOperationException doe && doe.getErrorObject() != null) {

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.

Codex AI review · Finding arf_v1_hp5bcyxuzbh2vgqafztcdoghc5

[P2] Unwrap unrecoverable execution errors too

DurableExecutor also supplies UnrecoverableDurableExecutionException for nondeterminism, illegal operations, and durable API failures. This branch only unwraps DurableOperationException, so those records lose ErrorObject.errorType—including service error codes—and report the generic wrapper class. Extract the ErrorObject from both wrapper types through a shared helper and add terminal and retrying error tests.

Comment thread pom.xml
<module>sdk-testing</module>
<module>sdk-integration-tests</module>
<module>otel-plugin</module>
<module>insight-plugin</module>

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.

Codex AI review · Finding arf_v1_luk5otghmahig7iqbjsa7g67gu

[P2] Trigger the build for insight-plugin-only changes

The main build workflow's path filters do not include insight-plugin/**. This PR runs because it also changes the root POM, but subsequent changes confined to the module will skip the multi-JDK Maven build and its tests. Add insight-plugin/** to both the pull-request and push filters in .github/workflows/build.yml.

static Object deepCopyContent(Object value) {
if (value == null
|| value instanceof String
|| value instanceof Number

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.

Codex AI review · Finding arf_v1_rzwdoyquezpr2qgby63imtmxcn

[P3] Do not treat every Number as immutable

Number includes mutable types such as AtomicInteger, AtomicLong, and custom implementations. Returning them unchanged means a first exporter can mutate a payload value that later exporters still share, defeating the isolation guarantee. Share only known immutable numeric classes or convert arbitrary numbers into detached JSON scalars; add an AtomicInteger isolation test.

return false;
}
long unsigned = fnv1a32(executionArn) & 0xffffffffL;
return (double) unsigned / 0xffffffffL < rate;

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.

Codex AI review · Finding arf_v1_47kz274xvx4sow4mmbm7gzor7a

[P3] Normalize sampling into the documented half-open interval

Dividing by the maximum unsigned 32-bit value maps 0xffffffff to exactly 1.0, producing [0,1] rather than [0,1) and shifting deterministic sampling boundaries. Coordinate the denominator with the other SDKs, divide by 2^32, and add fixed-vector compatibility tests.

Suggested change
return (double) unsigned / 0xffffffffL < rate;
return (double) unsigned / 0x1_0000_0000L < rate;

@github-actions

Copy link
Copy Markdown
Contributor

Codex AI review

Found eight actionable issues affecting checkpoint latency, input isolation, lifecycle cleanup, record fidelity, CI coverage, exporter isolation, and sampling. Tests were not run per review constraints.

Reviewed commit bdbd88fcdf777f50567d968c0e73fa11c8eb39ad. Workflow run

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