Skip to content

Commit 24ca337

Browse files
Ayushi AhjoliazhongkechenAlex Wang
authored
feat(plugin): Add result accessor to OperationEndInfo (#596)
* feat(plugin): Add result accessor to OperationEndInfo * fix(plugin): guard result on success, keep it out of toString, keep the old arity Review feedback on the result accessor: - Only a SUCCEEDED operation reports a result. A wait-for-condition is checkpointed as STEP and reuses stepDetails().result() to carry its intermediate check-loop state between attempts, so a failed one could surface that state as its result, contradicting the documented null-on-failure contract. Verified: without the guard the new test reports {"polls":2} for a FAILED operation. - Override toString() to omit result. Records render every component, so plugins that log the info object whole would have begun emitting customer payloads (possibly secrets or personal data). Output is otherwise unchanged; matches the invocation records from #622. - Add a constructor at the previous 11-argument arity delegating with a null result, so existing callers keep compiling and linking. - Cover the CHAINED_INVOKE, CALLBACK, and CONTEXT extraction branches, which had no direct test. --------- Co-authored-by: Frank Chen <65260095+zhongkechen@users.noreply.github.com> Co-authored-by: Alex Wang <wangyb@amazon.com>
1 parent cfeaabd commit 24ca337

7 files changed

Lines changed: 588 additions & 33 deletions

File tree

‎otel-plugin/src/test/java/software/amazon/lambda/durable/otel/ExecutionOtelPluginTest.java‎

Lines changed: 126 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,18 @@ void defaultConstructor_usesGlobalSdkTracerProviderDirectly() {
149149
defaultPlugin.onOperationStart(
150150
new OperationInfo("op-1", "step", "STEP", "Step", null, Instant.now(), null, null, false));
151151
defaultPlugin.onOperationEnd(new OperationEndInfo(
152-
"op-1", "step", "STEP", "Step", null, Instant.now(), Instant.now(), "SUCCEEDED", null, false, null));
152+
"op-1",
153+
"step",
154+
"STEP",
155+
"Step",
156+
null,
157+
Instant.now(),
158+
Instant.now(),
159+
"SUCCEEDED",
160+
null,
161+
false,
162+
null,
163+
null));
153164
defaultPlugin.onInvocationEnd(
154165
new InvocationEndInfo("req-1", "arn:exec1", true, InvocationStatus.SUCCEEDED, null));
155166

@@ -330,7 +341,18 @@ void operationSpan_carriesAttemptNumberAtEnd() {
330341
plugin.onOperationStart(
331342
new OperationInfo("op-1", "flaky", "STEP", "Step", null, Instant.now(), null, null, false));
332343
plugin.onOperationEnd(new OperationEndInfo(
333-
"op-1", "flaky", "STEP", "Step", null, Instant.now(), Instant.now(), "SUCCEEDED", 3, false, null));
344+
"op-1",
345+
"flaky",
346+
"STEP",
347+
"Step",
348+
null,
349+
Instant.now(),
350+
Instant.now(),
351+
"SUCCEEDED",
352+
3,
353+
false,
354+
null,
355+
null));
334356
plugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.SUCCEEDED, null));
335357

336358
var operationSpan = spanByName(spanExporter.getFinishedSpanItems(), "flaky");
@@ -347,7 +369,18 @@ void continuationOperationSpan_carriesAttemptNumber() {
347369
plugin.onInvocationStart(new InvocationInfo("req-2", ARN, false, Instant.now()));
348370
// No matching onOperationStart in this invocation — continuation branch.
349371
plugin.onOperationEnd(new OperationEndInfo(
350-
"op-1", "flaky", "STEP", "Step", null, Instant.now(), Instant.now(), "SUCCEEDED", 2, false, null));
372+
"op-1",
373+
"flaky",
374+
"STEP",
375+
"Step",
376+
null,
377+
Instant.now(),
378+
Instant.now(),
379+
"SUCCEEDED",
380+
2,
381+
false,
382+
null,
383+
null));
351384
plugin.onInvocationEnd(new InvocationEndInfo("req-2", ARN, false, InvocationStatus.SUCCEEDED, null));
352385

