@ontrails/logging 1.0.0-beta.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.
Files changed (53) hide show
  1. package/.turbo/turbo-build.log +1 -0
  2. package/.turbo/turbo-lint.log +3 -0
  3. package/.turbo/turbo-typecheck.log +1 -0
  4. package/CHANGELOG.md +20 -0
  5. package/README.md +160 -0
  6. package/dist/env.d.ts +13 -0
  7. package/dist/env.d.ts.map +1 -0
  8. package/dist/env.js +38 -0
  9. package/dist/env.js.map +1 -0
  10. package/dist/formatters.d.ts +8 -0
  11. package/dist/formatters.d.ts.map +1 -0
  12. package/dist/formatters.js +72 -0
  13. package/dist/formatters.js.map +1 -0
  14. package/dist/index.d.ts +8 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +10 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/levels.d.ts +9 -0
  19. package/dist/levels.d.ts.map +1 -0
  20. package/dist/levels.js +52 -0
  21. package/dist/levels.js.map +1 -0
  22. package/dist/logger.d.ts +10 -0
  23. package/dist/logger.d.ts.map +1 -0
  24. package/dist/logger.js +80 -0
  25. package/dist/logger.js.map +1 -0
  26. package/dist/logtape/index.d.ts +24 -0
  27. package/dist/logtape/index.d.ts.map +1 -0
  28. package/dist/logtape/index.js +31 -0
  29. package/dist/logtape/index.js.map +1 -0
  30. package/dist/sinks.d.ts +13 -0
  31. package/dist/sinks.d.ts.map +1 -0
  32. package/dist/sinks.js +58 -0
  33. package/dist/sinks.js.map +1 -0
  34. package/dist/types.d.ts +51 -0
  35. package/dist/types.d.ts.map +1 -0
  36. package/dist/types.js +5 -0
  37. package/dist/types.js.map +1 -0
  38. package/package.json +25 -0
  39. package/src/__tests__/env.test.ts +54 -0
  40. package/src/__tests__/formatters.test.ts +119 -0
  41. package/src/__tests__/levels.test.ts +82 -0
  42. package/src/__tests__/logger.test.ts +279 -0
  43. package/src/__tests__/sinks.test.ts +181 -0
  44. package/src/env.ts +49 -0
  45. package/src/formatters.ts +101 -0
  46. package/src/index.ts +28 -0
  47. package/src/levels.ts +69 -0
  48. package/src/logger.ts +135 -0
  49. package/src/logtape/index.ts +68 -0
  50. package/src/sinks.ts +71 -0
  51. package/src/types.ts +99 -0
  52. package/tsconfig.json +9 -0
  53. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1 @@
