Skip to content

Commit d7bf789

Browse files
committed
feat(logger): Enable log buffering feature
This commit enables the buffering feature for the logger utility It allows the user to configure the buffering functionality in the logger constructor.
1 parent 1d66a2a commit d7bf789

File tree

3 files changed

+239
-120
lines changed

3 files changed

+239
-120
lines changed

Diff for: packages/logger/src/Logger.ts

+46-11
Original file line numberDiff line numberDiff line change
@@ -172,25 +172,28 @@ class Logger extends Utility implements LoggerInterface {
172172
/**
173173
* Represents whether the buffering functionality is enabled in the logger
174174
*/
175-
protected isBufferEnabled = false;
175+
protected isBufferEnabled = true;
176176

177+
/**
178+
* Whether the buffer should be flushed when an error is logged
179+
*/
180+
protected flushOnErrorLog = true;
177181
/**
178182
* Log level threshold for the buffer
179183
* Logs with a level lower than this threshold will be buffered
184+
* Default is DEBUG
180185
*/
181-
protected bufferLogThreshold: number = LogLevelThreshold.DEBUG;
186+
protected bufferAtVerbosity: number = LogLevelThreshold.DEBUG;
182187
/**
183188
* Max size of the buffer. Additions to the buffer beyond this size will
184189
* cause older logs to be evicted from the buffer
185190
*/
186-
readonly #maxBufferBytesSize = 1024;
191+
#maxBufferBytesSize = 1024;
187192

188193
/**
189194
* Contains buffered logs, grouped by _X_AMZN_TRACE_ID, each group with a max size of `maxBufferBytesSize`
190195
*/
191-
readonly #buffer: CircularMap<string> = new CircularMap({
192-
maxBytesSize: this.#maxBufferBytesSize,
193-
});
196+
#buffer?: CircularMap<string>;
194197

195198
/**
196199
* Log level used by the current instance of Logger.
@@ -330,6 +333,9 @@ class Logger extends Utility implements LoggerInterface {
330333
* @param extraInput - The extra input to log.
331334
*/
332335
public error(input: LogItemMessage, ...extraInput: LogItemExtraInput): void {
336+
if (this.isBufferEnabled && this.flushOnErrorLog) {
337+
this.flushBuffer();
338+
}
333339
this.processLogItem(LogLevelThreshold.ERROR, input, extraInput);
334340
}
335341

@@ -1168,6 +1174,7 @@ class Logger extends Utility implements LoggerInterface {
11681174
environment,
11691175
jsonReplacerFn,
11701176
logRecordOrder,
1177+
logBufferOptions,
11711178
} = options;
11721179

