@rawnodes/logger 1.5.1 → 1.7.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 CHANGED
@@ -1,16 +1,16 @@
1
1
  # @rawnodes/logger
2
2
 
3
- Flexible Winston-based logger with AsyncLocalStorage context, level overrides, and timing utilities.
3
+ Flexible Winston-based logger with AsyncLocalStorage context, level rules, and multiple output formats.
4
4
 
5
5
  ## Features
6
6
 
7
+ - **Multiple Formats** - JSON, plain (colored), logfmt, simple
7
8
  - **Context Propagation** - Automatic context via AsyncLocalStorage
8
- - **Level Overrides** - Debug specific users/modules without global log level change
9
+ - **Level Rules** - Configure log levels per module/context in config
9
10
  - **Lazy Meta** - Defer metadata creation until log level check passes
10
11
  - **Timing Utilities** - Built-in performance measurement
11
12
  - **Request ID** - Generate and extract request IDs
12
- - **Secret Masking** - Mask sensitive data in logs
13
- - **Singleton Factory** - Easy setup with `createSingletonLogger()`
13
+ - **Secret Masking** - Automatic masking of sensitive data
14
14
  - **TypeScript First** - Full generic type support
15
15
 
16
16
  ## Installation
@@ -23,241 +23,321 @@ npm install @rawnodes/logger
23
23
 
24
24
  ## Quick Start
25
25
 
26
- ### 1. Create your app logger
27
-
28
26
  ```typescript
29
- // src/logger/app.logger.ts
30
- import { createSingletonLogger, type LoggerContext } from '@rawnodes/logger';
27
+ import { Logger } from '@rawnodes/logger';
31
28
 
32
- export interface AppLoggerContext extends LoggerContext {
33
- userId?: number;
34
- requestId?: string;
35
- }
29
+ const logger = Logger.create({
30
+ level: 'info',
31
+ console: { format: 'plain' },
32
+ });
36
33
 
37
- export const AppLogger = createSingletonLogger<AppLoggerContext>();
34
+ logger.info('Hello world');
35
+ logger.info('User logged in', { userId: 123 });
38
36
  ```
39
37
 
40
- ### 2. Initialize on startup
38
+ ## Configuration
39
+
40
+ ### Basic Config
41
41
 
42
42
  ```typescript
43
- // src/main.ts
44
- import { AppLogger } from './logger/app.logger.js';
43
+ import { Logger } from '@rawnodes/logger';
45
44
 
46
- AppLogger.getInstance({
47
- level: 'info',
48
- console: { level: 'debug' },
49
- file: {
45
+ const logger = Logger.create({
46
+ level: 'info', // default log level
47
+ console: { format: 'plain' }, // console output format
48
+ file: { // optional file output
49
+ format: 'json',
50
50
  dirname: 'logs',
51
51
  filename: 'app-%DATE%.log',
52
- level: 'info',
53
52
  datePattern: 'YYYY-MM-DD',
54
53
  maxFiles: '14d',
54
+ maxSize: '20m',
55
55
  },
56
56
  });
57
57
  ```
58
58
 
59
- ### 3. Use in your code
59
+ ### Level Rules
60
+
61
+ Configure different log levels for specific modules or contexts:
60
62
 
61
63
  ```typescript
62
- import { AppLogger } from './logger/app.logger.js';
64
+ const logger = Logger.create({
65
+ level: {
66
+ default: 'info',
67
+ rules: [
68
+ { match: { context: 'auth' }, level: 'debug' }, // debug for auth module
69
+ { match: { context: 'database' }, level: 'warn' }, // warn for database
70
+ { match: { userId: 123 }, level: 'debug' }, // debug for user 123
71
+ { match: { context: 'api', userId: 456 }, level: 'silly' }, // combined match
72
+ ],
73
+ },
74
+ console: { format: 'plain' },
75
+ });
63
76
 
64
- const logger = AppLogger.for('UserService');
77
+ const authLogger = logger.for('auth');
78
+ authLogger.debug('This will be logged'); // matches rule
79
+
80
+ const dbLogger = logger.for('database');
81
+ dbLogger.info('This will NOT be logged'); // level is warn
82
+ ```
83
+
84
+ Rules from config are **readonly** and cannot be removed via API.
65
85
 