353386
var operationSpan = spanByName(spanExporter.getFinishedSpanItems(), "flaky");
@@ -366,7 +399,7 @@ void operationSpan_startsAtOperationStartTimestamp() {
366399
plugin.onInvocationStart(new InvocationInfo("req-1", ARN, true, Instant.now()));
367400
plugin.onOperationStart(new OperationInfo("op-1", "step-a", "STEP", "Step", null, opStart, null, null, false));
368401
plugin.onOperationEnd(new OperationEndInfo(
369-
"op-1", "step-a", "STEP", "Step", null, opStart, opEnd, "SUCCEEDED", null, false, null));
402+
"op-1", "step-a", "STEP", "Step", null, opStart, opEnd, "SUCCEEDED", null, false, null, null));
370403
plugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.SUCCEEDED, null));
371404

372405
var operationSpan = spanByName(spanExporter.getFinishedSpanItems(), "step-a");
@@ -382,7 +415,18 @@ void operationSpan_parentedToWorkflow_linkedToInvocation() {
382415
plugin.onOperationStart(
383416
new OperationInfo("op-1", "step-a", "STEP", "Step", null, Instant.now(), null, null, false));
384417
plugin.onOperationEnd(new OperationEndInfo(
385-
"op-1", "step-a", "STEP", "Step", null, Instant.now(), Instant.now(), "SUCCEEDED", null, false, null));
418+
"op-1",
419+
"step-a",
420+
"STEP",
421+
"Step",
422+
null,
423+
Instant.now(),
424+
Instant.now(),
425+
"SUCCEEDED",
426+
null,
427+
false,
428+
null,
429+
null));
386430
plugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.SUCCEEDED, null));
387431

388432
var spans = spanExporter.getFinishedSpanItems();
@@ -410,7 +454,18 @@ void attemptSpan_childOfOperation_linkedToInvocation() {
410454
plugin.onUserFunctionEnd(new UserFunctionEndInfo(
411455
"op-1", "compute", "STEP", "Step", null, Instant.now(), Instant.now(), false, 1, true, null));
412456
plugin.onOperationEnd(new OperationEndInfo(
413-
"op-1", "compute", "STEP", "Step", null, Instant.now(), Instant.now(), "SUCCEEDED", null, false, null));
457+
"op-1",
458+
"compute",
459+
"STEP",
460+
"Step",
461+
null,
462+
Instant.now(),
463+
Instant.now(),
464+
"SUCCEEDED",
465+
null,
466+
false,
467+
null,
468+
null));
414469
plugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.SUCCEEDED, null));
415470

416471
var spans = spanExporter.getFinishedSpanItems();
@@ -469,6 +524,7 @@ void childOperation_parentedToParentOperationSpan() {
469524
"SUCCEEDED",
470525
null,
471526
false,
527+
null,
472528
null));
473529
plugin.onOperationEnd(new OperationEndInfo(
474530
"op-parent",
@@ -481,6 +537,7 @@ void childOperation_parentedToParentOperationSpan() {
481537
"SUCCEEDED",
482538
null,
483539
false,
540+
null,
484541
null));
485542
plugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.SUCCEEDED, null));
486543

@@ -543,7 +600,18 @@ void operationSuccess_setsOkOnOperationSpan() {
543600
plugin.onOperationStart(
544601
new OperationInfo("op-1", "step-ok", "STEP", "Step", null, Instant.now(), null, null, false));
545602
plugin.onOperationEnd(new OperationEndInfo(
546-
"op-1", "step-ok", "STEP", "Step", null, Instant.now(), Instant.now(), "SUCCEEDED", null, false, null));
603+
"op-1",
604+
"step-ok",
605+
"STEP",
606+
"Step",
607+
null,
608+
Instant.now(),
609+
Instant.now(),
610+
"SUCCEEDED",
611+
null,
612+
false,
613+
null,
614+
null));
547615
plugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.SUCCEEDED, null));
548616

549617
var operationSpan = spanByName(spanExporter.getFinishedSpanItems(), "step-ok");
@@ -569,6 +637,7 @@ void operationEnd_withNonSuccessStatusAndNoError_leavesOperationSpanUnset() {
569637
"CANCELLED",
570638
null,
571639
false,
640+
null,
572641
null));
573642
plugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.SUCCEEDED, null));
574643

@@ -592,6 +661,7 @@ void operationEnd_withoutStart_nonSuccessStatusAndNoError_leavesContinuationSpan
592661
"TIMED_OUT",
593662
null,
594663
false,
664+
null,
595665
null));
596666
plugin.onInvocationEnd(new InvocationEndInfo("req-2", ARN, false, InvocationStatus.SUCCEEDED, null));
597667

