Skip to content

Commit 17783cb

Browse files
Merge pull request #452 from lukecotter/feat-parser-add-duration-for-some-events-without-end
feat: parser add duration for some events without end
2 parents b65494f + e3cd0ad commit 17783cb

6 files changed

Lines changed: 199 additions & 97 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
- Open Apex Log Analyzer from a dirty vscode editor ([#213][#213])
2020
- Supports opening Apex Log Analyzer when a log is dragged and dropped into Salesforce Code Builder.
2121
- It allows for a log analysis to be shown when a file is deleted on local disk or a log is copy and pasted into an editor window without saving.
22+
- Show time taken for more events within the `Workflow:ApprovalProcessActions` Code Unit ([#336][#336])
23+
- Estimates the time taken for some events without an exit event within `Workflow:ApprovalProcessActions` Code Unit e.g `WF_APPROVAl` + `WF_EMAIL_SENT`
2224
- Make dragging more obvious on the Timeline by showing different cursors ([#423][#423])
2325
- Show the pointer cursor by default when hovering the Timeline.
2426
- Show the grabbing cursor when the mouse is pressed down on the Timeline, to indicate drag is now possible.
@@ -304,6 +306,7 @@ Skipped due to adopting odd numbering for pre releases and even number for relea
304306

305307
<!-- Unreleased -->
306308

309+
[#336]: https://github.com/certinia/debug-log-analyzer/issues/336
307310
[#213]: https://github.com/certinia/debug-log-analyzer/issues/213
308311
[#86]: https://github.com/certinia/debug-log-analyzer/issues/86
309312
[#115]: https://github.com/certinia/debug-log-analyzer/issues/115

log-viewer/modules/__tests__/ApexLogParser.test.ts

Lines changed: 105 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,98 @@ describe('parseLine tests', () => {
8080
});
8181
});
8282

83+
describe('Pseudo EXIT events', () => {
84+
it('WF_APPROVAL_SUBMIT', () => {
85+
const logData =
86+
'00:00:00.757 (1)|WF_APPROVAL_SUBMIT|[Record: myrecord1 anId1]\n' +
87+
'00:00:00.757 (2)|WF_PROCESS_FOUND|ProcessDefinitionNameOrId:<processId>|Applicable process was found.\n' +
88+
'00:00:00.757 (3)|WF_APPROVAL_SUBMIT|[Record: myrecord2 anId2]\n' +
89+
'00:00:00.757 (4)|WF_PROCESS_FOUND|ProcessDefinitionNameOrId:<processId>|Applicable process was found.';
90+
91+
const log1 = parse(logData);
92+
expect(log1.children.length).toEqual(4);
93+
expect(log1.duration).toEqual(3);
94+
95+
const approval1 = log1.children[0] as Method;
96+
expect(approval1.duration).toEqual(1);
97+
expect(approval1.type).toEqual('WF_APPROVAL_SUBMIT');
98+
99+
const processFound1 = log1.children[1] as Method;
100+
expect(processFound1.duration).toEqual(1);
101+
expect(processFound1.type).toEqual('WF_PROCESS_FOUND');
102+
103+
const approval2 = log1.children[2] as Method;
104+
expect(approval2.duration).toEqual(1);
105+
expect(approval2.type).toEqual('WF_APPROVAL_SUBMIT');
106+
107+
const processFound2 = log1.children[3] as Method;
108+
expect(processFound2.duration).toEqual(0); // no lines after the last WF_PROCESS_FOUND to use as an exit
109+
expect(processFound2.type).toEqual('WF_PROCESS_FOUND');
110+
});
111+
112+
it('Pseudo EXIT With Entry after last event', () => {
113+
const logData =
114+
'00:00:00.757 (1)|CODE_UNIT_STARTED|[EXTERNAL]|Workflow:ApprovalProcessActions\n' +
115+
'00:00:00.757 (2)|WF_NEXT_APPROVER|Phillip Box|Related User|: Approver\n' +
116+
'00:00:00.757 (3)|WF_NEXT_APPROVER|Phillip Box|Related User|: Approver\n' +
117+
'00:00:00.757 (4)|WF_NEXT_APPROVER|Phillip Box|Related User|: Approver\n' +
118+
'00:00:00.757 (5)|METHOD_ENTRY|[17]|a00000000000000|ns.MyClass.myMethod()\n' +
119+
'00:00:00.757 (6)|METHOD_EXIT|[17]|a00000000000000|ns.MyClass.myMethod()\n' +
120+
'00:00:00.757 (7)|CODE_UNIT_FINISHED|Workflow:ApprovalProcessActions\n';
121+
122+
const log1 = parse(logData);
123+
expect(log1.children.length).toEqual(1);
124+
expect(log1.duration).toEqual(6);
125+
126+
const children = (log1.children[0] as Method).children;
127+
expect(children.length).toEqual(4);
128+
129+
const child1 = children[0] as Method;
130+
expect(child1.timestamp).toEqual(2);
131+
expect(child1.exitStamp).toEqual(3);
132+
133+
const child2 = children[1] as Method;
134+
expect(child2.timestamp).toEqual(3);
135+
expect(child2.exitStamp).toEqual(4);
136+
137+
const child3 = children[2] as Method;
138+
expect(child3.timestamp).toEqual(4);
139+
expect(child3.exitStamp).toEqual(5);
140+
141+
const child4 = children[3] as Method;
142+
expect(child4.timestamp).toEqual(5);
143+
expect(child4.exitStamp).toEqual(6);
144+
});
145+
146+
it('Pseudo EXIT With Exit after last event', () => {
147+
const logData =
148+
'00:00:00.757 (1)|CODE_UNIT_STARTED|[EXTERNAL]|Workflow:ApprovalProcessActions\n' +
149+
'00:00:00.757 (2)|WF_NEXT_APPROVER|Phillip Box|Related User|: Approver\n' +
150+
'00:00:00.757 (3)|WF_NEXT_APPROVER|Phillip Box|Related User|: Approver\n' +
151+
'00:00:00.757 (4)|WF_NEXT_APPROVER|Phillip Box|Related User|: Approver\n' +
152+
'00:00:00.757 (5)|CODE_UNIT_FINISHED|Workflow:ApprovalProcessActions\n';
153+
154+
const log1 = parse(logData);
155+
expect(log1.children.length).toEqual(1);
156+
expect(log1.duration).toEqual(4);
157+
158+
const children = (log1.children[0] as Method).children;
159+
expect(children.length).toEqual(3);
160+
161+
const child1 = children[0] as Method;
162+
expect(child1.timestamp).toEqual(2);
163+
expect(child1.exitStamp).toEqual(3);
164+
165+
const child2 = children[1] as Method;
166+
expect(child2.timestamp).toEqual(3);
167+
expect(child2.exitStamp).toEqual(4);
168+
169+
const child3 = children[2] as Method;
170+
expect(child3.timestamp).toEqual(4);
171+
expect(child3.exitStamp).toEqual(5);
172+
});
173+
});
174+
83175
describe('Invalid Debug Lines tests', () => {
84176
it('Unrecognised line type will added to issues', () => {
85177
const log1 = parse('09:18:22.6 (1)|FAKE_TYPE');
@@ -379,12 +471,10 @@ describe('getRootMethod tests', () => {
379471
expect(interViewsBegin.text).toBe('FLOW_START_INTERVIEWS : Example Process Builder');
380472
expect(interViewsBegin.suffix).toBe(' (Process Builder)');
381473

382-
expect(interViewsBegin.children.length).toBe(2);
474+
expect(interViewsBegin.children.length).toBe(1);
383475
const interViewBegin = interViewsBegin.children[0];
384476
expect(interViewBegin?.type).toBe('FLOW_START_INTERVIEW_BEGIN');
385-
386-
const interViewEnd = interViewsBegin.children[1];
387-
expect(interViewEnd?.type).toBe('FLOW_START_INTERVIEW_END');
477+
expect(interViewBegin?.duration).toBe(6332706);
388478
});
389479

390480
it('FlowStartInterviewsBeginLine should be a flow ', async () => {
@@ -416,12 +506,10 @@ describe('getRootMethod tests', () => {
416506
expect(interViewsBegin.text).toBe('FLOW_START_INTERVIEWS : Example Flow');
417507
expect(interViewsBegin.suffix).toBe(' (Flow)');
418508

419-
expect(interViewsBegin.children.length).toBe(2);
509+
expect(interViewsBegin.children.length).toBe(1);
420510
const interViewBegin = interViewsBegin.children[0];
421511
expect(interViewBegin?.type).toBe('FLOW_START_INTERVIEW_BEGIN');
422-
423-
const interViewEnd = interViewsBegin.children[1];
424-
expect(interViewEnd?.type).toBe('FLOW_START_INTERVIEW_END');
512+
expect(interViewBegin?.duration).toBe(6332706);
425513
});
426514

427515
it('FlowStartInterviewsBeginLine should be a flow called from a process builder', async () => {
@@ -457,25 +545,21 @@ describe('getRootMethod tests', () => {
457545
expect(pbBegin.text).toBe('FLOW_START_INTERVIEWS : Example Process Builder');
458546
expect(pbBegin.suffix).toBe(' (Process Builder)');
459547

460-
expect(pbBegin.children.length).toBe(3);
548+
expect(pbBegin.children.length).toBe(1);
461549
const pbDetail = pbBegin.children[0] as TimedNode;
462550
expect(pbDetail.type).toBe('FLOW_START_INTERVIEW_BEGIN');
463551
expect(pbDetail.text).toBe('Example Process Builder');
464552

465-
const interViewsBegin = pbBegin.children[1] as TimedNode;
553+
const interViewsBegin = pbDetail.children[0] as TimedNode;
466554
expect(interViewsBegin.type).toBe('FLOW_START_INTERVIEWS_BEGIN');
467555
expect(interViewsBegin.text).toBe('FLOW_START_INTERVIEWS : Example Flow');
468556
expect(interViewsBegin.suffix).toBe(' (Flow)');
557+
expect(interViewsBegin.duration).toBe(3);
469558

470-
const pbDetailEnd = pbBegin.children[2] as TimedNode;
471-
expect(pbDetailEnd.type).toBe('FLOW_START_INTERVIEW_END');
472-
473-
expect(interViewsBegin.children.length).toBe(2);
559+
expect(interViewsBegin.children.length).toBe(1);
474560
const interViewBegin = interViewsBegin.children[0];
475561
expect(interViewBegin?.type).toBe('FLOW_START_INTERVIEW_BEGIN');
476-
477-
const interViewEnd = interViewsBegin.children[1];
478-
expect(interViewEnd?.type).toBe('FLOW_START_INTERVIEW_END');
562+
expect(interViewBegin?.duration).toBe(1);
479563
});
480564

481565
it('Root exitStamp should match last line pair with a duration', async () => {
@@ -574,40 +658,6 @@ describe('getRootMethod tests', () => {
574658
});
575659
});
576660

577-
describe('lineTypeMap tests', () => {
578-
it('Lines referenced by exitTypes should be exits', () => {
579-
for (const [_keyName, cls] of lineTypeMap) {
580-
const line = new cls([
581-
'14:32:07.563 (17358806534)',
582-
'DUMMY',
583-
'[10]',
584-
'Rows:3',
585-
'',
586-
'Rows:5',
587-
]) as LogLine;
588-
if (line instanceof Method) {
589-
expect(line.exitTypes).not.toBe(null);
590-
expect(line.isExit).toBe(false);
591-
line.exitTypes.forEach((exitType) => {
592-
const exitCls = lineTypeMap.get(exitType);
593-
expect(exitCls).not.toBe(null);
594-
if (exitCls) {
595-
const exitLine = new exitCls([
596-
'14:32:07.563 (17358806534)',
597-
'DUMMY',
598-
'[10]',
599-
'Rows:3',
600-
'',
601-
'Rows:5',
602-
]) as LogLine;
603-
expect(exitLine.isExit).toBe(true);
604-
}
605-
});
606-
}
607-
}
608-
});
609-
});
610-
611661
describe('Log Settings tests', () => {
612662
const log =
613663
'43.0 APEX_CODE,FINE;APEX_PROFILING,NONE;CALLOUT,NONE;DB,INFO;NBA,NONE;SYSTEM,NONE;VALIDATION,INFO;VISUALFORCE,NONE;WAVE,NONE;WORKFLOW,INFO\n' +
@@ -661,7 +711,7 @@ describe('Recalculate durations tests', () => {
661711

662712
describe('Line Type Tests', () => {
663713
it('Lines referenced by exitTypes should be exits', () => {
664-
for (const lineType of lineTypeMap.values()) {
714+
for (const [key, lineType] of lineTypeMap) {
665715
const line = new lineType([
666716
'14:32:07.563 (17358806534)',
667717
'DUMMY',
@@ -672,7 +722,9 @@ describe('Line Type Tests', () => {
672722
]) as LogLine;
673723
if (line instanceof Method) {
674724
expect(line.exitTypes).not.toBe(null);
675-
expect(line.isExit).toBe(false);
725+
if (line.isExit) {
726+
expect(line.exitTypes).toEqual([key]);
727+
}
676728
line.exitTypes.forEach((exitType) => {
677729
const exitCls = lineTypeMap.get(exitType);
678730
expect(exitCls).not.toBe(null);

log-viewer/modules/components/LogViewer.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,6 @@ export class LogViewer extends LitElement {
9797
logMessage.message = element.description;
9898
logMessage.severity = severity;
9999
localNotifications.push(logMessage);
100-
101-
console.debug('s,', severity, logMessage);
102100
});
103101
this.notifications = localNotifications;
104102

log-viewer/modules/components/calltree-view/CalltreeView.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,12 +212,17 @@ function deepFilter(
212212
}
213213

214214
let childMatch = false;
215-
for (const childRow of rowData._children || []) {
216-
const match = deepFilter(childRow, filterFunction, filterParams);
217-
218-
if (match) {
219-
childMatch = true;
220-
break;
215+
const children = rowData._children || [];
216+
let len = children.length;
217+
while (len-- > 0) {
218+
const childRow = children[len];
219+
if (childRow) {
220+
const match = deepFilter(childRow, filterFunction, filterParams);
221+
222+
if (match) {
223+
childMatch = true;
224+
break;
225+
}
221226
}
222227
}
223228

0 commit comments

Comments
 (0)