@polygonlabs/logger 0.2.0 → 0.3.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 +48 -72
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/logger.d.ts +6 -53
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +47 -53
- package/dist/logger.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @polygonlabs/logger
|
|
2
2
|
|
|
3
3
|
Shared pino-based logger for Polygon Apps Team services. Pre-configured for Datadog
|
|
4
|
-
ingestion with VError-aware error
|
|
4
|
+
ingestion with automatic VError-aware error handling and optional Sentry capture.
|
|
5
5
|
|
|
6
6
|
## Why this package exists
|
|
7
7
|
|
|
@@ -10,8 +10,9 @@ Every service in the team needs the same pino configuration: `message` key inste
|
|
|
10
10
|
in each service individually leads to drift — one service logs `"msg"` while another logs
|
|
11
11
|
`"message"`, breaking Datadog log parsing.
|
|
12
12
|
|
|
13
|
-
This package provides one factory
|
|
14
|
-
|
|
13
|
+
This package provides one factory and a consistent output shape across all services.
|
|
14
|
+
VError/WError handling and Sentry capture are wired in at the pino level, so every log
|
|
15
|
+
call benefits automatically — no special method required.
|
|
15
16
|
|
|
16
17
|
## Usage
|
|
17
18
|
|
|
@@ -20,7 +21,7 @@ import { createLogger } from '@polygonlabs/logger';
|
|
|
20
21
|
|
|
21
22
|
const logger = await createLogger();
|
|
22
23
|
logger.info({ requestId: '123' }, 'request received');
|
|
23
|
-
logger.
|
|
24
|
+
logger.error({ err }, err.message);
|
|
24
25
|
```
|
|
25
26
|
|
|
26
27
|
**Do not import as a module-level singleton.** Construct once at the service entry point
|
|
@@ -34,7 +35,7 @@ const logger = await createLogger({ sentry });
|
|
|
34
35
|
|
|
35
36
|
// handler / service layer
|
|
36
37
|
class UserService {
|
|
37
|
-
constructor(private readonly logger:
|
|
38
|
+
constructor(private readonly logger: Logger) {}
|
|
38
39
|
|
|
39
40
|
async getUser(id: string) {
|
|
40
41
|
const log = this.logger.child({ userId: id });
|
|
@@ -43,6 +44,8 @@ class UserService {
|
|
|
43
44
|
}
|
|
44
45
|
```
|
|
45
46
|
|
|
47
|
+
`createLogger` returns pino's `Logger` type directly — import it from `pino`.
|
|
48
|
+
|
|
46
49
|
## Customisation via child loggers
|
|
47
50
|
|
|
48
51
|
`createLogger()` intentionally does not accept options for the output shape — that
|
|
@@ -84,84 +87,48 @@ const httpLogger = logger.child(
|
|
|
84
87
|
**Request/handler-scoped fields** — create further children inside handlers:
|
|
85
88
|
|
|
86
89
|
```ts
|
|
87
|
-
async function handleRequest(req: Request, logger:
|
|
90
|
+
async function handleRequest(req: Request, logger: Logger) {
|
|
88
91
|
const log = logger.child({ requestId: req.id, method: req.method });
|
|
89
|
-
log.info('handling request');
|
|
90
|
-
log.
|
|
92
|
+
log.info('handling request');
|
|
93
|
+
log.error({ err }, err.message);
|
|
91
94
|
}
|
|
92
95
|
```
|
|
93
96
|
|
|
94
97
|
Child bindings and options merge at any depth — grandchild loggers carry all ancestor
|
|
95
|
-
bindings, and
|
|
96
|
-
|
|
97
|
-
## `AppLogger` type
|
|
98
|
-
|
|
99
|
-
`AppLogger` is a standard `pino.Logger` with two additions:
|
|
100
|
-
|
|
101
|
-
- **`logError({ err, ...context }, message?)`** — VError/WError-aware error logging (see below)
|
|
102
|
-
- **`child()`** — overridden to return `AppLogger` so child loggers carry `logError`
|
|
103
|
-
at any depth
|
|
104
|
-
|
|
105
|
-
Use `AppLogger` as the type throughout your service code rather than importing
|
|
106
|
-
`createLogger` everywhere.
|
|
98
|
+
bindings, and all VError/WError behaviour is preserved at every level.
|
|
107
99
|
|
|
108
|
-
##
|
|
100
|
+
## VError and WError handling
|
|
109
101
|
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
VError/WError handling is automatic for every log level. Pass `err` in the merge object
|
|
103
|
+
as you would any other pino log call:
|
|
112
104
|
|
|
113
105
|
```ts
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
logger.logError({ err });
|
|
118
|
-
logger.logError({ err, requestId, userId }); // with call-site context
|
|
119
|
-
logger.logError({ err, requestId }, 'user-facing message'); // with message override
|
|
120
|
-
}
|
|
106
|
+
logger.error({ err }, err.message)
|
|
107
|
+
logger.warn({ err, requestId }, 'degraded — retrying')
|
|
108
|
+
logger.error({ err, requestId, userId }, 'optional message override')
|
|
121
109
|
```
|
|
122
110
|
|
|
123
|
-
|
|
124
|
-
would be if you called `logger.error({ err, requestId }, message)` directly. All entries
|
|
125
|
-
carry the child bindings of the logger and are always at `error` level.
|
|
126
|
-
|
|
127
|
-
`err` must be an `Error` instance — passing a non-Error is a TypeScript error. For unknown
|
|
128
|
-
values from a catch block, narrow first or fall back to `logger.error()` directly:
|
|
129
|
-
|
|
130
|
-
```ts
|
|
131
|
-
try {
|
|
132
|
-
await something();
|
|
133
|
-
} catch (err) {
|
|
134
|
-
if (err instanceof Error) {
|
|
135
|
-
logger.logError({ err });
|
|
136
|
-
} else {
|
|
137
|
-
logger.error(String(err));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### VError `info` is namespaced under `"error_info"`
|
|
111
|
+
### `error_info`
|
|
143
112
|
|
|
144
113
|
VError `info` fields from the full cause chain are always emitted under the reserved
|
|
145
114
|
`error_info` key — never spread at the top level. This keeps error-carried context clearly
|
|
146
|
-
separated from call-site context, with no collision risk
|
|
115
|
+
separated from call-site context, with no collision risk:
|
|
147
116
|
|
|
148
117
|
```ts
|
|
149
118
|
const err = new VError('query failed', { info: { requestId: 'abc', table: 'users' } });
|
|
150
|
-
logger.
|
|
151
|
-
// {
|
|
152
|
-
//
|
|
119
|
+
logger.error({ err, traceId: 'xyz' }, err.message);
|
|
120
|
+
// {
|
|
121
|
+
// level: 'error', message: 'query failed', err: { ... },
|
|
122
|
+
// traceId: 'xyz', ← call-site context, top level
|
|
153
123
|
// error_info: { requestId: 'abc', table: 'users' } ← error info, always nested
|
|
154
124
|
// }
|
|
155
125
|
```
|
|
156
126
|
|
|
157
|
-
|
|
127
|
+
If a VError has no `info`, the `error_info` key is omitted entirely.
|
|
158
128
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
If a VError has no `info`, the `error_info` key is omitted from the log entry entirely.
|
|
129
|
+
`error_info` is a **reserved key** — do not include it in merge objects. If a caller
|
|
130
|
+
supplies it, the logger emits a `warn`-level diagnostic with the conflicting value under
|
|
131
|
+
`callerErrorInfo`, then overwrites the key with the real VError info.
|
|
165
132
|
|
|
166
133
|
### Behaviour by `err` type
|
|
167
134
|
|
|
@@ -169,7 +136,7 @@ If a VError has no `info`, the `error_info` key is omitted from the log entry en
|
|
|
169
136
|
`stdSerializers.err`) and the error message as the log message. No `error_info` key:
|
|
170
137
|
|
|
171
138
|
```ts
|
|
172
|
-
logger.
|
|
139
|
+
logger.error({ err: new Error('connection refused') }, 'connection refused');
|
|
173
140
|
// { level: 'error', message: 'connection refused', err: { message, stack, type } }
|
|
174
141
|
```
|
|
175
142
|
|
|
@@ -177,7 +144,7 @@ logger.logError({ err: new Error('connection refused') });
|
|
|
177
144
|
|
|
178
145
|
```ts
|
|
179
146
|
const err = new VError('query failed', { info: { requestId: 'abc', table: 'users' } });
|
|
180
|
-
logger.
|
|
147
|
+
logger.error({ err }, err.message);
|
|
181
148
|
// { level: 'error', message: 'query failed', err: { ... }, error_info: { requestId: 'abc', table: 'users' } }
|
|
182
149
|
```
|
|
183
150
|
|
|
@@ -187,19 +154,22 @@ context is carried through to the cause's entry:
|
|
|
187
154
|
```ts
|
|
188
155
|
const root = new Error('connection refused');
|
|
189
156
|
const err = new WError('could not load user', { cause: root });
|
|
190
|
-
logger.
|
|
157
|
+
logger.error({ err, requestId: 'abc' }, err.message);
|
|
191
158
|
// { level: 'error', message: 'connection refused', err: { ... }, requestId: 'abc' }
|
|
192
159
|
// 'could not load user' is NOT logged — the cause is what matters
|
|
193
160
|
```
|
|
194
161
|
|
|
195
162
|
The cause is processed by the same rules, so a `WError` wrapping a `VError` with `info`
|
|
196
|
-
will emit the `VError`
|
|
163
|
+
will emit the `VError`'s `error_info` alongside call-site context.
|
|
164
|
+
|
|
165
|
+
## Sentry
|
|
197
166
|
|
|
198
|
-
|
|
167
|
+
If a Sentry client was passed to `createLogger`, `captureException` fires automatically
|
|
168
|
+
for every `logger.error({ err })` call. It does not fire for `warn`, `info`, or other
|
|
169
|
+
levels — only `error`.
|
|
199
170
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
For a `WError`, only the cause is captured — consistent with the logging behaviour above.
|
|
171
|
+
For a `WError`, the cause is captured rather than the wrapper, consistent with what is
|
|
172
|
+
logged.
|
|
203
173
|
|
|
204
174
|
```ts
|
|
205
175
|
import * as Sentry from '@sentry/node';
|
|
@@ -232,6 +202,12 @@ The logger is pre-configured for Datadog ingestion:
|
|
|
232
202
|
| `pid`, `hostname` | suppressed |
|
|
233
203
|
| `err` | serialised via pino's built-in `stdSerializers.err` |
|
|
234
204
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
205
|
+
### Reserved keys
|
|
206
|
+
|
|
207
|
+
Two keys in the merge object are reserved and will trigger a `warn`-level diagnostic if
|
|
208
|
+
supplied by a caller:
|
|
209
|
+
|
|
210
|
+
| Key | Written by | Conflicting value preserved as |
|
|
211
|
+
|-----|-----------|-------------------------------|
|
|
212
|
+
| `timestamp` | `timestamp` function | `callerTimestamp` |
|
|
213
|
+
| `error_info` | VError info extractor | `callerErrorInfo` |
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,60 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DestinationStream, Logger } from 'pino';
|
|
2
2
|
/**
|
|
3
3
|
* Duck-typed interface for Sentry error capturing. Matches the surface of
|
|
4
|
-
* @sentry/node used by
|
|
5
|
-
*
|
|
4
|
+
* @sentry/node used by automatic error capture on logger.error() calls. Pass
|
|
5
|
+
* an initialised Sentry client to createLogger to activate it.
|
|
6
6
|
*/
|
|
7
7
|
export interface SentryAdapter {
|
|
8
8
|
captureException(err: unknown): void;
|
|
9
9
|
captureMessage(msg: string, level: string): void;
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
* pino Logger extended with logError and a narrowed child() return type.
|
|
13
|
-
*
|
|
14
|
-
* logError is a VError/WError-aware error logging helper: use it in preference
|
|
15
|
-
* to logger.error() for caught exceptions so that VError info fields are emitted
|
|
16
|
-
* as discrete structured fields and WError cause chains are fully unwound into
|
|
17
|
-
* separate log entries.
|
|
18
|
-
*
|
|
19
|
-
* child() is overridden to return AppLogger so child loggers inherit logError
|
|
20
|
-
* and the override is preserved at any depth.
|
|
21
|
-
*
|
|
22
|
-
* Inject this type throughout your service rather than importing a module-level
|
|
23
|
-
* singleton. Construct once at the entry point and pass down via constructor
|
|
24
|
-
* arguments or function parameters.
|
|
25
|
-
*/
|
|
26
|
-
export type AppLogger = Omit<Logger, 'child'> & {
|
|
27
|
-
/**
|
|
28
|
-
* Log an error at `error` level. Mirrors pino's merge-object signature with
|
|
29
|
-
* `err` as a required key:
|
|
30
|
-
*
|
|
31
|
-
* logger.logError({ err })
|
|
32
|
-
* logger.logError({ err, requestId, userId }, 'optional message override')
|
|
33
|
-
*
|
|
34
|
-
* VError `info` fields from the full cause chain are spread into the log entry
|
|
35
|
-
* alongside any call-site context. Call-site context wins on key collision.
|
|
36
|
-
* WError wrappers are skipped — only the cause is logged.
|
|
37
|
-
*/
|
|
38
|
-
/**
|
|
39
|
-
* Log an error at `error` level. Mirrors pino's merge-object signature with
|
|
40
|
-
* `err` as a required key:
|
|
41
|
-
*
|
|
42
|
-
* logger.logError({ err })
|
|
43
|
-
* logger.logError({ err, requestId, userId }, 'optional message override')
|
|
44
|
-
*
|
|
45
|
-
* VError `info` from the full cause chain is always emitted under the `error_info`
|
|
46
|
-
* key — never spread at the top level. This means `error_info` is a reserved key:
|
|
47
|
-
* passing it in the context object is a TypeScript error.
|
|
48
|
-
*
|
|
49
|
-
* `err` must be an `Error` instance. For non-Error caught values, narrow first or
|
|
50
|
-
* use `logger.error()` directly.
|
|
51
|
-
*/
|
|
52
|
-
logError(obj: {
|
|
53
|
-
err: Error;
|
|
54
|
-
error_info?: never;
|
|
55
|
-
} & Record<string, unknown>, message?: string): void;
|
|
56
|
-
child(bindings: Bindings, options?: ChildLoggerOptions): AppLogger;
|
|
57
|
-
};
|
|
58
11
|
export interface CreateLoggerOptions {
|
|
59
12
|
/** Enable pino-pretty output for development. Requires pino-pretty to be installed. */
|
|
60
13
|
pretty?: boolean;
|
|
@@ -64,11 +17,11 @@ export interface CreateLoggerOptions {
|
|
|
64
17
|
*/
|
|
65
18
|
destination?: DestinationStream;
|
|
66
19
|
/**
|
|
67
|
-
* Optional Sentry adapter for automatic error capturing
|
|
20
|
+
* Optional Sentry adapter for automatic error capturing on logger.error() calls.
|
|
68
21
|
* Pass your initialised @sentry/node instance (or any object satisfying
|
|
69
|
-
* SentryAdapter).
|
|
22
|
+
* SentryAdapter). Inherited by all child loggers.
|
|
70
23
|
*/
|
|
71
24
|
sentry?: SentryAdapter;
|
|
72
25
|
}
|
|
73
|
-
export declare function createLogger(options?: CreateLoggerOptions): Promise<
|
|
26
|
+
export declare function createLogger(options?: CreateLoggerOptions): Promise<Logger>;
|
|
74
27
|
//# sourceMappingURL=logger.d.ts.map
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAC;AAMrE;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IACrC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,mBAAmB;IAClC,uFAAuF;IACvF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAKD,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiGjF"}
|
package/dist/logger.js
CHANGED
|
@@ -1,25 +1,7 @@
|
|
|
1
1
|
import { pino, stdSerializers } from 'pino';
|
|
2
2
|
import { VError, WError } from '@polygonlabs/verror';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
// WError is a wrapper whose own message is intentionally not the useful signal —
|
|
6
|
-
// the cause is. Skip the WError itself and recurse directly into its cause.
|
|
7
|
-
// Carry call-site context through; discard the developer's message override since
|
|
8
|
-
// it described the wrapper, not the cause.
|
|
9
|
-
if (err instanceof WError) {
|
|
10
|
-
const cause = VError.cause(err);
|
|
11
|
-
// The spread of context (Record<string, unknown>) widens err back to unknown;
|
|
12
|
-
// cast is safe because cause is narrowed to Error by the if-guard above.
|
|
13
|
-
if (cause)
|
|
14
|
-
logError(logger, { err: cause, ...context }, undefined, sentry);
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
// info from the full cause chain is spread first so call-site context wins on collision.
|
|
18
|
-
const info = err instanceof VError ? VError.info(err) : {};
|
|
19
|
-
const infoEntry = Object.keys(info).length > 0 ? { error_info: info } : {};
|
|
20
|
-
logger.error({ err, ...context, ...infoEntry }, message ?? err.message);
|
|
21
|
-
sentry?.captureException(err);
|
|
22
|
-
}
|
|
3
|
+
// Pino's numeric level for "error". Used in hooks.logMethod to gate Sentry capture.
|
|
4
|
+
const PINO_ERROR_LEVEL = 50;
|
|
23
5
|
export async function createLogger(options) {
|
|
24
6
|
// ref.self is assigned immediately after pino() returns. The formatters.log
|
|
25
7
|
// closure only fires when a log method is called — never during construction —
|
|
@@ -41,19 +23,56 @@ export async function createLogger(options) {
|
|
|
41
23
|
level(label) {
|
|
42
24
|
return { level: label };
|
|
43
25
|
},
|
|
44
|
-
// Detect a caller-supplied "timestamp" key and rename it so it cannot
|
|
45
|
-
// shadow the authoritative timestamp written by the timestamp function.
|
|
46
26
|
log(object) {
|
|
47
|
-
|
|
48
|
-
|
|
27
|
+
let out = object;
|
|
28
|
+
// Detect a caller-supplied "timestamp" key and rename it so it cannot
|
|
29
|
+
// shadow the authoritative timestamp written by the timestamp function.
|
|
30
|
+
if ('timestamp' in out) {
|
|
31
|
+
const { timestamp, ...rest } = out;
|
|
49
32
|
ref.self?.warn({ callerTimestamp: timestamp }, 'Log call included "timestamp" in merge object — reserved key renamed to callerTimestamp. Fix the call site.');
|
|
50
|
-
|
|
33
|
+
out = { callerTimestamp: timestamp, ...rest };
|
|
34
|
+
}
|
|
35
|
+
// Detect a caller-supplied "error_info" key and strip it — the correct
|
|
36
|
+
// value is derived from the err below. Preserve the caller's value in a
|
|
37
|
+
// warning so it is not silently lost.
|
|
38
|
+
if ('error_info' in out) {
|
|
39
|
+
const { error_info, ...rest } = out;
|
|
40
|
+
ref.self?.warn({ callerErrorInfo: error_info }, 'Log call included "error_info" in merge object — reserved key ignored. Fix the call site.');
|
|
41
|
+
out = rest;
|
|
51
42
|
}
|
|
52
|
-
|
|
43
|
+
// Emit merged VError info chain under error_info for structured querying.
|
|
44
|
+
// By this point hooks.logMethod has already unwrapped any WError, so err
|
|
45
|
+
// is always the meaningful cause when it arrives here.
|
|
46
|
+
if (out['err'] instanceof VError) {
|
|
47
|
+
const info = VError.info(out['err']);
|
|
48
|
+
if (Object.keys(info).length > 0)
|
|
49
|
+
out = { ...out, error_info: info };
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
53
52
|
}
|
|
54
53
|
},
|
|
55
54
|
serializers: {
|
|
56
55
|
err: stdSerializers.err
|
|
56
|
+
},
|
|
57
|
+
hooks: {
|
|
58
|
+
logMethod(args, method, level) {
|
|
59
|
+
const first = args[0];
|
|
60
|
+
if (first !== null && typeof first === 'object' && 'err' in first) {
|
|
61
|
+
const obj = first;
|
|
62
|
+
if (obj['err'] instanceof Error) {
|
|
63
|
+
// Unwrap WError chain — WError's own message is never the useful signal.
|
|
64
|
+
let err = obj['err'];
|
|
65
|
+
while (err instanceof WError)
|
|
66
|
+
err = VError.cause(err) ?? err;
|
|
67
|
+
if (err !== obj['err'])
|
|
68
|
+
args[0] = { ...obj, err };
|
|
69
|
+
// Capture in Sentry for error-level calls only.
|
|
70
|
+
if (level === PINO_ERROR_LEVEL)
|
|
71
|
+
options?.sentry?.captureException(err);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
method.apply(this, args);
|
|
75
|
+
}
|
|
57
76
|
}
|
|
58
77
|
};
|
|
59
78
|
let destination = options?.destination;
|
|
@@ -67,32 +86,7 @@ export async function createLogger(options) {
|
|
|
67
86
|
});
|
|
68
87
|
}
|
|
69
88
|
const base = destination ? pino(pinoOptions, destination) : pino(pinoOptions);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// We call it with .call(target) where target is the raw pino instance (never the Proxy),
|
|
73
|
-
// so pino's child creation runs with a clean `this` and produces a raw child whose
|
|
74
|
-
// prototype chain is pure pino. We then wrap that child in a new Proxy via enrichLogger.
|
|
75
|
-
const pinoProtoChild = Object.getPrototypeOf(base).child;
|
|
76
|
-
function enrichLogger(instance) {
|
|
77
|
-
// Wrap in a Proxy rather than mutating the pino logger instance. Mutation would
|
|
78
|
-
// make logError and child OWN properties on the pino object, which become visible
|
|
79
|
-
// in descendant loggers via their prototype chain (pino creates children with
|
|
80
|
-
// Object.create(parent)). A Proxy intercepts only the two properties we care about
|
|
81
|
-
// and passes everything else through to the original logger untouched.
|
|
82
|
-
return new Proxy(instance, {
|
|
83
|
-
get(target, prop, receiver) {
|
|
84
|
-
if (prop === 'logError') {
|
|
85
|
-
return (obj, message) => logError(target, obj, message, options?.sentry);
|
|
86
|
-
}
|
|
87
|
-
if (prop === 'child') {
|
|
88
|
-
return (bindings, childOptions) => enrichLogger(pinoProtoChild.call(target, bindings, childOptions));
|
|
89
|
-
}
|
|
90
|
-
return Reflect.get(target, prop, receiver);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
const logger = enrichLogger(base);
|
|
95
|
-
ref.self = logger;
|
|
96
|
-
return logger;
|
|
89
|
+
ref.self = base;
|
|
90
|
+
return base;
|
|
97
91
|
}
|
|
98
92
|
//# sourceMappingURL=logger.js.map
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED