pino-seq 3.0.0 → 4.0.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 +54 -6
- package/dist/index.d.ts +7 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/pinoSeqStream.d.ts +21 -0
- package/dist/pinoSeqStream.js +125 -0
- package/dist/pinoSeqStream.js.map +1 -0
- package/package.json +21 -6
- package/.github/workflows/node.js.yml +0 -30
- package/.github/workflows/npm-publish.yml +0 -34
- package/.prettierrc +0 -7
- package/.vscode/launch.json +0 -62
- package/example/example.js +0 -12
- package/example/example.ts +0 -16
- package/index.d.ts +0 -19
- package/index.js +0 -10
- package/pinoSeqStream.js +0 -117
- package/test/pinoSeqSteam_tests.js +0 -11
package/README.md
CHANGED
|
@@ -2,21 +2,69 @@
|
|
|
2
2
|
|
|
3
3
|
A stream to send [Pino](https://github.com/pinojs/pino) events to [Seq](https://datalust.co/seq). Tested with Node.js versions 18.x and up.
|
|
4
4
|
|
|
5
|
+
**Now written in TypeScript** with automatic type definitions and full ES Module support!
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install pino-seq
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
5
15
|
Use the `createStream()` method to create a Pino stream configuration, passing `serverUrl`, `apiKey` and batching parameters.
|
|
6
16
|
|
|
7
|
-
|
|
17
|
+
This example works in both JavaScript and TypeScript projects:
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
8
20
|
import pino from 'pino';
|
|
9
|
-
import
|
|
21
|
+
import { createStream } from 'pino-seq';
|
|
10
22
|
|
|
11
|
-
|
|
12
|
-
|
|
23
|
+
// Create a stream to Seq
|
|
24
|
+
const stream = createStream({
|
|
25
|
+
serverUrl: 'http://localhost:5341',
|
|
26
|
+
apiKey: 'your-api-key' // optional
|
|
27
|
+
});
|
|
13
28
|
|
|
29
|
+
// Create a Pino logger
|
|
30
|
+
const logger = pino({ name: 'pino-seq example' }, stream);
|
|
31
|
+
|
|
32
|
+
// Log some messages
|
|
14
33
|
logger.info('Hello Seq, from Pino');
|
|
15
34
|
|
|
16
|
-
|
|
35
|
+
// Child loggers work too
|
|
36
|
+
const frLogger = logger.child({ lang: 'fr' });
|
|
17
37
|
frLogger.warn('au reviour');
|
|
38
|
+
|
|
39
|
+
// Flush logs before exit
|
|
40
|
+
await stream.flush();
|
|
18
41
|
```
|
|
19
42
|
|
|
20
|
-
|
|
43
|
+
For TypeScript projects with explicit typing:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { createStream, PinoSeqStreamConfig } from 'pino-seq';
|
|
47
|
+
|
|
48
|
+
const config: PinoSeqStreamConfig = {
|
|
49
|
+
serverUrl: 'http://localhost:5341',
|
|
50
|
+
// ... see Configuration section below for all options
|
|
51
|
+
};
|
|
52
|
+
const stream = createStream(config);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
The `createStream()` function accepts a configuration object with the following properties:
|
|
58
|
+
|
|
59
|
+
- `serverUrl` (string): The URL of your Seq server
|
|
60
|
+
- `apiKey` (string, optional): API key for authentication
|
|
61
|
+
- `logOtherAs` (string, optional): Log level for unstructured messages ('Verbose', 'Debug', 'Information', 'Warning', 'Error', 'Fatal')
|
|
62
|
+
- `additionalProperties` (object, optional): Additional properties to add to all log events
|
|
63
|
+
- `maxBatchingTime` (number, optional): Maximum time in milliseconds to wait before sending a batch
|
|
64
|
+
- `eventSizeLimit` (number, optional): Maximum size of a single event
|
|
65
|
+
- `batchSizeLimit` (number, optional): Maximum size of a batch
|
|
66
|
+
- `onError` (function, optional): Error handler callback
|
|
67
|
+
|
|
68
|
+
## Acknowledgements
|
|
21
69
|
|
|
22
70
|
Originally by Simi Hartstein and published as `simihartstein/pino-seq`; maintainership transferred to Datalust at version 0.5.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { PinoSeqStream, PinoSeqStreamConfig } from './pinoSeqStream.js';
|
|
2
|
+
export { PinoSeqStream, PinoSeqStreamConfig };
|
|
3
|
+
export declare function createStream(config?: PinoSeqStreamConfig): PinoSeqStream;
|
|
4
|
+
declare const _default: {
|
|
5
|
+
createStream: typeof createStream;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PinoSeqStream } from './pinoSeqStream.js';
|
|
2
|
+
export { PinoSeqStream };
|
|
3
|
+
export function createStream(config) {
|
|
4
|
+
return new PinoSeqStream(config);
|
|
5
|
+
}
|
|
6
|
+
// Default export for backward compatibility
|
|
7
|
+
export default {
|
|
8
|
+
createStream
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAuB,MAAM,oBAAoB,CAAC;AAExE,OAAO,EAAE,aAAa,EAAuB,CAAC;AAE9C,MAAM,UAAU,YAAY,CAAC,MAA4B;IACvD,OAAO,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,4CAA4C;AAC5C,eAAe;IACb,YAAY;CACb,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Writable } from 'stream';
|
|
2
|
+
import { SeqLoggerConfig } from 'seq-logging';
|
|
3
|
+
export interface PinoSeqStreamConfig extends Partial<SeqLoggerConfig> {
|
|
4
|
+
additionalProperties?: Record<string, any>;
|
|
5
|
+
logOtherAs?: 'Verbose' | 'Debug' | 'Information' | 'Warning' | 'Error' | 'Fatal';
|
|
6
|
+
_testLogger?: any;
|
|
7
|
+
}
|
|
8
|
+
export declare class PinoSeqStream extends Writable {
|
|
9
|
+
private _additionalProperties?;
|
|
10
|
+
private _logOtherAs?;
|
|
11
|
+
private _bufferTime;
|
|
12
|
+
private _buffer;
|
|
13
|
+
private _logger;
|
|
14
|
+
private _flushTimer?;
|
|
15
|
+
constructor(config?: PinoSeqStreamConfig);
|
|
16
|
+
_write(message: Buffer | string, enc: string, cb: (error?: Error | null) => void): void;
|
|
17
|
+
private handleUnstructuredMessage;
|
|
18
|
+
private flushBuffer;
|
|
19
|
+
flush(): Promise<boolean>;
|
|
20
|
+
_final(callback: (error?: Error | null) => void): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Writable } from 'stream';
|
|
2
|
+
import { Logger as SeqLogger } from 'seq-logging';
|
|
3
|
+
const LEVEL_NAMES = {
|
|
4
|
+
10: 'Verbose',
|
|
5
|
+
20: 'Debug',
|
|
6
|
+
30: 'Information',
|
|
7
|
+
40: 'Warning',
|
|
8
|
+
50: 'Error',
|
|
9
|
+
60: 'Fatal'
|
|
10
|
+
};
|
|
11
|
+
export class PinoSeqStream extends Writable {
|
|
12
|
+
constructor(config) {
|
|
13
|
+
super();
|
|
14
|
+
const { additionalProperties, logOtherAs, _testLogger, ...loggerConfig } = config || {};
|
|
15
|
+
this._additionalProperties = additionalProperties;
|
|
16
|
+
this._logOtherAs = logOtherAs;
|
|
17
|
+
this._bufferTime = false;
|
|
18
|
+
this._buffer = [];
|
|
19
|
+
// Allow injecting a mock logger for testing
|
|
20
|
+
if (_testLogger) {
|
|
21
|
+
this._logger = _testLogger;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const onError = loggerConfig.onError || ((e) => {
|
|
25
|
+
console.error('[PinoSeqStream]', e);
|
|
26
|
+
});
|
|
27
|
+
const configWithDefaults = {
|
|
28
|
+
...loggerConfig,
|
|
29
|
+
onError
|
|
30
|
+
};
|
|
31
|
+
this._logger = new SeqLogger(configWithDefaults);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
_write(message, enc, cb) {
|
|
35
|
+
if (message) {
|
|
36
|
+
try {
|
|
37
|
+
const eventCopy = JSON.parse(message.toString());
|
|
38
|
+
const { time, level, msg, err, error, stack, ...props } = eventCopy;
|
|
39
|
+
// Get the properties from the error
|
|
40
|
+
const errorObj = err || error;
|
|
41
|
+
const errMessage = errorObj?.message;
|
|
42
|
+
const errStack = errorObj?.stack;
|
|
43
|
+
const { message: _msg, stack: _stack, ...errorProps } = errorObj || {};
|
|
44
|
+
const forSeq = {
|
|
45
|
+
timestamp: new Date(time),
|
|
46
|
+
level: LEVEL_NAMES[level],
|
|
47
|
+
traceId: props.trace_id,
|
|
48
|
+
spanId: props.span_id,
|
|
49
|
+
messageTemplate: msg || errMessage,
|
|
50
|
+
properties: {
|
|
51
|
+
...this._additionalProperties,
|
|
52
|
+
...errorProps,
|
|
53
|
+
...props
|
|
54
|
+
},
|
|
55
|
+
exception: stack || errStack
|
|
56
|
+
};
|
|
57
|
+
// Handle sending to seq separately
|
|
58
|
+
try {
|
|
59
|
+
// If we get a new correctly formatted message, flush the buffer
|
|
60
|
+
if (this._logOtherAs) {
|
|
61
|
+
this.flushBuffer();
|
|
62
|
+
}
|
|
63
|
+
this._logger.emit(forSeq);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
console.error(err);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
const msg = String(message);
|
|
71
|
+
console.error(msg);
|
|
72
|
+
if (this._logOtherAs) {
|
|
73
|
+
this.handleUnstructuredMessage(msg);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
cb();
|
|
78
|
+
}
|
|
79
|
+
handleUnstructuredMessage(message) {
|
|
80
|
+
this._bufferTime = this._bufferTime || new Date();
|
|
81
|
+
this._buffer.push(message);
|
|
82
|
+
// Flush the message buffer after 1 sec of inactivity
|
|
83
|
+
if (!this._flushTimer) {
|
|
84
|
+
this._flushTimer = setTimeout(() => {
|
|
85
|
+
this.flushBuffer();
|
|
86
|
+
}, 1000);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
flushBuffer() {
|
|
90
|
+
if (this._buffer.length) {
|
|
91
|
+
try {
|
|
92
|
+
// No need to flush again
|
|
93
|
+
if (this._flushTimer) {
|
|
94
|
+
clearTimeout(this._flushTimer);
|
|
95
|
+
this._flushTimer = undefined;
|
|
96
|
+
}
|
|
97
|
+
this._logger.emit({
|
|
98
|
+
timestamp: this._bufferTime || new Date(),
|
|
99
|
+
level: this._logOtherAs,
|
|
100
|
+
messageTemplate: this._buffer.join('\n'),
|
|
101
|
+
properties: { ...this._additionalProperties },
|
|
102
|
+
});
|
|
103
|
+
this._bufferTime = false;
|
|
104
|
+
this._buffer = [];
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
console.error(err);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
flush() {
|
|
112
|
+
this.flushBuffer();
|
|
113
|
+
return this._logger.flush();
|
|
114
|
+
}
|
|
115
|
+
// Force the underlying logger to flush at the time of the call
|
|
116
|
+
// and wait for pending writes to complete
|
|
117
|
+
_final(callback) {
|
|
118
|
+
this.flushBuffer();
|
|
119
|
+
this._logger
|
|
120
|
+
.close()
|
|
121
|
+
.then(() => callback())
|
|
122
|
+
.catch((err) => callback(err));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=pinoSeqStream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pinoSeqStream.js","sourceRoot":"","sources":["../src/pinoSeqStream.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pino-seq",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "A stream that sends Pino log events to Seq",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"types": "index.d.ts",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
8
19
|
"scripts": {
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"prepublishOnly": "npm run build",
|
|
22
|
+
"test": "npm run build && mocha --ignore test/integration*.js",
|
|
23
|
+
"test:integration": "npm run build && mocha --include test/integration*.js --timeout 10000",
|
|
24
|
+
"dev": "tsc --watch"
|
|
12
25
|
},
|
|
13
26
|
"repository": {
|
|
14
27
|
"type": "git",
|
|
@@ -25,7 +38,9 @@
|
|
|
25
38
|
},
|
|
26
39
|
"homepage": "https://github.com/datalust/pino-seq#readme",
|
|
27
40
|
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.0.6",
|
|
28
42
|
"mocha": "^11.7.4",
|
|
43
|
+
"pino": "^10.1.1",
|
|
29
44
|
"tsx": "^4.20.6",
|
|
30
45
|
"typescript": "^5.9.3"
|
|
31
46
|
},
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
|
2
|
-
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
|
3
|
-
|
|
4
|
-
name: Test
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
push:
|
|
8
|
-
branches: [ dev ]
|
|
9
|
-
pull_request:
|
|
10
|
-
branches: [ dev ]
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
build:
|
|
14
|
-
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
|
|
17
|
-
strategy:
|
|
18
|
-
matrix:
|
|
19
|
-
node-version: [18.x, 20.x, 22.x]
|
|
20
|
-
os: [ubuntu-latest, windows-latest, macOS-latest]
|
|
21
|
-
|
|
22
|
-
steps:
|
|
23
|
-
- uses: actions/checkout@v2
|
|
24
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
25
|
-
uses: actions/setup-node@v1
|
|
26
|
-
with:
|
|
27
|
-
node-version: ${{ matrix.node-version }}
|
|
28
|
-
- run: npm ci
|
|
29
|
-
- run: npm run build --if-present
|
|
30
|
-
- run: npm test
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
-
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
|
|
3
|
-
|
|
4
|
-
name: Publish
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
push:
|
|
8
|
-
branches:
|
|
9
|
-
- main
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
build:
|
|
13
|
-
runs-on: ubuntu-latest
|
|
14
|
-
steps:
|
|
15
|
-
- uses: actions/checkout@v2
|
|
16
|
-
- uses: actions/setup-node@v1
|
|
17
|
-
with:
|
|
18
|
-
node-version: 20
|
|
19
|
-
- run: npm ci
|
|
20
|
-
- run: npm test
|
|
21
|
-
|
|
22
|
-
publish-npm:
|
|
23
|
-
needs: build
|
|
24
|
-
runs-on: ubuntu-latest
|
|
25
|
-
steps:
|
|
26
|
-
- uses: actions/checkout@v2
|
|
27
|
-
- uses: actions/setup-node@v1
|
|
28
|
-
with:
|
|
29
|
-
node-version: 20
|
|
30
|
-
registry-url: https://registry.npmjs.org/
|
|
31
|
-
- run: npm ci
|
|
32
|
-
- run: npm publish
|
|
33
|
-
env:
|
|
34
|
-
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
package/.prettierrc
DELETED
package/.vscode/launch.json
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "0.2.0",
|
|
3
|
-
"configurations": [
|
|
4
|
-
{
|
|
5
|
-
"name": "Current TS File",
|
|
6
|
-
"type": "node",
|
|
7
|
-
"request": "launch",
|
|
8
|
-
"args": [
|
|
9
|
-
"${relativeFile}"
|
|
10
|
-
],
|
|
11
|
-
"runtimeArgs": [
|
|
12
|
-
"--nolazy",
|
|
13
|
-
"-r",
|
|
14
|
-
"ts-node/register"
|
|
15
|
-
],
|
|
16
|
-
"sourceMaps": true,
|
|
17
|
-
"cwd": "${workspaceRoot}",
|
|
18
|
-
"protocol": "inspector",
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"name": "Launch",
|
|
22
|
-
"type": "node",
|
|
23
|
-
"request": "launch",
|
|
24
|
-
"program": "${workspaceRoot}/example/example.js",
|
|
25
|
-
"stopOnEntry": false,
|
|
26
|
-
"args": [],
|
|
27
|
-
"cwd": "${workspaceRoot}",
|
|
28
|
-
"preLaunchTask": null,
|
|
29
|
-
"runtimeExecutable": null,
|
|
30
|
-
"runtimeArgs": [
|
|
31
|
-
"--nolazy"
|
|
32
|
-
],
|
|
33
|
-
"env": {
|
|
34
|
-
"NODE_ENV": "development"
|
|
35
|
-
},
|
|
36
|
-
"console": "internalConsole",
|
|
37
|
-
"sourceMaps": false,
|
|
38
|
-
"outDir": null
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"name": "Attach",
|
|
42
|
-
"type": "node",
|
|
43
|
-
"request": "attach",
|
|
44
|
-
"port": 5858,
|
|
45
|
-
"address": "localhost",
|
|
46
|
-
"restart": false,
|
|
47
|
-
"sourceMaps": false,
|
|
48
|
-
"outDir": null,
|
|
49
|
-
"localRoot": "${workspaceRoot}",
|
|
50
|
-
"remoteRoot": null
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"name": "Attach to Process",
|
|
54
|
-
"type": "node",
|
|
55
|
-
"request": "attach",
|
|
56
|
-
"processId": "${command.PickProcess}",
|
|
57
|
-
"port": 5858,
|
|
58
|
-
"sourceMaps": false,
|
|
59
|
-
"outDir": null
|
|
60
|
-
}
|
|
61
|
-
]
|
|
62
|
-
}
|
package/example/example.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import pino from 'pino';
|
|
4
|
-
import pinoToSeq from '../index.js';
|
|
5
|
-
|
|
6
|
-
let stream = pinoToSeq.createStream({serverUrl: "http://localhost:5341"});
|
|
7
|
-
let logger = pino({name: "pino-seq example"}, stream);
|
|
8
|
-
|
|
9
|
-
logger.info("Hello Seq, from Pino");
|
|
10
|
-
|
|
11
|
-
let frLogger = logger.child({lang: "fr"});
|
|
12
|
-
frLogger.warn("au reviour");
|
package/example/example.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import Pino from "pino"
|
|
2
|
-
import PinoSeq from ".."
|
|
3
|
-
|
|
4
|
-
const stream = PinoSeq.createStream({serverUrl: "http://localhost:5341"});
|
|
5
|
-
|
|
6
|
-
const options: Pino.LoggerOptions = {
|
|
7
|
-
name: "pino-seq example"
|
|
8
|
-
}
|
|
9
|
-
const logger: Pino.Logger = Pino(options, stream);
|
|
10
|
-
|
|
11
|
-
logger.info("Hello Seq, from Pino");
|
|
12
|
-
|
|
13
|
-
const frLogger = logger.child({lang: "fr"});
|
|
14
|
-
frLogger.warn("au reviour");
|
|
15
|
-
|
|
16
|
-
stream.flush().then((_) => console.log('flushed'));
|
package/index.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Writable } from 'stream';
|
|
2
|
-
|
|
3
|
-
declare namespace PinoSeq {
|
|
4
|
-
interface SeqConfig {
|
|
5
|
-
serverUrl?: string;
|
|
6
|
-
apiKey?: string;
|
|
7
|
-
logOtherAs?: 'Verbose' | 'Debug' | 'Information' | 'Warning' | 'Error' | 'Fatal';
|
|
8
|
-
maxBatchingTime?: number;
|
|
9
|
-
eventSizeLimit?: number;
|
|
10
|
-
batchSizeLimit?: number;
|
|
11
|
-
onError?: (e: Error) => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function createStream(config: PinoSeq.SeqConfig): Writable & {
|
|
15
|
-
flush: () => Promise<boolean>;
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export = PinoSeq;
|
package/index.js
DELETED
package/pinoSeqStream.js
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import stream from 'stream';
|
|
4
|
-
import { Logger as SeqLogger } from 'seq-logging';
|
|
5
|
-
|
|
6
|
-
let LEVEL_NAMES = {
|
|
7
|
-
10: 'Verbose',
|
|
8
|
-
20: 'Debug',
|
|
9
|
-
30: 'Information',
|
|
10
|
-
40: 'Warning',
|
|
11
|
-
50: 'Error',
|
|
12
|
-
60: 'Fatal'
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
class PinoSeqStream extends stream.Writable {
|
|
16
|
-
constructor(config) {
|
|
17
|
-
super();
|
|
18
|
-
|
|
19
|
-
let { additionalProperties, logOtherAs, ...loggerConfig } = config == null ? {} : { ...config };
|
|
20
|
-
loggerConfig.onError = loggerConfig.onError || function (e) { console.error('[PinoSeqStream] Log batch failed\n', e) };
|
|
21
|
-
this._additionalProperties = additionalProperties;
|
|
22
|
-
this._logOtherAs = logOtherAs;
|
|
23
|
-
this._bufferTime = false;
|
|
24
|
-
this._buffer = [];
|
|
25
|
-
this._logger = new SeqLogger(loggerConfig);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
_write(message, enc, cb) {
|
|
29
|
-
if (message) {
|
|
30
|
-
try {
|
|
31
|
-
let eventCopy = JSON.parse(message);
|
|
32
|
-
|
|
33
|
-
let { time, level, msg, err, error, stack, ...props } = eventCopy;
|
|
34
|
-
|
|
35
|
-
// Get the properties from the error
|
|
36
|
-
let { message: errMessage, stack: errStack, ...errorProps } = err || error || {};
|
|
37
|
-
|
|
38
|
-
let forSeq = {
|
|
39
|
-
timestamp: new Date(time),
|
|
40
|
-
level: LEVEL_NAMES[level],
|
|
41
|
-
traceId: props.trace_id,
|
|
42
|
-
spanId: props.span_id,
|
|
43
|
-
messageTemplate: msg ? msg : errMessage,
|
|
44
|
-
properties: { ...this._additionalProperties, ...errorProps, ...props },
|
|
45
|
-
exception: stack ? stack : errStack
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
// Handle sending to sql separatly
|
|
49
|
-
try {
|
|
50
|
-
// If we get a new correctly formatted message, flush the buffer
|
|
51
|
-
if (this._logOtherAs) {
|
|
52
|
-
this.flushBuffer();
|
|
53
|
-
}
|
|
54
|
-
this._logger.emit(forSeq);
|
|
55
|
-
} catch (err) {
|
|
56
|
-
console.error(err);
|
|
57
|
-
}
|
|
58
|
-
} catch (err) {
|
|
59
|
-
const msg = String(message);
|
|
60
|
-
console.error(msg);
|
|
61
|
-
if (this._logOtherAs) {
|
|
62
|
-
this.handleUnstructuredMessage(msg);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
cb();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
handleUnstructuredMessage(message) {
|
|
70
|
-
this._bufferTime = this._bufferTime ? this._bufferTime : new Date();
|
|
71
|
-
this._buffer.push(message);
|
|
72
|
-
// Flush the message buffer after 1 sec of inacticity
|
|
73
|
-
if (!this._flushTimer) {
|
|
74
|
-
this._flushTimer = setTimeout(() => {
|
|
75
|
-
this.flushBuffer();
|
|
76
|
-
}, 1000);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
flushBuffer() {
|
|
81
|
-
if (this._buffer.length) {
|
|
82
|
-
try {
|
|
83
|
-
// No need to flush again
|
|
84
|
-
if (this._flushTimer) {
|
|
85
|
-
clearTimeout(this._flushTimer);
|
|
86
|
-
}
|
|
87
|
-
this._logger.emit({
|
|
88
|
-
timestamp: this._bufferTime,
|
|
89
|
-
level: this._logOtherAs,
|
|
90
|
-
messageTemplate: this._buffer.join('\n'),
|
|
91
|
-
properties: { ...this._additionalProperties },
|
|
92
|
-
});
|
|
93
|
-
this._bufferTime = false;
|
|
94
|
-
this._buffer = [];
|
|
95
|
-
} catch (err) {
|
|
96
|
-
console.error(err);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
flush() {
|
|
102
|
-
this.flushBuffer();
|
|
103
|
-
return this._logger.flush();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Force the underlying logger to flush at the time of the call
|
|
107
|
-
// and wait for pending writes to complete
|
|
108
|
-
_final(callback) {
|
|
109
|
-
this.flushBuffer();
|
|
110
|
-
this._logger
|
|
111
|
-
.close()
|
|
112
|
-
.then(() => callback())
|
|
113
|
-
.catch((err) => callback(err));
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export { PinoSeqStream };
|