@ontrails/pino 1.0.0-beta.18
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/CHANGELOG.md +22 -0
- package/README.md +74 -0
- package/package.json +27 -0
- package/src/index.ts +90 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# @ontrails/pino
|
|
2
|
+
|
|
3
|
+
## 1.0.0-beta.18
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- e504e67: Add the publishable `@ontrails/pino` package scaffold.
|
|
8
|
+
- 1a65022: Implement the structural Pino log sink.
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- bf44972: Document Pino sink usage and publish-readiness checks.
|
|
13
|
+
- Updated dependencies [bf44972]
|
|
14
|
+
- Updated dependencies [e0ae995]
|
|
15
|
+
- @ontrails/observe@1.0.0-beta.18
|
|
16
|
+
|
|
17
|
+
## 1.0.0-beta.17
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- Initial publishable package scaffold.
|
|
22
|
+
- Add structural Pino log sink.
|
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# @ontrails/pino
|
|
2
|
+
|
|
3
|
+
Pino adapter package for `@ontrails/observe`.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @ontrails/observe @ontrails/pino pino
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`pino` is supplied by your application. `@ontrails/pino` has no hard runtime
|
|
12
|
+
dependency on it.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
Use `createPinoSink(...)` when you already have a Pino-shaped logger and want
|
|
17
|
+
Trails log records to flow into it:
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import pino from 'pino';
|
|
21
|
+
import { createPinoSink } from '@ontrails/pino';
|
|
22
|
+
|
|
23
|
+
const sink = createPinoSink(pino());
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The package does not depend on `pino`; it accepts any object shaped like a Pino
|
|
27
|
+
logger through `PinoLoggerLike`. Records are forwarded in Pino's object-first
|
|
28
|
+
style as `logger.info(payload, message)`, preserving the metadata already
|
|
29
|
+
redacted by Trails.
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import pino from 'pino';
|
|
33
|
+
import { topo } from '@ontrails/core';
|
|
34
|
+
import { createPinoSink } from '@ontrails/pino';
|
|
35
|
+
|
|
36
|
+
const logger = pino();
|
|
37
|
+
// trails is your application's array of Trail definitions.
|
|
38
|
+
const graph = topo('app', trails, {
|
|
39
|
+
observe: {
|
|
40
|
+
log: createPinoSink(logger),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Structural Logger Shape
|
|
46
|
+
|
|
47
|
+
`PinoLoggerLike` requires `trace`, `debug`, `info`, `warn`, `error`, and
|
|
48
|
+
`fatal` methods that accept `(payload, message)`. The sink forwards:
|
|
49
|
+
|
|
50
|
+
- `record.message` as the Pino message argument.
|
|
51
|
+
- `record.category`, `record.timestamp`, and `record.metadata` in the payload.
|
|
52
|
+
- `silent` records as no-ops.
|
|
53
|
+
|
|
54
|
+
If a required method is missing at runtime, the sink throws instead of silently
|
|
55
|
+
dropping the record.
|
|
56
|
+
|
|
57
|
+
## Publishing
|
|
58
|
+
|
|
59
|
+
`@ontrails/pino` participates in the standard Trails package publish checks:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
bun run publish:check
|
|
63
|
+
bun run publish:registry-check
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`publish:registry-check` is read-only. Before the first registry publication it
|
|
67
|
+
may report `@ontrails/pino` as a first-time package candidate. Actual package
|
|
68
|
+
publication still goes through the repo script:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
bun run publish:packages
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Do not publish this package with `npm publish` or `changeset publish`.
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ontrails/pino",
|
|
3
|
+
"version": "1.0.0-beta.18",
|
|
4
|
+
"files": [
|
|
5
|
+
"src/**/*.ts",
|
|
6
|
+
"!src/**/__tests__/**",
|
|
7
|
+
"!src/**/*.test.ts",
|
|
8
|
+
"!src/**/*.test-d.ts",
|
|
9
|
+
"README.md",
|
|
10
|
+
"CHANGELOG.md"
|
|
11
|
+
],
|
|
12
|
+
"type": "module",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./src/index.ts",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -b",
|
|
19
|
+
"test": "bun test",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"lint": "oxlint ./src",
|
|
22
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
23
|
+
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@ontrails/observe": "^1.0.0-beta.17"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { LogLevel, LogRecord, LogSink } from '@ontrails/observe';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Package identifier for the publishable Pino adapter package.
|
|
5
|
+
*/
|
|
6
|
+
export const pinoPackageName = '@ontrails/pino';
|
|
7
|
+
|
|
8
|
+
export type PinoLogMethod = (
|
|
9
|
+
payload: Record<string, unknown>,
|
|
10
|
+
message?: string
|
|
11
|
+
) => void;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Structural subset of a Pino logger.
|
|
15
|
+
*/
|
|
16
|
+
export interface PinoLoggerLike {
|
|
17
|
+
debug: PinoLogMethod;
|
|
18
|
+
error: PinoLogMethod;
|
|
19
|
+
fatal: PinoLogMethod;
|
|
20
|
+
info: PinoLogMethod;
|
|
21
|
+
trace: PinoLogMethod;
|
|
22
|
+
warn: PinoLogMethod;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PinoSinkOptions {
|
|
26
|
+
/** Sink name exposed to Trails observe configuration. Defaults to `pino`. */
|
|
27
|
+
readonly name?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type ForwardMethod = Exclude<LogLevel, 'silent'>;
|
|
31
|
+
|
|
32
|
+
const LEVEL_MAP: Record<LogLevel, ForwardMethod | undefined> = {
|
|
33
|
+
debug: 'debug',
|
|
34
|
+
error: 'error',
|
|
35
|
+
fatal: 'fatal',
|
|
36
|
+
info: 'info',
|
|
37
|
+
silent: undefined,
|
|
38
|
+
trace: 'trace',
|
|
39
|
+
warn: 'warn',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const buildPayload = (record: LogRecord): Record<string, unknown> => ({
|
|
43
|
+
...record.metadata,
|
|
44
|
+
category: record.category,
|
|
45
|
+
timestamp: record.timestamp.toISOString(),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const resolveLoggerMethod = (
|
|
49
|
+
logger: PinoLoggerLike,
|
|
50
|
+
method: ForwardMethod
|
|
51
|
+
): PinoLogMethod => {
|
|
52
|
+
const loggerMethod = logger[method];
|
|
53
|
+
if (typeof loggerMethod !== 'function') {
|
|
54
|
+
throw new TypeError(`Pino logger is missing "${method}" method`);
|
|
55
|
+
}
|
|
56
|
+
return loggerMethod.bind(logger);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const resolveLoggerMethods = (
|
|
60
|
+
logger: PinoLoggerLike
|
|
61
|
+
): Record<ForwardMethod, PinoLogMethod> => ({
|
|
62
|
+
debug: resolveLoggerMethod(logger, 'debug'),
|
|
63
|
+
error: resolveLoggerMethod(logger, 'error'),
|
|
64
|
+
fatal: resolveLoggerMethod(logger, 'fatal'),
|
|
65
|
+
info: resolveLoggerMethod(logger, 'info'),
|
|
66
|
+
trace: resolveLoggerMethod(logger, 'trace'),
|
|
67
|
+
warn: resolveLoggerMethod(logger, 'warn'),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Create a Trails log sink that forwards records to a structural Pino logger.
|
|
72
|
+
*/
|
|
73
|
+
export const createPinoSink = (
|
|
74
|
+
logger: PinoLoggerLike,
|
|
75
|
+
options: PinoSinkOptions = {}
|
|
76
|
+
): LogSink => {
|
|
77
|
+
const methods = resolveLoggerMethods(logger);
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
name: options.name ?? 'pino',
|
|
81
|
+
write(record: LogRecord): void {
|
|
82
|
+
const method = LEVEL_MAP[record.level];
|
|
83
|
+
if (method === undefined) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
methods[method](buildPayload(record), record.message);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
};
|