Skip to content

Commit 4828f80

Browse files
committed
feat: add debug only call tree filter
1 parent f4a408e commit 4828f80

1 file changed

Lines changed: 143 additions & 37 deletions

File tree

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

Lines changed: 143 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,16 @@ provideVSCodeDesignSystem().register(vsCodeCheckbox());
3131
let calltreeTable: Tabulator;
3232
let tableContainer: HTMLDivElement | null;
3333
let rootMethod: ApexLog | null;
34+
const debugOnlyFilterCache = new Map<number, boolean>();
35+
const showDetailsFilterCache = new Map<number, boolean>();
3436

3537
@customElement('call-tree-view')
3638
export class CalltreeView extends LitElement {
3739
@property()
3840
timelineRoot: ApexLog | null = null;
3941

42+
filterState = { showDetails: false, debugOnly: false };
43+
4044
get _callTreeTableWrapper(): HTMLDivElement | null {
4145
return (tableContainer = this.renderRoot?.querySelector('#call-tree-table') ?? null);
4246
}
@@ -81,10 +85,20 @@ export class CalltreeView extends LitElement {
8185
vertical-align: bottom;
8286
}
8387
84-
.filter-container {
88+
.header-bar {
8589
display: flex;
8690
gap: 10px;
8791
}
92+
93+
.filter-container {
94+
display: flex;
95+
gap: 5px;
96+
align-items: end;
97+
}
98+
99+
.filter-section {
100+
display: block;
101+
}
88102
`,
89103
];
90104

@@ -94,17 +108,27 @@ export class CalltreeView extends LitElement {
94108
return html`
95109
<div id="call-tree-container">
96110
<div>
97-
<strong>Filter</strong>
98-
<div class="filter-container">
99-
<vscode-button appearance="secondary" @click="${this._expandButtonClick}"
100-
>Expand</vscode-button
101-
>
102-
<vscode-button appearance="secondary" @click="${this._collapseButtonClick}"
103-
>Collapse</vscode-button
104-
>
105-
<vscode-checkbox class="checkbox__middle" @change="${this._handleShowDetailsChange}"
106-
>Show Details</vscode-checkbox
107-
>
111+
<div class="header-bar">
112+
<div class="filter-container">
113+
<vscode-button appearance="secondary" @click="${this._expandButtonClick}"
114+
>Expand</vscode-button
115+
>
116+
<vscode-button appearance="secondary" @click="${this._collapseButtonClick}"
117+
>Collapse</vscode-button
118+
>
119+
</div>
120+
121+
<div class="filter-section">
122+
<strong>Filter</strong>
123+
<div class="filter-container">
124+
<vscode-checkbox class="checkbox__middle" @change="${this._handleShowDetailsChange}"
125+
>Details</vscode-checkbox
126+
>
127+
<vscode-checkbox class="checkbox__middle" @change="${this._handleDebugOnlyChange}"
128+
>Debug Only</vscode-checkbox
129+
>
130+
</div>
131+
</div>
108132
</div>
109133
</div>
110134
<div id="call-tree-table-container">
@@ -117,21 +141,47 @@ export class CalltreeView extends LitElement {
117141

118142
_handleShowDetailsChange(event: Event) {
119143
const target = event.target as HTMLInputElement;
120-
const showDetails = target.checked;
121-
calltreeTable.setFilter((data, _filterParams) => {
122-
return showDetails || data.originalData.duration || data.originalData.discontinuity;
123-
});
144+
this.filterState.showDetails = target.checked;
145+
this._updateFiltering();
146+
}
147+
148+
_handleDebugOnlyChange(event: Event) {
149+
const target = event.target as HTMLInputElement;
150+
this.filterState.debugOnly = target.checked;
151+
this._updateFiltering();
152+
}
153+
154+
_updateFiltering() {
155+
calltreeTable.blockRedraw();
156+
if (this.filterState.showDetails) {
157+
// @ts-expect-error valid
158+
calltreeTable.removeFilter(showDetailsFilter);
159+
} else if (!this.filterState.showDetails) {
160+
// @ts-expect-error valid
161+
calltreeTable.addFilter(showDetailsFilter);
162+
}
163+
164+
if (this.filterState.debugOnly) {
165+
calltreeTable.clearFilter(false);
166+
// @ts-expect-error valid
167+
calltreeTable.addFilter(debugFilter);
168+
} else if (!this.filterState.debugOnly) {
169+
// @ts-expect-error valid
170+
calltreeTable.removeFilter(debugFilter);
171+
}
172+
173+
calltreeTable.restoreRedraw();
124174
}
125175

126176
_expandButtonClick() {
127177
calltreeTable.blockRedraw();
128-
expandAll(calltreeTable.getRows());
178+
expandCollapseAll(calltreeTable.getRows(), true);
129179
calltreeTable.restoreRedraw();
130180
}
131181

132182
_collapseButtonClick() {
133183
calltreeTable.blockRedraw();
134-
collapseAll(calltreeTable.getRows());
184+
expandCollapseAll(calltreeTable.getRows(), false);
135185
calltreeTable.restoreRedraw();
136186
}
137187

@@ -151,6 +201,34 @@ export class CalltreeView extends LitElement {
151201
}
152202
}
153203

204+
function deepFilter(
205+
rowData: CalltreeRow,
206+
filterFunction: (rowData: CalltreeRow) => boolean,
207+
filterParams: { filterCache: Map<number, boolean> },
208+
): boolean {
209+
const cachedMatch = filterParams.filterCache.get(rowData.id);
210+
if (cachedMatch !== null && cachedMatch !== undefined) {
211+
return cachedMatch;
212+
}
213+
214+
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;
221+
}
222+
}
223+
224+
filterParams.filterCache.set(rowData.id, childMatch);
225+
if (childMatch) {
226+
return true;
227+
}
228+
229+
return filterFunction(rowData);
230+
}
231+
154232
export async function renderCallTree(
155233
callTreeTableContainer: HTMLDivElement,
156234
rootMethod: ApexLog,
@@ -326,7 +404,7 @@ export async function renderCallTree(
326404
precision: 3,
327405
},
328406
bottomCalcFormatter: NumberFormat,
329-
bottomCalc: 'sum',
407+
bottomCalc: 'max',
330408
bottomCalcParams: { precision: 3 },
331409
headerFilter: MinMaxEditor,
332410
headerFilterFunc: MinMaxFilter,
@@ -360,37 +438,30 @@ export async function renderCallTree(
360438
calltreeTable.on('dataFiltered', () => {
361439
totalTimeFilterCache.clear();
362440
selfTimeFilterCache.clear();
441+
debugOnlyFilterCache.clear();
442+
showDetailsFilterCache.clear();
363443
});
364444

365445
calltreeTable.on('tableBuilt', () => {
366446
resolve();
367-
calltreeTable.setFilter((data, _filterParams) => {
368-
return data.originalData.duration || data.originalData.discontinuity;
369-
});
447+
//@ts-expect-error valid
448+
calltreeTable.addFilter(showDetailsFilter);
370449
});
371450
});
372451
}
373452

