@abtnode/logger 1.15.17 → 1.16.0-beta-8ee536d7

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.
Files changed (3) hide show
  1. package/lib/logger.js +91 -24
  2. package/lib/util.js +40 -0
  3. 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} "${message}"`;
48
+ result = `${result} [${message}]`;
45
49
  }
46
50
 
47
- if (!isEmpty(metadata)) {
48
- if (metadata.error && metadata.error instanceof Error) {
49
- const { error } = metadata;
50
- metadata.error = error.message;
51
- metadata.error_stack = error.stack;
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} ${JSON.stringify(metadata)}`;
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
- ({ baseDirectory = process.env.ABT_NODE_LOG_DIR, filename = 'daemon', retain } = {}) => {
63
- if (!baseDirectory) {
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 = process.env.ABT_NODE_LOG_LEVEL || 'info';
79
- if (!fs.existsSync(baseDirectory)) {
80
- fs.mkdirSync(baseDirectory, { recursive: true });
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
- auditFile: `.${pathPrefix}-audit.json`,
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
- auditFile: `.${pathPrefix}-error-audit.json`,
100
- filename: `${pathPrefix}-error-%DATE%.log`,
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(baseDirectory, 'stderr.log'),
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(baseDirectory, 'stderr.log'),
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 = process.env.ABT_NODE_LOG_LEVEL || 'debug';
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: 60, ...options }));
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.15.17",
3
+ "version": "1.16.0-beta-8ee536d7",
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/abt-node#readme",
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/abt-node.git"
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/abt-node/issues"
34
+ "url": "https://github.com/ArcBlock/blocklet-server/issues"
35
35
  },
36
36
  "dependencies": {
37
- "debug": "^4.3.2",
38
- "fs-extra": "^10.0.0",
37
+ "@abtnode/constant": "1.16.0-beta-8ee536d7",
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
- "winston": "^3.3.3",
42
- "winston-daily-rotate-file": "^4.5.0"
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.17.1"
48
+ "express": "^4.18.2"
46
49
  },
47
- "gitHead": "22715c3ea74d0230f3413162a17f491614b6735a"
50
+ "gitHead": "57d0c45be311a5fbc1c0fffa2814b62c1a3ee34c"
48
51
  }