@xenterprises/fastify-xlogger 1.0.0 → 1.1.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 +91 -0
- package/package.json +8 -2
- package/src/xLogger.js +10 -2
- package/test/xLogger.test.js +0 -402
package/README.md
CHANGED
|
@@ -226,6 +226,91 @@ const options = getLoggerOptions();
|
|
|
226
226
|
const options = getLoggerOptions({ pretty: true });
|
|
227
227
|
```
|
|
228
228
|
|
|
229
|
+
### 7. Custom Transports (Betterstack, Logtail, etc.)
|
|
230
|
+
|
|
231
|
+
Send logs to centralized logging services like Betterstack/Logtail using custom transports:
|
|
232
|
+
|
|
233
|
+
#### Install Transport (Optional Peer Dependency)
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
npm install @logtail/pino
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Single Transport (Betterstack)
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
import Fastify from "fastify";
|
|
243
|
+
import xLogger, { getLoggerOptions } from "xlogger";
|
|
244
|
+
|
|
245
|
+
const fastify = Fastify({
|
|
246
|
+
logger: getLoggerOptions({
|
|
247
|
+
serviceName: "my-api",
|
|
248
|
+
transport: {
|
|
249
|
+
target: "@logtail/pino",
|
|
250
|
+
options: {
|
|
251
|
+
sourceToken: process.env.BETTERSTACK_SOURCE_TOKEN,
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
}),
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
await fastify.register(xLogger, {
|
|
258
|
+
serviceName: "my-api",
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Multiple Transports
|
|
263
|
+
|
|
264
|
+
Send logs to both Betterstack and a local file:
|
|
265
|
+
|
|
266
|
+
```javascript
|
|
267
|
+
const fastify = Fastify({
|
|
268
|
+
logger: getLoggerOptions({
|
|
269
|
+
serviceName: "my-api",
|
|
270
|
+
transport: {
|
|
271
|
+
targets: [
|
|
272
|
+
{
|
|
273
|
+
target: "@logtail/pino",
|
|
274
|
+
options: {
|
|
275
|
+
sourceToken: process.env.BETTERSTACK_SOURCE_TOKEN,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
target: "pino/file",
|
|
280
|
+
options: {
|
|
281
|
+
destination: "/var/log/app.log",
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
}),
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
#### Environment-Based Configuration
|
|
291
|
+
|
|
292
|
+
```javascript
|
|
293
|
+
// In development: use pino-pretty (default)
|
|
294
|
+
// In production: use Betterstack if token is set, otherwise JSON stdout
|
|
295
|
+
const transport = process.env.BETTERSTACK_SOURCE_TOKEN
|
|
296
|
+
? {
|
|
297
|
+
target: "@logtail/pino",
|
|
298
|
+
options: {
|
|
299
|
+
sourceToken: process.env.BETTERSTACK_SOURCE_TOKEN,
|
|
300
|
+
},
|
|
301
|
+
}
|
|
302
|
+
: undefined;
|
|
303
|
+
|
|
304
|
+
const fastify = Fastify({
|
|
305
|
+
logger: getLoggerOptions({
|
|
306
|
+
serviceName: "my-api",
|
|
307
|
+
transport,
|
|
308
|
+
}),
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Note**: When a custom transport is provided, it overrides the default environment-based transport configuration (pino-pretty in development, JSON in production).
|
|
313
|
+
|
|
229
314
|
## API Reference
|
|
230
315
|
|
|
231
316
|
### Decorators
|
|
@@ -320,6 +405,12 @@ const fastify = Fastify({
|
|
|
320
405
|
serviceName: "my-api", // Optional: service name
|
|
321
406
|
redactPaths: ["custom"], // Optional: additional redact paths
|
|
322
407
|
pretty: false, // Optional: force pretty printing
|
|
408
|
+
transport: { // Optional: custom transport configuration
|
|
409
|
+
target: "@logtail/pino",
|
|
410
|
+
options: {
|
|
411
|
+
sourceToken: process.env.BETTERSTACK_SOURCE_TOKEN,
|
|
412
|
+
},
|
|
413
|
+
},
|
|
323
414
|
}),
|
|
324
415
|
});
|
|
325
416
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xenterprises/fastify-xlogger",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Fastify plugin for standardized logging with Pino - context, redaction, and canonical schema",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/xLogger.js",
|
|
@@ -30,7 +30,13 @@
|
|
|
30
30
|
"fastify-plugin": "^5.0.1"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"fastify": "^5.0.0"
|
|
33
|
+
"fastify": "^5.0.0",
|
|
34
|
+
"@logtail/pino": "^0.5.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"@logtail/pino": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
34
40
|
},
|
|
35
41
|
"devDependencies": {
|
|
36
42
|
"eslint": "^9.0.0",
|
package/src/xLogger.js
CHANGED
|
@@ -399,6 +399,10 @@ export default fp(xLogger, {
|
|
|
399
399
|
* @param {string[]} [options.redactPaths] - Additional paths to redact
|
|
400
400
|
* @param {boolean} [options.pretty] - Force pretty printing
|
|
401
401
|
* @param {string} [options.serviceName] - Service name
|
|
402
|
+
* @param {Object} [options.transport] - Custom Pino transport configuration
|
|
403
|
+
* @param {string} [options.transport.target] - Transport target module (e.g., '@logtail/pino')
|
|
404
|
+
* @param {Object} [options.transport.options] - Transport options
|
|
405
|
+
* @param {Array} [options.transport.targets] - Multiple transport targets
|
|
402
406
|
* @returns {Object} Pino logger options
|
|
403
407
|
*/
|
|
404
408
|
export function getLoggerOptions(options = {}) {
|
|
@@ -444,8 +448,12 @@ export function getLoggerOptions(options = {}) {
|
|
|
444
448
|
},
|
|
445
449
|
};
|
|
446
450
|
|
|
447
|
-
//
|
|
448
|
-
if (
|
|
451
|
+
// If custom transport is provided, use it
|
|
452
|
+
if (options.transport) {
|
|
453
|
+
loggerOptions.transport = options.transport;
|
|
454
|
+
}
|
|
455
|
+
// Otherwise, use pretty print in development
|
|
456
|
+
else if (!isProd || options.pretty) {
|
|
449
457
|
loggerOptions.transport = {
|
|
450
458
|
target: "pino-pretty",
|
|
451
459
|
options: {
|
package/test/xLogger.test.js
DELETED
|
@@ -1,402 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* xLogger Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests for the xLogger Fastify plugin
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
8
|
-
import assert from "node:assert";
|
|
9
|
-
import Fastify from "fastify";
|
|
10
|
-
import xLogger, { getLoggerOptions, DEFAULT_REDACT_PATHS, LOG_LEVELS } from "../src/xLogger.js";
|
|
11
|
-
|
|
12
|
-
describe("xLogger Plugin", () => {
|
|
13
|
-
let fastify;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
fastify = Fastify({
|
|
17
|
-
logger: {
|
|
18
|
-
level: "silent", // Suppress logs during tests
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
afterEach(async () => {
|
|
24
|
-
await fastify.close();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe("Plugin Registration", () => {
|
|
28
|
-
test("should register successfully", async () => {
|
|
29
|
-
await fastify.register(xLogger, {});
|
|
30
|
-
await fastify.ready();
|
|
31
|
-
|
|
32
|
-
assert.ok(fastify.xlogger, "xlogger should exist");
|
|
33
|
-
assert.ok(fastify.xlogger.config, "xlogger.config should exist");
|
|
34
|
-
assert.ok(fastify.xlogger.logEvent, "xlogger.logEvent should exist");
|
|
35
|
-
assert.ok(fastify.xlogger.logBoundary, "xlogger.logBoundary should exist");
|
|
36
|
-
assert.ok(fastify.xlogger.createBoundaryLogger, "xlogger.createBoundaryLogger should exist");
|
|
37
|
-
assert.ok(fastify.xlogger.createJobContext, "xlogger.createJobContext should exist");
|
|
38
|
-
assert.ok(fastify.xlogger.extractContext, "xlogger.extractContext should exist");
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test("should skip registration when active is false", async () => {
|
|
42
|
-
await fastify.register(xLogger, { active: false });
|
|
43
|
-
await fastify.ready();
|
|
44
|
-
|
|
45
|
-
assert.ok(!fastify.xlogger, "xlogger should not exist");
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test("should use default redact paths", async () => {
|
|
49
|
-
await fastify.register(xLogger, {});
|
|
50
|
-
await fastify.ready();
|
|
51
|
-
|
|
52
|
-
assert.ok(fastify.xlogger.redactPaths.includes("password"));
|
|
53
|
-
assert.ok(fastify.xlogger.redactPaths.includes("token"));
|
|
54
|
-
assert.ok(fastify.xlogger.redactPaths.includes("req.headers.authorization"));
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test("should extend redact paths with custom paths", async () => {
|
|
58
|
-
await fastify.register(xLogger, {
|
|
59
|
-
redactPaths: ["customSecret", "myApiKey"],
|
|
60
|
-
});
|
|
61
|
-
await fastify.ready();
|
|
62
|
-
|
|
63
|
-
assert.ok(fastify.xlogger.redactPaths.includes("password"));
|
|
64
|
-
assert.ok(fastify.xlogger.redactPaths.includes("customSecret"));
|
|
65
|
-
assert.ok(fastify.xlogger.redactPaths.includes("myApiKey"));
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("should replace redact paths when redactClobber is true", async () => {
|
|
69
|
-
await fastify.register(xLogger, {
|
|
70
|
-
redactPaths: ["onlyThis"],
|
|
71
|
-
redactClobber: true,
|
|
72
|
-
});
|
|
73
|
-
await fastify.ready();
|
|
74
|
-
|
|
75
|
-
assert.ok(!fastify.xlogger.redactPaths.includes("password"));
|
|
76
|
-
assert.ok(fastify.xlogger.redactPaths.includes("onlyThis"));
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("should store service name in config", async () => {
|
|
80
|
-
await fastify.register(xLogger, {
|
|
81
|
-
serviceName: "my-test-service",
|
|
82
|
-
});
|
|
83
|
-
await fastify.ready();
|
|
84
|
-
|
|
85
|
-
assert.strictEqual(fastify.xlogger.config.serviceName, "my-test-service");
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
describe("Request Context", () => {
|
|
90
|
-
test("should decorate request with contextLog", async () => {
|
|
91
|
-
await fastify.register(xLogger, {});
|
|
92
|
-
|
|
93
|
-
fastify.get("/test", async (request) => {
|
|
94
|
-
assert.ok(request.contextLog, "contextLog should exist on request");
|
|
95
|
-
return { ok: true };
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
await fastify.ready();
|
|
99
|
-
|
|
100
|
-
const response = await fastify.inject({
|
|
101
|
-
method: "GET",
|
|
102
|
-
url: "/test",
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
assert.strictEqual(response.statusCode, 200);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
test("should extract context from request", async () => {
|
|
109
|
-
await fastify.register(xLogger, {});
|
|
110
|
-
let extractedContext;
|
|
111
|
-
|
|
112
|
-
fastify.get("/test", async (request) => {
|
|
113
|
-
extractedContext = fastify.xlogger.extractContext(request);
|
|
114
|
-
return { ok: true };
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
await fastify.ready();
|
|
118
|
-
|
|
119
|
-
await fastify.inject({
|
|
120
|
-
method: "GET",
|
|
121
|
-
url: "/test",
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
assert.ok(extractedContext.requestId, "requestId should exist");
|
|
125
|
-
assert.strictEqual(extractedContext.method, "GET");
|
|
126
|
-
assert.strictEqual(extractedContext.route, "/test");
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
test("should extract orgId from x-org-id header", async () => {
|
|
130
|
-
await fastify.register(xLogger, {});
|
|
131
|
-
let extractedContext;
|
|
132
|
-
|
|
133
|
-
fastify.get("/test", async (request) => {
|
|
134
|
-
extractedContext = fastify.xlogger.extractContext(request);
|
|
135
|
-
return { ok: true };
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
await fastify.ready();
|
|
139
|
-
|
|
140
|
-
await fastify.inject({
|
|
141
|
-
method: "GET",
|
|
142
|
-
url: "/test",
|
|
143
|
-
headers: {
|
|
144
|
-
"x-org-id": "org_123",
|
|
145
|
-
},
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
assert.strictEqual(extractedContext.orgId, "org_123");
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("should extract userId from x-user-id header", async () => {
|
|
152
|
-
await fastify.register(xLogger, {});
|
|
153
|
-
let extractedContext;
|
|
154
|
-
|
|
155
|
-
fastify.get("/test", async (request) => {
|
|
156
|
-
extractedContext = fastify.xlogger.extractContext(request);
|
|
157
|
-
return { ok: true };
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
await fastify.ready();
|
|
161
|
-
|
|
162
|
-
await fastify.inject({
|
|
163
|
-
method: "GET",
|
|
164
|
-
url: "/test",
|
|
165
|
-
headers: {
|
|
166
|
-
"x-user-id": "user_456",
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
assert.strictEqual(extractedContext.userId, "user_456");
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
test("should extract OpenTelemetry trace context", async () => {
|
|
174
|
-
await fastify.register(xLogger, {});
|
|
175
|
-
let extractedContext;
|
|
176
|
-
|
|
177
|
-
fastify.get("/test", async (request) => {
|
|
178
|
-
extractedContext = fastify.xlogger.extractContext(request);
|
|
179
|
-
return { ok: true };
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
await fastify.ready();
|
|
183
|
-
|
|
184
|
-
await fastify.inject({
|
|
185
|
-
method: "GET",
|
|
186
|
-
url: "/test",
|
|
187
|
-
headers: {
|
|
188
|
-
traceparent: "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01",
|
|
189
|
-
},
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
assert.strictEqual(extractedContext.traceId, "0af7651916cd43dd8448eb211c80319c");
|
|
193
|
-
assert.strictEqual(extractedContext.spanId, "b7ad6b7169203331");
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
test("should use custom context extractor", async () => {
|
|
197
|
-
await fastify.register(xLogger, {
|
|
198
|
-
contextExtractor: (request) => ({
|
|
199
|
-
customField: "custom_value",
|
|
200
|
-
fromQuery: request.query.foo,
|
|
201
|
-
}),
|
|
202
|
-
});
|
|
203
|
-
let extractedContext;
|
|
204
|
-
|
|
205
|
-
fastify.get("/test", async (request) => {
|
|
206
|
-
extractedContext = fastify.xlogger.extractContext(request);
|
|
207
|
-
return { ok: true };
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
await fastify.ready();
|
|
211
|
-
|
|
212
|
-
await fastify.inject({
|
|
213
|
-
method: "GET",
|
|
214
|
-
url: "/test?foo=bar",
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
assert.strictEqual(extractedContext.customField, "custom_value");
|
|
218
|
-
assert.strictEqual(extractedContext.fromQuery, "bar");
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
describe("Boundary Logging", () => {
|
|
223
|
-
test("should create boundary logger with timing", async () => {
|
|
224
|
-
await fastify.register(xLogger, {});
|
|
225
|
-
await fastify.ready();
|
|
226
|
-
|
|
227
|
-
const boundary = fastify.xlogger.createBoundaryLogger("stripe", "createCustomer");
|
|
228
|
-
|
|
229
|
-
assert.ok(boundary.success, "success method should exist");
|
|
230
|
-
assert.ok(boundary.fail, "fail method should exist");
|
|
231
|
-
assert.ok(boundary.retry, "retry method should exist");
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
test("should track retry count", async () => {
|
|
235
|
-
await fastify.register(xLogger, {});
|
|
236
|
-
await fastify.ready();
|
|
237
|
-
|
|
238
|
-
const boundary = fastify.xlogger.createBoundaryLogger("stripe", "createCustomer");
|
|
239
|
-
|
|
240
|
-
boundary.retry();
|
|
241
|
-
boundary.retry();
|
|
242
|
-
|
|
243
|
-
// The retry count is internal, but we can verify it doesn't throw
|
|
244
|
-
assert.doesNotThrow(() => boundary.success());
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
describe("Job Context", () => {
|
|
249
|
-
test("should create job context with correlation ID", async () => {
|
|
250
|
-
await fastify.register(xLogger, {});
|
|
251
|
-
await fastify.ready();
|
|
252
|
-
|
|
253
|
-
const job = fastify.xlogger.createJobContext({
|
|
254
|
-
jobName: "processPayments",
|
|
255
|
-
orgId: "org_123",
|
|
256
|
-
userId: "user_456",
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
assert.ok(job.context, "context should exist");
|
|
260
|
-
assert.ok(job.log, "log should exist");
|
|
261
|
-
assert.ok(job.start, "start method should exist");
|
|
262
|
-
assert.ok(job.complete, "complete method should exist");
|
|
263
|
-
assert.ok(job.fail, "fail method should exist");
|
|
264
|
-
assert.ok(job.context.correlationId, "correlationId should be generated");
|
|
265
|
-
assert.strictEqual(job.context.jobName, "processPayments");
|
|
266
|
-
assert.strictEqual(job.context.orgId, "org_123");
|
|
267
|
-
assert.strictEqual(job.context.userId, "user_456");
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
test("should use provided correlation ID", async () => {
|
|
271
|
-
await fastify.register(xLogger, {});
|
|
272
|
-
await fastify.ready();
|
|
273
|
-
|
|
274
|
-
const job = fastify.xlogger.createJobContext({
|
|
275
|
-
jobName: "syncData",
|
|
276
|
-
correlationId: "custom_corr_123",
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
assert.strictEqual(job.context.correlationId, "custom_corr_123");
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
test("should include original request ID", async () => {
|
|
283
|
-
await fastify.register(xLogger, {});
|
|
284
|
-
await fastify.ready();
|
|
285
|
-
|
|
286
|
-
const job = fastify.xlogger.createJobContext({
|
|
287
|
-
jobName: "asyncTask",
|
|
288
|
-
requestId: "req_789",
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
assert.strictEqual(job.context.originalRequestId, "req_789");
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
describe("Log Event", () => {
|
|
296
|
-
test("should log event without request", async () => {
|
|
297
|
-
await fastify.register(xLogger, {});
|
|
298
|
-
await fastify.ready();
|
|
299
|
-
|
|
300
|
-
// Should not throw
|
|
301
|
-
assert.doesNotThrow(() => {
|
|
302
|
-
fastify.xlogger.logEvent({
|
|
303
|
-
event: "user.created",
|
|
304
|
-
msg: "User was created",
|
|
305
|
-
data: { email: "test@example.com" },
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
test("should log event with different levels", async () => {
|
|
311
|
-
await fastify.register(xLogger, {});
|
|
312
|
-
await fastify.ready();
|
|
313
|
-
|
|
314
|
-
// Should not throw for different levels
|
|
315
|
-
assert.doesNotThrow(() => {
|
|
316
|
-
fastify.xlogger.logEvent({
|
|
317
|
-
event: "debug.event",
|
|
318
|
-
level: "debug",
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
assert.doesNotThrow(() => {
|
|
323
|
-
fastify.xlogger.logEvent({
|
|
324
|
-
event: "warn.event",
|
|
325
|
-
level: "warn",
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
assert.doesNotThrow(() => {
|
|
330
|
-
fastify.xlogger.logEvent({
|
|
331
|
-
event: "error.event",
|
|
332
|
-
level: "error",
|
|
333
|
-
});
|
|
334
|
-
});
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
describe("getLoggerOptions", () => {
|
|
340
|
-
test("should return valid Pino options", () => {
|
|
341
|
-
const options = getLoggerOptions();
|
|
342
|
-
|
|
343
|
-
assert.ok(options.level, "level should exist");
|
|
344
|
-
assert.ok(options.redact, "redact should exist");
|
|
345
|
-
assert.ok(options.serializers, "serializers should exist");
|
|
346
|
-
assert.ok(options.base, "base should exist");
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
test("should use debug level in non-production", () => {
|
|
350
|
-
const originalEnv = process.env.NODE_ENV;
|
|
351
|
-
process.env.NODE_ENV = "development";
|
|
352
|
-
|
|
353
|
-
const options = getLoggerOptions();
|
|
354
|
-
|
|
355
|
-
assert.strictEqual(options.level, "debug");
|
|
356
|
-
|
|
357
|
-
process.env.NODE_ENV = originalEnv;
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
test("should include pretty transport in non-production", () => {
|
|
361
|
-
const originalEnv = process.env.NODE_ENV;
|
|
362
|
-
process.env.NODE_ENV = "development";
|
|
363
|
-
|
|
364
|
-
const options = getLoggerOptions();
|
|
365
|
-
|
|
366
|
-
assert.ok(options.transport, "transport should exist");
|
|
367
|
-
assert.strictEqual(options.transport.target, "pino-pretty");
|
|
368
|
-
|
|
369
|
-
process.env.NODE_ENV = originalEnv;
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
test("should allow custom service name", () => {
|
|
373
|
-
const options = getLoggerOptions({ serviceName: "my-service" });
|
|
374
|
-
|
|
375
|
-
assert.strictEqual(options.base.service, "my-service");
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
test("should extend redact paths", () => {
|
|
379
|
-
const options = getLoggerOptions({ redactPaths: ["customPath"] });
|
|
380
|
-
|
|
381
|
-
assert.ok(options.redact.paths.includes("customPath"));
|
|
382
|
-
assert.ok(options.redact.paths.includes("password"));
|
|
383
|
-
});
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
describe("Exports", () => {
|
|
387
|
-
test("should export DEFAULT_REDACT_PATHS", () => {
|
|
388
|
-
assert.ok(Array.isArray(DEFAULT_REDACT_PATHS));
|
|
389
|
-
assert.ok(DEFAULT_REDACT_PATHS.length > 0);
|
|
390
|
-
assert.ok(DEFAULT_REDACT_PATHS.includes("password"));
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
test("should export LOG_LEVELS", () => {
|
|
394
|
-
assert.ok(LOG_LEVELS);
|
|
395
|
-
assert.strictEqual(LOG_LEVELS.fatal, 60);
|
|
396
|
-
assert.strictEqual(LOG_LEVELS.error, 50);
|
|
397
|
-
assert.strictEqual(LOG_LEVELS.warn, 40);
|
|
398
|
-
assert.strictEqual(LOG_LEVELS.info, 30);
|
|
399
|
-
assert.strictEqual(LOG_LEVELS.debug, 20);
|
|
400
|
-
assert.strictEqual(LOG_LEVELS.trace, 10);
|
|
401
|
-
});
|
|
402
|
-
});
|