@rawnodes/logger 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -0
- package/dist/index.d.mts +50 -6
- package/dist/index.d.ts +50 -6
- package/dist/index.js +96 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +95 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -414,6 +414,68 @@ logger.for('payments').error('Payment failed');
|
|
|
414
414
|
logger.for('auth').error('Login failed');
|
|
415
415
|
```
|
|
416
416
|
|
|
417
|
+
## Graceful Shutdown
|
|
418
|
+
|
|
419
|
+
External transports (Discord, Telegram, CloudWatch) buffer messages before sending. To ensure no logs are lost on process exit, use graceful shutdown.
|
|
420
|
+
|
|
421
|
+
### Automatic (Recommended)
|
|
422
|
+
|
|
423
|
+
Enable `autoShutdown` in config to automatically handle SIGTERM/SIGINT:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
const logger = Logger.create({
|
|
427
|
+
level: 'info',
|
|
428
|
+
console: { format: 'plain' },
|
|
429
|
+
cloudwatch: { /* ... */ },
|
|
430
|
+
autoShutdown: true, // Auto-register shutdown handlers
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// Or with options:
|
|
434
|
+
const logger = Logger.create({
|
|
435
|
+
level: 'info',
|
|
436
|
+
console: { format: 'plain' },
|
|
437
|
+
cloudwatch: { /* ... */ },
|
|
438
|
+
autoShutdown: {
|
|
439
|
+
timeout: 10000, // Max wait time (default: 5000ms)
|
|
440
|
+
signals: ['SIGTERM'], // Signals to handle (default: ['SIGTERM', 'SIGINT'])
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Manual
|
|
446
|
+
|
|
447
|
+
For more control, use `registerShutdown` or call `shutdown()` directly:
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
import { Logger, registerShutdown } from '@rawnodes/logger';
|
|
451
|
+
|
|
452
|
+
const logger = Logger.create(config);
|
|
453
|
+
|
|
454
|
+
// Option 1: Register handlers manually
|
|
455
|
+
registerShutdown(logger, {
|
|
456
|
+
timeout: 10000,
|
|
457
|
+
onShutdown: async () => {
|
|
458
|
+
console.log('Flushing logs...');
|
|
459
|
+
},
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
// Option 2: Call shutdown directly (e.g., in your own signal handler)
|
|
463
|
+
process.on('SIGTERM', async () => {
|
|
464
|
+
await logger.shutdown(); // Flush all buffered messages
|
|
465
|
+
process.exit(0);
|
|
466
|
+
});
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### In Tests
|
|
470
|
+
|
|
471
|
+
For tests, call `shutdown()` in `afterAll` to flush pending logs:
|
|
472
|
+
|
|
473
|
+
```typescript
|
|
474
|
+
afterAll(async () => {
|
|
475
|
+
await logger.shutdown();
|
|
476
|
+
});
|
|
477
|
+
```
|
|
478
|
+
|
|
417
479
|
## Singleton Pattern
|
|
418
480
|
|
|
419
481
|
For app-wide logging:
|
package/dist/index.d.mts
CHANGED
|
@@ -100,6 +100,12 @@ interface CallerInfo {
|
|
|
100
100
|
column?: number;
|
|
101
101
|
function?: string;
|
|
102
102
|
}
|
|
103
|
+
interface AutoShutdownConfig {
|
|
104
|
+
/** Timeout in ms before forcing exit (default: 5000) */
|
|
105
|
+
timeout?: number;
|
|
106
|
+
/** Custom signals to handle (default: ['SIGTERM', 'SIGINT']) */
|
|
107
|
+
signals?: NodeJS.Signals[];
|
|
108
|
+
}
|
|
103
109
|
interface LoggerConfig {
|
|
104
110
|
level: LevelConfig;
|
|
105
111
|
console: ConsoleConfig;
|
|
@@ -111,6 +117,8 @@ interface LoggerConfig {
|
|
|
111
117
|
caller?: boolean | CallerConfig;
|
|
112
118
|
/** Hostname to include in all log entries. Defaults to os.hostname() if not specified */
|
|
113
119
|
hostname?: string;
|
|
120
|
+
/** Auto-register graceful shutdown handlers. Pass true for defaults or config object */
|
|
121
|
+
autoShutdown?: boolean | AutoShutdownConfig;
|
|
114
122
|
}
|
|
115
123
|
type LoggerContext = Record<string, unknown>;
|
|
116
124
|
type LevelOverrideMatch<TContext extends LoggerContext> = Partial<TContext> & {
|
|
@@ -141,6 +149,11 @@ declare class Logger<TContext extends LoggerContext = LoggerContext> {
|
|
|
141
149
|
removeLevelOverride(match: LevelOverrideMatch<TContext>): boolean;
|
|
142
150
|
clearLevelOverrides(): void;
|
|
143
151
|
getLevelOverrides(): LevelOverride<TContext>[];
|
|
152
|
+
/**
|
|
153
|
+
* Gracefully shutdown the logger, flushing all pending messages.
|
|
154
|
+
* Should be called before process exit to ensure no logs are lost.
|
|
155
|
+
*/
|
|
156
|
+
shutdown(): Promise<void>;
|
|
144
157
|
profile(id: string, meta?: object): void;
|
|
145
158
|
error(errorOrMessage: Error | string, messageOrMeta?: string | Meta, meta?: Meta): void;
|
|
146
159
|
warn(message: string, meta?: Meta): void;
|
|
@@ -165,10 +178,6 @@ interface SingletonLogger<TContext extends LoggerContext> {
|
|
|
165
178
|
}
|
|
166
179
|
declare function createSingletonLogger<TContext extends LoggerContext = LoggerContext>(): SingletonLogger<TContext>;
|
|
167
180
|
|
|
168
|
-
declare function matchesContext(storeContext: LoggerContext | undefined, loggerContext: string | undefined, match: Record<string, unknown> & {
|
|
169
|
-
context?: string;
|
|
170
|
-
}): boolean;
|
|
171
|
-
|
|
172
181
|
interface BufferedMessage {
|
|
173
182
|
level: LogLevel;
|
|
174
183
|
message: string;
|
|
@@ -216,6 +225,10 @@ declare abstract class BaseHttpTransport extends EventEmitter {
|
|
|
216
225
|
protected abstract sendBatch(messages: BufferedMessage[]): Promise<void>;
|
|
217
226
|
}
|
|
218
227
|
|
|
228
|
+
declare function matchesContext(storeContext: LoggerContext | undefined, loggerContext: string | undefined, match: Record<string, unknown> & {
|
|
229
|
+
context?: string;
|
|
230
|
+
}): boolean;
|
|
231
|
+
|
|
219
232
|
declare class DiscordTransport extends BaseHttpTransport {
|
|
220
233
|
private config;
|
|
221
234
|
constructor(config: DiscordConfig);
|
|
@@ -295,7 +308,35 @@ declare function createMasker(options?: MaskSecretsOptions): (obj: unknown) => u
|
|
|
295
308
|
declare function getCallerInfo(config: CallerConfig, additionalOffset?: number): CallerInfo | undefined;
|
|
296
309
|
declare function formatCallerInfo(info: CallerInfo): string;
|
|
297
310
|
|
|
298
|
-
|
|
311
|
+
interface GracefulShutdownOptions {
|
|
312
|
+
/** Timeout in ms before forcing exit (default: 5000) */
|
|
313
|
+
timeout?: number;
|
|
314
|
+
/** Exit code on successful shutdown (default: 0) */
|
|
315
|
+
exitCode?: number;
|
|
316
|
+
/** Custom signals to handle (default: ['SIGTERM', 'SIGINT']) */
|
|
317
|
+
signals?: NodeJS.Signals[];
|
|
318
|
+
/** Called before shutdown starts */
|
|
319
|
+
onShutdown?: () => void | Promise<void>;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Register graceful shutdown handlers for the logger.
|
|
323
|
+
* Ensures all buffered logs are flushed before process exit.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```typescript
|
|
327
|
+
* const logger = Logger.create(config);
|
|
328
|
+
* registerShutdown(logger);
|
|
329
|
+
*
|
|
330
|
+
* // Or with options:
|
|
331
|
+
* registerShutdown(logger, {
|
|
332
|
+
* timeout: 10000,
|
|
333
|
+
* onShutdown: () => console.log('Shutting down...'),
|
|
334
|
+
* });
|
|
335
|
+
* ```
|
|
336
|
+
*/
|
|
337
|
+
declare function registerShutdown<TContext extends LoggerContext>(logger: Logger<TContext>, options?: GracefulShutdownOptions): () => Promise<void>;
|
|
338
|
+
|
|
339
|
+
declare function flattenObject(obj: Record<string, unknown>, prefix?: string, ancestors?: WeakSet<object>, depth?: number): Record<string, unknown>;
|
|
299
340
|
declare function formatLogfmtValue(value: unknown): string;
|
|
300
341
|
declare function formatLogfmt(data: Record<string, unknown>): string;
|
|
301
342
|
|
|
@@ -315,6 +356,7 @@ declare const CloudWatchConfigSchema: z.ZodType<CloudWatchConfig>;
|
|
|
315
356
|
declare const LevelConfigObjectSchema: z.ZodType<LevelConfigObject>;
|
|
316
357
|
declare const LevelConfigSchema: z.ZodType<LevelConfig>;
|
|
317
358
|
declare const CallerConfigSchema: z.ZodType<CallerConfig>;
|
|
359
|
+
declare const AutoShutdownConfigSchema: z.ZodType<AutoShutdownConfig>;
|
|
318
360
|
declare const LoggerConfigSchema: z.ZodObject<{
|
|
319
361
|
level: z.ZodType<LevelConfig, unknown, z.core.$ZodTypeInternals<LevelConfig, unknown>>;
|
|
320
362
|
console: z.ZodType<ConsoleConfig, unknown, z.core.$ZodTypeInternals<ConsoleConfig, unknown>>;
|
|
@@ -324,6 +366,7 @@ declare const LoggerConfigSchema: z.ZodObject<{
|
|
|
324
366
|
cloudwatch: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<CloudWatchConfig, unknown, z.core.$ZodTypeInternals<CloudWatchConfig, unknown>>, z.ZodArray<z.ZodType<CloudWatchConfig, unknown, z.core.$ZodTypeInternals<CloudWatchConfig, unknown>>>]>>;
|
|
325
367
|
caller: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodType<CallerConfig, unknown, z.core.$ZodTypeInternals<CallerConfig, unknown>>]>>;
|
|
326
368
|
hostname: z.ZodOptional<z.ZodString>;
|
|
369
|
+
autoShutdown: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodType<AutoShutdownConfig, unknown, z.core.$ZodTypeInternals<AutoShutdownConfig, unknown>>]>>;
|
|
327
370
|
}, z.core.$strip>;
|
|
328
371
|
declare function validateConfig(config: unknown): z.infer<typeof LoggerConfigSchema>;
|
|
329
372
|
declare function safeValidateConfig(config: unknown): z.ZodSafeParseResult<{
|
|
@@ -335,6 +378,7 @@ declare function safeValidateConfig(config: unknown): z.ZodSafeParseResult<{
|
|
|
335
378
|
cloudwatch?: CloudWatchConfig | CloudWatchConfig[] | undefined;
|
|
336
379
|
caller?: boolean | CallerConfig | undefined;
|
|
337
380
|
hostname?: string | undefined;
|
|
381
|
+
autoShutdown?: boolean | AutoShutdownConfig | undefined;
|
|
338
382
|
}>;
|
|
339
383
|
|
|
340
|
-
export { BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, safeValidateConfig, validateConfig };
|
|
384
|
+
export { type AutoShutdownConfig, AutoShutdownConfigSchema, BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type GracefulShutdownOptions, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, registerShutdown, safeValidateConfig, validateConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -100,6 +100,12 @@ interface CallerInfo {
|
|
|
100
100
|
column?: number;
|
|
101
101
|
function?: string;
|
|
102
102
|
}
|
|
103
|
+
interface AutoShutdownConfig {
|
|
104
|
+
/** Timeout in ms before forcing exit (default: 5000) */
|
|
105
|
+
timeout?: number;
|
|
106
|
+
/** Custom signals to handle (default: ['SIGTERM', 'SIGINT']) */
|
|
107
|
+
signals?: NodeJS.Signals[];
|
|
108
|
+
}
|
|
103
109
|
interface LoggerConfig {
|
|
104
110
|
level: LevelConfig;
|
|
105
111
|
console: ConsoleConfig;
|
|
@@ -111,6 +117,8 @@ interface LoggerConfig {
|
|
|
111
117
|
caller?: boolean | CallerConfig;
|
|
112
118
|
/** Hostname to include in all log entries. Defaults to os.hostname() if not specified */
|
|
113
119
|
hostname?: string;
|
|
120
|
+
/** Auto-register graceful shutdown handlers. Pass true for defaults or config object */
|
|
121
|
+
autoShutdown?: boolean | AutoShutdownConfig;
|
|
114
122
|
}
|
|
115
123
|
type LoggerContext = Record<string, unknown>;
|
|
116
124
|
type LevelOverrideMatch<TContext extends LoggerContext> = Partial<TContext> & {
|
|
@@ -141,6 +149,11 @@ declare class Logger<TContext extends LoggerContext = LoggerContext> {
|
|
|
141
149
|
removeLevelOverride(match: LevelOverrideMatch<TContext>): boolean;
|
|
142
150
|
clearLevelOverrides(): void;
|
|
143
151
|
getLevelOverrides(): LevelOverride<TContext>[];
|
|
152
|
+
/**
|
|
153
|
+
* Gracefully shutdown the logger, flushing all pending messages.
|
|
154
|
+
* Should be called before process exit to ensure no logs are lost.
|
|
155
|
+
*/
|
|
156
|
+
shutdown(): Promise<void>;
|
|
144
157
|
profile(id: string, meta?: object): void;
|
|
145
158
|
error(errorOrMessage: Error | string, messageOrMeta?: string | Meta, meta?: Meta): void;
|
|
146
159
|
warn(message: string, meta?: Meta): void;
|
|
@@ -165,10 +178,6 @@ interface SingletonLogger<TContext extends LoggerContext> {
|
|
|
165
178
|
}
|
|
166
179
|
declare function createSingletonLogger<TContext extends LoggerContext = LoggerContext>(): SingletonLogger<TContext>;
|
|
167
180
|
|
|
168
|
-
declare function matchesContext(storeContext: LoggerContext | undefined, loggerContext: string | undefined, match: Record<string, unknown> & {
|
|
169
|
-
context?: string;
|
|
170
|
-
}): boolean;
|
|
171
|
-
|
|
172
181
|
interface BufferedMessage {
|
|
173
182
|
level: LogLevel;
|
|
174
183
|
message: string;
|
|
@@ -216,6 +225,10 @@ declare abstract class BaseHttpTransport extends EventEmitter {
|
|
|
216
225
|
protected abstract sendBatch(messages: BufferedMessage[]): Promise<void>;
|
|
217
226
|
}
|
|
218
227
|
|
|
228
|
+
declare function matchesContext(storeContext: LoggerContext | undefined, loggerContext: string | undefined, match: Record<string, unknown> & {
|
|
229
|
+
context?: string;
|
|
230
|
+
}): boolean;
|
|
231
|
+
|
|
219
232
|
declare class DiscordTransport extends BaseHttpTransport {
|
|
220
233
|
private config;
|
|
221
234
|
constructor(config: DiscordConfig);
|
|
@@ -295,7 +308,35 @@ declare function createMasker(options?: MaskSecretsOptions): (obj: unknown) => u
|
|
|
295
308
|
declare function getCallerInfo(config: CallerConfig, additionalOffset?: number): CallerInfo | undefined;
|
|
296
309
|
declare function formatCallerInfo(info: CallerInfo): string;
|
|
297
310
|
|
|
298
|
-
|
|
311
|
+
interface GracefulShutdownOptions {
|
|
312
|
+
/** Timeout in ms before forcing exit (default: 5000) */
|
|
313
|
+
timeout?: number;
|
|
314
|
+
/** Exit code on successful shutdown (default: 0) */
|
|
315
|
+
exitCode?: number;
|
|
316
|
+
/** Custom signals to handle (default: ['SIGTERM', 'SIGINT']) */
|
|
317
|
+
signals?: NodeJS.Signals[];
|
|
318
|
+
/** Called before shutdown starts */
|
|
319
|
+
onShutdown?: () => void | Promise<void>;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Register graceful shutdown handlers for the logger.
|
|
323
|
+
* Ensures all buffered logs are flushed before process exit.
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```typescript
|
|
327
|
+
* const logger = Logger.create(config);
|
|
328
|
+
* registerShutdown(logger);
|
|
329
|
+
*
|
|
330
|
+
* // Or with options:
|
|
331
|
+
* registerShutdown(logger, {
|
|
332
|
+
* timeout: 10000,
|
|
333
|
+
* onShutdown: () => console.log('Shutting down...'),
|
|
334
|
+
* });
|
|
335
|
+
* ```
|
|
336
|
+
*/
|
|
337
|
+
declare function registerShutdown<TContext extends LoggerContext>(logger: Logger<TContext>, options?: GracefulShutdownOptions): () => Promise<void>;
|
|
338
|
+
|
|
339
|
+
declare function flattenObject(obj: Record<string, unknown>, prefix?: string, ancestors?: WeakSet<object>, depth?: number): Record<string, unknown>;
|
|
299
340
|
declare function formatLogfmtValue(value: unknown): string;
|
|
300
341
|
declare function formatLogfmt(data: Record<string, unknown>): string;
|
|
301
342
|
|
|
@@ -315,6 +356,7 @@ declare const CloudWatchConfigSchema: z.ZodType<CloudWatchConfig>;
|
|
|
315
356
|
declare const LevelConfigObjectSchema: z.ZodType<LevelConfigObject>;
|
|
316
357
|
declare const LevelConfigSchema: z.ZodType<LevelConfig>;
|
|
317
358
|
declare const CallerConfigSchema: z.ZodType<CallerConfig>;
|
|
359
|
+
declare const AutoShutdownConfigSchema: z.ZodType<AutoShutdownConfig>;
|
|
318
360
|
declare const LoggerConfigSchema: z.ZodObject<{
|
|
319
361
|
level: z.ZodType<LevelConfig, unknown, z.core.$ZodTypeInternals<LevelConfig, unknown>>;
|
|
320
362
|
console: z.ZodType<ConsoleConfig, unknown, z.core.$ZodTypeInternals<ConsoleConfig, unknown>>;
|
|
@@ -324,6 +366,7 @@ declare const LoggerConfigSchema: z.ZodObject<{
|
|
|
324
366
|
cloudwatch: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<CloudWatchConfig, unknown, z.core.$ZodTypeInternals<CloudWatchConfig, unknown>>, z.ZodArray<z.ZodType<CloudWatchConfig, unknown, z.core.$ZodTypeInternals<CloudWatchConfig, unknown>>>]>>;
|
|
325
367
|
caller: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodType<CallerConfig, unknown, z.core.$ZodTypeInternals<CallerConfig, unknown>>]>>;
|
|
326
368
|
hostname: z.ZodOptional<z.ZodString>;
|
|
369
|
+
autoShutdown: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodType<AutoShutdownConfig, unknown, z.core.$ZodTypeInternals<AutoShutdownConfig, unknown>>]>>;
|
|
327
370
|
}, z.core.$strip>;
|
|
328
371
|
declare function validateConfig(config: unknown): z.infer<typeof LoggerConfigSchema>;
|
|
329
372
|
declare function safeValidateConfig(config: unknown): z.ZodSafeParseResult<{
|
|
@@ -335,6 +378,7 @@ declare function safeValidateConfig(config: unknown): z.ZodSafeParseResult<{
|
|
|
335
378
|
cloudwatch?: CloudWatchConfig | CloudWatchConfig[] | undefined;
|
|
336
379
|
caller?: boolean | CallerConfig | undefined;
|
|
337
380
|
hostname?: string | undefined;
|
|
381
|
+
autoShutdown?: boolean | AutoShutdownConfig | undefined;
|
|
338
382
|
}>;
|
|
339
383
|
|
|
340
|
-
export { BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, safeValidateConfig, validateConfig };
|
|
384
|
+
export { type AutoShutdownConfig, AutoShutdownConfigSchema, BaseHttpTransport, type BaseHttpTransportOptions, type BufferOptions, type BufferedMessage, type CallerConfig, CallerConfigSchema, type CallerInfo, type CloudWatchConfig, CloudWatchConfigSchema, CloudWatchTransport, type ConsoleConfig, ConsoleConfigSchema, type DiscordConfig, DiscordConfigSchema, DiscordTransport, type FileConfig, FileConfigSchema, type GracefulShutdownOptions, type HttpTransportBaseConfig, HttpTransportBaseConfigSchema, LOG_LEVELS, type LevelConfig, type LevelConfigObject, LevelConfigObjectSchema, LevelConfigSchema, type LevelOverride, type LevelOverrideMatch, type LevelRule, LevelRuleSchema, type LogFormat, LogFormatSchema, type LogLevel, LogLevelSchema, type LogStreamName, LogStreamNameSchema, type LogStreamPattern, type LogStreamPatternConfig, LogStreamPatternConfigSchema, LogStreamPatternSchema, type LogStreamTemplateConfig, LogStreamTemplateConfigSchema, Logger, type LoggerConfig, LoggerConfigSchema, type LoggerContext, LoggerStore, type MaskSecretsOptions, MessageBuffer, type Meta, type RequestIdOptions, type SingletonLogger, type TelegramConfig, TelegramConfigSchema, TelegramTransport, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatCallerInfo, formatLogfmt, formatLogfmtValue, generateRequestId, getCallerInfo, getOrGenerateRequestId, isValidLogLevel, maskSecrets, matchesContext, measureAsync, measureSync, registerShutdown, safeValidateConfig, validateConfig };
|
package/dist/index.js
CHANGED
|
@@ -689,6 +689,7 @@ function createFormattedFilterStream(format, level, rules, store, destination) {
|
|
|
689
689
|
}
|
|
690
690
|
function createStreams(config, store) {
|
|
691
691
|
const streams = [];
|
|
692
|
+
const transports = [];
|
|
692
693
|
const consoleStream = createFormattedFilterStream(
|
|
693
694
|
config.console.format,
|
|
694
695
|
config.console.level,
|
|
@@ -736,6 +737,7 @@ function createStreams(config, store) {
|
|
|
736
737
|
}
|
|
737
738
|
for (const discordConfig of toArray(config.discord)) {
|
|
738
739
|
const transport = new DiscordTransport(discordConfig);
|
|
740
|
+
transports.push(transport);
|
|
739
741
|
const discordStream = createHttpTransportStream(transport, discordConfig.level, discordConfig.rules, store);
|
|
740
742
|
streams.push({
|
|
741
743
|
level: "trace",
|
|
@@ -744,6 +746,7 @@ function createStreams(config, store) {
|
|
|
744
746
|
}
|
|
745
747
|
for (const telegramConfig of toArray(config.telegram)) {
|
|
746
748
|
const transport = new TelegramTransport(telegramConfig);
|
|
749
|
+
transports.push(transport);
|
|
747
750
|
const telegramStream = createHttpTransportStream(transport, telegramConfig.level, telegramConfig.rules, store);
|
|
748
751
|
streams.push({
|
|
749
752
|
level: "trace",
|
|
@@ -752,13 +755,17 @@ function createStreams(config, store) {
|
|
|
752
755
|
}
|
|
753
756
|
for (const cloudwatchConfig of toArray(config.cloudwatch)) {
|
|
754
757
|
const transport = new CloudWatchTransport(cloudwatchConfig, config.hostname);
|
|
758
|
+
transports.push(transport);
|
|
755
759
|
const cwStream = createHttpTransportStream(transport, cloudwatchConfig.level, cloudwatchConfig.rules, store);
|
|
756
760
|
streams.push({
|
|
757
761
|
level: "trace",
|
|
758
762
|
stream: cwStream
|
|
759
763
|
});
|
|
760
764
|
}
|
|
761
|
-
return
|
|
765
|
+
return {
|
|
766
|
+
destination: pino__default.default.multistream(streams),
|
|
767
|
+
transports
|
|
768
|
+
};
|
|
762
769
|
}
|
|
763
770
|
function toArray(value) {
|
|
764
771
|
if (!value) return [];
|
|
@@ -843,14 +850,14 @@ function createState(config, store) {
|
|
|
843
850
|
levelOverrides.set(key, rule);
|
|
844
851
|
}
|
|
845
852
|
const { contextIndex, complexRules } = buildIndexes(levelOverrides);
|
|
846
|
-
const
|
|
853
|
+
const { destination, transports } = createStreams(config, loggerStore);
|
|
847
854
|
const options = {
|
|
848
855
|
level: "trace",
|
|
849
856
|
// Accept all, we filter in shouldLog()
|
|
850
857
|
customLevels: CUSTOM_LEVELS,
|
|
851
858
|
base: { hostname: config.hostname ?? os.hostname() }
|
|
852
859
|
};
|
|
853
|
-
const pinoLogger = pino__default.default(options,
|
|
860
|
+
const pinoLogger = pino__default.default(options, destination);
|
|
854
861
|
let callerConfig;
|
|
855
862
|
if (config.caller === true) {
|
|
856
863
|
callerConfig = {};
|
|
@@ -864,7 +871,8 @@ function createState(config, store) {
|
|
|
864
871
|
levelOverrides,
|
|
865
872
|
contextIndex,
|
|
866
873
|
complexRules,
|
|
867
|
-
callerConfig
|
|
874
|
+
callerConfig,
|
|
875
|
+
transports
|
|
868
876
|
};
|
|
869
877
|
}
|
|
870
878
|
function rebuildIndexes(state) {
|
|
@@ -1010,6 +1018,10 @@ var CallerConfigSchema = zod.z.object({
|
|
|
1010
1018
|
depth: zod.z.number().int().nonnegative().optional(),
|
|
1011
1019
|
fullPath: zod.z.boolean().optional()
|
|
1012
1020
|
});
|
|
1021
|
+
var AutoShutdownConfigSchema = zod.z.object({
|
|
1022
|
+
timeout: zod.z.number().int().positive().optional(),
|
|
1023
|
+
signals: zod.z.array(zod.z.string()).optional()
|
|
1024
|
+
});
|
|
1013
1025
|
var LoggerConfigSchema = zod.z.object({
|
|
1014
1026
|
level: LevelConfigSchema,
|
|
1015
1027
|
console: ConsoleConfigSchema,
|
|
@@ -1018,7 +1030,8 @@ var LoggerConfigSchema = zod.z.object({
|
|
|
1018
1030
|
telegram: zod.z.union([TelegramConfigSchema, zod.z.array(TelegramConfigSchema)]).optional(),
|
|
1019
1031
|
cloudwatch: zod.z.union([CloudWatchConfigSchema, zod.z.array(CloudWatchConfigSchema)]).optional(),
|
|
1020
1032
|
caller: zod.z.union([zod.z.boolean(), CallerConfigSchema]).optional(),
|
|
1021
|
-
hostname: zod.z.string().optional()
|
|
1033
|
+
hostname: zod.z.string().optional(),
|
|
1034
|
+
autoShutdown: zod.z.union([zod.z.boolean(), AutoShutdownConfigSchema]).optional()
|
|
1022
1035
|
});
|
|
1023
1036
|
function validateConfig(config) {
|
|
1024
1037
|
return LoggerConfigSchema.parse(config);
|
|
@@ -1087,6 +1100,53 @@ function formatCallerInfo(info) {
|
|
|
1087
1100
|
return location;
|
|
1088
1101
|
}
|
|
1089
1102
|
|
|
1103
|
+
// src/utils/shutdown.ts
|
|
1104
|
+
var DEFAULT_OPTIONS2 = {
|
|
1105
|
+
timeout: 5e3,
|
|
1106
|
+
exitCode: 0,
|
|
1107
|
+
signals: ["SIGTERM", "SIGINT"]
|
|
1108
|
+
};
|
|
1109
|
+
var registered = false;
|
|
1110
|
+
function registerShutdown(logger, options = {}) {
|
|
1111
|
+
const opts = { ...DEFAULT_OPTIONS2, ...options };
|
|
1112
|
+
const shutdown = async (signal) => {
|
|
1113
|
+
if (signal) {
|
|
1114
|
+
console.error(`[Logger] Received ${signal}, shutting down gracefully...`);
|
|
1115
|
+
}
|
|
1116
|
+
try {
|
|
1117
|
+
if (opts.onShutdown) {
|
|
1118
|
+
await opts.onShutdown();
|
|
1119
|
+
}
|
|
1120
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
1121
|
+
setTimeout(() => {
|
|
1122
|
+
reject(new Error(`Shutdown timed out after ${opts.timeout}ms`));
|
|
1123
|
+
}, opts.timeout);
|
|
1124
|
+
});
|
|
1125
|
+
await Promise.race([
|
|
1126
|
+
logger.shutdown(),
|
|
1127
|
+
timeoutPromise
|
|
1128
|
+
]);
|
|
1129
|
+
if (signal) {
|
|
1130
|
+
console.error("[Logger] Graceful shutdown completed");
|
|
1131
|
+
process.exit(opts.exitCode);
|
|
1132
|
+
}
|
|
1133
|
+
} catch (error) {
|
|
1134
|
+
console.error("[Logger] Shutdown error:", error instanceof Error ? error.message : error);
|
|
1135
|
+
if (signal) {
|
|
1136
|
+
process.exit(1);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
if (!registered) {
|
|
1141
|
+
for (const signal of opts.signals) {
|
|
1142
|
+
process.on(signal, () => void shutdown(signal));
|
|
1143
|
+
}
|
|
1144
|
+
process.on("beforeExit", () => void shutdown());
|
|
1145
|
+
registered = true;
|
|
1146
|
+
}
|
|
1147
|
+
return shutdown;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1090
1150
|
// src/logger.ts
|
|
1091
1151
|
var Logger = class _Logger {
|
|
1092
1152
|
constructor(state, context) {
|
|
@@ -1097,7 +1157,12 @@ var Logger = class _Logger {
|
|
|
1097
1157
|
static create(config, store) {
|
|
1098
1158
|
const validatedConfig = validateConfig(config);
|
|
1099
1159
|
const state = createState(validatedConfig, store);
|
|
1100
|
-
|
|
1160
|
+
const logger = new _Logger(state, "APP");
|
|
1161
|
+
if (validatedConfig.autoShutdown) {
|
|
1162
|
+
const shutdownConfig = typeof validatedConfig.autoShutdown === "object" ? validatedConfig.autoShutdown : {};
|
|
1163
|
+
registerShutdown(logger, shutdownConfig);
|
|
1164
|
+
}
|
|
1165
|
+
return logger;
|
|
1101
1166
|
}
|
|
1102
1167
|
for(context) {
|
|
1103
1168
|
return new _Logger(this.state, context);
|
|
@@ -1139,6 +1204,15 @@ var Logger = class _Logger {
|
|
|
1139
1204
|
getLevelOverrides() {
|
|
1140
1205
|
return Array.from(this.state.levelOverrides.values());
|
|
1141
1206
|
}
|
|
1207
|
+
// Shutdown
|
|
1208
|
+
/**
|
|
1209
|
+
* Gracefully shutdown the logger, flushing all pending messages.
|
|
1210
|
+
* Should be called before process exit to ensure no logs are lost.
|
|
1211
|
+
*/
|
|
1212
|
+
async shutdown() {
|
|
1213
|
+
const closePromises = this.state.transports.map((transport) => transport.close());
|
|
1214
|
+
await Promise.all(closePromises);
|
|
1215
|
+
}
|
|
1142
1216
|
// Profiling
|
|
1143
1217
|
profile(id, meta) {
|
|
1144
1218
|
const existing = this.profileTimers.get(id);
|
|
@@ -1405,16 +1479,28 @@ function createMasker(options = {}) {
|
|
|
1405
1479
|
}
|
|
1406
1480
|
|
|
1407
1481
|
// src/formatters.ts
|
|
1408
|
-
|
|
1482
|
+
var MAX_FLATTEN_DEPTH = 10;
|
|
1483
|
+
var CIRCULAR_REF = "[Circular]";
|
|
1484
|
+
function flattenObject(obj, prefix = "", ancestors = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
1409
1485
|
const result = {};
|
|
1486
|
+
if (depth > MAX_FLATTEN_DEPTH) {
|
|
1487
|
+
result[prefix || "value"] = "[Max depth exceeded]";
|
|
1488
|
+
return result;
|
|
1489
|
+
}
|
|
1490
|
+
ancestors.add(obj);
|
|
1410
1491
|
for (const [key, value] of Object.entries(obj)) {
|
|
1411
1492
|
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
1412
1493
|
if (value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Error)) {
|
|
1413
|
-
|
|
1494
|
+
if (ancestors.has(value)) {
|
|
1495
|
+
result[newKey] = CIRCULAR_REF;
|
|
1496
|
+
} else {
|
|
1497
|
+
Object.assign(result, flattenObject(value, newKey, ancestors, depth + 1));
|
|
1498
|
+
}
|
|
1414
1499
|
} else {
|
|
1415
1500
|
result[newKey] = value;
|
|
1416
1501
|
}
|
|
1417
1502
|
}
|
|
1503
|
+
ancestors.delete(obj);
|
|
1418
1504
|
return result;
|
|
1419
1505
|
}
|
|
1420
1506
|
function formatLogfmtValue(value) {
|
|
@@ -1443,6 +1529,7 @@ function formatLogfmt(data) {
|
|
|
1443
1529
|
return Object.entries(flattened).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}=${formatLogfmtValue(value)}`).join(" ");
|
|
1444
1530
|
}
|
|
1445
1531
|
|
|
1532
|
+
exports.AutoShutdownConfigSchema = AutoShutdownConfigSchema;
|
|
1446
1533
|
exports.BaseHttpTransport = BaseHttpTransport;
|
|
1447
1534
|
exports.CallerConfigSchema = CallerConfigSchema;
|
|
1448
1535
|
exports.CloudWatchConfigSchema = CloudWatchConfigSchema;
|
|
@@ -1484,6 +1571,7 @@ exports.maskSecrets = maskSecrets;
|
|
|
1484
1571
|
exports.matchesContext = matchesContext;
|
|
1485
1572
|
exports.measureAsync = measureAsync;
|
|
1486
1573
|
exports.measureSync = measureSync;
|
|
1574
|
+
exports.registerShutdown = registerShutdown;
|
|
1487
1575
|
exports.safeValidateConfig = safeValidateConfig;
|
|
1488
1576
|
exports.validateConfig = validateConfig;
|
|
1489
1577
|
//# sourceMappingURL=index.js.map
|