11731180
if (persistentLogAttributes && persistentKeys) {
@@ -1194,6 +1201,10 @@ class Logger extends Utility implements LoggerInterface {
11941201
this.setLogIndentation();
11951202
this.#jsonReplacerFn = jsonReplacerFn;
11961203

1204+
if (logBufferOptions !== undefined) {
1205+
this.#setLogBuffering(logBufferOptions);
1206+
}
1207+
11971208
return this;
11981209
}
11991210

@@ -1224,6 +1235,30 @@ class Logger extends Utility implements LoggerInterface {
12241235
persistentKeys && this.appendPersistentKeys(persistentKeys);
12251236
}
12261237

1238+
#setLogBuffering(
1239+
options: NonNullable<ConstructorOptions['logBufferOptions']>
1240+
) {
1241+
if (options.maxBytes !== undefined) {
1242+
this.#maxBufferBytesSize = options.maxBytes;
1243+
}
1244+
1245+
this.#buffer = new CircularMap({
1246+
maxBytesSize: this.#maxBufferBytesSize,
1247+
});
1248+
1249+
if (options.enabled !== undefined) {
1250+
this.isBufferEnabled = options.enabled;
1251+
}
1252+
1253+
const bufferAtLogLevel = options.bufferAtVerbosity?.toUpperCase();
1254+
1255+
if (this.isValidLogLevel(bufferAtLogLevel)) {
1256+
this.bufferAtVerbosity = LogLevelThreshold[bufferAtLogLevel];
1257+
1258+
return;
1259+
}
1260+
}
1261+
12271262
/**
12281263
* Add a log to the buffer
12291264
* @param xrayTraceId - _X_AMZN_TRACE_ID of the request
@@ -1243,20 +1278,20 @@ class Logger extends Utility implements LoggerInterface {
12431278
this.logIndentation
12441279
);
12451280

1246-
this.#buffer.setItem(xrayTraceId, stringified, logLevel);
1281+
this.#buffer?.setItem(xrayTraceId, stringified, logLevel);
12471282
}
12481283

12491284
/**
12501285
* Flushes all items of the respective _X_AMZN_TRACE_ID within
12511286
* the buffer.
12521287
*/
1253-
protected flushBuffer(): void {
1288+
flushBuffer(): void {
12541289
const traceId = this.envVarsService.getXrayTraceId();
12551290
if (traceId === undefined) {
12561291
return;
12571292
}
12581293

1259-
const buffer = this.#buffer.get(traceId);
1294+
const buffer = this.#buffer?.get(traceId);
12601295
if (buffer === undefined) {
12611296
return;
12621297
}
@@ -1281,7 +1316,7 @@ class Logger extends Utility implements LoggerInterface {
12811316
);
12821317
}
12831318

1284-
this.#buffer.delete(traceId);
1319+
this.#buffer?.delete(traceId);
12851320
}
12861321
/**
12871322
* Tests if the log meets the criteria to be buffered
@@ -1295,7 +1330,7 @@ class Logger extends Utility implements LoggerInterface {
12951330
return (
12961331
this.isBufferEnabled &&
12971332
traceId !== undefined &&
1298-
logLevel <= this.bufferLogThreshold
1333+
logLevel <= this.bufferAtVerbosity
12991334
);
13001335
}
13011336
}

Diff for: packages/logger/src/types/Logger.ts

+34-1
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,44 @@ type LogRecordOrderOption = {
173173
logFormatter?: never;
174174
};
175175

176+
/**
177+
* Options for the `logBuffer` constructor option.
178+
*
179+
* Used to configure the log buffer functionality.
180+
*/
181+
type LogBufferOption = {
182+
logBufferOptions?: {
183+
/**
184+
* Whether logs should be buffered
185+
*/
186+
enabled?: boolean;
187+
188+
/**
189+
* Maximum size in bytes of each buffer.
190+
*/
191+
maxBytes?: number;
192+
/**
193+
* Flush the buffer when an error is logged
194+
*/
195+
flushOnErrorLog?: boolean;
196+
/**
197+
* The threshold to buffer logs. Logs with a level below
198+
* this threshold will be buffered
199+
*/
200+
bufferAtVerbosity?: Omit<
201+
LogLevel,
202+
'ERROR' | 'error' | 'CRITICAL' | 'critical' | 'SILENT' | 'silent'
203+
>;
204+
};
205+
};
206+
176207
/**
177208
* Options to configure the Logger.
178209
*/
179210
type ConstructorOptions = BaseConstructorOptions &
180211
(PersistentKeysOption | DeprecatedPersistentKeysOption) &
181-
(LogFormatterOption | LogRecordOrderOption);
212+
(LogFormatterOption | LogRecordOrderOption) &
213+
LogBufferOption;
182214

183215
type LogItemMessage = string | LogAttributesWithMessage;
184216
type LogItemExtraInput = [Error | string] | LogAttributes[];
@@ -194,6 +226,7 @@ type LoggerInterface = {
194226
critical(input: LogItemMessage, ...extraInput: LogItemExtraInput): void;
195227
debug(input: LogItemMessage, ...extraInput: LogItemExtraInput): void;
196228
error(input: LogItemMessage, ...extraInput: LogItemExtraInput): void;
229+
flushBuffer(): void;
197230
getLevelName(): Uppercase<LogLevel>;
198231
getLogEvent(): boolean;
199232
getPersistentLogAttributes(): LogAttributes;

0 commit comments

Comments
 (0)