@@ -607,7 +677,18 @@ void operationEnd_withNullStatusAndNoError_setsOkOnOperationSpan() {
607677
plugin.onOperationStart(
608678
new OperationInfo("op-ctx", "my-ctx", "CONTEXT", null, null, Instant.now(), null, null, false));
609679
plugin.onOperationEnd(new OperationEndInfo(
610-
"op-ctx", "my-ctx", "CONTEXT", null, null, Instant.now(), Instant.now(), null, null, false, null));
680+
"op-ctx",
681+
"my-ctx",
682+
"CONTEXT",
683+
null,
684+
null,
685+
Instant.now(),
686+
Instant.now(),
687+
null,
688+
null,
689+
false,
690+
null,
691+
null));
611692
plugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.SUCCEEDED, null));
612693

613694
var operationSpan = spanByName(spanExporter.getFinishedSpanItems(), "my-ctx");
@@ -647,7 +728,18 @@ void operationOpenedThenCompletedNextInvocation_exportedOnceOnOperationEnd() {
647728
// Invocation 2: the operation completes → materialized once via onOperationEnd, linked to this invocation.
648729
plugin.onInvocationStart(new InvocationInfo("req-2", ARN, false, Instant.now()));
649730
plugin.onOperationEnd(new OperationEndInfo(
650-
"op-1", "my-wait", "WAIT", "Wait", null, Instant.now(), Instant.now(), "SUCCEEDED", null, false, null));
731+
"op-1",
732+
"my-wait",
733+
"WAIT",
734+
"Wait",
735+
null,
736+
Instant.now(),
737+
Instant.now(),
738+
"SUCCEEDED",
739+
null,
740+
false,
741+
null,
742+
null));
651743
plugin.onInvocationEnd(new InvocationEndInfo("req-2", ARN, false, InvocationStatus.SUCCEEDED, null));
652744

653745
var spans = spanExporter.getFinishedSpanItems();
@@ -669,7 +761,18 @@ void allSpansShareTraceId_acrossInvocations() {
669761
plugin.onOperationStart(
670762
new OperationInfo("op-1", "step-1", "STEP", "Step", null, Instant.now(), null, null, false));
671763
plugin.onOperationEnd(new OperationEndInfo(
672-
"op-1", "step-1", "STEP", "Step", null, Instant.now(), Instant.now(), "SUCCEEDED", null, false, null));
764+
"op-1",
765+
"step-1",
766+
"STEP",
767+
"Step",
768+
null,
769+
Instant.now(),
770+
Instant.now(),
771+
"SUCCEEDED",
772+
null,
773+
false,
774+
null,
775+
null));
673776
plugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.PENDING, null));
674777
var firstTraceId = spanExporter.getFinishedSpanItems().get(0).getTraceId();
675778
spanExporter.reset();
@@ -698,6 +801,7 @@ void operationEnd_withoutStart_createsContinuationSpanWithLink() {
698801
"SUCCEEDED",
699802
null,
700803
false,
804+
null,
701805
null));
702806
plugin.onInvocationEnd(new InvocationEndInfo("req-2", ARN, false, InvocationStatus.SUCCEEDED, null));
703807

@@ -775,7 +879,18 @@ void xrayExtraction_allSpansShareExtractedTraceId() {
775879
xrayPlugin.onOperationStart(
776880
new OperationInfo("op-1", "step-a", "STEP", "Step", null, Instant.now(), null, null, false));
777881
xrayPlugin.onOperationEnd(new OperationEndInfo(
778-
"op-1", "step-a", "STEP", "Step", null, Instant.now(), Instant.now(), "SUCCEEDED", null, false, null));
882+
"op-1",
883+
"step-a",
884+
"STEP",
885+
"Step",
886+
null,
887+
Instant.now(),
888+
Instant.now(),
889+
"SUCCEEDED",
890+
null,
891+
false,
892+
null,
893+
null));
779894
xrayPlugin.onInvocationEnd(new InvocationEndInfo("req-1", ARN, true, InvocationStatus.SUCCEEDED, null));
780895

781896
var spans = exporter.getFinishedSpanItems();

0 commit comments

Comments
 (0)