UNPKG

@aws-lambda-powertools/logger

Version:
123 lines (122 loc) 3.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CircularMap = exports.SizedSet = exports.SizedItem = void 0; const typeutils_1 = require("@aws-lambda-powertools/commons/typeutils"); /** * A data structure that holds a value and its byte size. * * @internal */ class SizedItem { value; logLevel; byteSize; constructor(value, logLevel) { if (!(0, typeutils_1.isString)(value)) { throw new Error('Value should be a string'); } this.value = value; this.logLevel = logLevel; this.byteSize = Buffer.byteLength(value); } } exports.SizedItem = SizedItem; /** * A set that tracks its current byte size. * * @internal */ class SizedSet extends Set { currentBytesSize = 0; hasEvictedLog = false; /** * Adds an item to the set and updates the current byte size. * * @param item - The item to add */ add(item) { this.currentBytesSize += item.byteSize; super.add(item); return this; } /** * Deletes an item from the set and updates the current byte size. * * @param item - The item to delete */ delete(item) { const wasDeleted = super.delete(item); if (wasDeleted) { this.currentBytesSize -= item.byteSize; } return wasDeleted; } /** * Clears all items from the set and resets the current byte size. */ clear() { super.clear(); this.currentBytesSize = 0; } /** * Removes the first item from the set and returns it. */ shift() { const firstElement = this.values().next().value; if (firstElement) { this.delete(firstElement); } return firstElement; } } exports.SizedSet = SizedSet; /** * A ring buffer that stores logs in a circular manner. * * @internal */ class CircularMap extends Map { #maxBytesSize; #onBufferOverflow; constructor({ maxBytesSize, onBufferOverflow, }) { super(); this.#maxBytesSize = maxBytesSize; this.#onBufferOverflow = onBufferOverflow; } /** * Adds an item to the buffer, evicting older items if necessary. * * @param key - The key to associate with the item * @param value - The item to add * @param logLevel - The log level of the item */ setItem(key, value, logLevel) { const item = new SizedItem(value, logLevel); if (item.byteSize > this.#maxBytesSize) { throw new Error('Item too big'); } const buffer = this.get(key) || new SizedSet(); if (buffer.currentBytesSize + item.byteSize >= this.#maxBytesSize) { this.#deleteFromBufferUntilSizeIsLessThanMax(buffer, item); if (this.#onBufferOverflow) { this.#onBufferOverflow(); } } buffer.add(item); super.set(key, buffer); return this; } /** * Deletes an item from the buffer. * * @param key - The key associated with the item * @param value - The item to delete */ #deleteFromBufferUntilSizeIsLessThanMax(buffer, item) { while (buffer.currentBytesSize + item.byteSize >= this.#maxBytesSize) { buffer.shift(); buffer.hasEvictedLog = true; } } } exports.CircularMap = CircularMap;