86
+ ### Output Formats
87
+
88
+ | Format | Description | Example |
89
+ |--------|-------------|---------|
90
+ | `json` | Structured JSON | `{"level":"info","message":"hello","timestamp":"..."}` |
91
+ | `plain` | Colored, human-readable | `[2025-01-01T12:00:00] info [APP] hello` |
92
+ | `logfmt` | Key=value pairs | `level=info msg=hello context=APP ts=2025-01-01T12:00:00` |
93
+ | `simple` | Minimal | `[2025-01-01T12:00:00] info: hello` |
94
+
95
+ ```typescript
96
+ // Different formats for console and file
97
+ const logger = Logger.create({
98
+ level: 'info',
99
+ console: { format: 'plain' }, // colored for development
100
+ file: {
101
+ format: 'json', // structured for log aggregation
102
+ dirname: 'logs',
103
+ filename: 'app-%DATE%.log',
104
+ },
105
+ });
106
+ ```
107
+
108
+ ## Singleton Pattern
109
+
110
+ For app-wide logging:
111
+
112
+ ```typescript
113
+ // src/logger.ts
114
+ import { createSingletonLogger, type LoggerContext } from '@rawnodes/logger';
115
+
116
+ export interface AppContext extends LoggerContext {
117
+ userId?: number;
118
+ requestId?: string;
119
+ }
120
+
121
+ export const AppLogger = createSingletonLogger<AppContext>();
122
+
123
+ // src/main.ts
124
+ import { AppLogger } from './logger.js';
125
+
126
+ AppLogger.init({
127
+ level: {
128
+ default: 'info',
129
+ rules: [{ match: { context: 'debug-module' }, level: 'debug' }],
130
+ },
131
+ console: { format: 'plain' },
132
+ });
133
+
134
+ // Anywhere in your app
135
+ const logger = AppLogger.for('UserService');
66
136
  logger.info('User created', { userId: 123 });
67
- logger.error('Failed to create user', { error });
68
137
  ```
69
138
 
70
- ### 4. Add context in middleware
139
+ ## Context Propagation
140
+
141
+ Automatically include context in all logs within an async scope:
71
142
 
72
143
  ```typescript
73
144
  // Express middleware
74
145
  app.use((req, res, next) => {
75
- const context: AppLoggerContext = {
146
+ const context = {
76
147
  userId: req.user?.id,
77
148
  requestId: req.headers['x-request-id'] || generateRequestId(),
78
149
  };
79
150
  AppLogger.getStore().run(context, () => next());
80
151
  });
81
- ```
82
152
 
83
- ## Configuration
84
-
85
- ```typescript
86
- interface LoggerConfig {
87
- level: string; // Default log level
88
-
89
- console: {
90
- level: string; // Console transport level
91
- };
92
-
93
- file?: {
94
- dirname: string; // Log directory
95
- filename: string; // Filename pattern (supports %DATE%)
96
- level: string; // File transport level
97
- datePattern: string; // Date pattern for rotation
98
- zippedArchive?: boolean;
99
- maxSize?: string; // e.g., '20m'
100
- maxFiles?: string; // e.g., '14d'
101
- };
102
- }
153
+ // All logs within this request will include userId and requestId
154
+ logger.info('Processing request');
155
+ // Output: [2025-01-01T12:00:00] info [APP] Processing request
156
+ // userId: 123
157
+ // requestId: abc-123
103
158
  ```
104
159
 
105
- ## Level Overrides
160
+ ## Dynamic Level Overrides
106
161
 
107
- Debug specific users/modules without changing global log level:
162
+ Add/remove level overrides at runtime:
108
163
 
