Skip to content

Commit 0cc4096

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 f471552 commit 0cc4096

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

@@ -1167,6 +1173,7 @@ class Logger extends Utility implements LoggerInterface {
11671173
environment,
11681174
jsonReplacerFn,
11691175
logRecordOrder,
1176+
logBufferOptions,
11701177
} = options;
11711178

11721179
if (persistentLogAttributes && persistentKeys) {
@@ -1193,6 +1200,10 @@ class Logger extends Utility implements LoggerInterface {
11931200
this.setLogIndentation();
11941201
this.#jsonReplacerFn = jsonReplacerFn;
11951202

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

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

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

1245-
this.#buffer.setItem(xrayTraceId, stringified, logLevel);
1280+
this.#buffer?.setItem(xrayTraceId, stringified, logLevel);
12461281
}
12471282

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

1258-
const buffer = this.#buffer.get(traceId);
1293+
const buffer = this.#buffer?.get(traceId);
12591294
if (buffer === undefined) {
12601295
return;
12611296
}
@@ -1280,7 +1315,7 @@ class Logger extends Utility implements LoggerInterface {
12801315
);
12811316
}
12821317

1283-
this.#buffer.delete(traceId);
1318+
this.#buffer?.delete(traceId);
12841319
}
12851320
/**
12861321
* Tests if the log meets the criteria to be buffered
@@ -1294,7 +1329,7 @@ class Logger extends Utility implements LoggerInterface {
12941329
return (
12951330
this.isBufferEnabled &&
12961331
traceId !== undefined &&
1297-
logLevel <= this.bufferLogThreshold
1332+
logLevel <= this.bufferAtVerbosity
12981333
);
12991334
}
13001335
}

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)