Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- ⚑ **Timeline**: A brand new **experimental** timeline Flame Chart that is up to **7X faster**. ([#446] [#251] [#92] [#564])
- Revert to the legacy timeline via **Settings -> Apex Log Analyzer -> Timeline -> Legacy**.
- Generally Improved performance, especially for large logs.
- Text labels on Timeline events.
- Zoom and pan are now **7X faster**.
- The Time axis scales more naturally when zooming, with larger gaps between the markers on longer logs.
- Search + highlight will grey out non matches to find matches more easily.
- Added 18 timeline color themes and improved the default theme for better contrast and readability.
- Supply multiple custom themes via **Settings -> Apex Log Analyzer -> Timeline -> Custom Themes**.
- Change the active theme via the new **Command Palette** command **Log: Timeline Theme** or via **Settings -> Apex Log Analyzer -> Timeline -> Active Theme**.
- ⚑ **Timeline**: A brand new **experimental** timeline Flame Chart built for massive logs and up to **7X faster**. ([#446] [#251] [#92] [#564])
- Toggle the legacy timeline anytime via **Settings -> Apex Log Analyzer -> Timeline -> Legacy**.
- Improved performance to handle huge Apex debug logs.
- Dynamic labels on Timeline events for faster log scanning.
- Zoom + pan are **7X faster** with smoother motion.
- Time axis auto-spaces markers intelligently and more naturally as you zoom.
- Search + highlight dims non-matches for fast scanning.
- 18 curated timeline themes plus the default theme has been improved for better contrast and readability.
- Add your own multiple custom themes via **Settings -> Apex Log Analyzer -> Timeline -> Custom Themes**.
- Fast theme switching via **Command Palette**: **Log: Timeline Theme** or **Settings -> Apex Log Analyzer -> Timeline -> Active Theme**.
- Adaptive level-of-detail bucketing reveals richer timeline detail as you zoom while keeping keeping the view clean and fast.

### Changed

Expand Down
31 changes: 17 additions & 14 deletions log-viewer/src/features/timeline/__tests__/batching.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ describe('EventBatchRenderer', () => {
rectangleManager = new RectangleManager(events, categories);
renderer = new EventBatchRenderer(container, batches);

const culledRects = rectangleManager.getCulledRectangles(viewport);
renderer.render(culledRects);
const { visibleRects, buckets } = rectangleManager.getCulledRectangles(viewport);
renderer.render(visibleRects, buckets);
}

beforeEach(() => {
Expand Down Expand Up @@ -122,18 +122,20 @@ describe('EventBatchRenderer', () => {
});

describe('initialization', () => {
it('should create Graphics objects for each batch', () => {
it('should create a SpritePool container', () => {
renderer = new EventBatchRenderer(container, batches);

expect(container.children).toHaveLength(3);
expect(container.children.every((child) => child instanceof PIXI.Graphics)).toBe(true);
// SpritePool creates a container for sprites
expect(container.children).toHaveLength(1);
expect(container.children[0] instanceof PIXI.Container).toBe(true);
});

it('should handle empty batches', () => {
it('should create SpritePool container with empty batches', () => {
const emptyBatches = new Map<string, RenderBatch>();
renderer = new EventBatchRenderer(container, emptyBatches);

expect(container.children).toHaveLength(0);
// SpritePool container is still created
expect(container.children).toHaveLength(1);
});
});

Expand Down Expand Up @@ -322,7 +324,7 @@ describe('EventBatchRenderer', () => {

it('should render events that meet minimum size threshold', () => {
const events = [
createEvent(0, 1, 'Method'), // Width = 1px at zoom=1
createEvent(0, 3, 'Method'), // Width = 3px at zoom=1 (> MIN_RECT_SIZE = 2px)
];

const viewport = createViewport(1, 0, 0);
Expand Down Expand Up @@ -454,8 +456,9 @@ describe('EventBatchRenderer', () => {

// Second render with different viewport (should recalculate)
const viewport2 = createViewport(1, 150, 0); // Pan to cull first event
const culledRects2 = rectangleManager.getCulledRectangles(viewport2);
renderer.render(culledRects2);
const { visibleRects: visibleRects2, buckets: buckets2 } =
rectangleManager.getCulledRectangles(viewport2);
renderer.render(visibleRects2, buckets2);
expect(batches.get('Method')?.rectangles).toHaveLength(1);
});
});
Expand Down Expand Up @@ -503,14 +506,14 @@ describe('EventBatchRenderer', () => {
});

describe('cleanup', () => {
it('should destroy all Graphics objects', () => {
it('should destroy SpritePool and remove all children', () => {
renderer = new EventBatchRenderer(container, batches);

const childrenCount = container.children.length;
expect(childrenCount).toBeGreaterThan(0);

renderer.destroy();
// After destruction, graphics are removed from their parent
// After destruction, SpritePool container is removed
// Container should have no children
expect(container.children.length).toBe(0);
});
Expand Down Expand Up @@ -541,9 +544,9 @@ describe('EventBatchRenderer', () => {
});

it('should render events when they meet minimum size threshold after zoom', () => {
const events = [createEvent(0, 100, 'Method')];
const events = [createEvent(0, 300, 'Method')];

// Zoom in so screenWidth = 100 * 0.01 = 1px (> MIN_RECT_SIZE = 0.5px)
// Zoom in so screenWidth = 300 * 0.01 = 3px (> MIN_RECT_SIZE = 2px)
const viewport = createViewport(0.01, 0, 0);
setupAndRender(events, viewport);

Expand Down
Loading
Loading