@outfitter/logging 0.1.0-rc.3 → 0.2.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 +1 -0
- package/dist/index.d.ts +53 -5
- package/dist/index.js +51 -22
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -184,6 +184,7 @@ Routes logs to stdout/stderr based on level:
|
|
|
184
184
|
|
|
185
185
|
- `trace`, `debug`, `info` -> stdout
|
|
186
186
|
- `warn`, `error`, `fatal` -> stderr
|
|
187
|
+
- Falls back to `console.*` when process streams are unavailable (edge/serverless)
|
|
187
188
|
|
|
188
189
|
```typescript
|
|
189
190
|
import { createConsoleSink } from "@outfitter/logging";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* @outfitter/logging
|
|
3
|
+
*
|
|
4
|
+
* Structured logging via logtape with automatic sensitive data redaction.
|
|
5
|
+
* Provides consistent log formatting across CLI, MCP, and server contexts.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
2
10
|
* Log levels supported by the logger, ordered from lowest to highest severity.
|
|
3
11
|
*
|
|
4
12
|
* Level priority (lowest to highest): trace (0) < debug (1) < info (2) < warn (3) < error (4) < fatal (5)
|
|
@@ -208,36 +216,42 @@ interface LoggerInstance {
|
|
|
208
216
|
* @param metadata - Optional structured metadata
|
|
209
217
|
*/
|
|
210
218
|
trace(message: string, metadata?: Record<string, unknown>): void;
|
|
219
|
+
trace(metadata: Record<string, unknown>, message: string): never;
|
|
211
220
|
/**
|
|
212
221
|
* Log at debug level (development debugging).
|
|
213
222
|
* @param message - Human-readable log message
|
|
214
223
|
* @param metadata - Optional structured metadata
|
|
215
224
|
*/
|
|
216
225
|
debug(message: string, metadata?: Record<string, unknown>): void;
|
|
226
|
+
debug(metadata: Record<string, unknown>, message: string): never;
|
|
217
227
|
/**
|
|
218
228
|
* Log at info level (normal operations).
|
|
219
229
|
* @param message - Human-readable log message
|
|
220
230
|
* @param metadata - Optional structured metadata
|
|
221
231
|
*/
|
|
222
232
|
info(message: string, metadata?: Record<string, unknown>): void;
|
|
233
|
+
info(metadata: Record<string, unknown>, message: string): never;
|
|
223
234
|
/**
|
|
224
235
|
* Log at warn level (unexpected but handled situations).
|
|
225
236
|
* @param message - Human-readable log message
|
|
226
237
|
* @param metadata - Optional structured metadata
|
|
227
238
|
*/
|
|
228
239
|
warn(message: string, metadata?: Record<string, unknown>): void;
|
|
240
|
+
warn(metadata: Record<string, unknown>, message: string): never;
|
|
229
241
|
/**
|
|
230
242
|
* Log at error level (failures requiring attention).
|
|
231
243
|
* @param message - Human-readable log message
|
|
232
244
|
* @param metadata - Optional structured metadata
|
|
233
245
|
*/
|
|
234
246
|
error(message: string, metadata?: Record<string, unknown>): void;
|
|
247
|
+
error(metadata: Record<string, unknown>, message: string): never;
|
|
235
248
|
/**
|
|
236
249
|
* Log at fatal level (unrecoverable failures).
|
|
237
250
|
* @param message - Human-readable log message
|
|
238
251
|
* @param metadata - Optional structured metadata
|
|
239
252
|
*/
|
|
240
253
|
fatal(message: string, metadata?: Record<string, unknown>): void;
|
|
254
|
+
fatal(metadata: Record<string, unknown>, message: string): never;
|
|
241
255
|
/**
|
|
242
256
|
* Get the current context metadata attached to this logger.
|
|
243
257
|
* @returns Copy of the logger's context object
|
|
@@ -302,6 +316,33 @@ interface PrettyFormatterOptions {
|
|
|
302
316
|
timestamp?: boolean;
|
|
303
317
|
}
|
|
304
318
|
/**
|
|
319
|
+
* Options for the console sink.
|
|
320
|
+
*
|
|
321
|
+
* Controls ANSI color output for terminal display. By default, colors are
|
|
322
|
+
* auto-detected based on whether stdout is a TTY.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```typescript
|
|
326
|
+
* // Auto-detect TTY (default)
|
|
327
|
+
* const sink = createConsoleSink();
|
|
328
|
+
*
|
|
329
|
+
* // Force colors off (for piped output, CI)
|
|
330
|
+
* const plainSink = createConsoleSink({ colors: false });
|
|
331
|
+
*
|
|
332
|
+
* // Force colors on (even in non-TTY)
|
|
333
|
+
* const colorSink = createConsoleSink({ colors: true });
|
|
334
|
+
* ```
|
|
335
|
+
*/
|
|
336
|
+
interface ConsoleSinkOptions {
|
|
337
|
+
/**
|
|
338
|
+
* Enable ANSI colors in output.
|
|
339
|
+
* - `undefined` (default): Auto-detect based on stdout TTY status
|
|
340
|
+
* - `true`: Always use colors
|
|
341
|
+
* - `false`: Never use colors
|
|
342
|
+
*/
|
|
343
|
+
colors?: boolean;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
305
346
|
* Options for the file sink.
|
|
306
347
|
*
|
|
307
348
|
* Configures the file path and append behavior for file-based logging.
|
|
@@ -326,7 +367,7 @@ interface FileSinkOptions {
|
|
|
326
367
|
/** Absolute path to the log file */
|
|
327
368
|
path: string;
|
|
328
369
|
/**
|
|
329
|
-
* Append to existing file or truncate
|
|
370
|
+
* Append to existing file or truncate before the first write.
|
|
330
371
|
* @defaultValue true
|
|
331
372
|
*/
|
|
332
373
|
append?: boolean;
|
|
@@ -444,9 +485,10 @@ declare function createJsonFormatter(): Formatter;
|
|
|
444
485
|
*/
|
|
445
486
|
declare function createPrettyFormatter(options?: PrettyFormatterOptions): Formatter;
|
|
446
487
|
/**
|
|
447
|
-
* Create a console sink that writes
|
|
448
|
-
* Info and below go to
|
|
488
|
+
* Create a console sink that writes via console methods.
|
|
489
|
+
* Info and below go to console.info/debug, warn and above go to console.warn/error.
|
|
449
490
|
*
|
|
491
|
+
* @param options - Console sink options
|
|
450
492
|
* @returns Sink configured for console output
|
|
451
493
|
*
|
|
452
494
|
* @example
|
|
@@ -455,9 +497,15 @@ declare function createPrettyFormatter(options?: PrettyFormatterOptions): Format
|
|
|
455
497
|
* name: "app",
|
|
456
498
|
* sinks: [createConsoleSink()],
|
|
457
499
|
* });
|
|
500
|
+
*
|
|
501
|
+
* // Disable colors for CI/piped output
|
|
502
|
+
* const plainLogger = createLogger({
|
|
503
|
+
* name: "app",
|
|
504
|
+
* sinks: [createConsoleSink({ colors: false })],
|
|
505
|
+
* });
|
|
458
506
|
* ```
|
|
459
507
|
*/
|
|
460
|
-
declare function createConsoleSink(): Sink;
|
|
508
|
+
declare function createConsoleSink(options?: ConsoleSinkOptions): Sink;
|
|
461
509
|
/**
|
|
462
510
|
* Create a file sink that writes to a specified file path.
|
|
463
511
|
*
|
|
@@ -501,4 +549,4 @@ declare function configureRedaction(config: GlobalRedactionConfig): void;
|
|
|
501
549
|
* ```
|
|
502
550
|
*/
|
|
503
551
|
declare function flush(): Promise<void>;
|
|
504
|
-
export { flush, createPrettyFormatter, createLogger, createJsonFormatter, createFileSink, createConsoleSink, createChildLogger, configureRedaction, Sink, RedactionConfig, PrettyFormatterOptions, LoggerInstance, LoggerConfig, LogRecord, LogLevel, GlobalRedactionConfig, Formatter, FileSinkOptions, DEFAULT_PATTERNS };
|
|
552
|
+
export { flush, createPrettyFormatter, createLogger, createJsonFormatter, createFileSink, createConsoleSink, createChildLogger, configureRedaction, Sink, RedactionConfig, PrettyFormatterOptions, LoggerInstance, LoggerConfig, LogRecord, LogLevel, GlobalRedactionConfig, Formatter, FileSinkOptions, DEFAULT_PATTERNS, ConsoleSinkOptions };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { writeFileSync } from "node:fs";
|
|
3
2
|
var LEVEL_PRIORITY = {
|
|
4
3
|
trace: 0,
|
|
5
4
|
debug: 1,
|
|
@@ -215,12 +214,30 @@ function createChildLogger(parent, context) {
|
|
|
215
214
|
const parentContext = parent.getContext();
|
|
216
215
|
const mergedContext = { ...parentContext, ...context };
|
|
217
216
|
const childLogger = {
|
|
218
|
-
trace: (message, metadata) => parent.trace(message, {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
217
|
+
trace: (message, metadata) => parent.trace(message, {
|
|
218
|
+
...context,
|
|
219
|
+
...metadata
|
|
220
|
+
}),
|
|
221
|
+
debug: (message, metadata) => parent.debug(message, {
|
|
222
|
+
...context,
|
|
223
|
+
...metadata
|
|
224
|
+
}),
|
|
225
|
+
info: (message, metadata) => parent.info(message, {
|
|
226
|
+
...context,
|
|
227
|
+
...metadata
|
|
228
|
+
}),
|
|
229
|
+
warn: (message, metadata) => parent.warn(message, {
|
|
230
|
+
...context,
|
|
231
|
+
...metadata
|
|
232
|
+
}),
|
|
233
|
+
error: (message, metadata) => parent.error(message, {
|
|
234
|
+
...context,
|
|
235
|
+
...metadata
|
|
236
|
+
}),
|
|
237
|
+
fatal: (message, metadata) => parent.fatal(message, {
|
|
238
|
+
...context,
|
|
239
|
+
...metadata
|
|
240
|
+
}),
|
|
224
241
|
getContext: () => mergedContext,
|
|
225
242
|
setLevel: (level) => parent.setLevel(level),
|
|
226
243
|
addSink: (sink) => parent.addSink(sink),
|
|
@@ -286,20 +303,29 @@ function createPrettyFormatter(options) {
|
|
|
286
303
|
}
|
|
287
304
|
};
|
|
288
305
|
}
|
|
289
|
-
function createConsoleSink() {
|
|
290
|
-
const
|
|
306
|
+
function createConsoleSink(options) {
|
|
307
|
+
const useColors = options?.colors ?? (typeof process !== "undefined" ? Boolean(process.stdout?.isTTY) : false);
|
|
308
|
+
const formatter = createPrettyFormatter({ colors: useColors });
|
|
291
309
|
const sink = {
|
|
292
310
|
formatter,
|
|
293
311
|
write(record, formatted) {
|
|
294
312
|
const output = formatted ?? formatter.format(record);
|
|
295
|
-
const
|
|
296
|
-
`) ? output :
|
|
297
|
-
|
|
298
|
-
if (
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
process.stdout.write(outputWithNewline);
|
|
313
|
+
const outputLine = output.endsWith(`
|
|
314
|
+
`) ? output.slice(0, -1) : output;
|
|
315
|
+
const runtimeConsole = globalThis["console"];
|
|
316
|
+
if (record.level === "fatal" || record.level === "error") {
|
|
317
|
+
runtimeConsole.error(outputLine);
|
|
318
|
+
return;
|
|
302
319
|
}
|
|
320
|
+
if (record.level === "warn") {
|
|
321
|
+
runtimeConsole.warn(outputLine);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (record.level === "debug" || record.level === "trace") {
|
|
325
|
+
runtimeConsole.debug(outputLine);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
runtimeConsole.info(outputLine);
|
|
303
329
|
}
|
|
304
330
|
};
|
|
305
331
|
registeredSinks.add(sink);
|
|
@@ -310,9 +336,7 @@ function createFileSink(options) {
|
|
|
310
336
|
const buffer = [];
|
|
311
337
|
const { path } = options;
|
|
312
338
|
const append = options.append ?? true;
|
|
313
|
-
|
|
314
|
-
writeFileSync(path, "");
|
|
315
|
-
}
|
|
339
|
+
let cachedContent = append ? null : "";
|
|
316
340
|
const sink = {
|
|
317
341
|
formatter,
|
|
318
342
|
write(record, formatted) {
|
|
@@ -326,9 +350,14 @@ function createFileSink(options) {
|
|
|
326
350
|
if (buffer.length > 0) {
|
|
327
351
|
const content = buffer.join("");
|
|
328
352
|
buffer.length = 0;
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
353
|
+
if (append) {
|
|
354
|
+
const file = Bun.file(path);
|
|
355
|
+
const existing = await file.exists() ? await file.text() : "";
|
|
356
|
+
await Bun.write(path, existing + content);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
cachedContent = (cachedContent ?? "") + content;
|
|
360
|
+
await Bun.write(path, cachedContent);
|
|
332
361
|
}
|
|
333
362
|
}
|
|
334
363
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@outfitter/logging",
|
|
3
3
|
"description": "Structured logging via logtape with redaction support for Outfitter",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"clean": "rm -rf dist"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@outfitter/contracts": "0.
|
|
30
|
+
"@outfitter/contracts": "0.2.0",
|
|
31
31
|
"@logtape/logtape": "^2.0.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|