@jaypie/logger 1.2.11 → 1.2.13
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/JaypieLogger.d.ts +7 -0
- package/dist/cjs/index.cjs +330 -86
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/pipelines.d.ts +7 -1
- package/dist/esm/JaypieLogger.d.ts +7 -0
- package/dist/esm/index.js +330 -86
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/pipelines.d.ts +7 -1
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -59,6 +59,224 @@ const DATADOG_TRANSPORT = {
|
|
|
59
59
|
MAX_BATCH_SIZE: 100,
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
+
//
|
|
63
|
+
// Key-based pipelines (match on var key name)
|
|
64
|
+
//
|
|
65
|
+
function isAxiosResponse(response) {
|
|
66
|
+
if (typeof response !== "object" || response === null) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const r = response;
|
|
70
|
+
return !!(r &&
|
|
71
|
+
r.config &&
|
|
72
|
+
r.data &&
|
|
73
|
+
r.headers &&
|
|
74
|
+
r.request &&
|
|
75
|
+
r.status &&
|
|
76
|
+
r.statusText);
|
|
77
|
+
}
|
|
78
|
+
function filterAxiosResponse(response) {
|
|
79
|
+
if (!isAxiosResponse(response)) {
|
|
80
|
+
return response;
|
|
81
|
+
}
|
|
82
|
+
const r = response;
|
|
83
|
+
const newResponse = {
|
|
84
|
+
data: r.data,
|
|
85
|
+
headers: r.headers,
|
|
86
|
+
status: r.status,
|
|
87
|
+
statusText: r.statusText,
|
|
88
|
+
};
|
|
89
|
+
if (r.isAxiosError) {
|
|
90
|
+
newResponse.isAxiosError = r.isAxiosError;
|
|
91
|
+
}
|
|
92
|
+
return newResponse;
|
|
93
|
+
}
|
|
94
|
+
const axiosResponseVarPipeline = {
|
|
95
|
+
filter: filterAxiosResponse,
|
|
96
|
+
key: "response",
|
|
97
|
+
};
|
|
98
|
+
const pipelines = [axiosResponseVarPipeline];
|
|
99
|
+
// Fetch Response
|
|
100
|
+
function isFetchResponse(value) {
|
|
101
|
+
if (typeof value !== "object" || value === null) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const r = value;
|
|
105
|
+
return !!(typeof r.ok === "boolean" &&
|
|
106
|
+
typeof r.status === "number" &&
|
|
107
|
+
typeof r.statusText === "string" &&
|
|
108
|
+
"headers" in r &&
|
|
109
|
+
"body" in r &&
|
|
110
|
+
typeof r.url === "string" &&
|
|
111
|
+
!("config" in r) &&
|
|
112
|
+
!("request" in r));
|
|
113
|
+
}
|
|
114
|
+
function headersToObject(headers) {
|
|
115
|
+
if (headers &&
|
|
116
|
+
typeof headers === "object" &&
|
|
117
|
+
typeof headers.entries === "function") {
|
|
118
|
+
const result = {};
|
|
119
|
+
for (const [key, value] of headers.entries()) {
|
|
120
|
+
result[key] = value;
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
return headers;
|
|
125
|
+
}
|
|
126
|
+
function filterFetchResponse(value) {
|
|
127
|
+
const r = value;
|
|
128
|
+
return {
|
|
129
|
+
headers: headersToObject(r.headers),
|
|
130
|
+
ok: r.ok,
|
|
131
|
+
redirected: r.redirected,
|
|
132
|
+
status: r.status,
|
|
133
|
+
statusText: r.statusText,
|
|
134
|
+
type: r.type,
|
|
135
|
+
url: r.url,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// Error
|
|
139
|
+
function isError(value) {
|
|
140
|
+
if (typeof value !== "object" || value === null) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
if (value instanceof Error) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
const i = value;
|
|
147
|
+
if (i.isProjectError) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
function filterError(value) {
|
|
153
|
+
const e = value;
|
|
154
|
+
const newItem = {
|
|
155
|
+
message: e.message,
|
|
156
|
+
name: e.name,
|
|
157
|
+
};
|
|
158
|
+
if (e.cause) {
|
|
159
|
+
newItem.cause = e.cause;
|
|
160
|
+
}
|
|
161
|
+
if (e.stack) {
|
|
162
|
+
newItem.stack = e.stack;
|
|
163
|
+
}
|
|
164
|
+
if (e.isProjectError) {
|
|
165
|
+
newItem.isProjectError = e.isProjectError;
|
|
166
|
+
newItem.title = e.title;
|
|
167
|
+
newItem.detail = e.detail;
|
|
168
|
+
newItem.status = e.status;
|
|
169
|
+
}
|
|
170
|
+
return newItem;
|
|
171
|
+
}
|
|
172
|
+
// Type filter registry (order matters — first match wins)
|
|
173
|
+
const typeFilters = [
|
|
174
|
+
{ detect: isFetchResponse, filter: filterFetchResponse },
|
|
175
|
+
{ detect: isError, filter: filterError },
|
|
176
|
+
];
|
|
177
|
+
//
|
|
178
|
+
// Opaque object detection and generic extraction
|
|
179
|
+
//
|
|
180
|
+
function isOpaqueObject(value) {
|
|
181
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
// Plain objects are fine
|
|
185
|
+
if (value.constructor === Object || value.constructor === undefined) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
// If JSON.stringify produces "{}" the object has no own enumerable properties
|
|
189
|
+
// and will log as useless "[object Type]"
|
|
190
|
+
try {
|
|
191
|
+
const json = JSON.stringify(value);
|
|
192
|
+
return json === "{}" || json === "[]";
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function extractOpaqueObject(value) {
|
|
199
|
+
const obj = value;
|
|
200
|
+
const result = {};
|
|
201
|
+
const ctorName = obj.constructor?.name;
|
|
202
|
+
if (ctorName && ctorName !== "Object") {
|
|
203
|
+
result._type = ctorName;
|
|
204
|
+
}
|
|
205
|
+
// If the object itself is map-like (Headers, URLSearchParams, FormData, etc.),
|
|
206
|
+
// convert its entries directly
|
|
207
|
+
const mapLike = obj;
|
|
208
|
+
if (typeof mapLike.entries === "function" &&
|
|
209
|
+
typeof mapLike.forEach === "function") {
|
|
210
|
+
try {
|
|
211
|
+
const entries = Object.fromEntries(mapLike.entries());
|
|
212
|
+
return { ...result, ...entries };
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// Fall through to generic extraction
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Collect readable non-function properties from the prototype chain
|
|
219
|
+
let proto = obj;
|
|
220
|
+
while (proto && proto !== Object.prototype) {
|
|
221
|
+
for (const key of Object.getOwnPropertyNames(proto)) {
|
|
222
|
+
if (key === "constructor" || key in result) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
const desc = Object.getOwnPropertyDescriptor(proto, key);
|
|
227
|
+
if (!desc)
|
|
228
|
+
continue;
|
|
229
|
+
// Read getters and value properties from the original object
|
|
230
|
+
const val = obj[key];
|
|
231
|
+
if (typeof val === "function" || typeof val === "symbol") {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
// Skip streams and other non-serializable objects
|
|
235
|
+
if (val &&
|
|
236
|
+
typeof val === "object" &&
|
|
237
|
+
typeof val.pipe === "function") {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
// Convert iterable map-like objects (Headers, URLSearchParams, etc.)
|
|
241
|
+
if (val &&
|
|
242
|
+
typeof val === "object" &&
|
|
243
|
+
typeof val.entries === "function" &&
|
|
244
|
+
typeof val.forEach === "function") {
|
|
245
|
+
result[key] = Object.fromEntries(val.entries());
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
result[key] = val;
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
// Property threw on access — skip
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
proto = Object.getPrototypeOf(proto);
|
|
255
|
+
}
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
//
|
|
259
|
+
// Public API
|
|
260
|
+
//
|
|
261
|
+
/**
|
|
262
|
+
* Filter a value by type, regardless of var key name.
|
|
263
|
+
* Tries known type filters first, then falls back to generic
|
|
264
|
+
* opaque object extraction for anything that would log as [object Type].
|
|
265
|
+
*/
|
|
266
|
+
function filterByType(value) {
|
|
267
|
+
// Try known type filters
|
|
268
|
+
for (const tf of typeFilters) {
|
|
269
|
+
if (tf.detect(value)) {
|
|
270
|
+
return tf.filter(value);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Generic fallback for opaque objects
|
|
274
|
+
if (isOpaqueObject(value)) {
|
|
275
|
+
return extractOpaqueObject(value);
|
|
276
|
+
}
|
|
277
|
+
return value;
|
|
278
|
+
}
|
|
279
|
+
|
|
62
280
|
//
|
|
63
281
|
//
|
|
64
282
|
// Helper
|
|
@@ -497,7 +715,13 @@ class Logger {
|
|
|
497
715
|
}
|
|
498
716
|
if (format === FORMAT.JSON) {
|
|
499
717
|
const messageKey = keys[0];
|
|
500
|
-
|
|
718
|
+
let messageVal = msgObj[messageKey];
|
|
719
|
+
for (const pipeline of pipelines) {
|
|
720
|
+
if (messageKey === pipeline.key) {
|
|
721
|
+
messageVal = pipeline.filter(messageVal);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
messageVal = filterByType(messageVal);
|
|
501
725
|
const json = {
|
|
502
726
|
data: parse(messageVal),
|
|
503
727
|
dataType: typeof messageVal,
|
|
@@ -619,81 +843,6 @@ function forceVar(key, value) {
|
|
|
619
843
|
}
|
|
620
844
|
}
|
|
621
845
|
|
|
622
|
-
function isAxiosResponse(response) {
|
|
623
|
-
if (typeof response !== "object" || response === null) {
|
|
624
|
-
return false;
|
|
625
|
-
}
|
|
626
|
-
const r = response;
|
|
627
|
-
return !!(r &&
|
|
628
|
-
r.config &&
|
|
629
|
-
r.data &&
|
|
630
|
-
r.headers &&
|
|
631
|
-
r.request &&
|
|
632
|
-
r.status &&
|
|
633
|
-
r.statusText);
|
|
634
|
-
}
|
|
635
|
-
function filterAxiosResponse(response) {
|
|
636
|
-
if (!isAxiosResponse(response)) {
|
|
637
|
-
return response;
|
|
638
|
-
}
|
|
639
|
-
const r = response;
|
|
640
|
-
const newResponse = {
|
|
641
|
-
data: r.data,
|
|
642
|
-
headers: r.headers,
|
|
643
|
-
status: r.status,
|
|
644
|
-
statusText: r.statusText,
|
|
645
|
-
};
|
|
646
|
-
if (r.isAxiosError) {
|
|
647
|
-
newResponse.isAxiosError = r.isAxiosError;
|
|
648
|
-
}
|
|
649
|
-
return newResponse;
|
|
650
|
-
}
|
|
651
|
-
const axiosResponseVarPipeline = {
|
|
652
|
-
filter: filterAxiosResponse,
|
|
653
|
-
key: "response",
|
|
654
|
-
};
|
|
655
|
-
function isError(item) {
|
|
656
|
-
if (typeof item !== "object" || item === null) {
|
|
657
|
-
return false;
|
|
658
|
-
}
|
|
659
|
-
if (item instanceof Error) {
|
|
660
|
-
return true;
|
|
661
|
-
}
|
|
662
|
-
const i = item;
|
|
663
|
-
if (i.isProjectError) {
|
|
664
|
-
return true;
|
|
665
|
-
}
|
|
666
|
-
return false;
|
|
667
|
-
}
|
|
668
|
-
function filterErrorVar(item) {
|
|
669
|
-
if (!isError(item)) {
|
|
670
|
-
return item;
|
|
671
|
-
}
|
|
672
|
-
const e = item;
|
|
673
|
-
const newItem = {
|
|
674
|
-
message: e.message,
|
|
675
|
-
name: e.name,
|
|
676
|
-
};
|
|
677
|
-
if (e.cause) {
|
|
678
|
-
newItem.cause = e.cause;
|
|
679
|
-
}
|
|
680
|
-
if (e.stack) {
|
|
681
|
-
newItem.stack = e.stack;
|
|
682
|
-
}
|
|
683
|
-
if (e.isProjectError) {
|
|
684
|
-
newItem.isProjectError = e.isProjectError;
|
|
685
|
-
newItem.title = e.title;
|
|
686
|
-
newItem.detail = e.detail;
|
|
687
|
-
newItem.status = e.status;
|
|
688
|
-
}
|
|
689
|
-
return newItem;
|
|
690
|
-
}
|
|
691
|
-
const errorVarPipeline = {
|
|
692
|
-
filter: filterErrorVar,
|
|
693
|
-
key: "error",
|
|
694
|
-
};
|
|
695
|
-
const pipelines = [axiosResponseVarPipeline, errorVarPipeline];
|
|
696
|
-
|
|
697
846
|
function keyValueToArray(keyValue) {
|
|
698
847
|
const key = Object.keys(keyValue)[0];
|
|
699
848
|
return [key, keyValue[key]];
|
|
@@ -705,6 +854,7 @@ function logVar(key, value) {
|
|
|
705
854
|
v = pipeline.filter(v);
|
|
706
855
|
}
|
|
707
856
|
}
|
|
857
|
+
v = filterByType(v);
|
|
708
858
|
return { [k]: v };
|
|
709
859
|
}
|
|
710
860
|
|
|
@@ -722,6 +872,10 @@ function envBoolean(key, { defaultValue }) {
|
|
|
722
872
|
}
|
|
723
873
|
class JaypieLogger {
|
|
724
874
|
constructor({ level = process.env.LOG_LEVEL, tags = {}, } = {}) {
|
|
875
|
+
this._errorCount = 0;
|
|
876
|
+
this._report = {};
|
|
877
|
+
this._sessionActive = false;
|
|
878
|
+
this._warnCount = 0;
|
|
725
879
|
this._params = { level, tags };
|
|
726
880
|
this._loggers = [];
|
|
727
881
|
this._tags = {};
|
|
@@ -736,16 +890,32 @@ class JaypieLogger {
|
|
|
736
890
|
this._loggers = [this._logger];
|
|
737
891
|
this.debug = ((...args) => this._logger.debug(...args));
|
|
738
892
|
this.debug.var = (messageObject, messageValue) => this._logger.debug.var(messageObject, messageValue);
|
|
739
|
-
this.error = ((...args) =>
|
|
740
|
-
|
|
893
|
+
this.error = ((...args) => {
|
|
894
|
+
if (this._sessionActive)
|
|
895
|
+
this._errorCount++;
|
|
896
|
+
this._logger.error(...args);
|
|
897
|
+
});
|
|
898
|
+
this.error.var = (messageObject, messageValue) => {
|
|
899
|
+
if (this._sessionActive)
|
|
900
|
+
this._errorCount++;
|
|
901
|
+
this._logger.error.var(messageObject, messageValue);
|
|
902
|
+
};
|
|
741
903
|
this.fatal = ((...args) => this._logger.fatal(...args));
|
|
742
904
|
this.fatal.var = (messageObject, messageValue) => this._logger.fatal.var(messageObject, messageValue);
|
|
743
905
|
this.info = ((...args) => this._logger.info(...args));
|
|
744
906
|
this.info.var = (messageObject, messageValue) => this._logger.info.var(messageObject, messageValue);
|
|
745
907
|
this.trace = ((...args) => this._logger.trace(...args));
|
|
746
908
|
this.trace.var = (messageObject, messageValue) => this._logger.trace.var(messageObject, messageValue);
|
|
747
|
-
this.warn = ((...args) =>
|
|
748
|
-
|
|
909
|
+
this.warn = ((...args) => {
|
|
910
|
+
if (this._sessionActive)
|
|
911
|
+
this._warnCount++;
|
|
912
|
+
this._logger.warn(...args);
|
|
913
|
+
});
|
|
914
|
+
this.warn.var = (messageObject, messageValue) => {
|
|
915
|
+
if (this._sessionActive)
|
|
916
|
+
this._warnCount++;
|
|
917
|
+
this._logger.warn.var(messageObject, messageValue);
|
|
918
|
+
};
|
|
749
919
|
this.var = (messageObject, messageValue) => this._logger.var(logVar(messageObject, messageValue));
|
|
750
920
|
}
|
|
751
921
|
init() {
|
|
@@ -766,6 +936,11 @@ class JaypieLogger {
|
|
|
766
936
|
});
|
|
767
937
|
this._loggers = [this._logger];
|
|
768
938
|
this._withLoggers = {};
|
|
939
|
+
// Reset session state
|
|
940
|
+
this._errorCount = 0;
|
|
941
|
+
this._report = {};
|
|
942
|
+
this._sessionActive = false;
|
|
943
|
+
this._warnCount = 0;
|
|
769
944
|
const levels = [
|
|
770
945
|
"debug",
|
|
771
946
|
"error",
|
|
@@ -775,12 +950,38 @@ class JaypieLogger {
|
|
|
775
950
|
"warn",
|
|
776
951
|
];
|
|
777
952
|
levels.forEach((lvl) => {
|
|
778
|
-
|
|
779
|
-
this.
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
953
|
+
if (lvl === "error") {
|
|
954
|
+
this.error = ((...args) => {
|
|
955
|
+
if (this._sessionActive)
|
|
956
|
+
this._errorCount++;
|
|
957
|
+
this._logger.error(...args);
|
|
958
|
+
});
|
|
959
|
+
this.error.var = (messageObject, messageValue) => {
|
|
960
|
+
if (this._sessionActive)
|
|
961
|
+
this._errorCount++;
|
|
962
|
+
this._logger.error.var(messageObject, messageValue);
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
else if (lvl === "warn") {
|
|
966
|
+
this.warn = ((...args) => {
|
|
967
|
+
if (this._sessionActive)
|
|
968
|
+
this._warnCount++;
|
|
969
|
+
this._logger.warn(...args);
|
|
970
|
+
});
|
|
971
|
+
this.warn.var = (messageObject, messageValue) => {
|
|
972
|
+
if (this._sessionActive)
|
|
973
|
+
this._warnCount++;
|
|
974
|
+
this._logger.warn.var(messageObject, messageValue);
|
|
975
|
+
};
|
|
976
|
+
}
|
|
977
|
+
else {
|
|
978
|
+
this[lvl] = ((...args) => {
|
|
979
|
+
this._logger[lvl](...args);
|
|
980
|
+
});
|
|
981
|
+
this[lvl].var = (messageObject, messageValue) => {
|
|
982
|
+
this._logger[lvl].var(messageObject, messageValue);
|
|
983
|
+
};
|
|
984
|
+
}
|
|
784
985
|
});
|
|
785
986
|
}
|
|
786
987
|
lib({ level, lib, tags = {}, } = {}) {
|
|
@@ -806,12 +1007,55 @@ class JaypieLogger {
|
|
|
806
1007
|
this._loggers.push(logger._logger);
|
|
807
1008
|
return logger;
|
|
808
1009
|
}
|
|
1010
|
+
report(data) {
|
|
1011
|
+
if (!this._sessionActive) {
|
|
1012
|
+
this.warn("[logger] report() called without active session");
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
for (const key of Object.keys(data)) {
|
|
1016
|
+
if (key in this._report) {
|
|
1017
|
+
this.warn(`[logger] Overwriting report key: ${key}`);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
Object.assign(this._report, data);
|
|
1021
|
+
}
|
|
1022
|
+
setup(tags) {
|
|
1023
|
+
if (this._sessionActive) {
|
|
1024
|
+
this.warn("[logger] setup() called while session already active");
|
|
1025
|
+
}
|
|
1026
|
+
this._errorCount = 0;
|
|
1027
|
+
this._report = {};
|
|
1028
|
+
this._sessionActive = true;
|
|
1029
|
+
this._warnCount = 0;
|
|
1030
|
+
if (tags) {
|
|
1031
|
+
this.tag(tags);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
809
1034
|
tag(tags) {
|
|
810
1035
|
for (const logger of this._loggers) {
|
|
811
1036
|
logger.tag(tags);
|
|
812
1037
|
}
|
|
813
1038
|
Object.assign(this._tags, tags);
|
|
814
1039
|
}
|
|
1040
|
+
teardown() {
|
|
1041
|
+
if (!this._sessionActive) {
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
const finalReport = {
|
|
1045
|
+
...this._report,
|
|
1046
|
+
log: {
|
|
1047
|
+
error: this._errorCount > 0,
|
|
1048
|
+
errors: this._errorCount,
|
|
1049
|
+
warn: this._warnCount > 0,
|
|
1050
|
+
warns: this._warnCount,
|
|
1051
|
+
},
|
|
1052
|
+
};
|
|
1053
|
+
this.info.var({ report: finalReport });
|
|
1054
|
+
this._errorCount = 0;
|
|
1055
|
+
this._report = {};
|
|
1056
|
+
this._sessionActive = false;
|
|
1057
|
+
this._warnCount = 0;
|
|
1058
|
+
}
|
|
815
1059
|
untag(key) {
|
|
816
1060
|
for (const logger of this._loggers) {
|
|
817
1061
|
logger.untag(key);
|