@mimik/sumologic-winston-logger 2.1.8 → 2.1.10
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 +24 -25
- package/README_Supplement.md +12 -13
- package/configuration/config.js +39 -42
- package/eslint.config.js +3 -1
- package/index.js +8 -8
- package/lib/awsKinesisTransport.js +6 -6
- package/lib/awsS3Transport.js +11 -13
- package/lib/common.js +9 -21
- package/lib/formatLib.js +23 -24
- package/lib/stackLib.js +3 -5
- package/lib/sumologicTransport.js +4 -3
- package/manual-test/eventsMock.js +0 -2
- package/manual-test/testManyLogs.js +1 -2
- package/package.json +22 -28
- package/test/logger.spec.js +423 -4
- package/test/loggerProd.spec.js +3 -4
- package/test/testEnv.js +3 -10
package/lib/common.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/* eslint-disable no-magic-numbers */
|
|
2
1
|
const ENV_DEV = ['development', 'dev'];
|
|
3
2
|
const ENV_LOCAL = 'local';
|
|
3
|
+
const DEBUG_LEVEL = 'debug';
|
|
4
4
|
|
|
5
5
|
const ALL_MODE = 'all'; // legacy support
|
|
6
6
|
const NONE_MODE = 'none';
|
|
@@ -9,25 +9,6 @@ const SUMOLOGIC = 'sumologic';
|
|
|
9
9
|
const AWS_KINESIS = 'awsKinesis';
|
|
10
10
|
const ALL_MODES = [AWS_S3, SUMOLOGIC, AWS_KINESIS, ALL_MODE, NONE_MODE];
|
|
11
11
|
|
|
12
|
-
const DEFAULT = {
|
|
13
|
-
ENV: ENV_LOCAL,
|
|
14
|
-
FILTER_FILE: null,
|
|
15
|
-
LEVEL: 'debug',
|
|
16
|
-
MODE: [NONE_MODE],
|
|
17
|
-
NO_STACK: 'yes',
|
|
18
|
-
|
|
19
|
-
EXIT_DELAY: 2000, // delay for flushing the transports and exiting, in millisecond
|
|
20
|
-
KINESIS_HTTP_OPTIONS_CONNECTION_TIMEOUT: 5000, // connection timeout for the http handler, in millisecond
|
|
21
|
-
KINESIS_HTTP_OPTIONS_SOCKET_TIMEOUT: 5000, // socket timeout for the http handler, in millisecond
|
|
22
|
-
KINESIS_MAX_EVENTS: 1000, // max number of events before sending to Kinesis
|
|
23
|
-
KINESIS_MAX_RETRIES: 4, // max retries to connect to Kinesis
|
|
24
|
-
KINESIS_MAX_SIZE: 5, // max size of the data before sending to Kinesis, in mByte
|
|
25
|
-
KINESIS_TIMEOUT: 1000, // max time before sending events to Kinesis, in millisecond
|
|
26
|
-
S3_MAX_EVENTS: 1000, // max number of events before sending to S3
|
|
27
|
-
S3_MAX_SIZE: 5, // max size of the data before sending to S3, in mByte
|
|
28
|
-
S3_TIMEOUT: 5, // max time before sending events to S3, in minute
|
|
29
|
-
};
|
|
30
|
-
|
|
31
12
|
const SPLAT = Symbol.for('splat');
|
|
32
13
|
const LEVEL = Symbol.for('level');
|
|
33
14
|
const MESSAGE = Symbol.for('message');
|
|
@@ -48,13 +29,17 @@ const OTHER = 'other';
|
|
|
48
29
|
|
|
49
30
|
const UNAUTHORIZED_ERROR = 401;
|
|
50
31
|
const NOT_FOUND_ERROR = 404;
|
|
32
|
+
const TEAPOT_ERROR = 418;
|
|
51
33
|
const SYSTEM_ERROR = 500;
|
|
52
34
|
|
|
35
|
+
const OK_RESPONSE = 200;
|
|
36
|
+
|
|
53
37
|
const START_TIMEOUT = 30000; // in millisecond
|
|
54
38
|
const FLUSH_TIMEOUT = 1000; // in millisecond
|
|
55
39
|
const OK_EXIT = 0;
|
|
56
40
|
|
|
57
41
|
const MEGA = 1048576; // 2^20 conversion to mega
|
|
42
|
+
const MILLI_MIN = 60000; // 1000*60 conversion to minute
|
|
58
43
|
|
|
59
44
|
export {
|
|
60
45
|
ALL_MODE,
|
|
@@ -62,7 +47,7 @@ export {
|
|
|
62
47
|
AWS_KINESIS,
|
|
63
48
|
AWS_S3,
|
|
64
49
|
CLIENTS,
|
|
65
|
-
|
|
50
|
+
DEBUG_LEVEL,
|
|
66
51
|
ENV_DEV,
|
|
67
52
|
ENV_LOCAL,
|
|
68
53
|
ERROR,
|
|
@@ -73,16 +58,19 @@ export {
|
|
|
73
58
|
LEVEL,
|
|
74
59
|
LOG,
|
|
75
60
|
MEGA,
|
|
61
|
+
MILLI_MIN,
|
|
76
62
|
MESSAGE,
|
|
77
63
|
NONE_MODE,
|
|
78
64
|
NOT_FOUND_ERROR,
|
|
79
65
|
OK_EXIT,
|
|
66
|
+
OK_RESPONSE,
|
|
80
67
|
OTHER,
|
|
81
68
|
PARTITION_KEY,
|
|
82
69
|
SPLAT,
|
|
83
70
|
START_TIMEOUT,
|
|
84
71
|
SUMOLOGIC,
|
|
85
72
|
SYSTEM_ERROR,
|
|
73
|
+
TEAPOT_ERROR,
|
|
86
74
|
UNAUTHORIZED_ERROR,
|
|
87
75
|
UNKNOWN_TYPE,
|
|
88
76
|
UNKNOWN_ID,
|
package/lib/formatLib.js
CHANGED
|
@@ -5,11 +5,7 @@ import {
|
|
|
5
5
|
MESSAGE,
|
|
6
6
|
SPLAT,
|
|
7
7
|
} from './common.js';
|
|
8
|
-
import forEach from 'lodash.foreach';
|
|
9
8
|
import { format } from 'winston';
|
|
10
|
-
import isNil from 'lodash.isnil';
|
|
11
|
-
import isObject from 'lodash.isobject';
|
|
12
|
-
import isString from 'lodash.isstring';
|
|
13
9
|
import { logs } from '@mimik/lib-filters';
|
|
14
10
|
import { parseStack } from './stackLib.js';
|
|
15
11
|
|
|
@@ -43,7 +39,7 @@ const correlationId = format((origInfo) => {
|
|
|
43
39
|
const info = origInfo;
|
|
44
40
|
const meta = info[SPLAT];
|
|
45
41
|
|
|
46
|
-
if (meta &&
|
|
42
|
+
if (meta && typeof meta[meta.length - INDEX_ADJUST] === 'string') {
|
|
47
43
|
const results = meta[meta.length - INDEX_ADJUST].split('/');
|
|
48
44
|
|
|
49
45
|
([info.correlationId, info.requestedAt] = results);
|
|
@@ -66,32 +62,35 @@ const filterMeta = format((origInfo, opts) => {
|
|
|
66
62
|
let target;
|
|
67
63
|
let index;
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
if (meta) {
|
|
66
|
+
for (let i = 0; i < meta.length; i += 1) {
|
|
67
|
+
if (typeof meta[i] === 'object' && meta[i] !== null) {
|
|
68
|
+
let item = meta[i];
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
item = origItem.toObject();
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
Object.keys(item).forEach((key) => {
|
|
70
|
+
// In order to avoid having to do it in the rest of the code for mongoose objects
|
|
79
71
|
try {
|
|
80
|
-
item
|
|
72
|
+
item = meta[i].toObject();
|
|
81
73
|
}
|
|
82
74
|
catch {
|
|
83
|
-
|
|
75
|
+
Object.keys(item).forEach((key) => {
|
|
76
|
+
try {
|
|
77
|
+
item[key] = item[key].toObject();
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// do nothing
|
|
81
|
+
}
|
|
82
|
+
});
|
|
84
83
|
}
|
|
85
|
-
|
|
84
|
+
// end of mongoose
|
|
85
|
+
target = logs(item, config);
|
|
86
|
+
index = i;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
86
89
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
index = i;
|
|
90
|
-
return false;
|
|
91
|
-
});
|
|
92
|
-
if (isNil(index)) return info;
|
|
90
|
+
}
|
|
91
|
+
if (index === undefined) return info;
|
|
93
92
|
meta[index] = target;
|
|
94
|
-
forEach(
|
|
93
|
+
Object.entries(target).forEach(([key, value]) => {
|
|
95
94
|
if (!isReserved(key)) {
|
|
96
95
|
info[key] = value;
|
|
97
96
|
}
|
package/lib/stackLib.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { basename } from 'node:path';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import reject from 'lodash.reject';
|
|
5
4
|
|
|
6
5
|
// Stack trace format :
|
|
7
6
|
// https://github.com/v8/v8/wiki/Stack%20Trace%20API
|
|
8
7
|
// these regexes are used to pull out the parts of the stack trace like method name, line number, etc.
|
|
9
8
|
const STACKREG = /at\s+(?<method>.*)\s+\((?<path>.*):(?<line>\d*):(?<position>\d*)\)/iu;
|
|
10
9
|
const STACKREG2 = /at\s+(?<method>)(?<path>.*):(?<line>\d*):(?<position>\d*)/iu;
|
|
11
|
-
const SECRET = 'a secret for creating the hash';
|
|
12
10
|
|
|
13
11
|
const POSITION = 4;
|
|
14
12
|
const LINE = 3;
|
|
@@ -29,13 +27,13 @@ const parseStack = (newError) => {
|
|
|
29
27
|
const stackList = newError.stack.split('\n').slice(STACK_SLICE);
|
|
30
28
|
// remove all lines that refer to this file.
|
|
31
29
|
// start the stack trace from the code that called this module.
|
|
32
|
-
const truncatedList =
|
|
30
|
+
const truncatedList = stackList.filter(line => !line.includes(filename) && !line.includes('winston') && !line.includes('logform') && !line.includes('formatLib'));
|
|
33
31
|
|
|
34
32
|
if (truncatedList.length === NO_LINE) return null;
|
|
35
33
|
const firstLine = truncatedList[FIRST_LINE];
|
|
36
34
|
const stackParts = STACKREG.exec(firstLine) || STACKREG2.exec(firstLine);
|
|
37
35
|
|
|
38
|
-
if (stackParts
|
|
36
|
+
if (!stackParts || stackParts.length !== ALL_STACK) return null;
|
|
39
37
|
const stackInfo = {
|
|
40
38
|
method: stackParts[METHOD],
|
|
41
39
|
path: stackParts[PATH],
|
|
@@ -44,7 +42,7 @@ const parseStack = (newError) => {
|
|
|
44
42
|
file: basename(stackParts[PATH]),
|
|
45
43
|
stack: `${SHIFT}${truncatedList.join('\n').trimStart()}`,
|
|
46
44
|
};
|
|
47
|
-
stackInfo.hash = createHash('sha256'
|
|
45
|
+
stackInfo.hash = createHash('sha256')
|
|
48
46
|
.update(stackInfo.stack)
|
|
49
47
|
.digest('hex');
|
|
50
48
|
// this is a hash of the stacktrace for easier searching for the stacktrace
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from './common.js';
|
|
13
13
|
import Transport from 'winston-transport';
|
|
14
14
|
import axios from 'axios';
|
|
15
|
+
import { inspect } from 'node:util';
|
|
15
16
|
import { setImmediate } from 'node:timers';
|
|
16
17
|
|
|
17
18
|
export default class Sumo extends Transport {
|
|
@@ -41,13 +42,13 @@ export default class Sumo extends Transport {
|
|
|
41
42
|
axios({
|
|
42
43
|
method: 'POST',
|
|
43
44
|
url: `${this.endpoint}${this.code}`,
|
|
44
|
-
data,
|
|
45
|
+
data: inspect(data, { depth: null, compact: false }),
|
|
45
46
|
})
|
|
46
|
-
.then(() => this.emit(LOG, { message: `
|
|
47
|
+
.then(() => this.emit(LOG, { message: `logs sent to ${SUMOLOGIC}` }))
|
|
47
48
|
.catch((err) => {
|
|
48
49
|
const { response } = err;
|
|
49
50
|
|
|
50
|
-
const resp = { endpoint: this.endpoint, info, message: `
|
|
51
|
+
const resp = { endpoint: this.endpoint, info, message: `could not log to ${SUMOLOGIC}` };
|
|
51
52
|
|
|
52
53
|
if (info && info[SPLAT] && Array.isArray(info[SPLAT])) [, resp.correlationId] = info[SPLAT];
|
|
53
54
|
if (!response) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import bodyParser from 'body-parser';
|
|
3
2
|
import express from 'express';
|
|
4
3
|
|
|
5
4
|
let i = 0;
|
|
@@ -12,7 +11,6 @@ const config = {
|
|
|
12
11
|
base: '/checkthat',
|
|
13
12
|
};
|
|
14
13
|
|
|
15
|
-
app.use(bodyParser.json());
|
|
16
14
|
app.post(`${config.base}`, (req, res) => {
|
|
17
15
|
i += 1;
|
|
18
16
|
console.log('Recieved a POST:', i);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import '../test/testEnv.js';
|
|
3
|
-
import Promise from 'bluebird';
|
|
4
3
|
import { getCorrelationId } from '@mimik/request-helper';
|
|
5
4
|
import logger from '../index.js';
|
|
6
5
|
|
|
@@ -35,7 +34,7 @@ for (let i = 0; i < MAX_ITEMS; i += 1) {
|
|
|
35
34
|
const startDate = new Date();
|
|
36
35
|
|
|
37
36
|
console.log('Test start at:', startDate.toISOString(), 'with:', MAX_ITEMS, 'items');
|
|
38
|
-
Promise.map(
|
|
37
|
+
Promise.all(objects.map(obj => logger.info('This is a test', { data: obj }, getCorrelationId('test-correlation-id')))).then(() => {
|
|
39
38
|
const endDate = new Date();
|
|
40
39
|
console.log('Test end at:', endDate.toISOString(), 'duration:', endDate - startDate, 'with:', MAX_ITEMS, 'items');
|
|
41
40
|
});
|
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mimik/sumologic-winston-logger",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.10",
|
|
4
4
|
"description": "Log wrapper for sumo, s3, kinesis and winston",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=24.0.0"
|
|
9
|
+
},
|
|
7
10
|
"scripts": {
|
|
8
11
|
"lint": "eslint . --no-error-on-unmatched-pattern",
|
|
9
12
|
"docs": "jsdoc2md configuration/config.js > README.md && cat README_Supplement.md >> README.md",
|
|
10
|
-
"test": "mocha --reporter mochawesome --bail --check-leaks test/
|
|
11
|
-
"test-ci": "c8 --reporter=lcov --reporter=text npm test
|
|
13
|
+
"test": "mocha --reporter mochawesome --bail --exit --check-leaks --global serverType,serverId test/logger.spec.js test/loggerProd.spec.js",
|
|
14
|
+
"test-ci": "c8 --reporter=lcov --reporter=text npm test",
|
|
12
15
|
"prepublishOnly": "npm run docs && npm run lint && npm run test-ci",
|
|
13
16
|
"commit-ready": "npm run docs && npm run lint && npm run test-ci"
|
|
14
17
|
},
|
|
@@ -33,39 +36,30 @@
|
|
|
33
36
|
"url": "https://bitbucket.org/mimiktech/sumologic-winston-logger"
|
|
34
37
|
},
|
|
35
38
|
"dependencies": {
|
|
36
|
-
"@mimik/lib-filters": "^2.0.
|
|
37
|
-
"@aws-sdk/client-s3": "3.
|
|
38
|
-
"@aws-sdk/client-kinesis": "3.
|
|
39
|
-
"@smithy/node-http-handler": "4.
|
|
40
|
-
"axios": "1.
|
|
41
|
-
"
|
|
42
|
-
"lodash.difference": "4.5.0",
|
|
43
|
-
"lodash.foreach": "4.5.0",
|
|
44
|
-
"lodash.isnil": "4.0.0",
|
|
45
|
-
"lodash.isobject": "3.0.2",
|
|
46
|
-
"lodash.isstring": "4.0.1",
|
|
47
|
-
"lodash.isundefined": "3.0.1",
|
|
48
|
-
"lodash.reject": "4.6.0",
|
|
49
|
-
"lodash.split": "4.4.2",
|
|
50
|
-
"winston": "3.17.0",
|
|
39
|
+
"@mimik/lib-filters": "^2.0.5",
|
|
40
|
+
"@aws-sdk/client-s3": "3.990.0",
|
|
41
|
+
"@aws-sdk/client-kinesis": "3.990.0",
|
|
42
|
+
"@smithy/node-http-handler": "4.4.10",
|
|
43
|
+
"axios": "1.13.5",
|
|
44
|
+
"winston": "3.19.0",
|
|
51
45
|
"winston-transport": "4.9.0"
|
|
52
46
|
},
|
|
53
47
|
"devDependencies": {
|
|
54
|
-
"@eslint/js": "9.
|
|
48
|
+
"@eslint/js": "9.39.2",
|
|
55
49
|
"@mimik/eslint-plugin-document-env": "^2.0.8",
|
|
56
50
|
"@mimik/request-helper": "^2.0.2",
|
|
57
|
-
"@stylistic/eslint-plugin": "5.
|
|
58
|
-
"
|
|
51
|
+
"@stylistic/eslint-plugin": "5.8.0",
|
|
52
|
+
"aws-sdk-client-mock": "4.1.0",
|
|
59
53
|
"c8": "10.1.3",
|
|
60
|
-
"chai": "6.
|
|
61
|
-
"eslint": "9.
|
|
54
|
+
"chai": "6.2.2",
|
|
55
|
+
"eslint": "9.39.2",
|
|
62
56
|
"eslint-plugin-import": "2.32.0",
|
|
63
|
-
"express": "5.1
|
|
57
|
+
"express": "5.2.1",
|
|
58
|
+
"globals": "17.3.0",
|
|
64
59
|
"husky": "9.1.7",
|
|
65
|
-
"jsdoc-to-markdown": "9.1.
|
|
66
|
-
"mocha": "11.7.
|
|
60
|
+
"jsdoc-to-markdown": "9.1.3",
|
|
61
|
+
"mocha": "11.7.5",
|
|
67
62
|
"mochawesome": "7.1.4",
|
|
68
|
-
"sinon": "21.0.
|
|
69
|
-
"supertest": "7.1.4"
|
|
63
|
+
"sinon": "21.0.1"
|
|
70
64
|
}
|
|
71
65
|
}
|