sasai-common-utils 1.0.49 → 1.0.51
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/package.json +1 -1
- package/src/features/logger/index.js +124 -49
package/package.json
CHANGED
|
@@ -7,9 +7,10 @@ let contextProvider = () => ({});
|
|
|
7
7
|
let globalConfig = {};
|
|
8
8
|
let loggerInstance;
|
|
9
9
|
let pinoLogger;
|
|
10
|
+
let pinoTransport;
|
|
10
11
|
|
|
11
12
|
function setContextProvider(provider) {
|
|
12
|
-
contextProvider = provider;
|
|
13
|
+
contextProvider = typeof provider === "function" ? provider : () => ({});
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
function setGlobalConfig(config) {
|
|
@@ -29,6 +30,54 @@ function cleanString(str) {
|
|
|
29
30
|
return typeof str === "string" ? str.replace(/\\"/g, '"') : str;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
function safeJsonStringify(value) {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.stringify(value);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
return JSON.stringify({
|
|
38
|
+
message: "Failed to stringify log payload",
|
|
39
|
+
error: error?.message || "Unknown stringify error",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function decodeTokenDetails(headers = {}) {
|
|
45
|
+
try {
|
|
46
|
+
const authHeader = headers?.authorization || headers?.Authorization;
|
|
47
|
+
const token = authHeader?.split(" ")[1];
|
|
48
|
+
const payload = jwt.decode(token, { complete: true })?.payload;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
customerId: payload?.customerId || "",
|
|
52
|
+
mid: payload?.mid || "",
|
|
53
|
+
tenantId: payload?.tenantId || "",
|
|
54
|
+
};
|
|
55
|
+
} catch (error) {
|
|
56
|
+
return {
|
|
57
|
+
customerId: "",
|
|
58
|
+
mid: "",
|
|
59
|
+
tenantId: "",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getTraceContext() {
|
|
65
|
+
try {
|
|
66
|
+
const traceContext = contextProvider?.() || {};
|
|
67
|
+
return {
|
|
68
|
+
trace_id: traceContext?.trace_id || "",
|
|
69
|
+
span_id: traceContext?.span_id || "",
|
|
70
|
+
parent_span_id: traceContext?.parent_span_id || "",
|
|
71
|
+
};
|
|
72
|
+
} catch (error) {
|
|
73
|
+
return {
|
|
74
|
+
trace_id: "",
|
|
75
|
+
span_id: "",
|
|
76
|
+
parent_span_id: "",
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
32
81
|
function initPinoLogger() {
|
|
33
82
|
const pinoOptions = {
|
|
34
83
|
timestamp: false,
|
|
@@ -37,8 +86,8 @@ function initPinoLogger() {
|
|
|
37
86
|
? "silent"
|
|
38
87
|
: globalConfig.LOG_LEVEL,
|
|
39
88
|
base: {
|
|
40
|
-
|
|
41
|
-
environment: globalConfig.NODE_ENV
|
|
89
|
+
"service.name": globalConfig.SERVICE_NAME,
|
|
90
|
+
"deployment.environment": globalConfig.NODE_ENV,
|
|
42
91
|
},
|
|
43
92
|
formatters: {
|
|
44
93
|
level(label) {
|
|
@@ -59,21 +108,25 @@ function initPinoLogger() {
|
|
|
59
108
|
url: globalConfig.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
|
|
60
109
|
protocol: globalConfig.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL,
|
|
61
110
|
resourceAttributes: {
|
|
62
|
-
"service.name": globalConfig.SERVICE_NAME
|
|
63
|
-
"deployment.environment": globalConfig.NODE_ENV
|
|
111
|
+
"service.name": globalConfig.SERVICE_NAME,
|
|
112
|
+
"deployment.environment": globalConfig.NODE_ENV,
|
|
64
113
|
},
|
|
65
114
|
},
|
|
66
115
|
};
|
|
67
116
|
|
|
68
|
-
|
|
117
|
+
pinoTransport = pino.transport({
|
|
69
118
|
targets: [stdoutTarget, otelTarget],
|
|
70
119
|
});
|
|
71
120
|
|
|
72
|
-
|
|
121
|
+
pinoTransport.on("error", (err) => {
|
|
73
122
|
console.error("Pino OTEL transport error:", err);
|
|
74
123
|
});
|
|
75
124
|
|
|
76
|
-
|
|
125
|
+
pinoTransport.on("close", () => {
|
|
126
|
+
console.warn("Pino OTEL transport closed");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
pinoLogger = pino(pinoOptions, pinoTransport);
|
|
77
130
|
} else {
|
|
78
131
|
let destination;
|
|
79
132
|
if (globalConfig.DEBUG_MODE === DEBUG_MODES.FILE) {
|
|
@@ -83,14 +136,29 @@ function initPinoLogger() {
|
|
|
83
136
|
}
|
|
84
137
|
pinoLogger = pino(pinoOptions, destination);
|
|
85
138
|
}
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
pinoLogger.info({
|
|
142
|
+
message: "Pino logger initialized",
|
|
143
|
+
"service.name": globalConfig.SERVICE_NAME,
|
|
144
|
+
"deployment.environment": globalConfig.NODE_ENV,
|
|
145
|
+
otel_logs_endpoint: globalConfig.OTEL_EXPORTER_OTLP_LOGS_ENDPOINT || "",
|
|
146
|
+
otel_logs_protocol: globalConfig.OTEL_EXPORTER_OTLP_LOGS_PROTOCOL || "",
|
|
147
|
+
});
|
|
148
|
+
} catch (error) {
|
|
149
|
+
console.error("Failed to write startup log:", error);
|
|
150
|
+
}
|
|
86
151
|
}
|
|
87
152
|
|
|
88
153
|
function emitLog(level, data) {
|
|
89
154
|
if (!pinoLogger) return;
|
|
90
|
-
|
|
155
|
+
|
|
156
|
+
const { trace, span, parentSpan, message, ...rest } = data;
|
|
157
|
+
|
|
91
158
|
pinoLogger[level]({
|
|
92
159
|
trace_id: trace || undefined,
|
|
93
160
|
span_id: span || undefined,
|
|
161
|
+
parent_span_id: parentSpan || undefined,
|
|
94
162
|
message: cleanString(message),
|
|
95
163
|
...rest,
|
|
96
164
|
});
|
|
@@ -104,20 +172,17 @@ function createLogger(config) {
|
|
|
104
172
|
|
|
105
173
|
loggerInstance = {
|
|
106
174
|
logInfo: (message, data = {}) => {
|
|
107
|
-
const traceContext =
|
|
108
|
-
const
|
|
109
|
-
data?.headers?.authorization || data?.headers?.Authorization;
|
|
110
|
-
const tokenData = jwt.decode(authHeader?.split(" ")[1], {
|
|
111
|
-
complete: true,
|
|
112
|
-
})?.payload;
|
|
175
|
+
const traceContext = getTraceContext();
|
|
176
|
+
const tokenDetails = decodeTokenDetails(data?.headers || {});
|
|
113
177
|
|
|
114
178
|
const logData = {
|
|
115
|
-
trace: traceContext
|
|
116
|
-
span: traceContext
|
|
179
|
+
trace: traceContext.trace_id,
|
|
180
|
+
span: traceContext.span_id,
|
|
181
|
+
parentSpan: traceContext.parent_span_id,
|
|
117
182
|
thread: "",
|
|
118
183
|
class: "",
|
|
119
|
-
|
|
120
|
-
step: data?.step,
|
|
184
|
+
body: safeJsonStringify({
|
|
185
|
+
step: data?.step || "",
|
|
121
186
|
message,
|
|
122
187
|
method: data?.method?.toUpperCase() || "",
|
|
123
188
|
parameters: data?.parameters || "",
|
|
@@ -125,11 +190,7 @@ function createLogger(config) {
|
|
|
125
190
|
headers: data?.headers || {},
|
|
126
191
|
responseHeaders: data?.responseHeaders || {},
|
|
127
192
|
api: data?.api || "",
|
|
128
|
-
tokenDetails
|
|
129
|
-
customerId: tokenData?.customerId || "",
|
|
130
|
-
mid: tokenData?.mid || "",
|
|
131
|
-
tenantId: tokenData?.tenantId || "",
|
|
132
|
-
},
|
|
193
|
+
tokenDetails,
|
|
133
194
|
responseStatus: data?.statusCode || "",
|
|
134
195
|
requestBody: data?.requestBody || {},
|
|
135
196
|
responseBody: data?.responseBody || {},
|
|
@@ -144,36 +205,38 @@ function createLogger(config) {
|
|
|
144
205
|
},
|
|
145
206
|
|
|
146
207
|
logError: (data = {}, req = {}) => {
|
|
147
|
-
const traceContext =
|
|
208
|
+
const traceContext = getTraceContext();
|
|
148
209
|
const errorResponse = data?.error?.response;
|
|
149
|
-
const
|
|
150
|
-
data?.headers
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
210
|
+
const tokenDetails = decodeTokenDetails(
|
|
211
|
+
data?.headers ||
|
|
212
|
+
errorResponse?.config?.headers ||
|
|
213
|
+
req?.headers ||
|
|
214
|
+
{}
|
|
215
|
+
);
|
|
154
216
|
|
|
155
217
|
const logData = {
|
|
156
|
-
trace: traceContext
|
|
157
|
-
span: traceContext
|
|
218
|
+
trace: traceContext.trace_id,
|
|
219
|
+
span: traceContext.span_id,
|
|
220
|
+
parentSpan: traceContext.parent_span_id,
|
|
158
221
|
thread: "",
|
|
159
222
|
class: "",
|
|
160
|
-
|
|
223
|
+
body: safeJsonStringify({
|
|
161
224
|
step: data?.step || "",
|
|
162
|
-
message: data?.error?.message,
|
|
163
|
-
method: errorResponse?.config?.method?.toUpperCase(),
|
|
225
|
+
message: data?.error?.message || "",
|
|
226
|
+
method: errorResponse?.config?.method?.toUpperCase() || "",
|
|
164
227
|
parameters: data?.parameters || "",
|
|
165
|
-
path: errorResponse?.config?.url || req?.originalUrl,
|
|
228
|
+
path: errorResponse?.config?.url || req?.originalUrl || "",
|
|
166
229
|
responseStatus:
|
|
167
230
|
errorResponse?.status || HTTP_STATUS_CODES.BAD_REQUEST,
|
|
168
|
-
headers: errorResponse?.config?.headers || {},
|
|
169
|
-
requestBody:
|
|
231
|
+
headers: errorResponse?.config?.headers || req?.headers || {},
|
|
232
|
+
requestBody:
|
|
233
|
+
errorResponse?.config?.data ||
|
|
234
|
+
errorResponse?.config?.body ||
|
|
235
|
+
req?.body ||
|
|
236
|
+
{},
|
|
170
237
|
responseBody: errorResponse?.data || {},
|
|
171
|
-
stack: data?.error?.stack,
|
|
172
|
-
tokenDetails
|
|
173
|
-
customerId: tokenData?.customerId || "",
|
|
174
|
-
mid: tokenData?.mid || "",
|
|
175
|
-
tenantId: tokenData?.tenantId || "",
|
|
176
|
-
},
|
|
238
|
+
stack: data?.error?.stack || "",
|
|
239
|
+
tokenDetails,
|
|
177
240
|
}),
|
|
178
241
|
};
|
|
179
242
|
|
|
@@ -185,15 +248,27 @@ function createLogger(config) {
|
|
|
185
248
|
},
|
|
186
249
|
|
|
187
250
|
logDebug: (message, data = {}) => {
|
|
188
|
-
const traceContext =
|
|
251
|
+
const traceContext = getTraceContext();
|
|
252
|
+
|
|
189
253
|
emitLog("debug", {
|
|
190
|
-
trace: traceContext
|
|
191
|
-
span: traceContext
|
|
192
|
-
|
|
193
|
-
|
|
254
|
+
trace: traceContext.trace_id,
|
|
255
|
+
span: traceContext.span_id,
|
|
256
|
+
parentSpan: traceContext.parent_span_id,
|
|
257
|
+
body:
|
|
258
|
+
typeof message === "string" ? message : safeJsonStringify(message),
|
|
194
259
|
...data,
|
|
195
260
|
});
|
|
196
261
|
},
|
|
262
|
+
|
|
263
|
+
flush: async () => {
|
|
264
|
+
try {
|
|
265
|
+
if (pinoTransport && typeof pinoTransport.flush === "function") {
|
|
266
|
+
await pinoTransport.flush();
|
|
267
|
+
}
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.error("Failed to flush pino transport:", error);
|
|
270
|
+
}
|
|
271
|
+
},
|
|
197
272
|
};
|
|
198
273
|
|
|
199
274
|
return loggerInstance;
|