You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					194 lines
				
				4.9 KiB
			
		
		
			
		
	
	
					194 lines
				
				4.9 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | /* eslint no-prototype-builtins: 0 */ | ||
|  | const flatstr = require('flatstr') | ||
|  | const { | ||
|  |   lsCacheSym, | ||
|  |   levelValSym, | ||
|  |   useOnlyCustomLevelsSym, | ||
|  |   streamSym, | ||
|  |   formattersSym, | ||
|  |   hooksSym | ||
|  | } = require('./symbols') | ||
|  | const { noop, genLog } = require('./tools') | ||
|  | 
 | ||
|  | const levels = { | ||
|  |   trace: 10, | ||
|  |   debug: 20, | ||
|  |   info: 30, | ||
|  |   warn: 40, | ||
|  |   error: 50, | ||
|  |   fatal: 60 | ||
|  | } | ||
|  | const levelMethods = { | ||
|  |   fatal: (hook) => { | ||
|  |     const logFatal = genLog(levels.fatal, hook) | ||
|  |     return function (...args) { | ||
|  |       const stream = this[streamSym] | ||
|  |       logFatal.call(this, ...args) | ||
|  |       if (typeof stream.flushSync === 'function') { | ||
|  |         try { | ||
|  |           stream.flushSync() | ||
|  |         } catch (e) { | ||
|  |           // https://github.com/pinojs/pino/pull/740#discussion_r346788313
 | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |   }, | ||
|  |   error: (hook) => genLog(levels.error, hook), | ||
|  |   warn: (hook) => genLog(levels.warn, hook), | ||
|  |   info: (hook) => genLog(levels.info, hook), | ||
|  |   debug: (hook) => genLog(levels.debug, hook), | ||
|  |   trace: (hook) => genLog(levels.trace, hook) | ||
|  | } | ||
|  | 
 | ||
|  | const nums = Object.keys(levels).reduce((o, k) => { | ||
|  |   o[levels[k]] = k | ||
|  |   return o | ||
|  | }, {}) | ||
|  | 
 | ||
|  | const initialLsCache = Object.keys(nums).reduce((o, k) => { | ||
|  |   o[k] = flatstr('{"level":' + Number(k)) | ||
|  |   return o | ||
|  | }, {}) | ||
|  | 
 | ||
|  | function genLsCache (instance) { | ||
|  |   const formatter = instance[formattersSym].level | ||
|  |   const { labels } = instance.levels | ||
|  |   const cache = {} | ||
|  |   for (const label in labels) { | ||
|  |     const level = formatter(labels[label], Number(label)) | ||
|  |     cache[label] = JSON.stringify(level).slice(0, -1) | ||
|  |   } | ||
|  |   instance[lsCacheSym] = cache | ||
|  |   return instance | ||
|  | } | ||
|  | 
 | ||
|  | function isStandardLevel (level, useOnlyCustomLevels) { | ||
|  |   if (useOnlyCustomLevels) { | ||
|  |     return false | ||
|  |   } | ||
|  | 
 | ||
|  |   switch (level) { | ||
|  |     case 'fatal': | ||
|  |     case 'error': | ||
|  |     case 'warn': | ||
|  |     case 'info': | ||
|  |     case 'debug': | ||
|  |     case 'trace': | ||
|  |       return true | ||
|  |     default: | ||
|  |       return false | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function setLevel (level) { | ||
|  |   const { labels, values } = this.levels | ||
|  |   if (typeof level === 'number') { | ||
|  |     if (labels[level] === undefined) throw Error('unknown level value' + level) | ||
|  |     level = labels[level] | ||
|  |   } | ||
|  |   if (values[level] === undefined) throw Error('unknown level ' + level) | ||
|  |   const preLevelVal = this[levelValSym] | ||
|  |   const levelVal = this[levelValSym] = values[level] | ||
|  |   const useOnlyCustomLevelsVal = this[useOnlyCustomLevelsSym] | ||
|  |   const hook = this[hooksSym].logMethod | ||
|  | 
 | ||
|  |   for (const key in values) { | ||
|  |     if (levelVal > values[key]) { | ||
|  |       this[key] = noop | ||
|  |       continue | ||
|  |     } | ||
|  |     this[key] = isStandardLevel(key, useOnlyCustomLevelsVal) ? levelMethods[key](hook) : genLog(values[key], hook) | ||
|  |   } | ||
|  | 
 | ||
|  |   this.emit( | ||
|  |     'level-change', | ||
|  |     level, | ||
|  |     levelVal, | ||
|  |     labels[preLevelVal], | ||
|  |     preLevelVal | ||
|  |   ) | ||
|  | } | ||
|  | 
 | ||
|  | function getLevel (level) { | ||
|  |   const { levels, levelVal } = this | ||
|  |   // protection against potential loss of Pino scope from serializers (edge case with circular refs - https://github.com/pinojs/pino/issues/833)
 | ||
|  |   return (levels && levels.labels) ? levels.labels[levelVal] : '' | ||
|  | } | ||
|  | 
 | ||
|  | function isLevelEnabled (logLevel) { | ||
|  |   const { values } = this.levels | ||
|  |   const logLevelVal = values[logLevel] | ||
|  |   return logLevelVal !== undefined && (logLevelVal >= this[levelValSym]) | ||
|  | } | ||
|  | 
 | ||
|  | function mappings (customLevels = null, useOnlyCustomLevels = false) { | ||
|  |   const customNums = customLevels | ||
|  |     /* eslint-disable */ | ||
|  |     ? Object.keys(customLevels).reduce((o, k) => { | ||
|  |         o[customLevels[k]] = k | ||
|  |         return o | ||
|  |       }, {}) | ||
|  |     : null | ||
|  |     /* eslint-enable */ | ||
|  | 
 | ||
|  |   const labels = Object.assign( | ||
|  |     Object.create(Object.prototype, { Infinity: { value: 'silent' } }), | ||
|  |     useOnlyCustomLevels ? null : nums, | ||
|  |     customNums | ||
|  |   ) | ||
|  |   const values = Object.assign( | ||
|  |     Object.create(Object.prototype, { silent: { value: Infinity } }), | ||
|  |     useOnlyCustomLevels ? null : levels, | ||
|  |     customLevels | ||
|  |   ) | ||
|  |   return { labels, values } | ||
|  | } | ||
|  | 
 | ||
|  | function assertDefaultLevelFound (defaultLevel, customLevels, useOnlyCustomLevels) { | ||
|  |   if (typeof defaultLevel === 'number') { | ||
|  |     const values = [].concat( | ||
|  |       Object.keys(customLevels || {}).map(key => customLevels[key]), | ||
|  |       useOnlyCustomLevels ? [] : Object.keys(nums).map(level => +level), | ||
|  |       Infinity | ||
|  |     ) | ||
|  |     if (!values.includes(defaultLevel)) { | ||
|  |       throw Error(`default level:${defaultLevel} must be included in custom levels`) | ||
|  |     } | ||
|  |     return | ||
|  |   } | ||
|  | 
 | ||
|  |   const labels = Object.assign( | ||
|  |     Object.create(Object.prototype, { silent: { value: Infinity } }), | ||
|  |     useOnlyCustomLevels ? null : levels, | ||
|  |     customLevels | ||
|  |   ) | ||
|  |   if (!(defaultLevel in labels)) { | ||
|  |     throw Error(`default level:${defaultLevel} must be included in custom levels`) | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | function assertNoLevelCollisions (levels, customLevels) { | ||
|  |   const { labels, values } = levels | ||
|  |   for (const k in customLevels) { | ||
|  |     if (k in values) { | ||
|  |       throw Error('levels cannot be overridden') | ||
|  |     } | ||
|  |     if (customLevels[k] in labels) { | ||
|  |       throw Error('pre-existing level values cannot be used for new levels') | ||
|  |     } | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = { | ||
|  |   initialLsCache, | ||
|  |   genLsCache, | ||
|  |   levelMethods, | ||
|  |   getLevel, | ||
|  |   setLevel, | ||
|  |   isLevelEnabled, | ||
|  |   mappings, | ||
|  |   assertNoLevelCollisions, | ||
|  |   assertDefaultLevelFound | ||
|  | } |