@nestjs-labs/pino-http-extra 0.0.1
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 +148 -0
- package/dist/formatters.d.ts +7 -0
- package/dist/formatters.d.ts.map +1 -0
- package/dist/formatters.js +22 -0
- package/dist/formatters.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/options.d.ts +3 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +54 -0
- package/dist/options.js.map +1 -0
- package/dist/serializers.d.ts +3 -0
- package/dist/serializers.d.ts.map +1 -0
- package/dist/serializers.js +26 -0
- package/dist/serializers.js.map +1 -0
- package/dist/streams.d.ts +6 -0
- package/dist/streams.d.ts.map +1 -0
- package/dist/streams.js +52 -0
- package/dist/streams.js.map +1 -0
- package/package.json +95 -0
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @nestjs-labs/pino-http-extra
|
|
2
|
+
|
|
3
|
+
Enhanced pino-http with OpenTelemetry, Loki, file rotation and enterprise features.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @nestjs-labs/pino-http-extra
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- 🔍 **OpenTelemetry Integration**: Automatic span and trace ID injection
|
|
14
|
+
- 📊 **Loki Transport**: Send logs to Grafana Loki
|
|
15
|
+
- 📁 **File Rotation**: Automatic log file rotation with compression
|
|
16
|
+
- 🎨 **Pretty Logging**: Colored and formatted console output
|
|
17
|
+
- 🔒 **Security**: Automatic redaction of sensitive fields
|
|
18
|
+
- ⚡ **Performance**: High-performance logging with Pino
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Basic Usage
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { Module } from '@nestjs/common';
|
|
26
|
+
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
27
|
+
import { LoggerModule } from '@nestjs-labs/nest-pino-extra';
|
|
28
|
+
|
|
29
|
+
@Module({
|
|
30
|
+
imports: [
|
|
31
|
+
ConfigModule.forRoot(),
|
|
32
|
+
LoggerModule.forRootAsync({
|
|
33
|
+
imports: [ConfigModule],
|
|
34
|
+
useFactory: (configService: ConfigService) =>
|
|
35
|
+
getNestjsPinoModuleOptions(configService),
|
|
36
|
+
inject: [ConfigService],
|
|
37
|
+
}),
|
|
38
|
+
],
|
|
39
|
+
})
|
|
40
|
+
export class AppModule {}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Environment Variables
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Required
|
|
47
|
+
OTLP_SERVICE_NAME=my-app
|
|
48
|
+
|
|
49
|
+
# Optional
|
|
50
|
+
LOG_LEVEL=info
|
|
51
|
+
LOG_FILE=/var/log/app.log
|
|
52
|
+
LOG_LOKI=http://loki:3100
|
|
53
|
+
OTEL_SPAN_ID_KEY=spanId
|
|
54
|
+
OTEL_TRACE_ID_KEY=traceId
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Advanced Configuration
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { Module } from '@nestjs/common';
|
|
61
|
+
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
62
|
+
import { LoggerModule } from '@nestjs-labs/nest-pino-extra';
|
|
63
|
+
|
|
64
|
+
@Module({
|
|
65
|
+
imports: [
|
|
66
|
+
ConfigModule.forRoot(),
|
|
67
|
+
LoggerModule.forRootAsync({
|
|
68
|
+
imports: [ConfigModule],
|
|
69
|
+
useFactory: (configService: ConfigService) =>
|
|
70
|
+
getNestjsPinoModuleOptions(configService, {
|
|
71
|
+
exclude: [
|
|
72
|
+
{ method: 0, path: '/health' },
|
|
73
|
+
{ method: 0, path: '/metrics' },
|
|
74
|
+
],
|
|
75
|
+
}),
|
|
76
|
+
inject: [ConfigService],
|
|
77
|
+
}),
|
|
78
|
+
],
|
|
79
|
+
})
|
|
80
|
+
export class AppModule {}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## API Reference
|
|
84
|
+
|
|
85
|
+
### Functions
|
|
86
|
+
|
|
87
|
+
#### `getNestjsPinoModuleOptions(configService, overrides?)`
|
|
88
|
+
|
|
89
|
+
Get nestjs-pino module options with improved type safety and validation.
|
|
90
|
+
|
|
91
|
+
**Parameters:**
|
|
92
|
+
- `configService`: ConfigService - NestJS configuration service
|
|
93
|
+
- `overrides`: Params (optional) - Overrides for the module options
|
|
94
|
+
|
|
95
|
+
**Returns:** Params - Configured nestjs-pino module options
|
|
96
|
+
|
|
97
|
+
#### `getPinoHttpOption(level?, spanIdKey?, traceIdKey?)`
|
|
98
|
+
|
|
99
|
+
Get pino-http options with OpenTelemetry integration.
|
|
100
|
+
|
|
101
|
+
**Parameters:**
|
|
102
|
+
- `level`: string (default: 'info') - Log level
|
|
103
|
+
- `spanIdKey`: string (default: 'spanId') - OpenTelemetry span ID key
|
|
104
|
+
- `traceIdKey`: string (default: 'traceId') - OpenTelemetry trace ID key
|
|
105
|
+
|
|
106
|
+
**Returns:** Options - Configured pino-http options
|
|
107
|
+
|
|
108
|
+
#### `getMultiDestinationStream(app, level?, filepath?, loki?)`
|
|
109
|
+
|
|
110
|
+
Create multi-destination stream supporting pretty, file, and Loki outputs.
|
|
111
|
+
|
|
112
|
+
**Parameters:**
|
|
113
|
+
- `app`: string - Application name
|
|
114
|
+
- `level`: pino.Level (default: 'info') - Log level
|
|
115
|
+
- `filepath`: string (optional) - Log file path for rotation
|
|
116
|
+
- `loki`: string (optional) - Loki host URL
|
|
117
|
+
|
|
118
|
+
**Returns:** MultiStreamRes - Configured multi-stream
|
|
119
|
+
|
|
120
|
+
## Examples
|
|
121
|
+
|
|
122
|
+
### Custom Logging
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import { Injectable, Logger } from '@nestjs/common';
|
|
126
|
+
|
|
127
|
+
@Injectable()
|
|
128
|
+
export class AppService {
|
|
129
|
+
private readonly logger = new Logger(AppService.name);
|
|
130
|
+
|
|
131
|
+
getHello(): string {
|
|
132
|
+
this.logger.log('Hello World!');
|
|
133
|
+
return 'Hello World!';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### HTTP Request Logging
|
|
139
|
+
|
|
140
|
+
The middleware automatically logs HTTP requests with:
|
|
141
|
+
- Request ID generation
|
|
142
|
+
- Response time tracking
|
|
143
|
+
- Status code-based log levels
|
|
144
|
+
- Sensitive data redaction
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"AAMA,wBAAgB,iBAAiB,CAChC,SAAS,SAAW,EACpB,UAAU,SAAY;mBAGN,MAAM;;;gBAIT,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;EAapC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getOtelFormatters = getOtelFormatters;
|
|
4
|
+
const api_1 = require("@opentelemetry/api");
|
|
5
|
+
function getOtelFormatters(spanIdKey = 'spanId', traceIdKey = 'traceId') {
|
|
6
|
+
return {
|
|
7
|
+
level: (label) => {
|
|
8
|
+
return { level: label };
|
|
9
|
+
},
|
|
10
|
+
log(object) {
|
|
11
|
+
const span = api_1.trace.getSpan(api_1.context.active());
|
|
12
|
+
if (!span)
|
|
13
|
+
return object;
|
|
14
|
+
const spanContext = api_1.trace.getSpan(api_1.context.active())?.spanContext();
|
|
15
|
+
if (!spanContext)
|
|
16
|
+
return object;
|
|
17
|
+
const { spanId, traceId } = spanContext;
|
|
18
|
+
return { ...object, [spanIdKey]: spanId, [traceIdKey]: traceId };
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=formatters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":";;AAMA,8CAsBC;AA5BD,4CAAoD;AAMpD,SAAgB,iBAAiB,CAChC,SAAS,GAAG,QAAQ,EACpB,UAAU,GAAG,SAAS;IAEtB,OAAO;QACN,KAAK,EAAE,CAAC,KAAa,EAAE,EAAE;YACxB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACzB,CAAC;QAED,GAAG,CAAC,MAA+B;YAClC,MAAM,IAAI,GAAG,WAAK,CAAC,OAAO,CAAC,aAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAE7C,IAAI,CAAC,IAAI;gBAAE,OAAO,MAAM,CAAC;YACzB,MAAM,WAAW,GAAG,WAAK,CAAC,OAAO,CAAC,aAAO,CAAC,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;YAEnE,IAAI,CAAC,WAAW;gBAAE,OAAO,MAAM,CAAC;YAEhC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW,CAAC;YAExC,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC;QAClE,CAAC;KACD,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { getOtelFormatters } from './formatters.js';
|
|
2
|
+
export { getPinoHttpOption } from './options.js';
|
|
3
|
+
export { getSerializers } from './serializers.js';
|
|
4
|
+
export { createFileStreamEntry, createLokiStreamEntry, createPrettyStreamEntry, getMultiDestinationStream, } from './streams.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMultiDestinationStream = exports.createPrettyStreamEntry = exports.createLokiStreamEntry = exports.createFileStreamEntry = exports.getSerializers = exports.getPinoHttpOption = exports.getOtelFormatters = void 0;
|
|
4
|
+
var formatters_js_1 = require("./formatters.js");
|
|
5
|
+
Object.defineProperty(exports, "getOtelFormatters", { enumerable: true, get: function () { return formatters_js_1.getOtelFormatters; } });
|
|
6
|
+
var options_js_1 = require("./options.js");
|
|
7
|
+
Object.defineProperty(exports, "getPinoHttpOption", { enumerable: true, get: function () { return options_js_1.getPinoHttpOption; } });
|
|
8
|
+
var serializers_js_1 = require("./serializers.js");
|
|
9
|
+
Object.defineProperty(exports, "getSerializers", { enumerable: true, get: function () { return serializers_js_1.getSerializers; } });
|
|
10
|
+
var streams_js_1 = require("./streams.js");
|
|
11
|
+
Object.defineProperty(exports, "createFileStreamEntry", { enumerable: true, get: function () { return streams_js_1.createFileStreamEntry; } });
|
|
12
|
+
Object.defineProperty(exports, "createLokiStreamEntry", { enumerable: true, get: function () { return streams_js_1.createLokiStreamEntry; } });
|
|
13
|
+
Object.defineProperty(exports, "createPrettyStreamEntry", { enumerable: true, get: function () { return streams_js_1.createPrettyStreamEntry; } });
|
|
14
|
+
Object.defineProperty(exports, "getMultiDestinationStream", { enumerable: true, get: function () { return streams_js_1.getMultiDestinationStream; } });
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAOA,iDAAoD;AAA3C,kHAAA,iBAAiB,OAAA;AAC1B,2CAAiD;AAAxC,+GAAA,iBAAiB,OAAA;AAC1B,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,2CAKsB;AAJpB,mHAAA,qBAAqB,OAAA;AACrB,mHAAA,qBAAqB,OAAA;AACrB,qHAAA,uBAAuB,OAAA;AACvB,uHAAA,yBAAyB,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,wBAAgB,iBAAiB,CAChC,KAAK,SAAS,EACd,SAAS,SAAW,EACpB,UAAU,SAAY,GACpB,OAAO,CAmDT"}
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getPinoHttpOption = getPinoHttpOption;
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const pino_1 = __importDefault(require("pino"));
|
|
9
|
+
const formatters_js_1 = require("./formatters.js");
|
|
10
|
+
const serializers_js_1 = require("./serializers.js");
|
|
11
|
+
function getPinoHttpOption(level = 'info', spanIdKey = 'spanId', traceIdKey = 'traceId') {
|
|
12
|
+
return {
|
|
13
|
+
level,
|
|
14
|
+
quietReqLogger: false,
|
|
15
|
+
timestamp: pino_1.default.stdTimeFunctions.isoTime,
|
|
16
|
+
customAttributeKeys: {
|
|
17
|
+
req: 'req',
|
|
18
|
+
res: 'res',
|
|
19
|
+
err: 'err',
|
|
20
|
+
responseTime: 'taken(ms)',
|
|
21
|
+
},
|
|
22
|
+
formatters: (0, formatters_js_1.getOtelFormatters)(spanIdKey, traceIdKey),
|
|
23
|
+
serializers: (0, serializers_js_1.getSerializers)(),
|
|
24
|
+
redact: {
|
|
25
|
+
paths: [
|
|
26
|
+
'password',
|
|
27
|
+
'reqBody.password',
|
|
28
|
+
'user.password',
|
|
29
|
+
'reqBody.user.password',
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
genReqId: function (req, res) {
|
|
33
|
+
const reqId = req.id ?? req.headers['x-request-id'];
|
|
34
|
+
if (reqId)
|
|
35
|
+
return reqId;
|
|
36
|
+
const id = (0, node_crypto_1.randomUUID)();
|
|
37
|
+
res.setHeader('X-Request-Id', id);
|
|
38
|
+
return id;
|
|
39
|
+
},
|
|
40
|
+
customLogLevel(_, res, err) {
|
|
41
|
+
if (res.statusCode >= 400 && res.statusCode < 500) {
|
|
42
|
+
return 'warn';
|
|
43
|
+
}
|
|
44
|
+
else if (res.statusCode >= 500 || err) {
|
|
45
|
+
return 'error';
|
|
46
|
+
}
|
|
47
|
+
else if (res.statusCode >= 300 && res.statusCode < 400) {
|
|
48
|
+
return 'silent';
|
|
49
|
+
}
|
|
50
|
+
return 'info';
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":";;;;;AAcA,8CAuDC;AApED,6CAAyC;AAKzC,gDAAwB;AAExB,mDAAoD;AACpD,qDAAkD;AAKlD,SAAgB,iBAAiB,CAChC,KAAK,GAAG,MAAM,EACd,SAAS,GAAG,QAAQ,EACpB,UAAU,GAAG,SAAS;IAEtB,OAAO;QAIN,KAAK;QACL,cAAc,EAAE,KAAK;QACrB,SAAS,EAAE,cAAI,CAAC,gBAAgB,CAAC,OAAO;QACxC,mBAAmB,EAAE;YACpB,GAAG,EAAE,KAAK;YACV,GAAG,EAAE,KAAK;YACV,GAAG,EAAE,KAAK;YACV,YAAY,EAAE,WAAW;SACzB;QACD,UAAU,EAAE,IAAA,iCAAiB,EAAC,SAAS,EAAE,UAAU,CAAC;QACpD,WAAW,EAAE,IAAA,+BAAc,GAAE;QAC7B,MAAM,EAAE;YACP,KAAK,EAAE;gBACN,UAAU;gBACV,kBAAkB;gBAClB,eAAe;gBACf,uBAAuB;aACvB;SACD;QACD,QAAQ,EAAE,UAAU,GAAG,EAAE,GAAG;YAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAEpD,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;YACxB,MAAM,EAAE,GAAG,IAAA,wBAAU,GAAE,CAAC;YAExB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;YAElC,OAAO,EAAE,CAAC;QACX,CAAC;QAED,cAAc,CACb,CAAkB,EAClB,GAAoC,EACpC,GAAW;YAEX,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;gBACnD,OAAO,MAAM,CAAC;YACf,CAAC;iBAAM,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;gBACzC,OAAO,OAAO,CAAC;YAChB,CAAC;iBAAM,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC;gBAC1D,OAAO,QAAQ,CAAC;YACjB,CAAC;YAED,OAAO,MAAM,CAAC;QACf,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serializers.d.ts","sourceRoot":"","sources":["../src/serializers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAWzC,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAyB7D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSerializers = getSerializers;
|
|
4
|
+
function getSerializers() {
|
|
5
|
+
return {
|
|
6
|
+
req(req) {
|
|
7
|
+
const request = req.raw;
|
|
8
|
+
return {
|
|
9
|
+
id: req.id,
|
|
10
|
+
method: req.method,
|
|
11
|
+
url: req.url,
|
|
12
|
+
headers: request.headers,
|
|
13
|
+
query: request.query,
|
|
14
|
+
body: request.body,
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
res(response) {
|
|
18
|
+
const { statusCode: status, ...serialized } = response;
|
|
19
|
+
return Object.assign({ status }, serialized);
|
|
20
|
+
},
|
|
21
|
+
err(err) {
|
|
22
|
+
return err;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=serializers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serializers.js","sourceRoot":"","sources":["../src/serializers.ts"],"names":[],"mappings":";;AAYA,wCAyBC;AAzBD,SAAgB,cAAc;IAC7B,OAAO;QACN,GAAG,CAAC,GAAsB;YACzB,MAAM,OAAO,GAAG,GAAG,CAAC,GAEnB,CAAC;YAEF,OAAO;gBACN,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,IAAI,EAAE,OAAO,CAAC,IAAI;aAClB,CAAC;QACH,CAAC;QACD,GAAG,CAAC,QAA4B;YAC/B,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ,CAAC;YAEvD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC;QAC9C,CAAC;QACD,GAAG,CAAC,GAAoB;YACvB,OAAO,GAAG,CAAC;QACZ,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import pino from 'pino';
|
|
2
|
+
export declare function createPrettyStreamEntry(_app: string, level: pino.Level): pino.StreamEntry;
|
|
3
|
+
export declare function createLokiStreamEntry(app: string, level: pino.Level, host: string): pino.StreamEntry;
|
|
4
|
+
export declare function createFileStreamEntry(_app: string, level: pino.Level, filepath: string): pino.StreamEntry;
|
|
5
|
+
export declare function getMultiDestinationStream(app: string, level?: pino.Level, filepath?: string, loki?: string): pino.MultiStreamRes;
|
|
6
|
+
//# sourceMappingURL=streams.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streams.d.ts","sourceRoot":"","sources":["../src/streams.ts"],"names":[],"mappings":"AAGA,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,wBAAgB,uBAAuB,CACtC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,IAAI,CAAC,KAAK,GACf,IAAI,CAAC,WAAW,CAQlB;AAMD,wBAAgB,qBAAqB,CACpC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,IAAI,EAAE,MAAM,GACV,IAAI,CAAC,WAAW,CAWlB;AAMD,wBAAgB,qBAAqB,CACpC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,QAAQ,EAAE,MAAM,GACd,IAAI,CAAC,WAAW,CAWlB;AAMD,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,IAAI,CAAC,KAAc,EAC1B,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACX,IAAI,CAAC,cAAc,CAOrB"}
|
package/dist/streams.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createPrettyStreamEntry = createPrettyStreamEntry;
|
|
7
|
+
exports.createLokiStreamEntry = createLokiStreamEntry;
|
|
8
|
+
exports.createFileStreamEntry = createFileStreamEntry;
|
|
9
|
+
exports.getMultiDestinationStream = getMultiDestinationStream;
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const pino_1 = __importDefault(require("pino"));
|
|
12
|
+
const pino_loki_1 = require("pino-loki");
|
|
13
|
+
const pino_pretty_1 = __importDefault(require("pino-pretty"));
|
|
14
|
+
const rotating_file_stream_1 = require("rotating-file-stream");
|
|
15
|
+
function createPrettyStreamEntry(_app, level) {
|
|
16
|
+
const stream = (0, pino_pretty_1.default)({
|
|
17
|
+
translateTime: false,
|
|
18
|
+
hideObject: false,
|
|
19
|
+
colorize: true,
|
|
20
|
+
});
|
|
21
|
+
return { level, stream };
|
|
22
|
+
}
|
|
23
|
+
function createLokiStreamEntry(app, level, host) {
|
|
24
|
+
console.log('createLokiStreamEntry', app, level, host);
|
|
25
|
+
const stream = (0, pino_loki_1.pinoLoki)({
|
|
26
|
+
replaceTimestamp: true,
|
|
27
|
+
batching: true,
|
|
28
|
+
interval: 5,
|
|
29
|
+
host,
|
|
30
|
+
labels: { app, service: app },
|
|
31
|
+
});
|
|
32
|
+
return { level, stream };
|
|
33
|
+
}
|
|
34
|
+
function createFileStreamEntry(_app, level, filepath) {
|
|
35
|
+
const { base, dir } = node_path_1.default.parse(filepath);
|
|
36
|
+
const stream = (0, rotating_file_stream_1.createStream)(base, {
|
|
37
|
+
size: '1G',
|
|
38
|
+
interval: '1d',
|
|
39
|
+
compress: 'gzip',
|
|
40
|
+
path: dir,
|
|
41
|
+
});
|
|
42
|
+
return { level, stream };
|
|
43
|
+
}
|
|
44
|
+
function getMultiDestinationStream(app, level = 'info', filepath, loki) {
|
|
45
|
+
const entries = [createPrettyStreamEntry(app, level)];
|
|
46
|
+
if (filepath)
|
|
47
|
+
entries.push(createFileStreamEntry(app, level, filepath));
|
|
48
|
+
if (loki)
|
|
49
|
+
entries.push(createLokiStreamEntry(app, level, loki));
|
|
50
|
+
return pino_1.default.multistream(entries);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=streams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streams.js","sourceRoot":"","sources":["../src/streams.ts"],"names":[],"mappings":";;;;;AAWA,0DAWC;AAMD,sDAeC;AAMD,sDAeC;AAMD,8DAYC;AAjFD,0DAA6B;AAE7B,gDAAwB;AACxB,yCAAqC;AACrC,8DAAqC;AACrC,+DAAoD;AAKpD,SAAgB,uBAAuB,CACtC,IAAY,EACZ,KAAiB;IAEjB,MAAM,MAAM,GAAG,IAAA,qBAAU,EAAC;QACzB,aAAa,EAAE,KAAK;QACpB,UAAU,EAAE,KAAK;QACjB,QAAQ,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC;AAMD,SAAgB,qBAAqB,CACpC,GAAW,EACX,KAAiB,EACjB,IAAY;IAEZ,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,IAAA,oBAAQ,EAAC;QACvB,gBAAgB,EAAE,IAAI;QACtB,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,CAAC;QACX,IAAI;QACJ,MAAM,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE;KAC7B,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC;AAMD,SAAgB,qBAAqB,CACpC,IAAY,EACZ,KAAiB,EACjB,QAAgB;IAEhB,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,mBAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,IAAA,mCAAY,EAAC,IAAI,EAAE;QACjC,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,GAAG;KACT,CAAC,CAAC;IAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC;AAMD,SAAgB,yBAAyB,CACxC,GAAW,EACX,QAAoB,MAAM,EAC1B,QAAiB,EACjB,IAAa;IAEb,MAAM,OAAO,GAAuB,CAAC,uBAAuB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAE1E,IAAI,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IACxE,IAAI,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IAEhE,OAAO,cAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nestjs-labs/pino-http-extra",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Enhanced pino-http with OpenTelemetry, Loki, file rotation and enterprise features",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"require": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./options": {
|
|
14
|
+
"import": "./dist/options.js",
|
|
15
|
+
"require": "./dist/options.js"
|
|
16
|
+
},
|
|
17
|
+
"./streams": {
|
|
18
|
+
"import": "./dist/streams.js",
|
|
19
|
+
"require": "./dist/streams.js"
|
|
20
|
+
},
|
|
21
|
+
"./serializers": {
|
|
22
|
+
"import": "./dist/serializers.js",
|
|
23
|
+
"require": "./dist/serializers.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc",
|
|
28
|
+
"lint": "eslint .",
|
|
29
|
+
"lint:fix": "eslint . --fix && prettier --write .",
|
|
30
|
+
"format": "prettier --write .",
|
|
31
|
+
"dry-run": "npm publish --dry-run",
|
|
32
|
+
"prepublishOnly": "npm run build",
|
|
33
|
+
"semantic-release": "semantic-release"
|
|
34
|
+
},
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/nestjs-labs/nestjs-pino-extra.git",
|
|
38
|
+
"directory": "packages/pino-http-extra"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"pino",
|
|
42
|
+
"http",
|
|
43
|
+
"logging",
|
|
44
|
+
"opentelemetry",
|
|
45
|
+
"loki",
|
|
46
|
+
"file-rotation",
|
|
47
|
+
"middleware"
|
|
48
|
+
],
|
|
49
|
+
"author": "NestJS Labs AB",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/nestjs-labs/nestjs-pino-extra/issues"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://nestjs-labs.github.io/nestjs-pino-extra",
|
|
55
|
+
"docs": "https://nestjs-labs.github.io/nestjs-pino-extra",
|
|
56
|
+
"files": [
|
|
57
|
+
"dist"
|
|
58
|
+
],
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@opentelemetry/api": "^1.9.0",
|
|
61
|
+
"pino": "^9.7.0",
|
|
62
|
+
"pino-http": "^10.5.0",
|
|
63
|
+
"pino-loki": "^2.6.0",
|
|
64
|
+
"pino-pretty": "^13.0.0",
|
|
65
|
+
"pino-std-serializers": "^7.0.0",
|
|
66
|
+
"rotating-file-stream": "^3.2.6"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@commitlint/cli": "^19.4.1",
|
|
70
|
+
"@commitlint/config-conventional": "^19.4.1",
|
|
71
|
+
"@nestjs-labs/eslint-config": "^1.0.1",
|
|
72
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
73
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
74
|
+
"@semantic-release/git": "^10.0.1",
|
|
75
|
+
"@semantic-release/github": "^11.0.3",
|
|
76
|
+
"@semantic-release/npm": "^12.0.2",
|
|
77
|
+
"@semantic-release/release-notes-generator": "^14.0.3",
|
|
78
|
+
"eslint": "^9.31.0",
|
|
79
|
+
"prettier": "^3.6.2",
|
|
80
|
+
"semantic-release": "^24.2.7",
|
|
81
|
+
"tslib": "^2.8.0",
|
|
82
|
+
"typedoc": "^0.28.7",
|
|
83
|
+
"typescript": "^5.5.4"
|
|
84
|
+
},
|
|
85
|
+
"config": {
|
|
86
|
+
"commitizen": {
|
|
87
|
+
"path": "node_modules/cz-conventional-changelog"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"commitlint": {
|
|
91
|
+
"extends": [
|
|
92
|
+
"@commitlint/config-conventional"
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
}
|