374-
function expandAll(rows: RowComponent[]) {
453+
function expandCollapseAll(rows: RowComponent[], expand: boolean = true) {
375454
const len = rows.length;
376455
for (let i = 0; i < len; i++) {
377456
const row = rows[i];
378457
if (row) {
379-
row.treeExpand();
380-
381-
expandAll(row.getTreeChildren());
382-
}
383-
}
384-
}
385-
386-
function collapseAll(rows: RowComponent[]) {
387-
const len = rows.length;
388-
for (let i = 0; i < len; i++) {
389-
const row = rows[i];
390-
if (row) {
391-
row.treeCollapse();
458+
if (expand) {
459+
row.treeExpand();
460+
} else {
461+
row.treeCollapse();
462+
}
392463

393-
collapseAll(row.getTreeChildren());
464+
expandCollapseAll(row.getTreeChildren(), expand);
394465
}
395466
}
396467
}
@@ -486,3 +557,38 @@ interface CalltreeRow {
486557
totalThrownCount: number;
487558
rows: number;
488559
}
560+
561+
const showDetailsFilter = (data: CalltreeRow) => {
562+
return deepFilter(
563+
data,
564+
(rowData) => {
565+
return rowData.originalData.duration > 0 || rowData.originalData.discontinuity;
566+
},
567+
{
568+
filterCache: showDetailsFilterCache,
569+
},
570+
);
571+
};
572+
573+
const debugFilter = (data: CalltreeRow) => {
574+
return deepFilter(
575+
data,
576+
(rowData) => {
577+
const debugValues = [
578+
'USER_DEBUG',
579+
'DATAWEAVE_USER_DEBUG',
580+
'USER_DEBUG_FINER',
581+
'USER_DEBUG_FINEST',
582+
'USER_DEBUG_FINE',
583+
'USER_DEBUG_DEBUG',
584+
'USER_DEBUG_INFO',
585+
'USER_DEBUG_WARN',
586+
'USER_DEBUG_ERROR',
587+
];
588+
return debugValues.includes(rowData.originalData.type || '');
589+
},
590+
{
591+
filterCache: debugOnlyFilterCache,
592+
},
593+
);
594+
};

0 commit comments

Comments
 (0)