109
164
  ```typescript
110
- // Enable debug logging for user 123
165
+ // Enable debug for specific user (e.g., for troubleshooting)
111
166
  logger.setLevelOverride({ userId: 123 }, 'debug');
112
167
 
113
- // Enable debug only for 'auth' module
114
- const authLogger = logger.child('auth');
115
- logger.setLevelOverride({ context: 'auth' }, 'debug');
116
-
117
- // Enable debug for specific user in specific module
118
- logger.setLevelOverride({ context: 'auth', userId: 123 }, 'debug');
119
-
120
- // Now only auth module logs for user 123 will include debug level
121
- // Other users and modules still get the default level
168
+ // Enable debug for specific module
169
+ logger.setLevelOverride({ context: 'payments' }, 'debug');
122
170
 
123
- // Remove override when done
124
- logger.removeLevelOverride({ context: 'auth', userId: 123 });
171
+ // Remove override
172
+ logger.removeLevelOverride({ userId: 123 });
125
173
 
126
- // Or clear all overrides
174
+ // Clear all dynamic overrides (keeps config rules)
127
175
  logger.clearLevelOverrides();
176
+
177
+ // Get all overrides
178
+ const overrides = logger.getLevelOverrides();
179
+ // [{ match: { context: 'payments' }, level: 'debug', readonly: false }]
128
180
  ```
129
181
 
130
182
  ## Lazy Meta
131
183
 
132
- Avoid creating objects when log level doesn't allow logging:
184
+ Defer expensive object creation:
133
185
 
134
186
  ```typescript
135
- // Object is always created (even if debug is disabled)
136
- logger.debug('message', { heavy: computeExpensiveData() });
187
+ // BAD: Object created even if debug is disabled
188
+ logger.debug('Data processed', { result: expensiveSerialize(data) });
137
189
 
138
- // Function is only called when debug level is enabled
139
- logger.debug('message', () => ({ heavy: computeExpensiveData() }));
190
+ // GOOD: Function only called when debug is enabled
191
+ logger.debug('Data processed', () => ({ result: expensiveSerialize(data) }));
140
192
  ```
141
193
 
142
- This is useful for performance-critical code where you want debug logs but don't want to pay the cost of creating log metadata when debug is disabled.
143
-
144
- ## Timing
194
+ ## Child Loggers
145
195
 
146
- Measure execution time:
196
+ Create scoped loggers:
147
197
 
148
198
  ```typescript
149
- const logger = AppLogger.getInstance();
199
+ const logger = AppLogger.for('PaymentService');
200
+ logger.info('Processing payment');
201
+ // Output: [timestamp] info [PaymentService] Processing payment
202
+
203
+ const stripeLogger = logger.for('Stripe');
204
+ stripeLogger.info('Charging card');
205
+ // Output: [timestamp] info [Stripe] Charging card
206
+ ```
150
207
 
151
- // Manual timing
152
- const timer = logger.time('database-query');
153
- await db.query('SELECT ...');
154
- logger.timeEnd(timer); // Logs: "database-query completed in 45.23ms"
208
+ ## Utilities
155
209
 
