Skip to content

Commit 71b2c32

Browse files
Merge pull request certinia#712 from lukecotter/feat-timeline-minimap
feat: timeline minimap
2 parents 849d3ef + 0ee3648 commit 71b2c32

46 files changed

Lines changed: 7424 additions & 1038 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12-
- **⚡ Performance**: Improved performance to handle huge Apex debug logs; Zoom + pan are **7X faster** with smoother motion; Adaptive level-of-detail bucketing reveals richer timeline detail as you zoom while keeping the view clean and fast.
13-
- **Visual Display**: Dynamic labels on Timeline events for faster log scanning; Time axis auto-spaces markers intelligently and more naturally as you zoom; Search + highlight dims non-matches for fast scanning.
14-
1512
-**Timeline**: A brand new **experimental** timeline Flame Chart built for massive logs and up to **7X faster**. ([#446] [#251] [#92] [#564])
16-
- Full feature parity with the original Timeline including:
17-
- Zoom and pan navigation (mouse + keyboard)
18-
- Search with result highlighting
19-
- Frame tooltips on hover
20-
- Markers for errors, skipped lines, and truncation
21-
- Click to navigate to Call Tree (now on key press of `J` or `Cmd/Ctrl+Click`)
2213
- **⚡ Performance**: Improved performance to handle huge Apex debug logs.
2314
- Zoom + pan are **7X faster** with smoother motion.
24-
- **Visual Display**:
25-
- Adaptive level-of-detail bucketing reveals richer timeline detail as you zoom while keeping the view clean and fast.
26-
- Dynamic labels on Timeline events for faster log scanning. ([#92])
27-
- Time axis auto-spaces markers intelligently and more naturally as you zoom.
28-
- Search + highlight dims non-matches for fast scanning.
29-
- **🎨 Themes**:
30-
- 18 curated timeline themes plus the default theme has been improved for better contrast and readability.
31-
- Add your own multiple custom themes via **Settings -> Apex Log Analyzer -> Timeline -> Custom Themes**.
32-
- Fast theme switching via **Command Palette**: **Log: Timeline Theme** or **Settings -> Apex Log Analyzer -> Timeline -> Active Theme**.
15+
- **Minimap**: Navigate massive logs at a glance with the new minimap overview. ([#245] [#446])
16+
- **Skyline Overview**: Density-based visualization shows stack depth and event distribution across the entire timeline. Color-coded categories and logarithmic opacity reveal hotspots instantly.
17+
- **Viewport Lens**: A window highlights exactly what's visible in the main timeline — both time range and depth. Drag to create zoom selections, resize edges to adjust, or teleport with `Cmd/Ctrl+Click`.
18+
- **Cursor Mirroring**: Hover on the minimap to see a guide line on the main timeline.
19+
- **Rich Interactions**:
20+
- **Drag anywhere** → draw a new zoom selection
21+
- **Drag lens edges** → resize the viewport
22+
- **Shift+Drag inside lens** → pan the viewport
23+
- **Cmd/Ctrl+Click** → instantly teleport the lens
24+
- **Scroll** → zoom (vertical) or pan (horizontal)
25+
- **Double-click** → reset to full timeline view
26+
- **Keyboard shortcuts** (when hovering minimap): Arrow keys pan, `W`/`S` zoom, `Home`/`End` jump, `0` resets.
27+
- **Adaptive Frame Bucketing**: Reveals nested frame detail and stack structure as you zoom, automatically adjusting frame granularity to understand complex call hierarchies.
28+
- **Dynamic Frame Labels**: Labels automatically appear on timeline frames as you zoom and pan, making log scanning and navigation effortless without manually hovering to see event details. ([#92])
3329
- **Keyboard and Mouse Navigation**: Comprehensive interaction controls for the timeline. ([#573] [#366] [#296] [#295] [#535])
3430
- **Selection & Focus**:
3531
- **Frame Selection**: Click to select and highlight a frame without navigating away.
@@ -49,6 +45,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4945
- **Copy**: `Cmd/Ctrl+C` copies the selected frame name.
5046
- **Marker Navigation**: Click markers to select; arrow Left/Right to navigate between markers.
5147
- **Clear Selection**: Press `Escape` to deselect the current frame or marker.
48+
- **Visual Display**:
49+
- Time axis auto-spaces markers intelligently and more naturally as you zoom.
50+
- Search + highlight dims non-matches for fast scanning.
51+
- **🎨 Themes**:
52+
- 18 curated timeline themes plus the default theme has been improved for better contrast and readability.
53+
- Add your own multiple custom themes via **Settings -> Apex Log Analyzer -> Timeline -> Custom Themes**.
54+
- Fast theme switching via **Command Palette**: **Log: Timeline Theme** or **Settings -> Apex Log Analyzer -> Timeline -> Active Theme**.
55+
- **Full support for all original Timeline features** including:
56+
- Zoom and pan navigation (mouse + keyboard)
57+
- Search with result highlighting
58+
- Frame tooltips on hover
59+
- Markers for errors, skipped lines, and truncation
60+
- Click to navigate to Call Tree (now on key press of `J` or `Cmd/Ctrl+Click`)
5261
- **Legacy Support**: Toggle the legacy timeline anytime via **Settings -> Apex Log Analyzer -> Timeline -> Legacy**.
5362

5463
### Changed
@@ -450,6 +459,7 @@ Skipped due to adopting odd numbering for pre releases and even number for relea
450459

451460
<!-- Unreleased -->
452461

462+
[#245]: https://github.com/certinia/debug-log-analyzer/issues/245
453463
[#164]: https://github.com/certinia/debug-log-analyzer/issues/164
454464
[#535]: https://github.com/certinia/debug-log-analyzer/issues/535
455465
[#295]: https://github.com/certinia/debug-log-analyzer/issues/295

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ Apex Log Analyzer is a blazing-fast VS Code extension for Salesforce developers.
1212

1313
[Installation](#%EF%B8%8F-installation 'Install Apex Log Analyzer in VS Code') |
1414
[Debug Log Levels](#%EF%B8%8F-recommended-debug-log-levels 'Go to Recommended Debug Log Levels') |
15-
[Features](#-flame-chart-timeline 'Go to Features') |
15+
[Features](#-timeline 'Go to Features') |
1616
[Customization](#-customization 'Go to Customization') |
1717
[Documentation](#-documentation 'Go to Documentation') |
1818
[Contributors](#%EF%B8%8F-contributors 'Go to Contributors') |
1919
[License](#-license 'Go to License')
2020

2121
## 🚀 Key Features
2222

23-
- **🔥 [Flame Chart Timeline](#-flame-chart-timeline)** – Visualize every method, SOQL query, and DML operation in your Apex logs.
23+
- **🔥 [Timeline](#-timeline)** – Visualize every method, SOQL query, and DML operation in your Apex logs with an interactive flame chart and minimap navigation.
2424
- **🌲 [Interactive Call Tree](#-call-tree)** – Dive into execution stacks with timing, row counts, and DML/ SOQL metrics.
2525
- **📊 [Apex](#-apex-analysis) + [Database](#%EF%B8%8F-database-analysis) Analysis** – Identify slow-performing SOQL, high-impact DML, and time-heavy Apex methods.
2626
- **🧠 Smart Filtering + Sorting** – Focus on what matters: filter by namespace, event type, or duration.
@@ -81,20 +81,21 @@ Use `Log: Retrieve Apex Log And Show Analysis` from the Command Palette.
8181
- Avoid truncated logs — they can result in incomplete or misleading analysis.
8282
- Recommended settings for a good balance of detail and performance: `APEX_CODE,FINE; APEX_PROFILING,FINE; CALLOUT,INFO; DB,FINEST; NBA,INFO; SYSTEM,DEBUG; VALIDATION,INFO; VISUALFORCE,FINE; WAVE,INFO; WORKFLOW,FINE`
8383

84-
## 🔥 Flame Chart Timeline
84+
## 🔥 Timeline
8585

86-
The Flame Chart view shows a timeline of the Salesforce Apex log execution — including methods, SOQL queries, DML operations, workflows, flows, and more.
86+
The Timeline view shows a live visualization of your Salesforce Apex log execution — including methods, SOQL queries, DML operations, workflows, flows, and more.
8787

8888
- **⚡ Fast** – Blazing-fast zoom, pan, and rendering even on massive logs (500k+ lines).
8989
- **🎯 Frame Selection & Navigation** – Click to select frames, use arrow keys to navigate the call stack, double-click or press `Enter` to zoom and focus.
9090
- **Zoom & Pan** – Navigate your logs down to 0.001 ms with precision zoom. `W`/`S` keys or scroll wheel for zoom; `A`/`D` keys or drag for pan.
91+
- **Dynamic Frame Labels** – Instantly see method names on timeline frames for faster scanning.
92+
- **🗺️ Minimap** – Bird's-eye view with skyline overview showing call stack depth, viewport lens for navigation, and instant teleport to any position.
9193
- **📏 Measure Range**`Shift+Drag` to measure the duration between any two points. Resize edges, double-click to zoom.
9294
- **🔍 Area Zoom**`Alt/Option+Drag` to select a region and instantly zoom to fit.
93-
- **Dynamic Labels** – Instantly see method names on timeline events for faster scanning.
94-
- **19 Curated Themes** – Choose from beautiful, optimized color themes or create your own via Settings.
95-
- **Smart Interaction** – Right-click for context actions; `Cmd/Ctrl+Click` to jump directly to the Call Tree; `Cmd/Ctrl+C` to copy frame names.
9695
- **Tooltips** – Hover for duration, event name, SOQL/DML/Exception counts, SOQL/DML rows, and more.
97-
- **Adaptive Detail** – Level-of-detail bucketing reveals richer detail as you zoom while keeping performance snappy.
96+
- **Cotext Menu Actions** – Right-click for context actions; `Cmd/Ctrl+Click` to jump directly to the Call Tree; `Cmd/Ctrl+C` to copy frame names.
97+
- **19 Curated Themes** – Choose from beautiful, optimized color themes or create your own via Settings.
98+
- **Adaptive Frame Detail** – Level-of-detail bucketing reveals richer detail as you zoom while keeping performance snappy.
9899
- **Stacked by Time** – See how execution time is distributed across nested method calls and system events.
99100

100101
![Flame Chart](https://raw.githubusercontent.com/certinia/debug-log-analyzer/main/lana/assets/v1.18/lana-timeline.png)

lana-docs-site/docs/docs/features/timeline.md

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
id: timeline
33
title: Timeline
4-
description: Use the Timeline to visualize code execution, event durations, and performance bottlenecks. Zoom, pan, measure time ranges, and interact with detailed tooltips for efficient Salesforce Apex log analysis and debugging.
4+
description: Use the Timeline to visualize code execution, event durations, and performance bottlenecks. Zoom, pan, measure time ranges, and navigate massive logs with the minimap overview for efficient Salesforce Apex log analysis and debugging.
55
keywords:
66
[
77
salesforce apex log analysis,
@@ -12,23 +12,80 @@ keywords:
1212
apex performance analysis,
1313
measure time range,
1414
area zoom selection,
15+
timeline minimap,
16+
log navigation,
1517
]
1618
image: https://raw.githubusercontent.com/certinia/debug-log-analyzer/main/lana/assets/v1.18/lana-timeline.png
1719
hide_title: true
1820
---
1921

2022
## 🔥 Timeline / Flame Chart
2123

22-
Use the Timeline to visualize code execution, event durations, and performance bottlenecks. Zoom, pan, and interact with detailed tooltips for efficient Salesforce apex log analysis and debugging.
24+
Use the Timeline to visualize code execution, event durations, and performance bottlenecks. Zoom, pan, navigate with the minimap overview, and interact with detailed tooltips for efficient Salesforce apex log analysis and debugging.
2325

2426
![Timeline view screenshot showing a color-coded flame chart of Salesforce event types such as DB, Method, and SOQL, visualizing code execution duration and performance](https://raw.githubusercontent.com/certinia/debug-log-analyzer/main/lana/assets/v1.18/lana-timeline.png)
2527

26-
The new experimental timeline is up to **7X faster** than the legacy timeline, with improved performance especially for large logs. It includes text labels on events, faster zoom/pan operations, and a more natural time axis scaling.
28+
The new experimental timeline is up to **7X faster** than the legacy timeline, with improved performance especially for large logs. It includes text labels on frames, faster zoom/pan operations, and a more natural time axis scaling.
2729

2830
:::tip Legacy Timeline
2931
To revert to the legacy timeline, navigate to **Settings → Apex Log Analyzer → Timeline → Legacy** and enable it.
3032
:::
3133

34+
## Minimap
35+
36+
The minimap gives you instant context of your entire log. Spot hotspots at a glance, jump anywhere with a click, and always know exactly where you are—all without scrolling.
37+
38+
### What the Minimap Shows
39+
40+
- **Skyline Chart**: A density-based visualization:
41+
- **Height** = maximum call stack depth at that point
42+
- **Color** = dominant event category (method, SOQL, DML, etc.)
43+
- **Opacity** = event density (brighter = more events)
44+
- **Viewport Lens**: A window showing exactly what's visible in the main timeline (time range horizontal, depth range vertical)
45+
- **Time Axis**: Time reference markers at the top
46+
- **Markers**: Error, skip, and truncation markers from the main timeline
47+
- **Cursor Mirroring**: Hover to see a guide line on the main timeline
48+
49+
### Mouse Interactions
50+
51+
| Action | Mouse | Result |
52+
| ---------------- | --------------------- | ----------------------------------- |
53+
| Create Zoom | Drag anywhere | Draw a viewport area and zoom to it |
54+
| Resize Viewport | Drag lens edge | Adjust zoom range |
55+
| Move Viewport | Drag top/`Shift+Drag` | Pan the viewport |
56+
| Teleport Lens | `Cmd/Ctrl+Click` | Center the lens on click position |
57+
| Zoom In/Out | Scroll (vertical) | Zoom at cursor position |
58+
| Pan Horizontally | Scroll (horizontal) | Move viewport left/right |
59+
| Pan Depth | Drag (vertical) | Scroll the main timeline up/down |
60+
| Reset | Double-click | Zoom out to fit entire timeline |
61+
62+
:::tip Teleport Navigation
63+
`Cmd/Ctrl+Click` is the fastest way to jump to any point in a massive log. The lens teleports to center on your click while preserving the current zoom level.
64+
:::
65+
66+
### Keyboard Shortcuts
67+
68+
When your mouse is hovering over the minimap, these keyboard shortcuts are available:
69+
70+
| Key | Action |
71+
| --------------- | ------------------------------------------- |
72+
| `Arrow Left` | Pan viewport left (10% of selection width) |
73+
| `Arrow Right` | Pan viewport right (10% of selection width) |
74+
| `Arrow Up` | Pan depth up (show deeper frames) |
75+
| `Arrow Down` | Pan depth down (show shallower frames) |
76+
| `W` / `+` / `=` | Zoom in (narrow the lens) |
77+
| `S` / `-` | Zoom out (widen the lens) |
78+
| `Home` | Jump to timeline start |
79+
| `End` | Jump to timeline end |
80+
| `0` / `Escape` | Reset zoom (fit entire timeline) |
81+
82+
### Lens Label
83+
84+
When hovering over the viewport lens or dragging, a label appears showing:
85+
86+
- The **duration** of the selected time range (e.g., "1.23s")
87+
- The **time range** start and end (e.g., "0.5s - 1.73s")
88+
3289
## Navigation
3390

3491
### Zoom + Pan

lana/src/commands/LogView.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ export class LogView {
6464
}
6565

6666
case 'openPath': {
67-
const filePath = <string>payload;
67+
const filePath = payload as string;
6868
if (filePath) {
6969
context.display.showFile(filePath);
7070
}
7171
break;
7272
}
7373

7474
case 'openType': {
75-
const symbol = <string>payload;
75+
const symbol = payload as string;
7676
if (symbol) {
7777
OpenFileInPackage.openFileForSymbol(context, symbol);
7878
}
@@ -94,9 +94,10 @@ export class LogView {
9494
}
9595

9696
case 'saveFile': {
97-
const { fileContent, options } = <
98-
{ fileContent: string; options: { defaultFileName?: string } }
99-
>payload;
97+
const { fileContent, options } = payload as {
98+
fileContent: string;
99+
options: { defaultFileName?: string };
100+
};
100101

101102
if (fileContent && options?.defaultFileName) {
102103
const defaultWorkspace = (workspace.workspaceFolders || [])[0];
@@ -116,7 +117,7 @@ export class LogView {
116117
}
117118

118119
case 'showError': {
119-
const { text } = <{ text: string }>payload;
120+
const { text } = payload as { text: string };
120121
if (text) {
121122
vscWindow.showErrorMessage(text);
122123
}

lana/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
"strict": true,
1515
"noUncheckedIndexedAccess": true,
16+
"erasableSyntaxOnly": true,
1617

1718
"moduleResolution": "Bundler",
1819
"module": "ESNext",

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ describe('parseLog tests', () => {
424424
'09:19:13.82 (51595120059)|EXECUTION_FINISHED\n';
425425

426426
const apexLog = parse(log);
427-
const execEvent = <MethodEntryLine>apexLog.children[0];
427+
const execEvent = apexLog.children[0] as MethodEntryLine;
428428
expect(execEvent).toBeInstanceOf(ExecutionStartedLine);
429429

430430
expect(execEvent.children.length).toEqual(1);

log-viewer/src/core/utility/Util.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,25 @@ function round(value: number, precision: number): number {
6363
return Math.round(value * precision) / precision;
6464
}
6565

66+
/**
67+
* Formats a time range showing start and end times with an arrow separator.
68+
*
69+
* Used by measurement overlay and minimap lens labels for consistent formatting.
70+
*
71+
* @param startTimeNs - Start time in nanoseconds
72+
* @param endTimeNs - End time in nanoseconds
73+
* @returns Formatted string like "1.2 s → 3.7 s"
74+
*
75+
* @example
76+
* ```typescript
77+
* formatTimeRange(1200000000, 3700000000); // "1.2 s → 3.7 s"
78+
* formatTimeRange(0, 150000000); // "0 ms → 150 ms"
79+
* ```
80+
*/
81+
export function formatTimeRange(startTimeNs: number, endTimeNs: number): string {
82+
return `${formatDuration(startTimeNs)}${formatDuration(endTimeNs)}`;
83+
}
84+
6685
export function debounce<T extends unknown[]>(callBack: (...args: T) => unknown) {
6786
let requestId: number = 0;
6887

log-viewer/src/features/timeline/__tests__/keyboard-handler.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ describe('KeyboardHandler', () => {
5353
onJumpToCallTree: jest.fn(),
5454
onFocus: jest.fn(),
5555
onCopy: jest.fn(),
56+
// Minimap keyboard callbacks
57+
isInMinimapArea: jest.fn().mockReturnValue(false),
58+
onMinimapPanViewport: jest.fn(),
59+
onMinimapPanDepth: jest.fn(),
60+
onMinimapZoom: jest.fn(),
61+
onMinimapJumpStart: jest.fn(),
62+
onMinimapJumpEnd: jest.fn(),
63+
onMinimapResetZoom: jest.fn(),
5664
};
5765

5866
handler = new KeyboardHandler(container, viewport, callbacks);

log-viewer/src/features/timeline/__tests__/search-highlight.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ describe('SearchHighlightRenderer', () => {
6666
timeEnd: timestamp + duration,
6767
depth,
6868
duration,
69+
selfDuration: duration,
6970
category: 'Method',
7071
};
7172
return {
@@ -94,6 +95,14 @@ describe('SearchHighlightRenderer', () => {
9495
hasNext: jest.fn(() => currentIndex < matches.length - 1),
9596
hasPrev: jest.fn(() => currentIndex > 0),
9697
getMatchedEventIds: jest.fn(() => new Set(matches.map((m) => m.event.id))),
98+
getMatchedEventsInfo: jest.fn(() =>
99+
matches.map((m) => ({
100+
timestamp: m.event.timestamp,
101+
duration: m.event.duration,
102+
depth: m.depth,
103+
category: m.event.subCategory ?? '',
104+
})),
105+
),
97106
};
98107
};
99108

log-viewer/src/features/timeline/components/TimelineView.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class TimelineView extends LitElement {
6262
flex: 1;
6363
position: relative;
6464
width: 100%;
65-
height: 80%;
65+
height: 90%;
6666
}
6767
`,
6868
];

0 commit comments

Comments
 (0)