forked from aws-powertools/powertools-lambda-typescript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogBuffer.ts
94 lines (79 loc) · 2.18 KB
/
logBuffer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { isString } from '@aws-lambda-powertools/commons/typeutils';
export class SizedItem<V> {
public value: V;
public logLevel: number;
public byteSize: number;
constructor(value: V, logLevel: number) {
if (!isString(value)) {
throw new Error('Value should be a string');
}
this.value = value;
this.logLevel = logLevel;
this.byteSize = Buffer.byteLength(value as unknown as string);
}
}
export class SizedSet<V> extends Set<SizedItem<V>> {
public currentBytesSize = 0;
add(item: SizedItem<V>): this {
this.currentBytesSize += item.byteSize;
super.add(item);
return this;
}
delete(item: SizedItem<V>): boolean {
const wasDeleted = super.delete(item);
if (wasDeleted) {
this.currentBytesSize -= item.byteSize;
}
return wasDeleted;
}
clear(): void {
super.clear();
this.currentBytesSize = 0;
}
shift(): SizedItem<V> | undefined {
const firstElement = this.values().next().value;
if (firstElement) {
this.delete(firstElement);
}
return firstElement;
}
}
export class CircularMap<V> extends Map<string, SizedSet<V>> {
readonly #maxBytesSize: number;
readonly #onBufferOverflow?: () => void;
constructor({
maxBytesSize,
onBufferOverflow,
}: {
maxBytesSize: number;
onBufferOverflow?: () => void;
}) {
super();
this.#maxBytesSize = maxBytesSize;
this.#onBufferOverflow = onBufferOverflow;
}
setItem(key: string, value: V, logLevel: number): this {
const item = new SizedItem<V>(value, logLevel);
if (item.byteSize > this.#maxBytesSize) {
throw new Error('Item too big');
}
const buffer = this.get(key) || new SizedSet<V>();
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;
}
readonly #deleteFromBufferUntilSizeIsLessThanMax = (
buffer: SizedSet<V>,
item: SizedItem<V>
) => {
while (buffer.currentBytesSize + item.byteSize >= this.#maxBytesSize) {
buffer.shift();
}
};
}