@mhmdhammoud/meritt-utils 1.5.7 → 1.5.9
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.
|
@@ -94,7 +94,7 @@ describe('route and format logs', () => {
|
|
|
94
94
|
key0: 'val0',
|
|
95
95
|
key1: 'val1',
|
|
96
96
|
};
|
|
97
|
-
test('log info with structured context (single object
|
|
97
|
+
test('log info with structured context (single object in context field)', () => {
|
|
98
98
|
//@ts-ignore
|
|
99
99
|
jest.spyOn(pino_1.pino, 'destination').mockReturnValue(PINO_DESTINATION);
|
|
100
100
|
//@ts-ignore
|
|
@@ -105,11 +105,10 @@ describe('route and format logs', () => {
|
|
|
105
105
|
component: LOGGER_NAME,
|
|
106
106
|
code: LOG_EVENT.code,
|
|
107
107
|
msg: LOG_EVENT.msg,
|
|
108
|
-
key0: 'val0',
|
|
109
|
-
key1: 'val1',
|
|
108
|
+
context: { key0: 'val0', key1: 'val1' },
|
|
110
109
|
}));
|
|
111
110
|
});
|
|
112
|
-
test('remap reserved elastic field names
|
|
111
|
+
test('remap reserved elastic field names in context', () => {
|
|
113
112
|
//@ts-ignore
|
|
114
113
|
jest.spyOn(pino_1.pino, 'destination').mockReturnValue(PINO_DESTINATION);
|
|
115
114
|
//@ts-ignore
|
|
@@ -122,11 +121,11 @@ describe('route and format logs', () => {
|
|
|
122
121
|
_index: 'bad-index',
|
|
123
122
|
},
|
|
124
123
|
});
|
|
124
|
+
// Context holds sanitized structure; reserved names remapped recursively
|
|
125
125
|
expect(PINO.info).toHaveBeenCalledWith(expect.objectContaining({
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
mongo_id: 'nested-1',
|
|
129
|
-
es_index: 'bad-index',
|
|
126
|
+
context: expect.objectContaining({
|
|
127
|
+
mongo_id: 'abc123',
|
|
128
|
+
nested: { mongo_id: 'nested-1', es_index: 'bad-index' },
|
|
130
129
|
}),
|
|
131
130
|
}));
|
|
132
131
|
expect(PINO.info).not.toHaveBeenCalledWith(expect.objectContaining({
|
package/dist/lib/logger.js
CHANGED
|
@@ -381,20 +381,18 @@ class Logger {
|
|
|
381
381
|
if (trace) {
|
|
382
382
|
ecs.trace_id = trace.traceId;
|
|
383
383
|
}
|
|
384
|
-
// Structured context:
|
|
385
|
-
//
|
|
384
|
+
// Structured context: put in single 'context' field to avoid ES mapping conflicts.
|
|
385
|
+
// Flattening to top-level caused document_parsing_exception (object vs scalar type mismatches).
|
|
386
|
+
// Nesting in context keeps structure consistent and avoids per-field mapping conflicts.
|
|
387
|
+
let context;
|
|
386
388
|
let detail;
|
|
387
389
|
if (args.length === 1 &&
|
|
388
390
|
isPlainObject(args[0]) &&
|
|
389
391
|
Object.keys(args[0]).length > 0) {
|
|
390
|
-
|
|
391
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
392
|
-
const key = toSafeElasticFieldName(k);
|
|
393
|
-
ecs[key] = sanitizeForElastic(v);
|
|
394
|
-
}
|
|
392
|
+
context = sanitizeForElastic(args[0]);
|
|
395
393
|
}
|
|
396
394
|
else {
|
|
397
|
-
detail = isLocal ? args : JSON.stringify(args);
|
|
395
|
+
detail = isLocal ? args : JSON.stringify(sanitizeForElastic(args));
|
|
398
396
|
}
|
|
399
397
|
// Legacy fields for backward compatibility (component, code, msg)
|
|
400
398
|
const base = {
|
|
@@ -403,6 +401,9 @@ class Logger {
|
|
|
403
401
|
code: event.code,
|
|
404
402
|
msg: event.msg,
|
|
405
403
|
};
|
|
404
|
+
if (context !== undefined) {
|
|
405
|
+
base.context = context;
|
|
406
|
+
}
|
|
406
407
|
if (detail !== undefined) {
|
|
407
408
|
base.detail = detail;
|
|
408
409
|
}
|
package/package.json
CHANGED
|
@@ -70,7 +70,7 @@ describe('route and format logs', () => {
|
|
|
70
70
|
key0: 'val0',
|
|
71
71
|
key1: 'val1',
|
|
72
72
|
}
|
|
73
|
-
test('log info with structured context (single object
|
|
73
|
+
test('log info with structured context (single object in context field)', () => {
|
|
74
74
|
//@ts-ignore
|
|
75
75
|
jest.spyOn(pino, 'destination').mockReturnValue(PINO_DESTINATION)
|
|
76
76
|
//@ts-ignore
|
|
@@ -84,13 +84,12 @@ describe('route and format logs', () => {
|
|
|
84
84
|
component: LOGGER_NAME,
|
|
85
85
|
code: LOG_EVENT.code,
|
|
86
86
|
msg: LOG_EVENT.msg,
|
|
87
|
-
key0: 'val0',
|
|
88
|
-
key1: 'val1',
|
|
87
|
+
context: { key0: 'val0', key1: 'val1' },
|
|
89
88
|
})
|
|
90
89
|
)
|
|
91
90
|
})
|
|
92
91
|
|
|
93
|
-
test('remap reserved elastic field names
|
|
92
|
+
test('remap reserved elastic field names in context', () => {
|
|
94
93
|
//@ts-ignore
|
|
95
94
|
jest.spyOn(pino, 'destination').mockReturnValue(PINO_DESTINATION)
|
|
96
95
|
//@ts-ignore
|
|
@@ -105,12 +104,12 @@ describe('route and format logs', () => {
|
|
|
105
104
|
},
|
|
106
105
|
})
|
|
107
106
|
|
|
107
|
+
// Context holds sanitized structure; reserved names remapped recursively
|
|
108
108
|
expect(PINO.info).toHaveBeenCalledWith(
|
|
109
109
|
expect.objectContaining({
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
mongo_id: 'nested-1',
|
|
113
|
-
es_index: 'bad-index',
|
|
110
|
+
context: expect.objectContaining({
|
|
111
|
+
mongo_id: 'abc123',
|
|
112
|
+
nested: { mongo_id: 'nested-1', es_index: 'bad-index' },
|
|
114
113
|
}),
|
|
115
114
|
})
|
|
116
115
|
)
|
package/src/lib/logger.ts
CHANGED
|
@@ -461,21 +461,19 @@ class Logger {
|
|
|
461
461
|
ecs.trace_id = trace.traceId
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
-
// Structured context:
|
|
465
|
-
//
|
|
464
|
+
// Structured context: put in single 'context' field to avoid ES mapping conflicts.
|
|
465
|
+
// Flattening to top-level caused document_parsing_exception (object vs scalar type mismatches).
|
|
466
|
+
// Nesting in context keeps structure consistent and avoids per-field mapping conflicts.
|
|
467
|
+
let context: Record<string, unknown> | undefined
|
|
466
468
|
let detail: unknown
|
|
467
469
|
if (
|
|
468
470
|
args.length === 1 &&
|
|
469
471
|
isPlainObject(args[0]) &&
|
|
470
472
|
Object.keys(args[0]).length > 0
|
|
471
473
|
) {
|
|
472
|
-
|
|
473
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
474
|
-
const key = toSafeElasticFieldName(k)
|
|
475
|
-
ecs[key] = sanitizeForElastic(v)
|
|
476
|
-
}
|
|
474
|
+
context = sanitizeForElastic(args[0]) as Record<string, unknown>
|
|
477
475
|
} else {
|
|
478
|
-
detail = isLocal ? args : JSON.stringify(args)
|
|
476
|
+
detail = isLocal ? args : JSON.stringify(sanitizeForElastic(args))
|
|
479
477
|
}
|
|
480
478
|
|
|
481
479
|
// Legacy fields for backward compatibility (component, code, msg)
|
|
@@ -485,6 +483,9 @@ class Logger {
|
|
|
485
483
|
code: event.code,
|
|
486
484
|
msg: event.msg,
|
|
487
485
|
}
|
|
486
|
+
if (context !== undefined) {
|
|
487
|
+
base.context = context
|
|
488
|
+
}
|
|
488
489
|
if (detail !== undefined) {
|
|
489
490
|
base.detail = detail
|
|
490
491
|
}
|