1
+ $ tsc -b
@@ -0,0 +1,3 @@
1
+ $ oxlint ./src
2
+ Found 0 warnings and 0 errors.
3
+ Finished in 106ms on 13 files with 93 rules using 24 threads.
@@ -0,0 +1 @@
1
+ $ tsc --noEmit
package/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # @ontrails/logging
2
+
3
+ ## 1.0.0-beta.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Initial v1 beta release of the Trails framework.
8
+
9
+ - **@ontrails/core** — Result type, error taxonomy, trail/hike/event/topo, validateTopo, validateInput/Output, deriveFields, patterns, redaction, branded types, resilience
10
+ - **@ontrails/cli** — CLI surface adapter, Commander integration, flag derivation, layers
11
+ - **@ontrails/mcp** — MCP surface adapter, tool generation, annotations, progress bridge
12
+ - **@ontrails/logging** — Structured logging, sinks, formatters, LogTape adapter
13
+ - **@ontrails/testing** — testAll, testExamples, testTrail, testHike, testContracts, testDetours, surface harnesses
14
+ - **@ontrails/warden** — AST-based code convention rules via oxc-parser, drift detection, CI formatters
15
+ - **@ontrails/schema** — Surface map generation, hashing, semantic diffing
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies
20
+ - @ontrails/core@1.0.0-beta.0
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # @ontrails/logging
2
+
3
+ Structured logging for Trails. One API: `createLogger(config)`. Built-in sinks and formatters, hierarchical category filtering, automatic redaction, and an optional LogTape adapter.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add @ontrails/logging @ontrails/core
9
+ ```
10
+
11
+ For LogTape integration:
12
+
13
+ ```bash
14
+ bun add @logtape/logtape
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```typescript
20
+ import { createLogger } from '@ontrails/logging';
21
+
22
+ const logger = createLogger({
23
+ name: 'app.entity',
24
+ level: 'info',
25
+ });
26
+
27
+ logger.info('Entity created', { entityId: 'e1', name: 'Alpha' });
28
+ // 10:00:00 INFO [app.entity] Entity created entityId=e1 name=Alpha
29
+ ```
30
+
31
+ ## API Overview
32
+
33
+ ### `createLogger(config)`
34
+
35
+ The single entry point. Returns a `Logger` (from `@ontrails/core`) that plugs directly into `TrailContext.logger`.
36
+
37
+ ```typescript
38
+ const logger = createLogger({
39
+ name: 'app.db.queries',
40
+ level: 'info',
41
+ levels: {
42
+ app: 'info',
43
+ 'app.db': 'debug',
44
+ 'app.http': 'warn',
45
+ },
46
+ sinks: [createConsoleSink(), createFileSink({ path: './app.log' })],
47
+ redaction: { sensitiveKeys: ['password', 'token'] },
48
+ });
49
+ ```
50
+
51
+ ### Sinks
52
+
53
+ A `LogSink` receives formatted log records and writes them somewhere.
54
+
55
+ ```typescript
56
+ import { createConsoleSink, createFileSink } from '@ontrails/logging';
57
+
58
+ // Console output (default sink)
59
+ createConsoleSink({ formatter: createPrettyFormatter() });
60
+
61
+ // File output
62
+ createFileSink({ path: './logs/app.log', formatter: createJsonFormatter() });
63
+ ```
64
+
65
+ ### Formatters
66
+
67
+ ```typescript
68
+ import { createJsonFormatter, createPrettyFormatter } from '@ontrails/logging';
69
+
70
+ // Structured JSON -- one object per line, ISO 8601 timestamps
71
+ createJsonFormatter();
72
+ // {"level":"info","message":"Entity created","category":"app.entity","timestamp":"2026-03-25T10:00:00.000Z"}
73
+
74
+ // Human-readable -- optional ANSI colors, compact metadata
75
+ createPrettyFormatter();
76
+ // 10:00:00 INFO [app.entity] Entity created entityId=e1
77
+ ```
78
+
79
+ ### Hierarchical Category Filtering
80
+
81
+ Categories are dot-separated. Level resolution walks up the hierarchy until a match is found:
82
+
83
+ ```typescript
84
+ const logger = createLogger({
85
+ name: 'app.db.queries',
86
+ level: 'info', // global fallback
87
+ levels: {
88
+ app: 'info',
89
+ 'app.db': 'debug', // matches "app.db.queries"
90
+ 'app.http': 'warn',
91
+ },
92
+ });
93
+ ```
94
+
95
+ Resolution for `"app.db.queries"`: check exact match, then `"app.db"` (found: `"debug"`), then `"app"`, then `config.level`, then `TRAILS_LOG_LEVEL` env var, then `"info"`.
96
+
97
+ ### Child Loggers
98
+
99
+ ```typescript
100
+ const child = logger.child({ requestId: 'abc-123', trail: 'entity.show' });
101
+ child.info('Processing');
102
+ // Every log record from this child includes requestId and trail metadata
103
+ ```
104
+
105
+ Children inherit the parent's sinks, level config, and redaction. They share the parent's sink pipeline.
106
+
107
+ ### Redaction
108
+
109
+ Sensitive data is automatically stripped before any sink dispatch. Uses `@ontrails/core/redaction` under the hood.
110
+
111
+ ```typescript
112
+ const logger = createLogger({
113
+ name: 'app',
114
+ redaction: {
115
+ patterns: [/custom-secret-\w+/g],
116
+ sensitiveKeys: ['password', 'internalToken'],
117
+ },
118
+ });
119
+
120
+ logger.info('Auth', { user: 'admin', password: 'hunter2' });
121
+ // password is redacted: "[REDACTED]"
122
+ ```
123
+
124
+ ### Environment Configuration
125
+
126
+ Log level can be set via environment:
127
+
128
+ 1. Explicit `config.level` (highest priority)
129
+ 2. `config.levels` hierarchy
130
+ 3. `TRAILS_LOG_LEVEL` env var
131
+ 4. `TRAILS_ENV` profile defaults (`development` = `"debug"`, `test` = silent)
132
+ 5. Fallback: `"info"`
133
+
134
+ ### LogTape Adapter (`@ontrails/logging/logtape`)
135
+
136
+ Bridge Trails logging to an existing LogTape infrastructure:
137
+
138
+ ```typescript
139
+ import { logtapeSink } from '@ontrails/logging/logtape';
140
+ import { getLogger } from '@logtape/logtape';
141
+
142
+ const logger = createLogger({
143
+ name: 'app',
144
+ sinks: [logtapeSink({ logger: getLogger('app') })],
145
+ });
146
+ ```
147
+
148
+ `@logtape/logtape` is an optional peer dependency. The main package does not depend on it.
149
+
150
+ ## Subpath Exports
151
+
152
+ | Export | Contents |
153
+ | --- | --- |
154
+ | `@ontrails/logging` | `createLogger`, `createConsoleSink`, `createFileSink`, `createJsonFormatter`, `createPrettyFormatter`, level resolution |
155
+ | `@ontrails/logging/logtape` | `logtapeSink` adapter (requires `@logtape/logtape` peer) |
156
+
157
+ ## Further Reading
158
+
159
+ - [Getting Started](../../docs/getting-started.md)
160
+ - [Architecture](../../docs/architecture.md)
package/dist/env.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import type { LogLevel } from './types.js';
2
+ /**
3
+ * Resolve log level from environment variables.
4
+ *
5
+ * 1. `TRAILS_LOG_LEVEL` -- explicit override (if valid).
6
+ * 2. `TRAILS_ENV` profile defaults:
7
+ * - `development` -> `"debug"`
8
+ * - `test` -> `undefined` (no logging by default)
9
+ * - `production` -> `undefined` (caller falls through to `"info"`)
10
+ * 3. `undefined` -- no env-based level configured.
11
+ */
12
+ export declare const resolveLogLevel: (env?: Record<string, string | undefined>) => LogLevel | undefined;
13
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAe3C;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KACvC,QAAQ,GAAG,SAoBb,CAAC"}
package/dist/env.js ADDED
@@ -0,0 +1,38 @@
1
+ import { LEVEL_PRIORITY } from './levels.js';
2
+ // ---------------------------------------------------------------------------
3
+ // Valid log level set (for validation)
4
+ // ---------------------------------------------------------------------------
5
+ const VALID_LEVELS = new Set(Object.keys(LEVEL_PRIORITY));
6
+ const isValidLogLevel = (value) => VALID_LEVELS.has(value);
7
+ // ---------------------------------------------------------------------------
8
+ // resolveLogLevel
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * Resolve log level from environment variables.
12
+ *
13
+ * 1. `TRAILS_LOG_LEVEL` -- explicit override (if valid).
14
+ * 2. `TRAILS_ENV` profile defaults:
15
+ * - `development` -> `"debug"`
16
+ * - `test` -> `undefined` (no logging by default)
17
+ * - `production` -> `undefined` (caller falls through to `"info"`)
18
+ * 3. `undefined` -- no env-based level configured.
19
+ */
20
+ export const resolveLogLevel = (env) => {
21
+ const source = env ?? process.env;
22
+ // 1. Explicit override
23
+ const explicit = source['TRAILS_LOG_LEVEL'];
24
+ if (explicit !== undefined && isValidLogLevel(explicit)) {
25
+ return explicit;
26
+ }
27
+ // 2. Profile defaults
28
+ const profile = source['TRAILS_ENV'];
29
+ if (profile === 'development') {
30
+ return 'debug';
31
+ }
32
+ if (profile === 'test') {
33
+ return undefined;
34
+ }
35
+ // production and everything else -- no opinion
36
+ return undefined;
37
+ };
38
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,8EAA8E;AAC9E,uCAAuC;AACvC,8EAA8E;AAE9E,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;AAElE,MAAM,eAAe,GAAG,CAAC,KAAa,EAAqB,EAAE,CAC3D,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAE1B,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,GAAwC,EAClB,EAAE;IACxB,MAAM,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAElC,uBAAuB;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC5C,IAAI,QAAQ,KAAK,SAAS,IAAI,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,sBAAsB;IACtB,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,+CAA+C;IAC/C,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { LogFormatter, PrettyFormatterOptions } from './types.js';
2
+ /**
3
+ * One JSON object per log record, newline-delimited.
4
+ * Metadata fields are flattened into the top-level object.
5
+ */
6
+ export declare const createJsonFormatter: () => LogFormatter;
7
+ export declare const createPrettyFormatter: (options?: PrettyFormatterOptions) => LogFormatter;
8
+ //# sourceMappingURL=formatters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAEZ,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAMpB;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAAO,YAYrC,CAAC;AAoDH,eAAO,MAAM,qBAAqB,GAChC,UAAU,sBAAsB,KAC/B,YAoBF,CAAC"}
@@ -0,0 +1,72 @@
1
+ // ---------------------------------------------------------------------------
2
+ // JSON Formatter
3
+ // ---------------------------------------------------------------------------
4
+ /**
5
+ * One JSON object per log record, newline-delimited.
6
+ * Metadata fields are flattened into the top-level object.
7
+ */
8
+ export const createJsonFormatter = () => ({
9
+ format(record) {
10
+ const { level, message, category, timestamp, metadata } = record;
11
+ const obj = {
12
+ category,
13
+ level,
14
+ message,
15
+ timestamp: timestamp.toISOString(),
16
+ ...metadata,
17
+ };
18
+ return JSON.stringify(obj);
19
+ },
20
+ });
21
+ // ---------------------------------------------------------------------------
22
+ // Pretty Formatter
23
+ // ---------------------------------------------------------------------------
24
+ const LEVEL_COLORS = {
25
+ debug: '\u001B[36m',
26
+ error: '\u001B[31m',
27
+ fatal: '\u001B[35m',
28
+ info: '\u001B[32m',
29
+ trace: '\u001B[90m',
30
+ warn: '\u001B[33m',
31
+ };
32
+ const RESET = '\u001B[0m';
33
+ const formatMetadata = (metadata) => {
34
+ const entries = Object.entries(metadata);
35
+ if (entries.length === 0) {
36
+ return '';
37
+ }
38
+ return ` ${entries
39
+ .map(([k, v]) => {
40
+ const display = typeof v === 'string' ? v : JSON.stringify(v);
41
+ return `${k}=${display}`;
42
+ })
43
+ .join(' ')}`;
44
+ };
45
+ /**
46
+ * Human-readable formatter.
47
+ *
48
+ * Output: `10:00:00 INFO [app.entity] Entity created requestId=abc-123`
49
+ */
50
+ const formatTimestamp = (timestamp) => `${timestamp.toISOString().slice(11, 19)} `;
51
+ const formatLevelAndMessage = (level, levelLabel, category, message, useColors) => {
52
+ if (useColors) {
53
+ const color = LEVEL_COLORS[level] ?? '';
54
+ return `${color}${levelLabel}${RESET} [${category}] ${message}`;
55
+ }
56
+ return `${levelLabel} [${category}] ${message}`;
57
+ };
58
+ export const createPrettyFormatter = (options) => {
59
+ const showTimestamps = options?.timestamps !== false;
60
+ const useColors = options?.colors ?? process.stdout?.isTTY === true;
61
+ return {
62
+ format(record) {
63
+ const { level, message, category, timestamp, metadata } = record;
64
+ const levelLabel = level.toUpperCase().padEnd(5);
65
+ const meta = formatMetadata(metadata);
66
+ const prefix = showTimestamps ? formatTimestamp(timestamp) : '';
67
+ const body = formatLevelAndMessage(level, levelLabel, category, message, useColors);
68
+ return meta.length > 0 ? `${prefix}${body}${meta}` : `${prefix}${body}`;
69
+ },
70
+ };
71
+ };
72
+ //# sourceMappingURL=formatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export { createLogger } from './logger.js';
2
+ export type { Logger } from '@ontrails/core';
3
+ export { createConsoleSink, createFileSink } from './sinks.js';
4
+ export { createJsonFormatter, createPrettyFormatter } from './formatters.js';
5
+ export { resolveLogLevel } from './env.js';
6
+ export { LEVEL_PRIORITY, shouldLog, resolveCategory } from './levels.js';
7
+ export type { LogLevel, LogMetadata, LogRecord, LoggerConfig, LogSink, LogFormatter, ConsoleSinkOptions, FileSinkOptions, PrettyFormatterOptions, } from './types.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAG7C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG7E,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAG3C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGzE,YAAY,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // Logger
2
+ export { createLogger } from './logger.js';
3
+ // Sinks and formatters
4
+ export { createConsoleSink, createFileSink } from './sinks.js';
5
+ export { createJsonFormatter, createPrettyFormatter } from './formatters.js';
6
+ // Level resolution
7
+ export { resolveLogLevel } from './env.js';
8
+ // Levels
9
+ export { LEVEL_PRIORITY, shouldLog, resolveCategory } from './levels.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,uBAAuB;AACvB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAE7E,mBAAmB;AACnB,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,SAAS;AACT,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { LogLevel } from './types.js';
2
+ export declare const LEVEL_PRIORITY: Record<LogLevel, number>;
3
+ /**
4
+ * Returns true if a message at `messageLevel` should be emitted given the
5
+ * configured threshold `configuredLevel`.
6
+ */
7
+ export declare const shouldLog: (messageLevel: LogLevel, configuredLevel: LogLevel) => boolean;
8
+ export declare const resolveCategory: (name: string, levels: Record<string, LogLevel> | undefined, fallback: LogLevel) => LogLevel;
9
+ //# sourceMappingURL=levels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"levels.d.ts","sourceRoot":"","sources":["../src/levels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAM3C,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAQnD,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,SAAS,GACpB,cAAc,QAAQ,EACtB,iBAAiB,QAAQ,KACxB,OAA0E,CAAC;AAgC9E,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,EACZ,QAAQ,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,EAC5C,UAAU,QAAQ,KACjB,QAKF,CAAC"}
package/dist/levels.js ADDED
@@ -0,0 +1,52 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Level Priority
3
+ // ---------------------------------------------------------------------------
4
+ export const LEVEL_PRIORITY = {
5
+ debug: 1,
6
+ error: 4,
7
+ fatal: 5,
8
+ info: 2,
9
+ silent: 6,
10
+ trace: 0,
11
+ warn: 3,
12
+ };
13
+ // ---------------------------------------------------------------------------
14
+ // shouldLog
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Returns true if a message at `messageLevel` should be emitted given the
18
+ * configured threshold `configuredLevel`.
19
+ */
20
+ export const shouldLog = (messageLevel, configuredLevel) => LEVEL_PRIORITY[messageLevel] >= LEVEL_PRIORITY[configuredLevel];
21
+ // ---------------------------------------------------------------------------
22
+ // resolveCategory
23
+ // ---------------------------------------------------------------------------
24
+ /**
25
+ * Walk up the dot-separated category hierarchy to find the most specific
26
+ * configured level.
27
+ *
28
+ * Example: "app.db.queries" -> "app.db" -> "app" -> fallback
29
+ */
30
+ /** Walk up the dot-separated hierarchy looking for a configured level. */
31
+ const findLevel = (name, levels) => {
32
+ let prefix = name;
33
+ while (prefix.length > 0) {
34
+ const level = levels[prefix];
35
+ if (level !== undefined) {
36
+ return level;
37
+ }
38
+ const lastDot = prefix.lastIndexOf('.');
39
+ if (lastDot === -1) {
40
+ break;
41
+ }
42
+ prefix = prefix.slice(0, lastDot);
43
+ }
44
+ return undefined;
45
+ };
46
+ export const resolveCategory = (name, levels, fallback) => {
47
+ if (!levels) {
48
+ return fallback;
49
+ }
50
+ return findLevel(name, levels) ?? fallback;
51
+ };
52
+ //# sourceMappingURL=levels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"levels.js","sourceRoot":"","sources":["../src/levels.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,cAAc,GAA6B;IACtD,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;CACR,CAAC;AAEF,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,YAAsB,EACtB,eAAyB,EAChB,EAAE,CAAC,cAAc,CAAC,YAAY,CAAC,IAAI,cAAc,CAAC,eAAe,CAAC,CAAC;AAE9E,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;;GAKG;AACH,0EAA0E;AAC1E,MAAM,SAAS,GAAG,CAChB,IAAY,EACZ,MAAgC,EACV,EAAE;IACxB,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;YACnB,MAAM;QACR,CAAC;QACD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,IAAY,EACZ,MAA4C,EAC5C,QAAkB,EACR,EAAE;IACZ,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,QAAQ,CAAC;AAC7C,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Logger } from '@ontrails/core';
2
+ import type { LoggerConfig } from './types.js';
3
+ /**
4
+ * Create a structured logger with hierarchical category filtering,
5
+ * automatic redaction, and pluggable sinks.
6
+ *
7
+ * This is the **only** API for creating loggers in `@ontrails/logging`.
8
+ */
9
+ export declare const createLogger: (config: LoggerConfig) => Logger;
10
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAK7C,OAAO,KAAK,EAGV,YAAY,EAGb,MAAM,YAAY,CAAC;AAwFpB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,QAAQ,YAAY,KAAG,MAuBnD,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,80 @@
1
+ import { createRedactor, DEFAULT_PATTERNS, DEFAULT_SENSITIVE_KEYS, } from '@ontrails/core/redaction';
2
+ import { resolveLogLevel } from './env.js';
3
+ import { resolveCategory, shouldLog } from './levels.js';
4
+ import { createConsoleSink } from './sinks.js';
5
+ const buildInstance = (name, effectiveLevel, redactor, sinks,
6
+ // oxlint-disable-next-line only-used-in-recursion
7
+ config, baseMetadata) => {
8
+ const log = (level, message, metadata) => {
9
+ if (!shouldLog(level, effectiveLevel)) {
10
+ return;
11
+ }
12
+ const mergedMeta = {
13
+ ...baseMetadata,
14
+ ...metadata,
15
+ };
16
+ const record = {
17
+ category: name,
18
+ level,
19
+ message: redactor.redact(message),
20
+ metadata: Object.keys(mergedMeta).length > 0
21
+ ? redactor.redactObject(mergedMeta)
22
+ : {},
23
+ timestamp: new Date(),
24
+ };
25
+ for (const sink of sinks) {
26
+ sink.write(record);
27
+ }
28
+ };
29
+ return {
30
+ child(metadata) {
31
+ return buildInstance(name, effectiveLevel, redactor, sinks, config, {
32
+ ...baseMetadata,
33
+ ...metadata,
34
+ });
35
+ },
36
+ debug(message, metadata) {
37
+ log('debug', message, metadata);
38
+ },
39
+ error(message, metadata) {
40
+ log('error', message, metadata);
41
+ },
42
+ fatal(message, metadata) {
43
+ log('fatal', message, metadata);
44
+ },
45
+ info(message, metadata) {
46
+ log('info', message, metadata);
47
+ },
48
+ name,
49
+ trace(message, metadata) {
50
+ log('trace', message, metadata);
51
+ },
52
+ warn(message, metadata) {
53
+ log('warn', message, metadata);
54
+ },
55
+ };
56
+ };
57
+ // ---------------------------------------------------------------------------
58
+ // createLogger
59
+ // ---------------------------------------------------------------------------
60
+ /**
61
+ * Create a structured logger with hierarchical category filtering,
62
+ * automatic redaction, and pluggable sinks.
63
+ *
64
+ * This is the **only** API for creating loggers in `@ontrails/logging`.
65
+ */
66
+ export const createLogger = (config) => {
67
+ const envLevel = resolveLogLevel();
68
+ const baseLevel = config.level ?? envLevel ?? 'info';
69
+ const effectiveLevel = resolveCategory(config.name, config.levels, baseLevel);
70
+ const redactor = createRedactor({
71
+ patterns: [...DEFAULT_PATTERNS, ...(config.redaction?.patterns ?? [])],
72
+ sensitiveKeys: [
73
+ ...DEFAULT_SENSITIVE_KEYS,
74
+ ...(config.redaction?.sensitiveKeys ?? []),
75
+ ],
76
+ });
77
+ const sinks = config.sinks ?? [createConsoleSink()];
78
+ return buildInstance(config.name, effectiveLevel, redactor, sinks, { baseLevel, levels: config.levels }, {});
79
+ };
80
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { LogSink } from '../types.js';
2
+ /**
3
+ * Subset of the logtape Logger interface that we forward records to.
4
+ * Accepts any object that provides the standard log-level methods.
5
+ */
6
+ export interface LogtapeLoggerLike {
7
+ trace(message: string, props?: Record<string, unknown>): void;
8
+ debug(message: string, props?: Record<string, unknown>): void;
9
+ info(message: string, props?: Record<string, unknown>): void;
10
+ warn(message: string, props?: Record<string, unknown>): void;
11
+ error(message: string, props?: Record<string, unknown>): void;
12
+ fatal(message: string, props?: Record<string, unknown>): void;
13
+ }
14
+ export interface LogtapeSinkOptions {
15
+ /** An existing logtape logger (or compatible object) to forward records to. */
16
+ readonly logger: LogtapeLoggerLike;
17
+ }
18
+ /**
19
+ * Sink adapter that forwards `LogRecord` instances to an existing logtape
20
+ * logger. Redaction runs _before_ the sink receives records, so sensitive
21
+ * data is scrubbed regardless of the backend.
22
+ */
23
+ export declare const logtapeSink: (options: LogtapeSinkOptions) => LogSink;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/logtape/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,OAAO,EAAE,MAAM,aAAa,CAAC;AAMtD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC/D;AAMD,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;CACpC;AAiBD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,kBAAkB,KAAG,OAmBzD,CAAC"}
@@ -0,0 +1,31 @@
1
+ const LEVEL_MAP = {
2
+ debug: 'debug',
3
+ error: 'error',
4
+ fatal: 'fatal',
5
+ info: 'info',
6
+ trace: 'trace',
7
+ warn: 'warn',
8
+ };
9
+ /**
10
+ * Sink adapter that forwards `LogRecord` instances to an existing logtape
11
+ * logger. Redaction runs _before_ the sink receives records, so sensitive
12
+ * data is scrubbed regardless of the backend.
13
+ */
14
+ export const logtapeSink = (options) => {
15
+ const { logger } = options;
16
+ return {
17
+ name: 'logtape',
18
+ write(record) {
19
+ const method = LEVEL_MAP[record.level];
20
+ if (method === undefined) {
21
+ return;
22
+ }
23
+ const props = {
24
+ category: record.category,
25
+ ...record.metadata,
26
+ };
27
+ logger[method](record.message, props);
28
+ },
29
+ };
30
+ };
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/logtape/index.ts"],"names":[],"mappings":"AAkCA,MAAM,SAAS,GAAkC;IAC/C,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;CACb,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAA2B,EAAW,EAAE;IAClE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE3B,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,CAAC,MAAiB;YACrB,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAA4B;gBACrC,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,GAAG,MAAM,CAAC,QAAQ;aACnB,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { ConsoleSinkOptions, FileSinkOptions, LogSink } from './types.js';
2
+ /**
3
+ * Sink that writes to `console.*` methods.
4
+ *
5
+ * By default, uses `createPrettyFormatter()` when `TRAILS_ENV` is
6
+ * `"development"` and `createJsonFormatter()` otherwise.
7
+ */
8
+ export declare const createConsoleSink: (options?: ConsoleSinkOptions) => LogSink;
9
+ /**
10
+ * Sink that appends log records to a file using `Bun.file()`.
11
+ */
12
+ export declare const createFileSink: (options: FileSinkOptions) => LogSink;
13
+ //# sourceMappingURL=sinks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sinks.d.ts","sourceRoot":"","sources":["../src/sinks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EAEf,OAAO,EACR,MAAM,YAAY,CAAC;AAepB;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,kBAAkB,KAAG,OAoBhE,CAAC;AAMF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,SAAS,eAAe,KAAG,OAczD,CAAC"}