@abtnode/logger 1.15.17 → 1.16.0-beta-b16cb035
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/lib/logger.js +91 -24
- package/lib/util.js +40 -0
- package/package.json +13 -10
package/lib/logger.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
const fs = require('fs-extra');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const isEmpty = require('lodash.isempty');
|
|
4
|
+
const safeStringify = require('fast-safe-stringify').default;
|
|
4
5
|
const { createLogger, format, transports } = require('winston');
|
|
5
6
|
const debug = require('debug');
|
|
7
|
+
const rfs = require('rotating-file-stream');
|
|
6
8
|
require('winston-daily-rotate-file');
|
|
9
|
+
const { LOG_RETAIN_IN_DAYS } = require('@abtnode/constant');
|
|
7
10
|
const CustomRotateFileTransport = require('./transport');
|
|
11
|
+
const { getAccessLogFilenameGenerator } = require('./util');
|
|
8
12
|
|
|
9
13
|
const instanceMap = new Map();
|
|
10
14
|
|
|
@@ -34,24 +38,29 @@ const getNoopLogger = (label = '') => {
|
|
|
34
38
|
// singleton per process
|
|
35
39
|
let addedRejectionExceptionTransport = false;
|
|
36
40
|
|
|
37
|
-
const customPrintfCallback = ({ level, message, label, timestamp, metadata }) => {
|
|
38
|
-
let result = `[${timestamp}] [${level}]`;
|
|
41
|
+
const customPrintfCallback = ({ level, message, label, timestamp, metadata, [Symbol.for('splat')]: splat }) => {
|
|
42
|
+
let result = `[${process.pid}] [${timestamp}] [${level}]`;
|
|
39
43
|
if (label) {
|
|
40
44
|
result = `${result} [${label}]`;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
if (!isEmpty(message)) {
|
|
44
|
-
result = `${result}
|
|
48
|
+
result = `${result} [${message}]`;
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
let newMetaData = metadata;
|
|
52
|
+
if (isEmpty(newMetaData) && !isEmpty(splat)) {
|
|
53
|
+
newMetaData = { data: splat[0] };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!isEmpty(newMetaData)) {
|
|
57
|
+
if (newMetaData.error && newMetaData.error instanceof Error) {
|
|
58
|
+
const { error } = newMetaData;
|
|
59
|
+
newMetaData.error = error.message;
|
|
60
|
+
newMetaData.error_stack = error.stack;
|
|
52
61
|
}
|
|
53
62
|
|
|
54
|
-
result = `${result} ${
|
|
63
|
+
result = `${result} ${safeStringify(newMetaData)}`;
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
return result;
|
|
@@ -59,8 +68,13 @@ const customPrintfCallback = ({ level, message, label, timestamp, metadata }) =>
|
|
|
59
68
|
|
|
60
69
|
const initLogger =
|
|
61
70
|
(label = '') =>
|
|
62
|
-
({
|
|
63
|
-
|
|
71
|
+
({
|
|
72
|
+
logDir = process.env.ABT_NODE_LOG_DIR,
|
|
73
|
+
filename = 'daemon',
|
|
74
|
+
retain,
|
|
75
|
+
level = process.env.ABT_NODE_LOG_LEVEL,
|
|
76
|
+
} = {}) => {
|
|
77
|
+
if (!logDir) {
|
|
64
78
|
return getNoopLogger(label);
|
|
65
79
|
}
|
|
66
80
|
|
|
@@ -68,36 +82,41 @@ const initLogger =
|
|
|
68
82
|
format: format.combine(
|
|
69
83
|
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
|
|
70
84
|
format.label({ label }),
|
|
71
|
-
format.splat(),
|
|
72
85
|
format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }),
|
|
73
86
|
format.printf(customPrintfCallback)
|
|
74
87
|
),
|
|
75
88
|
});
|
|
76
89
|
|
|
77
90
|
if (process.env.NODE_ENV === 'production') {
|
|
78
|
-
logger.level =
|
|
79
|
-
if (!fs.existsSync(
|
|
80
|
-
fs.mkdirSync(
|
|
91
|
+
logger.level = level || 'info';
|
|
92
|
+
if (!fs.existsSync(logDir)) {
|
|
93
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
81
94
|
}
|
|
82
95
|
|
|
83
|
-
const pathPrefix = path.join(baseDirectory, filename);
|
|
84
96
|
const rotateConfig = {
|
|
85
97
|
datePattern: 'YYYY-MM-DD',
|
|
98
|
+
dirname: logDir,
|
|
86
99
|
zippedArchive: true,
|
|
100
|
+
createSymlink: true,
|
|
87
101
|
maxSize: '20m',
|
|
88
102
|
};
|
|
89
103
|
|
|
104
|
+
const infoAuditFilename = `.${filename}-info.audit.json`;
|
|
105
|
+
const errorAuditFilename = `.${filename}-error.audit.json`;
|
|
106
|
+
|
|
90
107
|
const infoRotateFileParams = {
|
|
91
108
|
...rotateConfig,
|
|
92
|
-
|
|
93
|
-
filename: `${pathPrefix}-%DATE%.log`,
|
|
109
|
+
filename: `${filename}-%DATE%.log`,
|
|
94
110
|
ignoreLevels: ['error'],
|
|
111
|
+
symlinkName: `${filename}.log`,
|
|
112
|
+
auditFile: path.join(logDir, infoAuditFilename),
|
|
95
113
|
};
|
|
96
114
|
|
|
97
115
|
const errorRotateFileParams = {
|
|
98
116
|
...rotateConfig,
|
|
99
|
-
|
|
100
|
-
|
|
117
|
+
filename: `${filename}-error-%DATE%.log`,
|
|
118
|
+
symlinkName: `${filename}-error.log`,
|
|
119
|
+
auditFile: path.join(logDir, errorAuditFilename),
|
|
101
120
|
level: 'error',
|
|
102
121
|
};
|
|
103
122
|
|
|
@@ -112,20 +131,20 @@ const initLogger =
|
|
|
112
131
|
if (!addedRejectionExceptionTransport) {
|
|
113
132
|
logger.rejections.handle(
|
|
114
133
|
new transports.File({
|
|
115
|
-
filename: path.join(
|
|
134
|
+
filename: path.join(logDir, 'stderr.log'),
|
|
116
135
|
})
|
|
117
136
|
);
|
|
118
137
|
|
|
119
138
|
logger.exceptions.handle(
|
|
120
139
|
new transports.File({
|
|
121
|
-
filename: path.join(
|
|
140
|
+
filename: path.join(logDir, 'stderr.log'),
|
|
122
141
|
})
|
|
123
142
|
);
|
|
124
143
|
|
|
125
144
|
addedRejectionExceptionTransport = true;
|
|
126
145
|
}
|
|
127
146
|
} else {
|
|
128
|
-
logger.level =
|
|
147
|
+
logger.level = level || 'debug';
|
|
129
148
|
const transport = new transports.Console();
|
|
130
149
|
|
|
131
150
|
logger.add(transport);
|
|
@@ -142,11 +161,59 @@ const initLogger =
|
|
|
142
161
|
|
|
143
162
|
const getLogger = (label = '', options = {}) => {
|
|
144
163
|
if (!instanceMap.has(label)) {
|
|
145
|
-
instanceMap.set(label, initLogger(label)({ retain:
|
|
164
|
+
instanceMap.set(label, initLogger(label)({ retain: LOG_RETAIN_IN_DAYS, ...options }));
|
|
146
165
|
}
|
|
147
166
|
|
|
148
167
|
return instanceMap.get(label);
|
|
149
168
|
};
|
|
150
169
|
|
|
170
|
+
const deleteOldLogfiles = (file, retain) => {
|
|
171
|
+
if (typeof retain !== 'number') {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (file === '/dev/null') {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const extname = path.extname(file);
|
|
180
|
+
const fileBaseName = `${path.basename(file, extname)}`;
|
|
181
|
+
const dirName = path.dirname(file);
|
|
182
|
+
const files = fs.readdirSync(dirName);
|
|
183
|
+
let i;
|
|
184
|
+
let len;
|
|
185
|
+
const rotatedFiles = [];
|
|
186
|
+
for (i = 0, len = files.length; i < len; i++) {
|
|
187
|
+
if (files[i].startsWith(`${fileBaseName}-`)) {
|
|
188
|
+
rotatedFiles.push(files[i]);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
rotatedFiles.sort().reverse();
|
|
193
|
+
|
|
194
|
+
for (i = rotatedFiles.length - 1; i >= retain; i--) {
|
|
195
|
+
fs.unlinkSync(path.resolve(dirName, rotatedFiles[i]));
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const getAccessLogStream = (dir, filename = 'access.log') => {
|
|
200
|
+
const stream = rfs.createStream(getAccessLogFilenameGenerator(filename), {
|
|
201
|
+
interval: '1d',
|
|
202
|
+
path: dir,
|
|
203
|
+
compress: 'gzip',
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
stream.on('rotated', () => {
|
|
207
|
+
deleteOldLogfiles(path.join(dir, filename), LOG_RETAIN_IN_DAYS);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
return stream;
|
|
211
|
+
};
|
|
212
|
+
|
|
151
213
|
module.exports = getLogger;
|
|
152
214
|
module.exports.initLogger = initLogger;
|
|
215
|
+
module.exports.getNoopLogger = getNoopLogger;
|
|
216
|
+
module.exports.customPrintfCallback = customPrintfCallback;
|
|
217
|
+
module.exports.getInstanceSize = () => instanceMap.size;
|
|
218
|
+
module.exports.getAccessLogStream = getAccessLogStream;
|
|
219
|
+
module.exports.deleteOldLogfiles = deleteOldLogfiles;
|
package/lib/util.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
const getPreDate = (date) => {
|
|
4
|
+
date.setDate(date.getDate() - 1);
|
|
5
|
+
|
|
6
|
+
const year = date.getFullYear().toString();
|
|
7
|
+
const month = (date.getMonth() + 1).toString().padStart(2, 0);
|
|
8
|
+
const day = date.getDate().toString().padStart(2, 0);
|
|
9
|
+
|
|
10
|
+
return { year, month, day };
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const getAccessLogFilenameGenerator = (filename) => (time, index) => {
|
|
14
|
+
let tempFilename = filename || 'access.log';
|
|
15
|
+
|
|
16
|
+
if (path.extname(tempFilename) !== '.log') {
|
|
17
|
+
tempFilename = `${tempFilename}.log`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!time) {
|
|
21
|
+
return tempFilename;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { year, month, day } = getPreDate(time);
|
|
25
|
+
|
|
26
|
+
const nameWithoutExtension = path.basename(tempFilename, '.log');
|
|
27
|
+
|
|
28
|
+
let finalName = `${nameWithoutExtension}-${year}-${month}-${day}`;
|
|
29
|
+
|
|
30
|
+
if (index > 1) {
|
|
31
|
+
finalName = `${finalName}-${index}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return `${finalName}.log.gz`;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
getPreDate,
|
|
39
|
+
getAccessLogFilenameGenerator,
|
|
40
|
+
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abtnode/logger",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0-beta-b16cb035",
|
|
4
4
|
"description": "ABT Node logger lib",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"logger",
|
|
7
7
|
"lib"
|
|
8
8
|
],
|
|
9
9
|
"author": "polunzh <polunzh@gmail.com>",
|
|
10
|
-
"homepage": "https://github.com/ArcBlock/
|
|
10
|
+
"homepage": "https://github.com/ArcBlock/blocklet-server#readme",
|
|
11
11
|
"license": "Apache-2.0",
|
|
12
12
|
"main": "lib/logger.js",
|
|
13
13
|
"publishConfig": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "git+https://github.com/ArcBlock/
|
|
25
|
+
"url": "git+https://github.com/ArcBlock/blocklet-server.git"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"lint": "eslint tests lib",
|
|
@@ -31,18 +31,21 @@
|
|
|
31
31
|
"coverage": "npm run test -- --coverage"
|
|
32
32
|
},
|
|
33
33
|
"bugs": {
|
|
34
|
-
"url": "https://github.com/ArcBlock/
|
|
34
|
+
"url": "https://github.com/ArcBlock/blocklet-server/issues"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"
|
|
38
|
-
"
|
|
37
|
+
"@abtnode/constant": "1.16.0-beta-b16cb035",
|
|
38
|
+
"debug": "^4.3.4",
|
|
39
|
+
"fast-safe-stringify": "^2.1.1",
|
|
40
|
+
"fs-extra": "^10.1.0",
|
|
39
41
|
"lodash.isempty": "^4.4.0",
|
|
40
42
|
"rewire": "^5.0.0",
|
|
41
|
-
"
|
|
42
|
-
"winston
|
|
43
|
+
"rotating-file-stream": "^2.1.6",
|
|
44
|
+
"winston": "^3.8.2",
|
|
45
|
+
"winston-daily-rotate-file": "^4.7.1"
|
|
43
46
|
},
|
|
44
47
|
"devDependencies": {
|
|
45
|
-
"express": "^4.
|
|
48
|
+
"express": "^4.18.2"
|
|
46
49
|
},
|
|
47
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "138bd91aee5a35b28c2de4e1e924c44932efaf3a"
|
|
48
51
|
}
|