156
- // Async wrapper
157
- const users = await logger.timeAsync('fetch-users', async () => {
210
+ ### Timing
211
+
212
+ ```typescript
213
+ import { measureAsync, measureSync } from '@rawnodes/logger';
214
+
215
+ // Async
216
+ const { result, timing } = await measureAsync('fetch-users', async () => {
158
217
  return await userService.findAll();
159
218
  });
219
+ console.log(timing); // { label: 'fetch-users', durationMs: 45.23, durationFormatted: '45.23ms' }
220
+
221
+ // Sync
222
+ const { result, timing } = measureSync('compute', () => {
223
+ return heavyComputation();
224
+ });
160
225
  ```
161
226
 
162
- ## Request ID Utilities
227
+ ### Request ID
163
228
 
164
229
  ```typescript
165
- import { generateRequestId, getOrGenerateRequestId } from '@rawnodes/logger';
166
-
167
- // Generate new request ID
168
- const requestId = generateRequestId();
169
- // => "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
230
+ import { generateRequestId, extractRequestId, getOrGenerateRequestId } from '@rawnodes/logger';
170
231
 
171
- // Short format
172
- const shortId = generateRequestId({ short: true });
173
- // => "a1b2c3d4"
232
+ // Generate new
233
+ generateRequestId(); // "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
234
+ generateRequestId({ short: true }); // "a1b2c3d4"
235
+ generateRequestId({ prefix: 'req' }); // "req-a1b2c3d4-e5f6-..."
174
236
 
175
- // With prefix
176
- const prefixedId = generateRequestId({ prefix: 'req' });
177
- // => "req-a1b2c3d4-e5f6-..."
237
+ // Extract from headers (checks x-request-id, x-correlation-id, x-trace-id)
238
+ extractRequestId(req.headers); // string | undefined
178
239
 
179
- // Extract from headers or generate new
180
- const id = getOrGenerateRequestId(req.headers);
240
+ // Extract or generate
241
+ getOrGenerateRequestId(req.headers); // always returns string
181
242
  ```
182
243
 
183
- ## Secret Masking
244
+ ### Secret Masking
245
+
246
+ Automatically masks sensitive fields in logs:
184
247
 
185
248
  ```typescript
186
- import { maskSecrets } from '@rawnodes/logger';
249
+ import { maskSecrets, createMasker } from '@rawnodes/logger';
187
250
 
188
- const masked = maskSecrets({
251
+ maskSecrets({
189
252
  user: 'admin',
190
253
  password: 'secret123',
191
- apiToken: 'tok_abc123xyz',
192
- url: 'postgres://user:pass@localhost/db',
254
+ apiKey: 'key_abc123',
193
255
  });
256
+ // { user: 'admin', password: '***', apiKey: '***' }
194
257
 
195
- // Result:
196
- // {
197
- // user: 'admin',
198
- // password: '***',
199
- // apiToken: '***',
200
- // url: 'postgres://user:***@localhost/db'
201
- // }
258
+ // Custom masker
259
+ const masker = createMasker({
260
+ patterns: ['ssn', 'creditCard'],
261
+ mask: '[REDACTED]'
262
+ });
202
263
  ```
203
264
 
204
- ## Child Loggers
265
+ **Default masked patterns:** `password`, `secret`, `token`, `apikey`, `api_key`, `api-key`, `auth`, `credential`, `private`
205
266
 
206
- Create scoped loggers with automatic context:
267
+ ## Logfmt Utilities
268
+
269
+ Helper functions for logfmt format:
207
270
 
208
271
  ```typescript
209
- // Get child logger with context name
210
- const logger = AppLogger.for('PaymentService');
211
- logger.info('Processing payment'); // [PaymentService] Processing payment
272
+ import { flattenObject, formatLogfmt, formatLogfmtValue } from '@rawnodes/logger';
273
+
274
+ flattenObject({ user: { id: 123, name: 'John' } });
275
+ // { 'user.id': 123, 'user.name': 'John' }
212
276
 
213
- // Or from instance
214
- const baseLogger = AppLogger.getInstance();
215
- const childLogger = baseLogger.getChildLogger('EmailService');
277
+ formatLogfmt({ level: 'info', msg: 'hello', userId: 123 });
278
+ // "level=info msg=hello userId=123"
216
279
  ```
217
280
 
218
281
  ## API Reference
219
282
 
220
- ### `createSingletonLogger<TContext>()`
283
+ ### Logger
221
284
 
222
- Creates a singleton logger factory.
223
-
224
- Returns:
225
285
  ```typescript
226
- interface SingletonLogger<TContext> {
227
- getInstance(config?: LoggerConfig): BaseLogger<TContext>;
228
- getStore(): LoggerStore<TContext>;
286
+ class Logger<TContext> {
287
+ static create(config: LoggerConfig, store?: LoggerStore): Logger;
288
+
229
289
  for(context: string): Logger;
230
- setLevelOverride(match: Partial<TContext>, level: string): void;
231
- removeLevelOverride(match: Partial<TContext>): void;
232
- getLevelOverrides(): LevelOverride<TContext>[];
290
+ getStore(): LoggerStore<TContext>;
291
+
292
+ // Logging
293
+ error(message: string, error?: Error, meta?: Meta): void;
294
+ warn(message: string, meta?: Meta): void;
295
+ info(message: string, meta?: Meta): void;
296
+ http(message: string, meta?: Meta): void;
297
+ verbose(message: string, meta?: Meta): void;
298
+ debug(message: string, meta?: Meta): void;
299
+ silly(message: string, meta?: Meta): void;
300
+
301
+ // Level overrides
302
+ setLevelOverride(match: LevelOverrideMatch, level: LogLevel): void;
303
+ removeLevelOverride(match: LevelOverrideMatch): boolean;
233
304
  clearLevelOverrides(): void;
305
+ getLevelOverrides(): LevelOverride[];
306
+
307
+ // Winston profiling
308
+ profile(id: string, meta?: object): void;
234
309
  }
235
310
  ```
236
311
 
237
- ### `BaseLogger<TContext>`
238
-
239
- Main logger class with methods:
240
- - `log(message, context?, meta?)`
241
- - `info(message, context?, meta?)`
242
- - `warn(message, context?, meta?)`
243
- - `error(message, error?, context?)`
244
- - `debug(message, context?, meta?)`
245
- - `verbose(message, context?, meta?)`
246
- - `time(label): Timer`
247
- - `timeEnd(timer, context?): TimingResult`
248
- - `timeAsync<T>(label, fn, context?): Promise<T>`
249
- - `getChildLogger(context): Logger`
250
- - `getStore(): LoggerStore<TContext>`
251
- - `setLevelOverride(match, level)`
252
- - `removeLevelOverride(match)`
253
- - `getLevelOverrides()`
254
- - `clearLevelOverrides()`
255
-
256
- ### `LoggerStore<TContext>`
257
-
258
- AsyncLocalStorage wrapper:
259
- - `getStore(): TContext | undefined`
260
- - `run<T>(context, fn): T`
312
+ ### Types
313
+
314
+ ```typescript
315
+ type LogLevel = 'error' | 'warn' | 'info' | 'http' | 'verbose' | 'debug' | 'silly';
316
+ type LogFormat = 'json' | 'plain' | 'logfmt' | 'simple';
317
+ type Meta = object | (() => object);
318
+
319
+ interface LoggerConfig {
320
+ level: LogLevel | {
321
+ default: LogLevel;
322
+ rules?: LevelRule[];
323
+ };
324
+ console: { format: LogFormat };
325
+ file?: {
326
+ format: LogFormat;
327
+ dirname: string;
328
+ filename: string;
329
+ datePattern?: string;
330
+ maxFiles?: string;
331
+ maxSize?: string;
332
+ zippedArchive?: boolean;
333
+ };
334
+ }
335
+
336
+ interface LevelRule {
337
+ match: Record<string, unknown> & { context?: string };
338
+ level: LogLevel;
339
+ }
340
+ ```
261
341
 
262
342
  ## Integration Examples
263
343
 
@@ -295,7 +375,7 @@ export class LoggerMiddleware implements NestMiddleware {
295
375
  }
296
376
  ```
297
377
 
298
- ### Telegraf (Telegram Bot)
378
+ ### Telegraf
299
379
 
300
380
  ```typescript
301
381
  import { Telegraf } from 'telegraf';
package/dist/index.d.mts CHANGED
@@ -10,7 +10,12 @@ declare const LOG_LEVELS: {
10
10
  type LogLevel = keyof typeof LOG_LEVELS;
11
11
  declare function isValidLogLevel(level: string): level is LogLevel;
12
12
  declare function assertLogLevel(level: string): asserts level is LogLevel;
13
+ type LogFormat = 'json' | 'plain' | 'logfmt' | 'simple';
14
+ interface ConsoleConfig {
15
+ format: LogFormat;
16
+ }
13
17
  interface FileConfig {
18
+ format: LogFormat;
14
19
  dirname: string;
15
20
  filename: string;
16
21
  datePattern?: string;
@@ -18,8 +23,20 @@ interface FileConfig {
18
23
  maxSize?: string;
19
24
  maxFiles?: string;
20
25
  }
21
- interface LoggerConfig {
26
+ interface LevelRule {
27
+ match: Record<string, unknown> & {
28
+ context?: string;
29
+ };
22
30
  level: LogLevel;
31
+ }
32
+ interface LevelConfigObject {
33
+ default: LogLevel;
34
+ rules?: LevelRule[];
35
+ }
36
+ type LevelConfig = LogLevel | LevelConfigObject;
37
+ interface LoggerConfig {
38
+ level: LevelConfig;
39
+ console: ConsoleConfig;
23
40
  file?: FileConfig;
24
41
  }
25
42
  type LoggerContext = Record<string, unknown>;
@@ -29,6 +46,7 @@ type LevelOverrideMatch<TContext extends LoggerContext> = Partial<TContext> & {
29
46
  interface LevelOverride<TContext extends LoggerContext> {
30
47
  match: LevelOverrideMatch<TContext>;
31
48
  level: LogLevel;
49
+ readonly?: boolean;
32
50
  }
33
51
  type Meta = object | (() => object);
34
52
 
@@ -46,7 +64,7 @@ declare class Logger<TContext extends LoggerContext = LoggerContext> {
46
64
  for(context: string): Logger<TContext>;
47
65
  getStore(): LoggerStore<TContext>;
48
66
  setLevelOverride(match: LevelOverrideMatch<TContext>, level: LogLevel): void;
49
- removeLevelOverride(match: LevelOverrideMatch<TContext>): void;
67
+ removeLevelOverride(match: LevelOverrideMatch<TContext>): boolean;
50
68
  clearLevelOverrides(): void;
51
69
  getLevelOverrides(): LevelOverride<TContext>[];
52
70
  profile(id: string, meta?: object): void;
@@ -102,4 +120,8 @@ interface MaskSecretsOptions {
102
120
  declare function maskSecrets(obj: unknown, options?: MaskSecretsOptions): unknown;
103
121
  declare function createMasker(options?: MaskSecretsOptions): (obj: unknown) => unknown;
104
122
 
105
- export { type FileConfig, LOG_LEVELS, type LevelOverride, type LevelOverrideMatch, type LogLevel, Logger, type LoggerConfig, type LoggerContext, LoggerStore, type MaskSecretsOptions, type Meta, type RequestIdOptions, type SingletonLogger, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, generateRequestId, getOrGenerateRequestId, isValidLogLevel, maskSecrets, measureAsync, measureSync };
123
+ declare function flattenObject(obj: Record<string, unknown>, prefix?: string): Record<string, unknown>;
124
+ declare function formatLogfmtValue(value: unknown): string;
125
+ declare function formatLogfmt(data: Record<string, unknown>): string;
126
+
127
+ export { type ConsoleConfig, type FileConfig, LOG_LEVELS, type LevelConfig, type LevelConfigObject, type LevelOverride, type LevelOverrideMatch, type LevelRule, type LogFormat, type LogLevel, Logger, type LoggerConfig, type LoggerContext, LoggerStore, type MaskSecretsOptions, type Meta, type RequestIdOptions, type SingletonLogger, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatLogfmt, formatLogfmtValue, generateRequestId, getOrGenerateRequestId, isValidLogLevel, maskSecrets, measureAsync, measureSync };
package/dist/index.d.ts CHANGED
@@ -10,7 +10,12 @@ declare const LOG_LEVELS: {
10
10
  type LogLevel = keyof typeof LOG_LEVELS;
11
11
  declare function isValidLogLevel(level: string): level is LogLevel;
12
12
  declare function assertLogLevel(level: string): asserts level is LogLevel;
13
+ type LogFormat = 'json' | 'plain' | 'logfmt' | 'simple';
14
+ interface ConsoleConfig {
15
+ format: LogFormat;
16
+ }
13
17
  interface FileConfig {
18
+ format: LogFormat;
14
19
  dirname: string;
15
20
  filename: string;
16
21
  datePattern?: string;
@@ -18,8 +23,20 @@ interface FileConfig {
18
23
  maxSize?: string;
19
24
  maxFiles?: string;
20
25
  }
21
- interface LoggerConfig {
26
+ interface LevelRule {
27
+ match: Record<string, unknown> & {
28
+ context?: string;
29
+ };
22
30
  level: LogLevel;
31
+ }
32
+ interface LevelConfigObject {
33
+ default: LogLevel;
34
+ rules?: LevelRule[];
35
+ }
36
+ type LevelConfig = LogLevel | LevelConfigObject;
37
+ interface LoggerConfig {
38
+ level: LevelConfig;
39
+ console: ConsoleConfig;
23
40
  file?: FileConfig;
24
41
  }
25
42
  type LoggerContext = Record<string, unknown>;
@@ -29,6 +46,7 @@ type LevelOverrideMatch<TContext extends LoggerContext> = Partial<TContext> & {
29
46
  interface LevelOverride<TContext extends LoggerContext> {
30
47
  match: LevelOverrideMatch<TContext>;
31
48
  level: LogLevel;
49
+ readonly?: boolean;
32
50
  }
33
51
  type Meta = object | (() => object);
34
52
 
@@ -46,7 +64,7 @@ declare class Logger<TContext extends LoggerContext = LoggerContext> {
46
64
  for(context: string): Logger<TContext>;
47
65
  getStore(): LoggerStore<TContext>;
48
66
  setLevelOverride(match: LevelOverrideMatch<TContext>, level: LogLevel): void;
49
- removeLevelOverride(match: LevelOverrideMatch<TContext>): void;
67
+ removeLevelOverride(match: LevelOverrideMatch<TContext>): boolean;
50
68
  clearLevelOverrides(): void;
51
69
  getLevelOverrides(): LevelOverride<TContext>[];
52
70
  profile(id: string, meta?: object): void;
@@ -102,4 +120,8 @@ interface MaskSecretsOptions {
102
120
  declare function maskSecrets(obj: unknown, options?: MaskSecretsOptions): unknown;
103
121
  declare function createMasker(options?: MaskSecretsOptions): (obj: unknown) => unknown;
104
122
 
105
- export { type FileConfig, LOG_LEVELS, type LevelOverride, type LevelOverrideMatch, type LogLevel, Logger, type LoggerConfig, type LoggerContext, LoggerStore, type MaskSecretsOptions, type Meta, type RequestIdOptions, type SingletonLogger, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, generateRequestId, getOrGenerateRequestId, isValidLogLevel, maskSecrets, measureAsync, measureSync };
123
+ declare function flattenObject(obj: Record<string, unknown>, prefix?: string): Record<string, unknown>;
124
+ declare function formatLogfmtValue(value: unknown): string;
125
+ declare function formatLogfmt(data: Record<string, unknown>): string;
126
+
127
+ export { type ConsoleConfig, type FileConfig, LOG_LEVELS, type LevelConfig, type LevelConfigObject, type LevelOverride, type LevelOverrideMatch, type LevelRule, type LogFormat, type LogLevel, Logger, type LoggerConfig, type LoggerContext, LoggerStore, type MaskSecretsOptions, type Meta, type RequestIdOptions, type SingletonLogger, type TimingResult, assertLogLevel, createMasker, createSingletonLogger, extractRequestId, flattenObject, formatLogfmt, formatLogfmtValue, generateRequestId, getOrGenerateRequestId, isValidLogLevel, maskSecrets, measureAsync, measureSync };