@pryv/boiler 1.2.3 → 1.2.4
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/LICENSE +1 -1
- package/examples/customLogger/src/index.js +14 -10
- package/package.json +1 -1
- package/src/config.js +56 -66
- package/src/index.js +3 -3
- package/src/logging.js +78 -75
package/LICENSE
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* [BSD-3-Clause](https://github.com/pryv/pryv-boiler/blob/master/LICENSE)
|
|
4
|
+
*/
|
|
1
5
|
|
|
2
|
-
module.exports = {
|
|
3
|
-
init,
|
|
6
|
+
module.exports = {
|
|
7
|
+
init,
|
|
4
8
|
log
|
|
5
|
-
}
|
|
9
|
+
};
|
|
6
10
|
|
|
7
|
-
async function init(settings) {
|
|
11
|
+
async function init (settings) {
|
|
8
12
|
console.log('CUSTOM LOGGER initilaized with', settings);
|
|
9
13
|
}
|
|
10
14
|
|
|
11
15
|
/**
|
|
12
|
-
*
|
|
16
|
+
*
|
|
13
17
|
* @param {string} level one of 'debug', 'info', 'warn', 'error'
|
|
14
18
|
* @param {string} key ':' namespaced keys
|
|
15
|
-
* @param {message} message
|
|
16
|
-
* @param {object} meta
|
|
19
|
+
* @param {message} message
|
|
20
|
+
* @param {object} meta
|
|
17
21
|
*/
|
|
18
|
-
function log(level, key, text, meta) {
|
|
19
|
-
console.log('Custom: ' + JSON.stringify({level, key, text, meta}));
|
|
20
|
-
}
|
|
22
|
+
function log (level, key, text, meta) {
|
|
23
|
+
console.log('Custom: ' + JSON.stringify({ level, key, text, meta }));
|
|
24
|
+
}
|
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -50,8 +50,6 @@ const defaults = {
|
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
53
|
/**
|
|
56
54
|
* Config manager
|
|
57
55
|
*/
|
|
@@ -62,7 +60,7 @@ class Config {
|
|
|
62
60
|
baseConfigDir;
|
|
63
61
|
learnDirectoryAndFilename;
|
|
64
62
|
|
|
65
|
-
constructor() {
|
|
63
|
+
constructor () {
|
|
66
64
|
this.extraAsync = [];
|
|
67
65
|
}
|
|
68
66
|
|
|
@@ -78,7 +76,7 @@ class Config {
|
|
|
78
76
|
* @param {Object} logging
|
|
79
77
|
* @returns {Config} this
|
|
80
78
|
*/
|
|
81
|
-
initSync(options, logging) {
|
|
79
|
+
initSync (options, logging) {
|
|
82
80
|
this.appName = options.appName;
|
|
83
81
|
this.learnDirectoryAndFilename = getLearnFilename(options.appName, options.learnDirectory);
|
|
84
82
|
this.baseFilesDir = options.baseFilesDir || process.cwd();
|
|
@@ -103,12 +101,12 @@ class Config {
|
|
|
103
101
|
// memory must come first for config.set() to work without loading config files
|
|
104
102
|
// 3. `process.env`
|
|
105
103
|
// 4. `process.argv`
|
|
106
|
-
store.argv({parseValues: true}).env({parseValues: true, separator: '__'});
|
|
104
|
+
store.argv({ parseValues: true }).env({ parseValues: true, separator: '__' });
|
|
107
105
|
|
|
108
106
|
// 5. Values in `${NODE_ENV}-config.yml` or from --config parameter
|
|
109
107
|
let configFile;
|
|
110
108
|
if (store.get('config')) {
|
|
111
|
-
configFile = store.get('config')
|
|
109
|
+
configFile = store.get('config');
|
|
112
110
|
} else if (store.get('NODE_ENV')) {
|
|
113
111
|
configFile = path.resolve(baseConfigDir, store.get('NODE_ENV') + '-config.yml');
|
|
114
112
|
}
|
|
@@ -122,7 +120,7 @@ class Config {
|
|
|
122
120
|
|
|
123
121
|
// load extra config files & plugins
|
|
124
122
|
if (options.extras) {
|
|
125
|
-
for (
|
|
123
|
+
for (const extra of options.extras) {
|
|
126
124
|
if (extra.file) {
|
|
127
125
|
loadFile(extra.scope, extra.file);
|
|
128
126
|
continue;
|
|
@@ -133,7 +131,7 @@ class Config {
|
|
|
133
131
|
continue;
|
|
134
132
|
}
|
|
135
133
|
if (extra.data) {
|
|
136
|
-
const conf = extra.key ? {[extra.key]: extra.data} : extra.data;
|
|
134
|
+
const conf = extra.key ? { [extra.key]: extra.data } : extra.data;
|
|
137
135
|
store.use(extra.scope, { type: 'literal', store: conf });
|
|
138
136
|
logger.debug('Loaded [' + extra.scope + '] from DATA: ' + (extra.key ? ' under [' + extra.key + ']' : ''));
|
|
139
137
|
continue;
|
|
@@ -141,7 +139,7 @@ class Config {
|
|
|
141
139
|
if (extra.url || extra.urlFromKey || extra.fileAsync) {
|
|
142
140
|
// register scope in the chain to keep order of configs
|
|
143
141
|
store.use(extra.scope, { type: 'literal', store: {} });
|
|
144
|
-
logger.debug('Booked [' + extra.scope +'] for async Loading ');
|
|
142
|
+
logger.debug('Booked [' + extra.scope + '] for async Loading ');
|
|
145
143
|
this.extraAsync.push(extra);
|
|
146
144
|
continue;
|
|
147
145
|
}
|
|
@@ -154,7 +152,6 @@ class Config {
|
|
|
154
152
|
}
|
|
155
153
|
}
|
|
156
154
|
|
|
157
|
-
|
|
158
155
|
// .end-1 load default and custom config from configs/default-config.json
|
|
159
156
|
loadFile('default-file', path.resolve(baseConfigDir, 'default-config.yml'));
|
|
160
157
|
|
|
@@ -167,36 +164,34 @@ class Config {
|
|
|
167
164
|
|
|
168
165
|
// --- helpers --/
|
|
169
166
|
|
|
170
|
-
function loadFile(scope, filePath) {
|
|
171
|
-
|
|
167
|
+
function loadFile (scope, filePath) {
|
|
172
168
|
if (fs.existsSync(filePath)) {
|
|
173
|
-
|
|
174
|
-
if (filePath.endsWith('.js')) { // JS file
|
|
169
|
+
if (filePath.endsWith('.js')) { // JS file
|
|
175
170
|
const conf = require(filePath);
|
|
176
171
|
store.use(scope, { type: 'literal', store: conf });
|
|
177
|
-
} else {
|
|
178
|
-
const options = { file: filePath }
|
|
179
|
-
if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) { options.format = nconf.formats.yaml }
|
|
172
|
+
} else { // JSON or YAML
|
|
173
|
+
const options = { file: filePath };
|
|
174
|
+
if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) { options.format = nconf.formats.yaml; }
|
|
180
175
|
store.file(scope, options);
|
|
181
176
|
}
|
|
182
177
|
|
|
183
|
-
logger.debug('Loaded [' + scope + '] from file: ' + filePath)
|
|
178
|
+
logger.debug('Loaded [' + scope + '] from file: ' + filePath);
|
|
184
179
|
} else {
|
|
185
180
|
logger.debug('Cannot find file: ' + filePath + ' for scope [' + scope + ']');
|
|
186
181
|
}
|
|
187
182
|
}
|
|
188
183
|
}
|
|
189
184
|
|
|
190
|
-
async initASync() {
|
|
185
|
+
async initASync () {
|
|
191
186
|
const store = this.store;
|
|
192
187
|
const logger = this.logger;
|
|
193
188
|
const baseConfigDir = this.baseConfigDir;
|
|
194
189
|
const baseFilesDir = this.baseFilesDir;
|
|
195
190
|
|
|
196
|
-
async function loadUrl(scope, key, url) {
|
|
191
|
+
async function loadUrl (scope, key, url) {
|
|
197
192
|
if (typeof url === 'undefined' || url === null) {
|
|
198
|
-
|
|
199
|
-
|
|
193
|
+
logger.warn('Null or Undefined Url for [' + scope + ']');
|
|
194
|
+
return;
|
|
200
195
|
}
|
|
201
196
|
|
|
202
197
|
let res = null;
|
|
@@ -205,13 +200,13 @@ class Config {
|
|
|
205
200
|
} else {
|
|
206
201
|
res = await loadFromUrl(url);
|
|
207
202
|
}
|
|
208
|
-
const conf = key ? {[key]: res} : res;
|
|
203
|
+
const conf = key ? { [key]: res } : res;
|
|
209
204
|
store.add(scope, { type: 'literal', store: conf });
|
|
210
205
|
logger.debug('Loaded [' + scope + '] from URL: ' + url + (key ? ' under [' + key + ']' : ''));
|
|
211
206
|
}
|
|
212
207
|
|
|
213
208
|
// load remote config files
|
|
214
|
-
for (
|
|
209
|
+
for (const extra of this.extraAsync) {
|
|
215
210
|
if (extra.url) {
|
|
216
211
|
await loadUrl(extra.scope, extra.key, extra.url);
|
|
217
212
|
continue;
|
|
@@ -231,11 +226,11 @@ class Config {
|
|
|
231
226
|
if (extra.fileAsync) {
|
|
232
227
|
const filePath = path.resolve(baseConfigDir, extra.fileAsync);
|
|
233
228
|
|
|
234
|
-
if (!
|
|
229
|
+
if (!fs.existsSync(filePath)) {
|
|
235
230
|
logger.warn('Cannot find file: ' + filePath + ' for scope [' + extra.scope + ']');
|
|
236
231
|
continue;
|
|
237
232
|
}
|
|
238
|
-
if (!
|
|
233
|
+
if (!filePath.endsWith('.js')) {
|
|
239
234
|
logger.warn('Cannot only load .js file: ' + filePath + ' for scope [' + extra.scope + ']');
|
|
240
235
|
continue;
|
|
241
236
|
}
|
|
@@ -257,8 +252,8 @@ class Config {
|
|
|
257
252
|
* @param {string} key
|
|
258
253
|
* @returns {boolean}
|
|
259
254
|
*/
|
|
260
|
-
has(key) {
|
|
261
|
-
if (!
|
|
255
|
+
has (key) {
|
|
256
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
262
257
|
const value = this.store.get(key);
|
|
263
258
|
return (typeof value !== 'undefined');
|
|
264
259
|
}
|
|
@@ -267,10 +262,10 @@ class Config {
|
|
|
267
262
|
* Retreive value
|
|
268
263
|
* @param {string} [key] if no key is provided all the config is returned
|
|
269
264
|
*/
|
|
270
|
-
get(key) {
|
|
271
|
-
if (!
|
|
265
|
+
get (key) {
|
|
266
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
272
267
|
const value = this.store.get(key);
|
|
273
|
-
if (typeof value === 'undefined') this.logger.debug('get: [' + key +'] is undefined');
|
|
268
|
+
if (typeof value === 'undefined') this.logger.debug('get: [' + key + '] is undefined');
|
|
274
269
|
learn(this.learnDirectoryAndFilename, key);
|
|
275
270
|
return value;
|
|
276
271
|
}
|
|
@@ -279,20 +274,20 @@ class Config {
|
|
|
279
274
|
* Retreive value and store info that applies
|
|
280
275
|
* @param {string} key
|
|
281
276
|
*/
|
|
282
|
-
getScopeAndValue(key) {
|
|
283
|
-
if (!
|
|
284
|
-
for (
|
|
277
|
+
getScopeAndValue (key) {
|
|
278
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
279
|
+
for (const scopeName of Object.keys(this.store.stores)) {
|
|
285
280
|
const store = this.store.stores[scopeName];
|
|
286
281
|
const value = store.get(key);
|
|
287
282
|
if (typeof value !== 'undefined') {
|
|
288
283
|
const res = {
|
|
289
|
-
value
|
|
284
|
+
value,
|
|
290
285
|
scope: scopeName
|
|
291
|
-
}
|
|
286
|
+
};
|
|
292
287
|
if (store.type === 'file') {
|
|
293
|
-
res.info = 'From file: ' + store.file
|
|
288
|
+
res.info = 'From file: ' + store.file;
|
|
294
289
|
} else {
|
|
295
|
-
info = 'Type: ' + store.type
|
|
290
|
+
info = 'Type: ' + store.type;
|
|
296
291
|
}
|
|
297
292
|
return res;
|
|
298
293
|
}
|
|
@@ -305,8 +300,8 @@ class Config {
|
|
|
305
300
|
* @param {string} key
|
|
306
301
|
* @param {Object} value
|
|
307
302
|
*/
|
|
308
|
-
set(key, value) {
|
|
309
|
-
if (!
|
|
303
|
+
set (key, value) {
|
|
304
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
310
305
|
this.store.set(key, value);
|
|
311
306
|
}
|
|
312
307
|
|
|
@@ -314,7 +309,7 @@ class Config {
|
|
|
314
309
|
* Inject Test Config and override any other option
|
|
315
310
|
* @param {Object} configObject;
|
|
316
311
|
*/
|
|
317
|
-
injectTestConfig(configObject) {
|
|
312
|
+
injectTestConfig (configObject) {
|
|
318
313
|
this.replaceScopeConfig('test', configObject);
|
|
319
314
|
}
|
|
320
315
|
|
|
@@ -323,12 +318,11 @@ class Config {
|
|
|
323
318
|
* @param {string} scope;
|
|
324
319
|
* @param {Object} configObject;
|
|
325
320
|
*/
|
|
326
|
-
replaceScopeConfig(scope, configObject) {
|
|
327
|
-
if (!
|
|
328
|
-
this.logger.debug('Replace ['+ scope + '] with: ', configObject);
|
|
329
|
-
this.store.add(scope, {type: 'literal', store: configObject});
|
|
321
|
+
replaceScopeConfig (scope, configObject) {
|
|
322
|
+
if (!this.store) { throw (new Error('Config not yet initialized')); }
|
|
323
|
+
this.logger.debug('Replace [' + scope + '] with: ', configObject);
|
|
324
|
+
this.store.add(scope, { type: 'literal', store: configObject });
|
|
330
325
|
}
|
|
331
|
-
|
|
332
326
|
}
|
|
333
327
|
|
|
334
328
|
module.exports = Config;
|
|
@@ -338,12 +332,12 @@ module.exports = Config;
|
|
|
338
332
|
const FILE_PROTOCOL = 'file://';
|
|
339
333
|
const FILE_PROTOCOL_LENGTH = FILE_PROTOCOL.length;
|
|
340
334
|
|
|
341
|
-
async function loadFromUrl(url) {
|
|
335
|
+
async function loadFromUrl (url) {
|
|
342
336
|
const res = await superagent.get(url);
|
|
343
337
|
return res.body;
|
|
344
338
|
}
|
|
345
339
|
|
|
346
|
-
function loadFromFile(fileUrl, baseFilesDir) {
|
|
340
|
+
function loadFromFile (fileUrl, baseFilesDir) {
|
|
347
341
|
const filePath = stripFileProtocol(fileUrl);
|
|
348
342
|
|
|
349
343
|
if (isRelativePath(filePath)) {
|
|
@@ -358,69 +352,65 @@ function loadFromFile(fileUrl, baseFilesDir) {
|
|
|
358
352
|
return res;
|
|
359
353
|
}
|
|
360
354
|
|
|
361
|
-
|
|
362
|
-
function isFileUrl(filePath) {
|
|
355
|
+
function isFileUrl (filePath) {
|
|
363
356
|
return filePath.startsWith(FILE_PROTOCOL);
|
|
364
357
|
}
|
|
365
358
|
|
|
366
|
-
function isRelativePath(filePath) {
|
|
359
|
+
function isRelativePath (filePath) {
|
|
367
360
|
return !path.isAbsolute(filePath);
|
|
368
361
|
}
|
|
369
362
|
|
|
370
|
-
function stripFileProtocol(filePath) {
|
|
363
|
+
function stripFileProtocol (filePath) {
|
|
371
364
|
return filePath.substring(FILE_PROTOCOL_LENGTH);
|
|
372
365
|
}
|
|
373
366
|
|
|
374
|
-
|
|
375
367
|
// -------- learning mode ------- //
|
|
376
368
|
|
|
377
|
-
function getLearnFilename(appName, learnDirectory) {
|
|
378
|
-
if (!
|
|
369
|
+
function getLearnFilename (appName, learnDirectory) {
|
|
370
|
+
if (!learnDirectory) return;
|
|
379
371
|
let i = 0;
|
|
380
372
|
let res;
|
|
381
373
|
do {
|
|
382
|
-
res = path.join(learnDirectory, appName + i
|
|
374
|
+
res = path.join(learnDirectory, appName + i);
|
|
383
375
|
i++;
|
|
384
|
-
} while(fs.existsSync(res + '-config.json'));
|
|
376
|
+
} while (fs.existsSync(res + '-config.json'));
|
|
385
377
|
return res;
|
|
386
378
|
}
|
|
387
379
|
|
|
388
|
-
function learn(learnDirectoryAndFilename, key) {
|
|
380
|
+
function learn (learnDirectoryAndFilename, key) {
|
|
389
381
|
if (learnDirectoryAndFilename) {
|
|
390
382
|
const caller_line = (new Error()).stack.split('\n')[3]; // get callee name and line
|
|
391
|
-
const index = caller_line.indexOf(
|
|
392
|
-
const str = key + ';' + caller_line.slice(index+3, caller_line.length) + '\n';
|
|
383
|
+
const index = caller_line.indexOf('at ');
|
|
384
|
+
const str = key + ';' + caller_line.slice(index + 3, caller_line.length) + '\n';
|
|
393
385
|
fs.appendFileSync(learnDirectoryAndFilename + '-calls.csv', str);
|
|
394
386
|
}
|
|
395
387
|
}
|
|
396
388
|
|
|
397
|
-
function saveConfig(learnDirectoryAndFilename, store) {
|
|
389
|
+
function saveConfig (learnDirectoryAndFilename, store) {
|
|
398
390
|
if (learnDirectoryAndFilename) {
|
|
399
391
|
const filename = learnDirectoryAndFilename + '-config.json';
|
|
400
|
-
fs.writeFileSync(filename, JSON.stringify({stores: store.stores, config: store.get()}, null, 2));
|
|
392
|
+
fs.writeFileSync(filename, JSON.stringify({ stores: store.stores, config: store.get() }, null, 2));
|
|
401
393
|
}
|
|
402
394
|
}
|
|
403
395
|
|
|
404
|
-
|
|
405
396
|
/**
|
|
406
397
|
* @typedef ConfigFile
|
|
407
398
|
* @property {string} scope - scope for nconf hierachical load
|
|
408
399
|
* @property {string} file - the config file (.yml, .json, .js)
|
|
409
400
|
*/
|
|
410
401
|
|
|
411
|
-
|
|
402
|
+
/**
|
|
412
403
|
* @typedef ConfigPlugin
|
|
413
404
|
* @property {Object} plugin
|
|
414
405
|
* @property {Function} plugin.load - a function that takes the "nconf store" as argument and returns the "name" of the plugin
|
|
415
406
|
*/
|
|
416
407
|
|
|
417
|
-
|
|
408
|
+
/**
|
|
418
409
|
* @typedef ConfigData
|
|
419
410
|
* @property {string} scope - scope for nconf hierachical load
|
|
420
411
|
* @property {string} [key] - (optional) key to load result of url. If null loaded at root of the config
|
|
421
412
|
* @property {object} data - the data to load
|
|
422
413
|
|
|
423
|
-
|
|
424
414
|
/**
|
|
425
415
|
* @typedef ConfigRemoteURL
|
|
426
416
|
* @property {string} scope - scope for nconf hierachical load
|
package/src/index.js
CHANGED
|
@@ -25,14 +25,14 @@ const boiler = {
|
|
|
25
25
|
* Prefered way to get the configuration
|
|
26
26
|
* @returns {Promise<Config>}
|
|
27
27
|
*/
|
|
28
|
-
getConfig
|
|
28
|
+
getConfig,
|
|
29
29
|
/**
|
|
30
30
|
* get the configuration.
|
|
31
31
|
* If the configuration is not fully initialized throw an error
|
|
32
32
|
* @param {boolean} warnOnly - Only warns about potential misuse of config
|
|
33
33
|
* @returns {Config}
|
|
34
34
|
*/
|
|
35
|
-
getConfigUnsafe
|
|
35
|
+
getConfigUnsafe,
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Init Boiler, should be called just once when starting an APP
|
|
@@ -42,7 +42,7 @@ const boiler = {
|
|
|
42
42
|
* @param {Array<ConfigFile|ConfigRemoteURL|ConfigRemoteURLFromKey|ConfigPlugin>} [options.extraConfigs] - (optional) and array of extra files to load
|
|
43
43
|
* @param {Function} [fullyLoadedCallback] - (optional) called when the config is fully loaded
|
|
44
44
|
*/
|
|
45
|
-
init
|
|
45
|
+
init
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
let logger;
|
package/src/logging.js
CHANGED
|
@@ -13,17 +13,17 @@ let customLoggerInstance = null;
|
|
|
13
13
|
// ------ winston formating
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
* @param {Object} options
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} options
|
|
18
18
|
* @param {boolean} options.color - set to true to have colors
|
|
19
19
|
* @param {boolean} options.time - set to true to for timestamp
|
|
20
20
|
* @param {boolean} options.align - set to true to allign logs items
|
|
21
21
|
*/
|
|
22
|
-
function generateFormat(options) {
|
|
22
|
+
function generateFormat (options) {
|
|
23
23
|
const formats = [];
|
|
24
24
|
if (options.color) {
|
|
25
25
|
formats.push(winston.format.colorize());
|
|
26
|
-
}
|
|
26
|
+
}
|
|
27
27
|
if (options.time) {
|
|
28
28
|
formats.push(winston.format.timestamp());
|
|
29
29
|
}
|
|
@@ -31,13 +31,13 @@ function generateFormat(options) {
|
|
|
31
31
|
formats.push(winston.format.align());
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function printf(info) {
|
|
34
|
+
function printf (info) {
|
|
35
35
|
const {
|
|
36
36
|
timestamp, level, message, ...args
|
|
37
37
|
} = info;
|
|
38
|
-
|
|
39
|
-
let items = info[Symbol.for('splat')] ||
|
|
40
|
-
|
|
38
|
+
|
|
39
|
+
let items = info[Symbol.for('splat')] || {};
|
|
40
|
+
|
|
41
41
|
let itemStr = '';
|
|
42
42
|
if (items.length > 0) {
|
|
43
43
|
let skip = false;
|
|
@@ -45,17 +45,14 @@ function generateFormat(options) {
|
|
|
45
45
|
if (typeof items[0] === 'undefined') {
|
|
46
46
|
skip = true;
|
|
47
47
|
} else {
|
|
48
|
-
if (items[0] && items[0].context) {
|
|
48
|
+
if (items[0] && items[0].context) {
|
|
49
49
|
items = items[0].context;
|
|
50
|
-
}
|
|
50
|
+
}
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
if (!
|
|
54
|
-
itemStr = util.inspect(items, {depth: 10, colors: true});
|
|
53
|
+
if (!skip) { itemStr = util.inspect(items, { depth: 10, colors: true }); }
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
56
|
const line = `[${level}]: ${message} ${itemStr}`;
|
|
60
57
|
|
|
61
58
|
if (options.time) {
|
|
@@ -69,12 +66,10 @@ function generateFormat(options) {
|
|
|
69
66
|
return winston.format.combine(...formats);
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
|
|
73
|
-
|
|
74
69
|
/**
|
|
75
70
|
* Helper to pass log instructions to winston
|
|
76
71
|
*/
|
|
77
|
-
function globalLog(level, key, message, context) {
|
|
72
|
+
function globalLog (level, key, message, context) {
|
|
78
73
|
const text = `[${key}] ${message}`;
|
|
79
74
|
if (winstonInstance) {
|
|
80
75
|
winstonInstance[level](text, context);
|
|
@@ -86,56 +81,60 @@ function globalLog(level, key, message, context) {
|
|
|
86
81
|
}
|
|
87
82
|
}
|
|
88
83
|
|
|
89
|
-
|
|
90
84
|
/**
|
|
91
85
|
* Config initialize Logger right after beeing loaded
|
|
92
86
|
* This is done by config Only
|
|
93
|
-
*/
|
|
94
|
-
async function initLoggerWithConfig(config) {
|
|
87
|
+
*/
|
|
88
|
+
async function initLoggerWithConfig (config) {
|
|
95
89
|
if (winstonInstance) {
|
|
96
|
-
throw new Error(
|
|
90
|
+
throw new Error('Logger was already initialized');
|
|
97
91
|
}
|
|
98
92
|
// console
|
|
99
93
|
winstonInstance = winston.createLogger({ });
|
|
100
94
|
const logConsole = config.get('logs:console');
|
|
101
|
-
let isSilent = !
|
|
95
|
+
let isSilent = !config.get('logs:console:active');
|
|
102
96
|
|
|
103
97
|
// LOGS env var can override settings
|
|
104
98
|
if (process.env.LOGS) {
|
|
105
99
|
logConsole.level = process.env.LOGS;
|
|
106
100
|
isSilent = false;
|
|
107
|
-
}
|
|
108
|
-
|
|
101
|
+
}
|
|
109
102
|
|
|
110
|
-
const
|
|
111
|
-
const myconsole = new winston.transports.Console({ format:
|
|
103
|
+
const consoleFormat = generateFormat(logConsole.format);
|
|
104
|
+
const myconsole = new winston.transports.Console({ format: consoleFormat, level: logConsole.level, silent: isSilent });
|
|
112
105
|
winstonInstance.add(myconsole);
|
|
113
|
-
|
|
114
|
-
rootLogger.debug((isSilent ?
|
|
106
|
+
|
|
107
|
+
rootLogger.debug((isSilent ? '** silent ** ' : '') + 'Console with level: ', logConsole.level);
|
|
115
108
|
|
|
116
109
|
// file
|
|
117
110
|
const logFile = config.get('logs:file');
|
|
118
111
|
if (config.get('logs:file:active')) {
|
|
112
|
+
const fileFormat = winston.format.combine(
|
|
113
|
+
winston.format.timestamp(),
|
|
114
|
+
winston.format.json()
|
|
115
|
+
);
|
|
116
|
+
|
|
119
117
|
rootLogger.debug('File active: ' + logFile.path);
|
|
120
118
|
if (logFile.rotation.isActive) {
|
|
121
|
-
const
|
|
119
|
+
const rotatedFiles = new winston.transports.DailyRotateFile({
|
|
122
120
|
filename: logFile.path + '.%DATE%',
|
|
123
121
|
datePattern: 'YYYY-MM-DD',
|
|
124
122
|
zippedArchive: true,
|
|
123
|
+
level: logFile.level,
|
|
125
124
|
maxFiles: logFile.rotation.days ? logFile.rotation.days + 'd' : null,
|
|
125
|
+
format: fileFormat
|
|
126
126
|
});
|
|
127
|
+
winstonInstance.add(rotatedFiles);
|
|
127
128
|
} else {
|
|
128
|
-
const files = new winston.transports.File({
|
|
129
|
+
const files = new winston.transports.File({
|
|
129
130
|
filename: logFile.path,
|
|
130
131
|
level: logFile.level,
|
|
131
|
-
|
|
132
|
-
maxFiles: logFile.maxNbFiles,
|
|
133
|
-
|
|
134
|
-
json: false
|
|
132
|
+
maxSize: logFile.maxFileBytes || '10m',
|
|
133
|
+
maxFiles: logFile.maxNbFiles || '14d',
|
|
134
|
+
format: fileFormat
|
|
135
135
|
});
|
|
136
136
|
winstonInstance.add(files);
|
|
137
137
|
}
|
|
138
|
-
|
|
139
138
|
}
|
|
140
139
|
|
|
141
140
|
// custom
|
|
@@ -144,17 +143,23 @@ async function initLoggerWithConfig(config) {
|
|
|
144
143
|
await customLoggerInstance.init(config.get('logs:custom:settings'));
|
|
145
144
|
}
|
|
146
145
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
// catch all errors.
|
|
147
|
+
if (!config.get('logs:skipUncaughtException')) {
|
|
148
|
+
process.on('uncaughtException', function (err) {
|
|
149
|
+
rootLogger.error('UncaughtException', { message: err.message, name: err.name, stack: err.stack });
|
|
150
|
+
throw err;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
150
153
|
|
|
154
|
+
rootLogger.debug('Logger Initialized');
|
|
155
|
+
}
|
|
151
156
|
|
|
152
|
-
// --------------- debug utils
|
|
157
|
+
// --------------- debug utils
|
|
153
158
|
|
|
154
159
|
/**
|
|
155
160
|
* Dump objects with file and line
|
|
156
161
|
*/
|
|
157
|
-
function inspect() {
|
|
162
|
+
function inspect () {
|
|
158
163
|
let line = '';
|
|
159
164
|
try {
|
|
160
165
|
throw new Error();
|
|
@@ -162,38 +167,37 @@ function inspect() {
|
|
|
162
167
|
line = e.stack.split(' at ')[2].trim();
|
|
163
168
|
}
|
|
164
169
|
let res = '\n * dump at: ' + line;
|
|
165
|
-
for (
|
|
170
|
+
for (let i = 0; i < arguments.length; i++) {
|
|
166
171
|
res += '\n' + i + ' ' + util.inspect(arguments[i], true, 10, true) + '\n';
|
|
167
172
|
}
|
|
168
173
|
return res;
|
|
169
|
-
}
|
|
170
|
-
|
|
174
|
+
}
|
|
171
175
|
|
|
172
|
-
function setGlobalName(name) {
|
|
176
|
+
function setGlobalName (name) {
|
|
173
177
|
// create root logger
|
|
174
178
|
rootLogger = new Logger(name, null);
|
|
175
179
|
rootLogger.debug('setGlobalName: ' + name);
|
|
176
180
|
}
|
|
177
181
|
|
|
178
|
-
|
|
179
182
|
class Logger {
|
|
180
183
|
parent; // eventual parent
|
|
181
184
|
debugInstance; // debug instance
|
|
182
185
|
|
|
183
|
-
constructor(name, parent) {
|
|
186
|
+
constructor (name, parent) {
|
|
184
187
|
this.name = name;
|
|
185
188
|
this.parent = parent;
|
|
186
|
-
this.debugInstance =
|
|
189
|
+
this.debugInstance = debugModule('pryv:' + this._name());
|
|
187
190
|
}
|
|
191
|
+
|
|
188
192
|
/**
|
|
189
193
|
* Private
|
|
190
194
|
*/
|
|
191
|
-
_name() {
|
|
195
|
+
_name () {
|
|
192
196
|
if (this.parent) return this.parent._name() + ':' + this.name;
|
|
193
197
|
return this.name;
|
|
194
198
|
}
|
|
195
199
|
|
|
196
|
-
log() {
|
|
200
|
+
log () {
|
|
197
201
|
const level = arguments[0];
|
|
198
202
|
const message = hideSensitiveValues(arguments[1]);
|
|
199
203
|
const context = [];
|
|
@@ -204,9 +208,9 @@ class Logger {
|
|
|
204
208
|
context.push(inspectAndHide(arguments[i]));
|
|
205
209
|
}
|
|
206
210
|
if (context.length === 1) {
|
|
207
|
-
meta = {context:
|
|
211
|
+
meta = { context: context[0] };
|
|
208
212
|
} else if (context.length > 1) {
|
|
209
|
-
meta = {context
|
|
213
|
+
meta = { context };
|
|
210
214
|
}
|
|
211
215
|
globalLog(level, this._name(), message, meta);
|
|
212
216
|
}
|
|
@@ -214,69 +218,69 @@ class Logger {
|
|
|
214
218
|
info () { this.log('info', ...arguments); }
|
|
215
219
|
warn () { this.log('warn', ...arguments); }
|
|
216
220
|
error () { this.log('error', ...arguments); }
|
|
217
|
-
debug () {
|
|
221
|
+
debug () {
|
|
218
222
|
if (winstonInstance) {
|
|
219
|
-
this.log('debug', ...arguments);
|
|
223
|
+
this.log('debug', ...arguments);
|
|
220
224
|
}
|
|
221
|
-
this.debugInstance(...arguments);
|
|
222
|
-
}
|
|
225
|
+
this.debugInstance(...arguments);
|
|
226
|
+
}
|
|
223
227
|
|
|
224
228
|
/**
|
|
225
229
|
* get a "sub" Logger
|
|
226
|
-
* @param {Logger} name
|
|
230
|
+
* @param {Logger} name
|
|
227
231
|
* @returns {Logger}
|
|
228
232
|
*/
|
|
229
233
|
getLogger (name) {
|
|
230
234
|
return new Logger(name, this);
|
|
231
235
|
}
|
|
232
236
|
|
|
233
|
-
inspect() { inspect(...arguments); }
|
|
237
|
+
inspect () { inspect(...arguments); }
|
|
234
238
|
}
|
|
235
239
|
|
|
236
240
|
/**
|
|
237
241
|
* Get a new logger, or root loggger if no name is provided
|
|
238
|
-
* @param {string} [name]
|
|
242
|
+
* @param {string} [name]
|
|
239
243
|
* @returns {Logger}
|
|
240
244
|
*/
|
|
241
|
-
function getLogger(name) {
|
|
242
|
-
if (!
|
|
243
|
-
throw new Error('Initalize boiler before using logger')
|
|
245
|
+
function getLogger (name) {
|
|
246
|
+
if (!rootLogger) {
|
|
247
|
+
throw new Error('Initalize boiler before using logger');
|
|
244
248
|
}
|
|
245
|
-
if(!
|
|
249
|
+
if (!name) {
|
|
246
250
|
return rootLogger;
|
|
247
251
|
}
|
|
248
252
|
return rootLogger.getLogger(name);
|
|
249
253
|
}
|
|
250
254
|
|
|
251
255
|
module.exports = {
|
|
252
|
-
getLogger
|
|
253
|
-
setGlobalName
|
|
254
|
-
initLoggerWithConfig
|
|
255
|
-
}
|
|
256
|
+
getLogger,
|
|
257
|
+
setGlobalName,
|
|
258
|
+
initLoggerWithConfig
|
|
259
|
+
};
|
|
256
260
|
|
|
257
261
|
// ----------------- Hide sensite data -------------------- //
|
|
258
262
|
|
|
259
|
-
function inspectAndHide(o) {
|
|
263
|
+
function inspectAndHide (o) {
|
|
260
264
|
if (typeof o === 'undefined') return o;
|
|
261
265
|
if (o instanceof Error) return o;
|
|
262
266
|
return _inspectAndHide(JSON.parse(JSON.stringify(o))); // clone and remove circular
|
|
263
267
|
}
|
|
264
268
|
|
|
265
|
-
function _inspectAndHide(o) {
|
|
269
|
+
function _inspectAndHide (o) {
|
|
266
270
|
if (typeof o === 'string') {
|
|
267
271
|
return hideSensitiveValues(o);
|
|
268
272
|
}
|
|
269
273
|
if (o !== null && typeof o === 'object') {
|
|
270
274
|
if (Array.isArray(o)) {
|
|
271
275
|
const res = [];
|
|
272
|
-
for (
|
|
276
|
+
for (const item of o) {
|
|
273
277
|
res.push(inspectAndHide(item));
|
|
274
278
|
}
|
|
275
279
|
return res;
|
|
276
280
|
}
|
|
277
281
|
|
|
278
282
|
const res = {};
|
|
279
|
-
for (
|
|
283
|
+
for (const key of Object.keys(o)) {
|
|
280
284
|
if (['password', 'passwordHash', 'newPassword'].includes(key)) {
|
|
281
285
|
res[key] = '(hidden password)';
|
|
282
286
|
} else {
|
|
@@ -288,7 +292,6 @@ function _inspectAndHide(o) {
|
|
|
288
292
|
return o;
|
|
289
293
|
}
|
|
290
294
|
|
|
291
|
-
|
|
292
295
|
// Hides sensitive values (auth tokens and passwords) in log messages
|
|
293
296
|
function hideSensitiveValues (msg) {
|
|
294
297
|
if (typeof msg !== 'string') return msg;
|
|
@@ -297,8 +300,8 @@ function hideSensitiveValues (msg) {
|
|
|
297
300
|
const mask = '(hidden)';
|
|
298
301
|
|
|
299
302
|
const res = msg
|
|
300
|
-
.replace(tokenRegexp, 'auth='+mask)
|
|
301
|
-
.replace(passwordRegexp, '$1='+mask);
|
|
302
|
-
|
|
303
|
+
.replace(tokenRegexp, 'auth=' + mask)
|
|
304
|
+
.replace(passwordRegexp, '$1=' + mask);
|
|
305
|
+
|
|
303
306
|
return res;
|
|
304
|
-
}
|
|
307
|
+
}
|