@ogcio/fastify-logging-wrapper 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 +55 -0
- package/__tests__/fastify-logging-wrapper.errors.test.ts +127 -0
- package/__tests__/fastify-logging-wrapper.test.ts +106 -0
- package/__tests__/helpers/build-fastify.ts +54 -0
- package/__tests__/helpers/build-logger.ts +28 -0
- package/__tests__/helpers/fastify-test-helpers.ts +258 -0
- package/__tests__/logging-wrapper.test.ts +168 -0
- package/dist/fastify-logging-wrapper.d.ts +5 -0
- package/dist/fastify-logging-wrapper.d.ts.map +1 -0
- package/dist/fastify-logging-wrapper.js +34 -0
- package/dist/fastify-logging-wrapper.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/logging-wrapper-entities.d.ts +55 -0
- package/dist/logging-wrapper-entities.d.ts.map +1 -0
- package/dist/logging-wrapper-entities.js +72 -0
- package/dist/logging-wrapper-entities.js.map +1 -0
- package/dist/logging-wrapper.d.ts +20 -0
- package/dist/logging-wrapper.d.ts.map +1 -0
- package/dist/logging-wrapper.js +66 -0
- package/dist/logging-wrapper.js.map +1 -0
- package/package.json +32 -0
- package/src/fastify-logging-wrapper.ts +59 -0
- package/src/index.ts +11 -0
- package/src/logging-wrapper-entities.ts +130 -0
- package/src/logging-wrapper.ts +106 -0
- package/tsconfig.json +12 -0
- package/tsconfig.prod.json +4 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Level } from "pino";
|
|
2
|
+
import { getLoggerConfiguration } from "../src/logging-wrapper.js";
|
|
3
|
+
import { buildLogger } from "./helpers/build-logger.js";
|
|
4
|
+
import { hostname } from "os";
|
|
5
|
+
import { REDACTED_VALUE } from "../src/logging-wrapper-entities.js";
|
|
6
|
+
import assert from "node:assert";
|
|
7
|
+
import { test } from "node:test";
|
|
8
|
+
|
|
9
|
+
const getRandomFieldValue = () => Math.random().toString(36).slice(2);
|
|
10
|
+
|
|
11
|
+
const toRedactFields = {
|
|
12
|
+
input_value: {
|
|
13
|
+
request: {
|
|
14
|
+
"x-api-key": "non redacted because not under headers",
|
|
15
|
+
headers: {
|
|
16
|
+
"x-amz-security-token": getRandomFieldValue(),
|
|
17
|
+
"x-api-key": getRandomFieldValue(),
|
|
18
|
+
authorization: getRandomFieldValue(),
|
|
19
|
+
cookie: getRandomFieldValue(),
|
|
20
|
+
"set-cookie": getRandomFieldValue(),
|
|
21
|
+
"proxy-authorization": getRandomFieldValue(),
|
|
22
|
+
non_to_redact: "non_redacted_value",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
response: {
|
|
26
|
+
headers: {
|
|
27
|
+
"x-amz-security-token": getRandomFieldValue(),
|
|
28
|
+
"x-api-key": getRandomFieldValue(),
|
|
29
|
+
authorization: getRandomFieldValue(),
|
|
30
|
+
cookie: getRandomFieldValue(),
|
|
31
|
+
"set-cookie": getRandomFieldValue(),
|
|
32
|
+
"proxy-authorization": getRandomFieldValue(),
|
|
33
|
+
non_to_redact: "non_redacted_value",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
expected_output: {
|
|
38
|
+
request: {
|
|
39
|
+
"x-api-key": "non redacted because not under headers",
|
|
40
|
+
headers: {
|
|
41
|
+
"x-amz-security-token": REDACTED_VALUE,
|
|
42
|
+
"x-api-key": REDACTED_VALUE,
|
|
43
|
+
authorization: REDACTED_VALUE,
|
|
44
|
+
cookie: REDACTED_VALUE,
|
|
45
|
+
"set-cookie": REDACTED_VALUE,
|
|
46
|
+
"proxy-authorization": REDACTED_VALUE,
|
|
47
|
+
non_to_redact: "non_redacted_value",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
response: {
|
|
51
|
+
headers: {
|
|
52
|
+
"x-amz-security-token": REDACTED_VALUE,
|
|
53
|
+
"x-api-key": REDACTED_VALUE,
|
|
54
|
+
authorization: REDACTED_VALUE,
|
|
55
|
+
cookie: REDACTED_VALUE,
|
|
56
|
+
"set-cookie": REDACTED_VALUE,
|
|
57
|
+
"proxy-authorization": REDACTED_VALUE,
|
|
58
|
+
non_to_redact: "non_redacted_value",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const methodsDataProvider = [
|
|
65
|
+
{
|
|
66
|
+
method: "trace",
|
|
67
|
+
expected: {
|
|
68
|
+
level: 10,
|
|
69
|
+
level_name: "TRACE",
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
method: "debug",
|
|
74
|
+
expected: {
|
|
75
|
+
level: 20,
|
|
76
|
+
level_name: "DEBUG",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
method: "info",
|
|
81
|
+
expected: {
|
|
82
|
+
level: 30,
|
|
83
|
+
level_name: "INFO",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
method: "warn",
|
|
88
|
+
expected: {
|
|
89
|
+
level: 40,
|
|
90
|
+
level_name: "WARN",
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
method: "error",
|
|
95
|
+
expected: {
|
|
96
|
+
level: 50,
|
|
97
|
+
level_name: "ERROR",
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
method: "fatal",
|
|
102
|
+
expected: {
|
|
103
|
+
level: 60,
|
|
104
|
+
level_name: "FATAL",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
test("Basic format is the expected one", async (t) => {
|
|
110
|
+
const { logger, loggedRecordsMethod } = buildLogger({
|
|
111
|
+
...getLoggerConfiguration("debug"),
|
|
112
|
+
});
|
|
113
|
+
logger.debug("test message");
|
|
114
|
+
logger.info("another message");
|
|
115
|
+
|
|
116
|
+
const loggedRecords = loggedRecordsMethod();
|
|
117
|
+
assert.strictEqual(loggedRecords.length, 2);
|
|
118
|
+
|
|
119
|
+
const parsed = JSON.parse(loggedRecords[0]);
|
|
120
|
+
assert.strictEqual(typeof parsed.timestamp, "number");
|
|
121
|
+
assert.ok(
|
|
122
|
+
parsed.timestamp > Date.now() - 2000,
|
|
123
|
+
"the timestamp must be newer than 2 seconds ago",
|
|
124
|
+
);
|
|
125
|
+
delete parsed.timestamp;
|
|
126
|
+
assert.deepStrictEqual(parsed, {
|
|
127
|
+
level: 20,
|
|
128
|
+
level_name: "DEBUG",
|
|
129
|
+
hostname: hostname(),
|
|
130
|
+
message: "test message",
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("Fields are redacted as expected", async (t) => {
|
|
135
|
+
const { logger, loggedRecordsMethod } = buildLogger({
|
|
136
|
+
...getLoggerConfiguration(),
|
|
137
|
+
});
|
|
138
|
+
logger.warn(toRedactFields.input_value);
|
|
139
|
+
|
|
140
|
+
const loggedRecords = loggedRecordsMethod();
|
|
141
|
+
const parsed = JSON.parse(loggedRecords[0]);
|
|
142
|
+
delete parsed.hostname;
|
|
143
|
+
delete parsed.level;
|
|
144
|
+
delete parsed.level_name;
|
|
145
|
+
delete parsed.timestamp;
|
|
146
|
+
|
|
147
|
+
assert.deepStrictEqual(parsed, toRedactFields.expected_output);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
methodsDataProvider.forEach((methodDataProvider) =>
|
|
151
|
+
test(`Methods are writing correct levels - ${methodDataProvider.method}`, async (t) => {
|
|
152
|
+
const { logger, loggedRecordsMethod } = buildLogger({
|
|
153
|
+
...getLoggerConfiguration("trace"),
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
logger[methodDataProvider.method]("test");
|
|
157
|
+
|
|
158
|
+
const loggedRecords = loggedRecordsMethod();
|
|
159
|
+
assert.strictEqual(loggedRecords.length, 1);
|
|
160
|
+
const parsed = JSON.parse(loggedRecords[0]);
|
|
161
|
+
|
|
162
|
+
assert.strictEqual(parsed.level, methodDataProvider.expected.level);
|
|
163
|
+
assert.strictEqual(
|
|
164
|
+
parsed.level_name,
|
|
165
|
+
methodDataProvider.expected.level_name,
|
|
166
|
+
);
|
|
167
|
+
}),
|
|
168
|
+
);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { FastifyServerOptions, FastifyInstance } from "fastify";
|
|
2
|
+
import { DestinationStream } from "pino";
|
|
3
|
+
export declare const initializeLoggingHooks: (server: FastifyInstance) => void;
|
|
4
|
+
export declare const getLoggingConfiguration: (loggerDestination?: DestinationStream) => FastifyServerOptions;
|
|
5
|
+
//# sourceMappingURL=fastify-logging-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify-logging-wrapper.d.ts","sourceRoot":"","sources":["../src/fastify-logging-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAchE,OAAO,EAAQ,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAK/C,eAAO,MAAM,sBAAsB,WAAY,eAAe,KAAG,IA6BhE,CAAC;AAEF,eAAO,MAAM,uBAAuB,uBACd,iBAAiB,KACpC,oBAMD,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import hyperid from "hyperid";
|
|
2
|
+
import { LogMessages, REQUEST_ID_LOG_LABEL, } from "./logging-wrapper-entities.js";
|
|
3
|
+
import { getLoggerConfiguration, getLoggingContextError, getPartialLoggingContextError, parseFullLoggingRequest, resetLoggingContext, setLoggingContext, } from "./logging-wrapper.js";
|
|
4
|
+
import { pino } from "pino";
|
|
5
|
+
import { REQUEST_ID_HEADER } from "@ogcio/shared-errors";
|
|
6
|
+
const hyperidInstance = hyperid({ fixedLength: true, urlSafe: true });
|
|
7
|
+
export const initializeLoggingHooks = (server) => {
|
|
8
|
+
server.addHook("preHandler", (request, _reply, done) => {
|
|
9
|
+
setLoggingContext({ request });
|
|
10
|
+
request.log.info({ request: parseFullLoggingRequest(request) }, LogMessages.NewRequest);
|
|
11
|
+
done();
|
|
12
|
+
});
|
|
13
|
+
server.addHook("onResponse", (_req, reply, done) => {
|
|
14
|
+
setLoggingContext({ response: reply });
|
|
15
|
+
reply.log.info(LogMessages.Response);
|
|
16
|
+
// Include error in API Track if exists
|
|
17
|
+
reply.log.info({ error: getPartialLoggingContextError() }, LogMessages.ApiTrack);
|
|
18
|
+
resetLoggingContext();
|
|
19
|
+
done();
|
|
20
|
+
});
|
|
21
|
+
server.addHook("onError", (request, _reply, error, done) => {
|
|
22
|
+
setLoggingContext({ error });
|
|
23
|
+
request.log.error({ error: getLoggingContextError() }, LogMessages.Error);
|
|
24
|
+
done();
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
export const getLoggingConfiguration = (loggerDestination) => ({
|
|
28
|
+
logger: pino(getLoggerConfiguration(), loggerDestination),
|
|
29
|
+
disableRequestLogging: true,
|
|
30
|
+
genReqId: () => hyperidInstance(),
|
|
31
|
+
requestIdLogLabel: REQUEST_ID_LOG_LABEL,
|
|
32
|
+
requestIdHeader: REQUEST_ID_HEADER,
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=fastify-logging-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify-logging-wrapper.js","sourceRoot":"","sources":["../src/fastify-logging-wrapper.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EACL,WAAW,EACX,oBAAoB,GACrB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,IAAI,EAAqB,MAAM,MAAM,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,eAAe,GAAG,OAAO,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AAEtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,MAAuB,EAAQ,EAAE;IACtE,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QACrD,iBAAiB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,CACd,EAAE,OAAO,EAAE,uBAAuB,CAAC,OAAO,CAAC,EAAE,EAC7C,WAAW,CAAC,UAAU,CACvB,CAAC;QACF,IAAI,EAAE,CAAC;IACT,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACjD,iBAAiB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACvC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACrC,uCAAuC;QACvC,KAAK,CAAC,GAAG,CAAC,IAAI,CACZ,EAAE,KAAK,EAAE,6BAA6B,EAAE,EAAE,EAC1C,WAAW,CAAC,QAAQ,CACrB,CAAC;QACF,mBAAmB,EAAE,CAAC;QACtB,IAAI,EAAE,CAAC;IACT,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACzD,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAE7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;QAE1E,IAAI,EAAE,CAAC;IACT,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,iBAAqC,EACf,EAAE,CAAC,CAAC;IAC1B,MAAM,EAAE,IAAI,CAAC,sBAAsB,EAAE,EAAE,iBAAiB,CAAC;IACzD,qBAAqB,EAAE,IAAI;IAC3B,QAAQ,EAAE,GAAG,EAAE,CAAC,eAAe,EAAE;IACjC,iBAAiB,EAAE,oBAAoB;IACvC,eAAe,EAAE,iBAAiB;CACnC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { getLoggingConfiguration, initializeLoggingHooks, } from "./fastify-logging-wrapper.js";
|
|
2
|
+
export { toLoggingError, LogMessages, LoggingError, } from "./logging-wrapper-entities.js";
|
|
3
|
+
export { getLoggingContextError, setLoggingContext } from "./logging-wrapper.js";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,cAAc,EACd,WAAW,EACX,YAAY,GACb,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { getLoggingConfiguration, initializeLoggingHooks, } from "./fastify-logging-wrapper.js";
|
|
2
|
+
export { toLoggingError, LogMessages, } from "./logging-wrapper-entities.js";
|
|
3
|
+
export { getLoggingContextError, setLoggingContext } from "./logging-wrapper.js";
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,cAAc,EACd,WAAW,GAEZ,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { FastifyError } from "fastify";
|
|
2
|
+
import { HttpError } from "@fastify/sensible";
|
|
3
|
+
export interface LoggingRequest {
|
|
4
|
+
scheme: string;
|
|
5
|
+
method: string;
|
|
6
|
+
path: string | undefined;
|
|
7
|
+
hostname: string;
|
|
8
|
+
query_params: unknown;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export interface FullLoggingRequest extends LoggingRequest {
|
|
12
|
+
headers: unknown;
|
|
13
|
+
user_agent: string | undefined;
|
|
14
|
+
client_ip: string;
|
|
15
|
+
}
|
|
16
|
+
export interface LoggingResponse {
|
|
17
|
+
headers: unknown;
|
|
18
|
+
status_code: number;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
export interface LoggingError {
|
|
22
|
+
class: LogErrorClasses;
|
|
23
|
+
message: string;
|
|
24
|
+
trace?: string;
|
|
25
|
+
parent?: {
|
|
26
|
+
name: string;
|
|
27
|
+
message: string;
|
|
28
|
+
stack?: string;
|
|
29
|
+
};
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
}
|
|
32
|
+
export interface LoggingContext {
|
|
33
|
+
request?: LoggingRequest;
|
|
34
|
+
response?: LoggingResponse;
|
|
35
|
+
error?: LoggingError;
|
|
36
|
+
}
|
|
37
|
+
export declare enum LogMessages {
|
|
38
|
+
NewRequest = "NEW_REQUEST",
|
|
39
|
+
Response = "RESPONSE",
|
|
40
|
+
Error = "ERROR",
|
|
41
|
+
ApiTrack = "API_TRACK"
|
|
42
|
+
}
|
|
43
|
+
export declare enum LogErrorClasses {
|
|
44
|
+
ServerError = "SERVER_ERROR",
|
|
45
|
+
ValidationError = "VALIDATION_ERROR",
|
|
46
|
+
RequestError = "REQUEST_ERROR",
|
|
47
|
+
GatewayError = "GATEWAY_ERROR",
|
|
48
|
+
UnknownError = "UNKNOWN_ERROR"
|
|
49
|
+
}
|
|
50
|
+
export declare const REDACTED_VALUE = "[redacted]";
|
|
51
|
+
export declare const REDACTED_PATHS: string[];
|
|
52
|
+
export declare const MESSAGE_KEY = "message";
|
|
53
|
+
export declare const REQUEST_ID_LOG_LABEL = "request_id";
|
|
54
|
+
export declare const toLoggingError: (error: HttpError | FastifyError) => LoggingError;
|
|
55
|
+
//# sourceMappingURL=logging-wrapper-entities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-wrapper-entities.d.ts","sourceRoot":"","sources":["../src/logging-wrapper-entities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIvC,OAAO,EAAE,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAG7C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,eAAe,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,oBAAY,WAAW;IACrB,UAAU,gBAAgB;IAC1B,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,QAAQ,cAAc;CACvB;AAED,oBAAY,eAAe;IACzB,WAAW,iBAAiB;IAC5B,eAAe,qBAAqB;IACpC,YAAY,kBAAkB;IAC9B,YAAY,kBAAkB;IAC9B,YAAY,kBAAkB;CAC/B;AAED,eAAO,MAAM,cAAc,eAAe,CAAC;AAE3C,eAAO,MAAM,cAAc,UAO1B,CAAC;AAEF,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAIjD,eAAO,MAAM,cAAc,UAClB,SAAS,GAAG,YAAY,KAC9B,YAyBF,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { parseErrorForLogging, } from "@ogcio/shared-errors";
|
|
2
|
+
import { isHttpError } from "http-errors";
|
|
3
|
+
export var LogMessages;
|
|
4
|
+
(function (LogMessages) {
|
|
5
|
+
LogMessages["NewRequest"] = "NEW_REQUEST";
|
|
6
|
+
LogMessages["Response"] = "RESPONSE";
|
|
7
|
+
LogMessages["Error"] = "ERROR";
|
|
8
|
+
LogMessages["ApiTrack"] = "API_TRACK";
|
|
9
|
+
})(LogMessages || (LogMessages = {}));
|
|
10
|
+
export var LogErrorClasses;
|
|
11
|
+
(function (LogErrorClasses) {
|
|
12
|
+
LogErrorClasses["ServerError"] = "SERVER_ERROR";
|
|
13
|
+
LogErrorClasses["ValidationError"] = "VALIDATION_ERROR";
|
|
14
|
+
LogErrorClasses["RequestError"] = "REQUEST_ERROR";
|
|
15
|
+
LogErrorClasses["GatewayError"] = "GATEWAY_ERROR";
|
|
16
|
+
LogErrorClasses["UnknownError"] = "UNKNOWN_ERROR";
|
|
17
|
+
})(LogErrorClasses || (LogErrorClasses = {}));
|
|
18
|
+
export const REDACTED_VALUE = "[redacted]";
|
|
19
|
+
export const REDACTED_PATHS = [
|
|
20
|
+
'*.headers["x-amz-security-token"]',
|
|
21
|
+
'*.headers["x-api-key"]',
|
|
22
|
+
'*.headers["authorization"]',
|
|
23
|
+
'*.headers["cookie"]',
|
|
24
|
+
'*.headers["set-cookie"]',
|
|
25
|
+
'*.headers["proxy-authorization"]',
|
|
26
|
+
];
|
|
27
|
+
export const MESSAGE_KEY = "message";
|
|
28
|
+
export const REQUEST_ID_LOG_LABEL = "request_id";
|
|
29
|
+
const UNHANDLED_EXCEPTION_CODE = "UNHANDLED_EXCEPTION";
|
|
30
|
+
export const toLoggingError = (error) => {
|
|
31
|
+
const output = {
|
|
32
|
+
class: parseErrorClass(error),
|
|
33
|
+
message: error.message,
|
|
34
|
+
trace: error.stack,
|
|
35
|
+
};
|
|
36
|
+
if (isHttpError(error)) {
|
|
37
|
+
const parentInput = error.parentError ?? error.parent;
|
|
38
|
+
const parent = parentInput
|
|
39
|
+
? { parent: parseErrorForLogging(parentInput) }
|
|
40
|
+
: {};
|
|
41
|
+
return {
|
|
42
|
+
...output,
|
|
43
|
+
code: error.name,
|
|
44
|
+
process: error.errorProcess,
|
|
45
|
+
...parent,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
...output,
|
|
50
|
+
code: error.code ?? UNHANDLED_EXCEPTION_CODE,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const parseErrorClass = (error) => {
|
|
54
|
+
if (!error.statusCode) {
|
|
55
|
+
return LogErrorClasses.UnknownError;
|
|
56
|
+
}
|
|
57
|
+
const statusCode = Number(error.statusCode);
|
|
58
|
+
if (statusCode === 502) {
|
|
59
|
+
return LogErrorClasses.GatewayError;
|
|
60
|
+
}
|
|
61
|
+
if (statusCode >= 500) {
|
|
62
|
+
return LogErrorClasses.ServerError;
|
|
63
|
+
}
|
|
64
|
+
if (statusCode === 422) {
|
|
65
|
+
return LogErrorClasses.ValidationError;
|
|
66
|
+
}
|
|
67
|
+
if (statusCode >= 400) {
|
|
68
|
+
return LogErrorClasses.RequestError;
|
|
69
|
+
}
|
|
70
|
+
return LogErrorClasses.UnknownError;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=logging-wrapper-entities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-wrapper-entities.js","sourceRoot":"","sources":["../src/logging-wrapper-entities.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAqCxC,MAAM,CAAN,IAAY,WAKX;AALD,WAAY,WAAW;IACrB,yCAA0B,CAAA;IAC1B,oCAAqB,CAAA;IACrB,8BAAe,CAAA;IACf,qCAAsB,CAAA;AACxB,CAAC,EALW,WAAW,KAAX,WAAW,QAKtB;AAED,MAAM,CAAN,IAAY,eAMX;AAND,WAAY,eAAe;IACzB,+CAA4B,CAAA;IAC5B,uDAAoC,CAAA;IACpC,iDAA8B,CAAA;IAC9B,iDAA8B,CAAA;IAC9B,iDAA8B,CAAA;AAChC,CAAC,EANW,eAAe,KAAf,eAAe,QAM1B;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC;AAE3C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,mCAAmC;IACnC,wBAAwB;IACxB,4BAA4B;IAC5B,qBAAqB;IACrB,yBAAyB;IACzB,kCAAkC;CACnC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAErC,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;AAEjD,MAAM,wBAAwB,GAAG,qBAAqB,CAAC;AAEvD,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,KAA+B,EACjB,EAAE;IAChB,MAAM,MAAM,GAAG;QACb,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC;QAC7B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC;IAEF,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC;QACtD,MAAM,MAAM,GAAG,WAAW;YACxB,CAAC,CAAC,EAAE,MAAM,EAAE,oBAAoB,CAAC,WAAW,CAAC,EAAE;YAC/C,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO;YACL,GAAG,MAAM;YACT,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,YAAY;YAC3B,GAAG,MAAM;SACV,CAAC;IACJ,CAAC;IAED,OAAO;QACL,GAAG,MAAM;QACT,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,wBAAwB;KAC7C,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CACtB,KAA+B,EACd,EAAE;IACnB,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACtB,OAAO,eAAe,CAAC,YAAY,CAAC;IACtC,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAE5C,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;QACvB,OAAO,eAAe,CAAC,YAAY,CAAC;IACtC,CAAC;IAED,IAAI,UAAU,IAAI,GAAG,EAAE,CAAC;QACtB,OAAO,eAAe,CAAC,WAAW,CAAC;IACrC,CAAC;IAED,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;QACvB,OAAO,eAAe,CAAC,eAAe,CAAC;IACzC,CAAC;IAED,IAAI,UAAU,IAAI,GAAG,EAAE,CAAC;QACtB,OAAO,eAAe,CAAC,YAAY,CAAC;IACtC,CAAC;IAED,OAAO,eAAe,CAAC,YAAY,CAAC;AACtC,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { FastifyRequest, FastifyReply, FastifyError } from "fastify";
|
|
2
|
+
import { LoggingContext, FullLoggingRequest, LoggingError } from "./logging-wrapper-entities.js";
|
|
3
|
+
import { LogLevel, PinoLoggerOptions } from "fastify/types/logger.js";
|
|
4
|
+
import { HttpError } from "@fastify/sensible";
|
|
5
|
+
type INPUT_ERROR_TYPES = FastifyError | HttpError;
|
|
6
|
+
export declare const getLoggingContext: (params: {
|
|
7
|
+
includeError: boolean;
|
|
8
|
+
}) => LoggingContext;
|
|
9
|
+
export declare const setLoggingContext: (params: {
|
|
10
|
+
request?: FastifyRequest;
|
|
11
|
+
response?: FastifyReply;
|
|
12
|
+
error?: INPUT_ERROR_TYPES;
|
|
13
|
+
}) => void;
|
|
14
|
+
export declare const resetLoggingContext: () => void;
|
|
15
|
+
export declare const getLoggingContextError: () => LoggingError | undefined;
|
|
16
|
+
export declare const getPartialLoggingContextError: () => Omit<LoggingError, "trace"> | undefined;
|
|
17
|
+
export declare const parseFullLoggingRequest: (req: FastifyRequest) => FullLoggingRequest;
|
|
18
|
+
export declare const getLoggerConfiguration: (minimumLevel?: LogLevel) => PinoLoggerOptions;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=logging-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-wrapper.d.ts","sourceRoot":"","sources":["../src/logging-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAErE,OAAO,EACL,cAAc,EAEd,kBAAkB,EAElB,YAAY,EAKb,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAI9C,KAAK,iBAAiB,GAAG,YAAY,GAAG,SAAS,CAAC;AAElD,eAAO,MAAM,iBAAiB,WAAY;IACxC,YAAY,EAAE,OAAO,CAAC;CACvB,KAAG,cAGyC,CAAC;AAE9C,eAAO,MAAM,iBAAiB,WAAY;IACxC,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,iBAAiB,CAAC;CAC3B,KAAG,IAUH,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAO,IAItC,CAAC;AAEF,eAAO,MAAM,sBAAsB,QAAO,YAAY,GAAG,SACR,CAAC;AAElD,eAAO,MAAM,6BAA6B,QACtC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAC3B,SAGF,CAAC;AAaH,eAAO,MAAM,uBAAuB,QAC7B,cAAc,KAClB,kBAKD,CAAC;AAOH,eAAO,MAAM,sBAAsB,kBACnB,QAAQ,KACrB,iBAmBD,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { hostname } from "os";
|
|
2
|
+
import { REDACTED_VALUE, REDACTED_PATHS, MESSAGE_KEY, toLoggingError, } from "./logging-wrapper-entities.js";
|
|
3
|
+
const loggingContext = {};
|
|
4
|
+
export const getLoggingContext = (params) => params.includeError
|
|
5
|
+
? loggingContext
|
|
6
|
+
: { ...loggingContext, error: undefined };
|
|
7
|
+
export const setLoggingContext = (params) => {
|
|
8
|
+
if (params.request !== undefined) {
|
|
9
|
+
loggingContext.request = parseLoggingRequest(params.request);
|
|
10
|
+
}
|
|
11
|
+
if (params.response !== undefined) {
|
|
12
|
+
loggingContext.response = parseLoggingResponse(params.response);
|
|
13
|
+
}
|
|
14
|
+
if (params.error !== undefined) {
|
|
15
|
+
loggingContext.error = toLoggingError(params.error);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
export const resetLoggingContext = () => {
|
|
19
|
+
loggingContext.request = undefined;
|
|
20
|
+
loggingContext.response = undefined;
|
|
21
|
+
loggingContext.error = undefined;
|
|
22
|
+
};
|
|
23
|
+
export const getLoggingContextError = () => getLoggingContext({ includeError: true }).error;
|
|
24
|
+
export const getPartialLoggingContextError = () => ({
|
|
25
|
+
...(getLoggingContext({ includeError: true }).error ?? {}),
|
|
26
|
+
trace: undefined,
|
|
27
|
+
});
|
|
28
|
+
const getPathWithoutParams = (req) => req.routeOptions?.url ?? req.url.split("?")[0];
|
|
29
|
+
const parseLoggingRequest = (req) => ({
|
|
30
|
+
scheme: req.protocol,
|
|
31
|
+
method: req.method,
|
|
32
|
+
path: getPathWithoutParams(req),
|
|
33
|
+
hostname: req.hostname,
|
|
34
|
+
query_params: req.query,
|
|
35
|
+
});
|
|
36
|
+
export const parseFullLoggingRequest = (req) => ({
|
|
37
|
+
...parseLoggingRequest(req),
|
|
38
|
+
headers: req.headers,
|
|
39
|
+
client_ip: req.ip,
|
|
40
|
+
user_agent: req.headers["user-agent"] ?? undefined,
|
|
41
|
+
});
|
|
42
|
+
const parseLoggingResponse = (res) => ({
|
|
43
|
+
status_code: res.statusCode,
|
|
44
|
+
headers: res.getHeaders(),
|
|
45
|
+
});
|
|
46
|
+
export const getLoggerConfiguration = (minimumLevel = "debug") => ({
|
|
47
|
+
base: { hostname: hostname() },
|
|
48
|
+
messageKey: MESSAGE_KEY,
|
|
49
|
+
mixin: () => ({
|
|
50
|
+
timestamp: Date.now(),
|
|
51
|
+
...getLoggingContext({ includeError: false }),
|
|
52
|
+
}),
|
|
53
|
+
redact: {
|
|
54
|
+
paths: REDACTED_PATHS,
|
|
55
|
+
censor: REDACTED_VALUE,
|
|
56
|
+
},
|
|
57
|
+
timestamp: false,
|
|
58
|
+
formatters: {
|
|
59
|
+
level: (name, levelVal) => ({
|
|
60
|
+
level: levelVal,
|
|
61
|
+
level_name: name.toUpperCase(),
|
|
62
|
+
}),
|
|
63
|
+
},
|
|
64
|
+
level: minimumLevel,
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=logging-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging-wrapper.js","sourceRoot":"","sources":["../src/logging-wrapper.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ogcio/fastify-logging-wrapper",
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "rm -rf dist tsconfig.prod.tsbuildinfo tsconfig.tsbuildinfo && tsc -p tsconfig.prod.json",
|
|
9
|
+
"test": "tap --jobs=1 --allow-incomplete-coverage __tests__/**/*.test.ts"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": {
|
|
13
|
+
"name": "Samuele Salvatico",
|
|
14
|
+
"email": "samuele.salvatico@nearform.com"
|
|
15
|
+
},
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"description": "Enable standardized log entries for each request in fastify",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@fastify/error": "^4.0.0",
|
|
20
|
+
"@fastify/sensible": "^5.6.0",
|
|
21
|
+
"fastify": "^4.28.1",
|
|
22
|
+
"hyperid": "^3.3.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/http-errors": "^2.0.4"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/ogcio/shared-node-utils.git",
|
|
30
|
+
"directory": "packages/fastify-logging-wrapper"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { FastifyServerOptions, FastifyInstance } from "fastify";
|
|
2
|
+
import hyperid from "hyperid";
|
|
3
|
+
import {
|
|
4
|
+
LogMessages,
|
|
5
|
+
REQUEST_ID_LOG_LABEL,
|
|
6
|
+
} from "./logging-wrapper-entities.js";
|
|
7
|
+
import {
|
|
8
|
+
getLoggerConfiguration,
|
|
9
|
+
getLoggingContextError,
|
|
10
|
+
getPartialLoggingContextError,
|
|
11
|
+
parseFullLoggingRequest,
|
|
12
|
+
resetLoggingContext,
|
|
13
|
+
setLoggingContext,
|
|
14
|
+
} from "./logging-wrapper.js";
|
|
15
|
+
import { pino, DestinationStream } from "pino";
|
|
16
|
+
import { REQUEST_ID_HEADER } from "@ogcio/shared-errors";
|
|
17
|
+
|
|
18
|
+
const hyperidInstance = hyperid({ fixedLength: true, urlSafe: true });
|
|
19
|
+
|
|
20
|
+
export const initializeLoggingHooks = (server: FastifyInstance): void => {
|
|
21
|
+
server.addHook("preHandler", (request, _reply, done) => {
|
|
22
|
+
setLoggingContext({ request });
|
|
23
|
+
request.log.info(
|
|
24
|
+
{ request: parseFullLoggingRequest(request) },
|
|
25
|
+
LogMessages.NewRequest,
|
|
26
|
+
);
|
|
27
|
+
done();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
server.addHook("onResponse", (_req, reply, done) => {
|
|
31
|
+
setLoggingContext({ response: reply });
|
|
32
|
+
reply.log.info(LogMessages.Response);
|
|
33
|
+
// Include error in API Track if exists
|
|
34
|
+
reply.log.info(
|
|
35
|
+
{ error: getPartialLoggingContextError() },
|
|
36
|
+
LogMessages.ApiTrack,
|
|
37
|
+
);
|
|
38
|
+
resetLoggingContext();
|
|
39
|
+
done();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
server.addHook("onError", (request, _reply, error, done) => {
|
|
43
|
+
setLoggingContext({ error });
|
|
44
|
+
|
|
45
|
+
request.log.error({ error: getLoggingContextError() }, LogMessages.Error);
|
|
46
|
+
|
|
47
|
+
done();
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const getLoggingConfiguration = (
|
|
52
|
+
loggerDestination?: DestinationStream,
|
|
53
|
+
): FastifyServerOptions => ({
|
|
54
|
+
logger: pino(getLoggerConfiguration(), loggerDestination),
|
|
55
|
+
disableRequestLogging: true,
|
|
56
|
+
genReqId: () => hyperidInstance(),
|
|
57
|
+
requestIdLogLabel: REQUEST_ID_LOG_LABEL,
|
|
58
|
+
requestIdHeader: REQUEST_ID_HEADER,
|
|
59
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export {
|
|
2
|
+
getLoggingConfiguration,
|
|
3
|
+
initializeLoggingHooks,
|
|
4
|
+
} from "./fastify-logging-wrapper.js";
|
|
5
|
+
export {
|
|
6
|
+
toLoggingError,
|
|
7
|
+
LogMessages,
|
|
8
|
+
LoggingError,
|
|
9
|
+
} from "./logging-wrapper-entities.js";
|
|
10
|
+
|
|
11
|
+
export { getLoggingContextError, setLoggingContext } from "./logging-wrapper.js";
|