diff --git a/packages/logger/src/logBuffer.ts b/packages/logger/src/logBuffer.ts index 54ce203bfd..4f520a19f0 100644 --- a/packages/logger/src/logBuffer.ts +++ b/packages/logger/src/logBuffer.ts @@ -110,8 +110,12 @@ export class CircularMap extends Map> { const buffer = this.get(key) || new SizedSet(); - if (buffer.currentBytesSize + item.byteSize >= this.#maxBytesSize) { + if ( + buffer.currentBytesSize !== 0 && + buffer.currentBytesSize + item.byteSize >= this.#maxBytesSize + ) { this.#deleteFromBufferUntilSizeIsLessThanMax(buffer, item); + if (this.#onBufferOverflow) { this.#onBufferOverflow(); } @@ -132,7 +136,10 @@ export class CircularMap extends Map> { buffer: SizedSet, item: SizedItem ) { - while (buffer.currentBytesSize + item.byteSize >= this.#maxBytesSize) { + while ( + buffer.size !== 0 && + buffer.currentBytesSize + item.byteSize >= this.#maxBytesSize + ) { buffer.shift(); buffer.hasEvictedLog = true; } diff --git a/packages/logger/tests/unit/logBufferStructures.test.ts b/packages/logger/tests/unit/logBufferStructures.test.ts index 8d44eb25c1..2248b8eb13 100644 --- a/packages/logger/tests/unit/logBufferStructures.test.ts +++ b/packages/logger/tests/unit/logBufferStructures.test.ts @@ -144,4 +144,74 @@ describe('CircularMap', () => { options.maxBytesSize ); }); + + it('stores item in buffer when item size is equal to maxBytesSize', () => { + // Prepare + const maxBytes = 10; + const onBufferOverflow = vi.fn(); + const circularMap = new CircularMap({ + maxBytesSize: maxBytes, + onBufferOverflow, + }); + const message = 'x'.repeat(maxBytes); + + // Act + circularMap.setItem('trace-1', message, 1); + + // Assess + const buffer = circularMap.get('trace-1'); + + expect(buffer).toBeDefined(); + expect(buffer?.currentBytesSize).toBe(maxBytes); + expect(buffer?.size).toBe(1); + expect(onBufferOverflow).toHaveBeenCalledTimes(0); + }); + + it('evicts existing non-empty item from buffer when item size is equal to maxBytesSize', () => { + // Prepare + const maxBytes = 10; + const onBufferOverflow = vi.fn(); + const circularMap = new CircularMap({ + maxBytesSize: maxBytes, + onBufferOverflow, + }); + + const message = 'x'.repeat(maxBytes); + + // Act + circularMap.setItem('trace-1', message, 1); + circularMap.setItem('trace-1', message, 1); + + // Assess + const buffer = circularMap.get('trace-1'); + + expect(buffer).toBeDefined(); + expect(buffer?.currentBytesSize).toBe(maxBytes); + expect(buffer?.size).toBe(1); + expect(onBufferOverflow).toHaveBeenCalledTimes(1); + }); + + it('should not evict existing empty item from buffer when new item size is equal to maxBytesSize', () => { + // Prepare + const maxBytes = 10; + const onBufferOverflow = vi.fn(); + const circularMap = new CircularMap({ + maxBytesSize: maxBytes, + onBufferOverflow, + }); + + const message = 'x'.repeat(maxBytes); + + // Act + circularMap.setItem('trace-1', '', 1); + circularMap.setItem('trace-1', message, 1); + + // Assess + const buffer = circularMap.get('trace-1'); + + expect(buffer).toBeDefined(); + expect(buffer?.currentBytesSize).toBe(maxBytes); + expect(buffer?.size).toBe(2); + expect(onBufferOverflow).toHaveBeenCalledTimes(0); + }); });