@outfitter/logging 0.1.0 → 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 +17 -3
- package/dist/index.js +49 -21
- 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
|
|
@@ -353,7 +367,7 @@ interface FileSinkOptions {
|
|
|
353
367
|
/** Absolute path to the log file */
|
|
354
368
|
path: string;
|
|
355
369
|
/**
|
|
356
|
-
* Append to existing file or truncate
|
|
370
|
+
* Append to existing file or truncate before the first write.
|
|
357
371
|
* @defaultValue true
|
|
358
372
|
*/
|
|
359
373
|
append?: boolean;
|
|
@@ -471,8 +485,8 @@ declare function createJsonFormatter(): Formatter;
|
|
|
471
485
|
*/
|
|
472
486
|
declare function createPrettyFormatter(options?: PrettyFormatterOptions): Formatter;
|
|
473
487
|
/**
|
|
474
|
-
* Create a console sink that writes
|
|
475
|
-
* 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.
|
|
476
490
|
*
|
|
477
491
|
* @param options - Console sink options
|
|
478
492
|
* @returns Sink configured for console output
|
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),
|
|
@@ -287,20 +304,28 @@ function createPrettyFormatter(options) {
|
|
|
287
304
|
};
|
|
288
305
|
}
|
|
289
306
|
function createConsoleSink(options) {
|
|
290
|
-
const useColors = options?.colors ?? process.stdout
|
|
307
|
+
const useColors = options?.colors ?? (typeof process !== "undefined" ? Boolean(process.stdout?.isTTY) : false);
|
|
291
308
|
const formatter = createPrettyFormatter({ colors: useColors });
|
|
292
309
|
const sink = {
|
|
293
310
|
formatter,
|
|
294
311
|
write(record, formatted) {
|
|
295
312
|
const output = formatted ?? formatter.format(record);
|
|
296
|
-
const
|
|
297
|
-
`) ? output :
|
|
298
|
-
|
|
299
|
-
if (
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
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;
|
|
303
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);
|
|
304
329
|
}
|
|
305
330
|
};
|
|
306
331
|
registeredSinks.add(sink);
|
|
@@ -311,9 +336,7 @@ function createFileSink(options) {
|
|
|
311
336
|
const buffer = [];
|
|
312
337
|
const { path } = options;
|
|
313
338
|
const append = options.append ?? true;
|
|
314
|
-
|
|
315
|
-
writeFileSync(path, "");
|
|
316
|
-
}
|
|
339
|
+
let cachedContent = append ? null : "";
|
|
317
340
|
const sink = {
|
|
318
341
|
formatter,
|
|
319
342
|
write(record, formatted) {
|
|
@@ -327,9 +350,14 @@ function createFileSink(options) {
|
|
|
327
350
|
if (buffer.length > 0) {
|
|
328
351
|
const content = buffer.join("");
|
|
329
352
|
buffer.length = 0;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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);
|
|
333
361
|
}
|
|
334
362
|
}
|
|
335
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": {
|