@jaypie/logger 1.2.10 → 1.2.12
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/dist/cjs/Logger.d.ts +3 -1
- package/dist/cjs/index.cjs +252 -77
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/pipelines.d.ts +7 -1
- package/dist/esm/Logger.d.ts +3 -1
- package/dist/esm/index.js +252 -77
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/pipelines.d.ts +7 -1
- package/package.json +1 -1
package/dist/cjs/Logger.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ type Tags = Record<string, string>;
|
|
|
4
4
|
interface LoggerOptions {
|
|
5
5
|
format?: LogFormat;
|
|
6
6
|
level?: LogLevel;
|
|
7
|
+
levelField?: boolean | string;
|
|
7
8
|
tags?: Tags;
|
|
8
9
|
varLevel?: LogLevel;
|
|
9
10
|
}
|
|
@@ -21,7 +22,8 @@ declare class Logger {
|
|
|
21
22
|
trace: LogMethod;
|
|
22
23
|
var: (messageObject: unknown, messageValue?: unknown) => void;
|
|
23
24
|
warn: LogMethod;
|
|
24
|
-
|
|
25
|
+
private levelField;
|
|
26
|
+
constructor({ format, level, levelField, tags, varLevel, }?: LoggerOptions);
|
|
25
27
|
private createLogMethod;
|
|
26
28
|
tag(key: unknown, value?: unknown): void;
|
|
27
29
|
untag(key: unknown): void;
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -63,6 +63,224 @@ const DATADOG_TRANSPORT = {
|
|
|
63
63
|
MAX_BATCH_SIZE: 100,
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
+
//
|
|
67
|
+
// Key-based pipelines (match on var key name)
|
|
68
|
+
//
|
|
69
|
+
function isAxiosResponse(response) {
|
|
70
|
+
if (typeof response !== "object" || response === null) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
const r = response;
|
|
74
|
+
return !!(r &&
|
|
75
|
+
r.config &&
|
|
76
|
+
r.data &&
|
|
77
|
+
r.headers &&
|
|
78
|
+
r.request &&
|
|
79
|
+
r.status &&
|
|
80
|
+
r.statusText);
|
|
81
|
+
}
|
|
82
|
+
function filterAxiosResponse(response) {
|
|
83
|
+
if (!isAxiosResponse(response)) {
|
|
84
|
+
return response;
|
|
85
|
+
}
|
|
86
|
+
const r = response;
|
|
87
|
+
const newResponse = {
|
|
88
|
+
data: r.data,
|
|
89
|
+
headers: r.headers,
|
|
90
|
+
status: r.status,
|
|
91
|
+
statusText: r.statusText,
|
|
92
|
+
};
|
|
93
|
+
if (r.isAxiosError) {
|
|
94
|
+
newResponse.isAxiosError = r.isAxiosError;
|
|
95
|
+
}
|
|
96
|
+
return newResponse;
|
|
97
|
+
}
|
|
98
|
+
const axiosResponseVarPipeline = {
|
|
99
|
+
filter: filterAxiosResponse,
|
|
100
|
+
key: "response",
|
|
101
|
+
};
|
|
102
|
+
const pipelines = [axiosResponseVarPipeline];
|
|
103
|
+
// Fetch Response
|
|
104
|
+
function isFetchResponse(value) {
|
|
105
|
+
if (typeof value !== "object" || value === null) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
const r = value;
|
|
109
|
+
return !!(typeof r.ok === "boolean" &&
|
|
110
|
+
typeof r.status === "number" &&
|
|
111
|
+
typeof r.statusText === "string" &&
|
|
112
|
+
"headers" in r &&
|
|
113
|
+
"body" in r &&
|
|
114
|
+
typeof r.url === "string" &&
|
|
115
|
+
!("config" in r) &&
|
|
116
|
+
!("request" in r));
|
|
117
|
+
}
|
|
118
|
+
function headersToObject(headers) {
|
|
119
|
+
if (headers &&
|
|
120
|
+
typeof headers === "object" &&
|
|
121
|
+
typeof headers.entries === "function") {
|
|
122
|
+
const result = {};
|
|
123
|
+
for (const [key, value] of headers.entries()) {
|
|
124
|
+
result[key] = value;
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
return headers;
|
|
129
|
+
}
|
|
130
|
+
function filterFetchResponse(value) {
|
|
131
|
+
const r = value;
|
|
132
|
+
return {
|
|
133
|
+
headers: headersToObject(r.headers),
|
|
134
|
+
ok: r.ok,
|
|
135
|
+
redirected: r.redirected,
|
|
136
|
+
status: r.status,
|
|
137
|
+
statusText: r.statusText,
|
|
138
|
+
type: r.type,
|
|
139
|
+
url: r.url,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// Error
|
|
143
|
+
function isError(value) {
|
|
144
|
+
if (typeof value !== "object" || value === null) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
if (value instanceof Error) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
const i = value;
|
|
151
|
+
if (i.isProjectError) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
function filterError(value) {
|
|
157
|
+
const e = value;
|
|
158
|
+
const newItem = {
|
|
159
|
+
message: e.message,
|
|
160
|
+
name: e.name,
|
|
161
|
+
};
|
|
162
|
+
if (e.cause) {
|
|
163
|
+
newItem.cause = e.cause;
|
|
164
|
+
}
|
|
165
|
+
if (e.stack) {
|
|
166
|
+
newItem.stack = e.stack;
|
|
167
|
+
}
|
|
168
|
+
if (e.isProjectError) {
|
|
169
|
+
newItem.isProjectError = e.isProjectError;
|
|
170
|
+
newItem.title = e.title;
|
|
171
|
+
newItem.detail = e.detail;
|
|
172
|
+
newItem.status = e.status;
|
|
173
|
+
}
|
|
174
|
+
return newItem;
|
|
175
|
+
}
|
|
176
|
+
// Type filter registry (order matters — first match wins)
|
|
177
|
+
const typeFilters = [
|
|
178
|
+
{ detect: isFetchResponse, filter: filterFetchResponse },
|
|
179
|
+
{ detect: isError, filter: filterError },
|
|
180
|
+
];
|
|
181
|
+
//
|
|
182
|
+
// Opaque object detection and generic extraction
|
|
183
|
+
//
|
|
184
|
+
function isOpaqueObject(value) {
|
|
185
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
// Plain objects are fine
|
|
189
|
+
if (value.constructor === Object || value.constructor === undefined) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
// If JSON.stringify produces "{}" the object has no own enumerable properties
|
|
193
|
+
// and will log as useless "[object Type]"
|
|
194
|
+
try {
|
|
195
|
+
const json = JSON.stringify(value);
|
|
196
|
+
return json === "{}" || json === "[]";
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function extractOpaqueObject(value) {
|
|
203
|
+
const obj = value;
|
|
204
|
+
const result = {};
|
|
205
|
+
const ctorName = obj.constructor?.name;
|
|
206
|
+
if (ctorName && ctorName !== "Object") {
|
|
207
|
+
result._type = ctorName;
|
|
208
|
+
}
|
|
209
|
+
// If the object itself is map-like (Headers, URLSearchParams, FormData, etc.),
|
|
210
|
+
// convert its entries directly
|
|
211
|
+
const mapLike = obj;
|
|
212
|
+
if (typeof mapLike.entries === "function" &&
|
|
213
|
+
typeof mapLike.forEach === "function") {
|
|
214
|
+
try {
|
|
215
|
+
const entries = Object.fromEntries(mapLike.entries());
|
|
216
|
+
return { ...result, ...entries };
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
// Fall through to generic extraction
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Collect readable non-function properties from the prototype chain
|
|
223
|
+
let proto = obj;
|
|
224
|
+
while (proto && proto !== Object.prototype) {
|
|
225
|
+
for (const key of Object.getOwnPropertyNames(proto)) {
|
|
226
|
+
if (key === "constructor" || key in result) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
const desc = Object.getOwnPropertyDescriptor(proto, key);
|
|
231
|
+
if (!desc)
|
|
232
|
+
continue;
|
|
233
|
+
// Read getters and value properties from the original object
|
|
234
|
+
const val = obj[key];
|
|
235
|
+
if (typeof val === "function" || typeof val === "symbol") {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
// Skip streams and other non-serializable objects
|
|
239
|
+
if (val &&
|
|
240
|
+
typeof val === "object" &&
|
|
241
|
+
typeof val.pipe === "function") {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
// Convert iterable map-like objects (Headers, URLSearchParams, etc.)
|
|
245
|
+
if (val &&
|
|
246
|
+
typeof val === "object" &&
|
|
247
|
+
typeof val.entries === "function" &&
|
|
248
|
+
typeof val.forEach === "function") {
|
|
249
|
+
result[key] = Object.fromEntries(val.entries());
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
result[key] = val;
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// Property threw on access — skip
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
proto = Object.getPrototypeOf(proto);
|
|
259
|
+
}
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
//
|
|
263
|
+
// Public API
|
|
264
|
+
//
|
|
265
|
+
/**
|
|
266
|
+
* Filter a value by type, regardless of var key name.
|
|
267
|
+
* Tries known type filters first, then falls back to generic
|
|
268
|
+
* opaque object extraction for anything that would log as [object Type].
|
|
269
|
+
*/
|
|
270
|
+
function filterByType(value) {
|
|
271
|
+
// Try known type filters
|
|
272
|
+
for (const tf of typeFilters) {
|
|
273
|
+
if (tf.detect(value)) {
|
|
274
|
+
return tf.filter(value);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Generic fallback for opaque objects
|
|
278
|
+
if (isOpaqueObject(value)) {
|
|
279
|
+
return extractOpaqueObject(value);
|
|
280
|
+
}
|
|
281
|
+
return value;
|
|
282
|
+
}
|
|
283
|
+
|
|
66
284
|
//
|
|
67
285
|
//
|
|
68
286
|
// Helper
|
|
@@ -407,11 +625,30 @@ function parsesTo(message) {
|
|
|
407
625
|
}
|
|
408
626
|
}
|
|
409
627
|
|
|
628
|
+
function resolveLevelField(value) {
|
|
629
|
+
if (value === undefined) {
|
|
630
|
+
const env = process.env.LOG_LEVEL_FIELD;
|
|
631
|
+
if (env === undefined || env === "")
|
|
632
|
+
return false;
|
|
633
|
+
if (env === "false" || env === "0" || env === "no")
|
|
634
|
+
return false;
|
|
635
|
+
if (env === "true" || env === "1" || env === "yes")
|
|
636
|
+
return "level";
|
|
637
|
+
return env;
|
|
638
|
+
}
|
|
639
|
+
if (value === false)
|
|
640
|
+
return false;
|
|
641
|
+
if (value === true)
|
|
642
|
+
return "level";
|
|
643
|
+
return value;
|
|
644
|
+
}
|
|
410
645
|
class Logger {
|
|
411
|
-
constructor({ format = process.env.LOG_FORMAT || DEFAULT.LEVEL, level = process.env.LOG_LEVEL || DEFAULT.LEVEL, tags = {}, varLevel = process.env.LOG_VAR_LEVEL || DEFAULT.VAR_LEVEL, } = {}) {
|
|
646
|
+
constructor({ format = process.env.LOG_FORMAT || DEFAULT.LEVEL, level = process.env.LOG_LEVEL || DEFAULT.LEVEL, levelField, tags = {}, varLevel = process.env.LOG_VAR_LEVEL || DEFAULT.VAR_LEVEL, } = {}) {
|
|
647
|
+
this.levelField = resolveLevelField(levelField);
|
|
412
648
|
this.options = {
|
|
413
649
|
format,
|
|
414
650
|
level,
|
|
651
|
+
levelField: this.levelField || undefined,
|
|
415
652
|
varLevel,
|
|
416
653
|
};
|
|
417
654
|
this.tags = {};
|
|
@@ -441,6 +678,9 @@ class Logger {
|
|
|
441
678
|
if (parses.parses) {
|
|
442
679
|
json.data = parses.message;
|
|
443
680
|
}
|
|
681
|
+
if (this.levelField) {
|
|
682
|
+
json[this.levelField] = logLevel;
|
|
683
|
+
}
|
|
444
684
|
out(json, { level: logLevel });
|
|
445
685
|
}
|
|
446
686
|
else {
|
|
@@ -479,7 +719,13 @@ class Logger {
|
|
|
479
719
|
}
|
|
480
720
|
if (format === FORMAT.JSON) {
|
|
481
721
|
const messageKey = keys[0];
|
|
482
|
-
|
|
722
|
+
let messageVal = msgObj[messageKey];
|
|
723
|
+
for (const pipeline of pipelines) {
|
|
724
|
+
if (messageKey === pipeline.key) {
|
|
725
|
+
messageVal = pipeline.filter(messageVal);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
messageVal = filterByType(messageVal);
|
|
483
729
|
const json = {
|
|
484
730
|
data: parse(messageVal),
|
|
485
731
|
dataType: typeof messageVal,
|
|
@@ -487,6 +733,9 @@ class Logger {
|
|
|
487
733
|
var: messageKey,
|
|
488
734
|
...this.tags,
|
|
489
735
|
};
|
|
736
|
+
if (this.levelField) {
|
|
737
|
+
json[this.levelField] = logLevel;
|
|
738
|
+
}
|
|
490
739
|
if (LEVEL_VALUES[logLevel] <= LEVEL_VALUES[checkLevel]) {
|
|
491
740
|
out(json, { level: logLevel });
|
|
492
741
|
}
|
|
@@ -598,81 +847,6 @@ function forceVar(key, value) {
|
|
|
598
847
|
}
|
|
599
848
|
}
|
|
600
849
|
|
|
601
|
-
function isAxiosResponse(response) {
|
|
602
|
-
if (typeof response !== "object" || response === null) {
|
|
603
|
-
return false;
|
|
604
|
-
}
|
|
605
|
-
const r = response;
|
|
606
|
-
return !!(r &&
|
|
607
|
-
r.config &&
|
|
608
|
-
r.data &&
|
|
609
|
-
r.headers &&
|
|
610
|
-
r.request &&
|
|
611
|
-
r.status &&
|
|
612
|
-
r.statusText);
|
|
613
|
-
}
|
|
614
|
-
function filterAxiosResponse(response) {
|
|
615
|
-
if (!isAxiosResponse(response)) {
|
|
616
|
-
return response;
|
|
617
|
-
}
|
|
618
|
-
const r = response;
|
|
619
|
-
const newResponse = {
|
|
620
|
-
data: r.data,
|
|
621
|
-
headers: r.headers,
|
|
622
|
-
status: r.status,
|
|
623
|
-
statusText: r.statusText,
|
|
624
|
-
};
|
|
625
|
-
if (r.isAxiosError) {
|
|
626
|
-
newResponse.isAxiosError = r.isAxiosError;
|
|
627
|
-
}
|
|
628
|
-
return newResponse;
|
|
629
|
-
}
|
|
630
|
-
const axiosResponseVarPipeline = {
|
|
631
|
-
filter: filterAxiosResponse,
|
|
632
|
-
key: "response",
|
|
633
|
-
};
|
|
634
|
-
function isError(item) {
|
|
635
|
-
if (typeof item !== "object" || item === null) {
|
|
636
|
-
return false;
|
|
637
|
-
}
|
|
638
|
-
if (item instanceof Error) {
|
|
639
|
-
return true;
|
|
640
|
-
}
|
|
641
|
-
const i = item;
|
|
642
|
-
if (i.isProjectError) {
|
|
643
|
-
return true;
|
|
644
|
-
}
|
|
645
|
-
return false;
|
|
646
|
-
}
|
|
647
|
-
function filterErrorVar(item) {
|
|
648
|
-
if (!isError(item)) {
|
|
649
|
-
return item;
|
|
650
|
-
}
|
|
651
|
-
const e = item;
|
|
652
|
-
const newItem = {
|
|
653
|
-
message: e.message,
|
|
654
|
-
name: e.name,
|
|
655
|
-
};
|
|
656
|
-
if (e.cause) {
|
|
657
|
-
newItem.cause = e.cause;
|
|
658
|
-
}
|
|
659
|
-
if (e.stack) {
|
|
660
|
-
newItem.stack = e.stack;
|
|
661
|
-
}
|
|
662
|
-
if (e.isProjectError) {
|
|
663
|
-
newItem.isProjectError = e.isProjectError;
|
|
664
|
-
newItem.title = e.title;
|
|
665
|
-
newItem.detail = e.detail;
|
|
666
|
-
newItem.status = e.status;
|
|
667
|
-
}
|
|
668
|
-
return newItem;
|
|
669
|
-
}
|
|
670
|
-
const errorVarPipeline = {
|
|
671
|
-
filter: filterErrorVar,
|
|
672
|
-
key: "error",
|
|
673
|
-
};
|
|
674
|
-
const pipelines = [axiosResponseVarPipeline, errorVarPipeline];
|
|
675
|
-
|
|
676
850
|
function keyValueToArray(keyValue) {
|
|
677
851
|
const key = Object.keys(keyValue)[0];
|
|
678
852
|
return [key, keyValue[key]];
|
|
@@ -684,6 +858,7 @@ function logVar(key, value) {
|
|
|
684
858
|
v = pipeline.filter(v);
|
|
685
859
|
}
|
|
686
860
|
}
|
|
861
|
+
v = filterByType(v);
|
|
687
862
|
return { [k]: v };
|
|
688
863
|
}
|
|
689
864
|
|