Skip to content

Commit 559d9cb

Browse files
Add lastFailureDetails and lastFailureReason to pending event summary (cadence-workflow#1033)
* Show lastFailureDetails and lastFailureReason on pending event summary, for a pending event that's retrying * Render them as negative fields * Parse lastFailureDetails as JSON * Fix the unit tests to use exact event metadata index instead of trying to find event metadata based on the label
1 parent c0e0564 commit 559d9cb

File tree

4 files changed

+70
-52
lines changed

4 files changed

+70
-52
lines changed

src/views/workflow-history/config/workflow-history-event-details.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const workflowHistoryEventDetailsConfig = [
5353
{
5454
name: 'Json as PrettyJson',
5555
pathRegex:
56-
'(input|result|details|failureDetails|Error|lastCompletionResult|heartbeatDetails)$',
56+
'(input|result|details|failureDetails|Error|lastCompletionResult|heartbeatDetails|lastFailureDetails)$',
5757
valueComponent: WorkflowHistoryEventDetailsJson,
5858
forceWrap: true,
5959
},

src/views/workflow-history/config/workflow-history-event-summary-field-parsers.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const workflowHistoryEventSummaryFieldParsersConfig: Array<WorkflowHistoryEventS
1515
matcher: (name, value) =>
1616
value !== null &&
1717
new RegExp(
18-
'(input|result|details|failureDetails|Error|lastCompletionResult|heartbeatDetails)$'
18+
'(input|result|details|failureDetails|Error|lastCompletionResult|heartbeatDetails|lastFailureDetails)$'
1919
).test(name),
2020
icon: null,
2121
customRenderValue: WorkflowHistoryEventSummaryJson,

src/views/workflow-history/helpers/get-history-group-from-events/__tests__/get-activity-group-from-events.test.ts

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -348,18 +348,14 @@ describe('getActivityGroupFromEvents', () => {
348348
const group = getActivityGroupFromEvents(events);
349349

350350
// The failed event should have negativeFields
351-
const failedEventMetadata = group.eventsMetadata.find(
352-
(metadata) => metadata.status === 'FAILED'
353-
);
354-
expect(failedEventMetadata?.negativeFields).toEqual(['reason', 'details']);
351+
expect(group.eventsMetadata[2].negativeFields).toEqual([
352+
'reason',
353+
'details',
354+
]);
355355

356356
// Other events should not have negativeFields
357-
const otherEventsMetadata = group.eventsMetadata.filter(
358-
(metadata) => metadata.status !== 'FAILED'
359-
);
360-
otherEventsMetadata.forEach((metadata) => {
361-
expect(metadata.negativeFields).toBeUndefined();
362-
});
357+
expect(group.eventsMetadata[0].negativeFields).toBeUndefined();
358+
expect(group.eventsMetadata[1].negativeFields).toBeUndefined();
363359
});
364360

365361
it('should include negativeFields for timed out activity events', () => {
@@ -371,21 +367,14 @@ describe('getActivityGroupFromEvents', () => {
371367
const group = getActivityGroupFromEvents(events);
372368

373369
// The timed out event should have negativeFields
374-
const timedOutEventMetadata = group.eventsMetadata.find(
375-
(metadata) => metadata.status === 'FAILED' // timeout events have FAILED status
376-
);
377-
expect(timedOutEventMetadata?.negativeFields).toEqual([
370+
expect(group.eventsMetadata[2].negativeFields).toEqual([
378371
'reason',
379372
'details',
380373
]);
381374

382375
// Other events should not have negativeFields
383-
const otherEventsMetadata = group.eventsMetadata.filter(
384-
(metadata) => metadata.status !== 'FAILED'
385-
);
386-
otherEventsMetadata.forEach((metadata) => {
387-
expect(metadata.negativeFields).toBeUndefined();
388-
});
376+
expect(group.eventsMetadata[0].negativeFields).toBeUndefined();
377+
expect(group.eventsMetadata[1].negativeFields).toBeUndefined();
389378
});
390379

391380
it('should include summaryFields for activity events', () => {
@@ -397,39 +386,30 @@ describe('getActivityGroupFromEvents', () => {
397386
const group = getActivityGroupFromEvents(events);
398387

399388
// The scheduled event should have summaryFields
400-
const scheduledEventMetadata = group.eventsMetadata.find(
401-
(metadata) => metadata.label === 'Scheduled'
402-
);
403-
expect(scheduledEventMetadata?.summaryFields).toEqual([
389+
expect(group.eventsMetadata[0].summaryFields).toEqual([
404390
'input',
405391
'scheduleToCloseTimeoutSeconds',
406392
]);
407393

408394
// The started event should also have summaryFields
409-
const startedEventMetadata = group.eventsMetadata.find(
410-
(metadata) => metadata.label === 'Started'
411-
);
412-
expect(startedEventMetadata?.summaryFields).toEqual([
395+
expect(group.eventsMetadata[1].summaryFields).toEqual([
413396
'heartbeatDetails',
414397
'lastHeartbeatTime',
415398
]);
416399

417400
// The completed event should also have summaryFields
418-
const completedEventMetadata = group.eventsMetadata.find(
419-
(metadata) => metadata.label === 'Completed'
420-
);
421-
expect(completedEventMetadata?.summaryFields).toEqual(['result']);
401+
expect(group.eventsMetadata[2].summaryFields).toEqual(['result']);
422402
});
423403

424404
it('should include summaryFields for failed activity events', () => {
425405
const events: ExtendedActivityHistoryEvent[] = [failedActivityTaskEvent];
426406
const group = getActivityGroupFromEvents(events);
427407

428408
// The failed event should have summaryFields
429-
const failedEventMetadata = group.eventsMetadata.find(
430-
(metadata) => metadata.status === 'FAILED'
431-
);
432-
expect(failedEventMetadata?.summaryFields).toEqual(['details', 'reason']);
409+
expect(group.eventsMetadata[0].summaryFields).toEqual([
410+
'details',
411+
'reason',
412+
]);
433413
});
434414

435415
it('should include heartbeat details in additionalDetails when pending activity start event is present', () => {
@@ -441,10 +421,7 @@ describe('getActivityGroupFromEvents', () => {
441421
const group = getActivityGroupFromEvents(events);
442422

443423
// The started event should have additionalDetails with heartbeat information
444-
const startedEventMetadata = group.eventsMetadata.find(
445-
(metadata) => metadata.label === 'Started'
446-
);
447-
expect(startedEventMetadata?.additionalDetails).toEqual({
424+
expect(group.eventsMetadata[1].additionalDetails).toEqual({
448425
heartbeatDetails: [
449426
'1725747370575409843',
450427
'gadence-canary-xdc',
@@ -454,12 +431,7 @@ describe('getActivityGroupFromEvents', () => {
454431
});
455432

456433
// Other events should not have additionalDetails
457-
const otherEventsMetadata = group.eventsMetadata.filter(
458-
(metadata) => metadata.label !== 'Started'
459-
);
460-
otherEventsMetadata.forEach((metadata) => {
461-
expect(metadata.additionalDetails).toBeUndefined();
462-
});
434+
expect(group.eventsMetadata[0].additionalDetails).toBeUndefined();
463435
});
464436

465437
it('should include last heartbeat time when pending activity start event has lastHeartbeatTime', () => {
@@ -481,10 +453,7 @@ describe('getActivityGroupFromEvents', () => {
481453
];
482454
const group = getActivityGroupFromEvents(events);
483455

484-
const startedEventMetadata = group.eventsMetadata.find(
485-
(metadata) => metadata.label === 'Started'
486-
);
487-
expect(startedEventMetadata?.additionalDetails).toEqual({
456+
expect(group.eventsMetadata[1].additionalDetails).toEqual({
488457
heartbeatDetails: [
489458
'1725747370575409843',
490459
'gadence-canary-xdc',
@@ -540,4 +509,45 @@ describe('getActivityGroupFromEvents', () => {
540509
'Starting',
541510
]);
542511
});
512+
513+
it('should include summaryFields for pending activity start events', () => {
514+
const events: ExtendedActivityHistoryEvent[] = [
515+
scheduleActivityTaskEvent,
516+
pendingActivityTaskStartEvent,
517+
];
518+
const group = getActivityGroupFromEvents(events);
519+
520+
// The pending start event should have summaryFields
521+
const pendingStartEventMetadata = group.eventsMetadata[1];
522+
expect(pendingStartEventMetadata?.summaryFields).toEqual([
523+
'lastFailureReason',
524+
'lastFailureDetails',
525+
]);
526+
527+
// Other events should not have the same summaryFields
528+
const scheduledEventMetadata = group.eventsMetadata[0];
529+
expect(scheduledEventMetadata?.summaryFields).toEqual([
530+
'input',
531+
'scheduleToCloseTimeoutSeconds',
532+
]);
533+
});
534+
535+
it('should include negativeFields for pending activity start events', () => {
536+
const events: ExtendedActivityHistoryEvent[] = [
537+
scheduleActivityTaskEvent,
538+
pendingActivityTaskStartEvent,
539+
];
540+
const group = getActivityGroupFromEvents(events);
541+
542+
// The pending start event should have negativeFields
543+
const pendingStartEventMetadata = group.eventsMetadata[1];
544+
expect(pendingStartEventMetadata?.negativeFields).toEqual([
545+
'lastFailureReason',
546+
'lastFailureDetails',
547+
]);
548+
549+
// Other events should not have negativeFields
550+
const scheduledEventMetadata = group.eventsMetadata[0];
551+
expect(scheduledEventMetadata?.negativeFields).toBeUndefined();
552+
});
543553
});

src/views/workflow-history/helpers/get-history-group-from-events/get-activity-group-from-events.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ export default function getActivityGroupFromEvents(
127127
{
128128
activityTaskFailedEventAttributes: ['reason', 'details'],
129129
activityTaskTimedOutEventAttributes: ['reason', 'details'],
130+
pendingActivityTaskStartEventAttributes: [
131+
'lastFailureReason',
132+
'lastFailureDetails',
133+
],
130134
};
131135

132136
const pendingStartEventTimePrefix = pendingStartEvent?.[pendingStartAttr]
@@ -158,6 +162,10 @@ export default function getActivityGroupFromEvents(
158162
'input',
159163
'scheduleToCloseTimeoutSeconds',
160164
],
165+
pendingActivityTaskStartEventAttributes: [
166+
'lastFailureReason',
167+
'lastFailureDetails',
168+
],
161169
activityTaskStartedEventAttributes: [
162170
'heartbeatDetails',
163171
'lastHeartbeatTime',

0 commit comments

Comments
 (0)