fix: warning about passed level property
refactor!: passed arguments separated into bindings and options feat: bound properties under meta: key in log feat: pino key of options argument for pino settings feat: in dev/pretty can (un)hide properties feat: add a unique id to each log line (can be loaded by nedb and such) feat: locate method to easily add line number and file to a log line BREAKING CHANGE: logger/pino options in second separate argument from bindingsmaster
parent
e776937738
commit
2bb6b65e63
33
.eslintrc.js
33
.eslintrc.js
|
@ -1,33 +0,0 @@
|
|||
module.exports = {
|
||||
"ecmaFeatures": {
|
||||
"modules": true,
|
||||
"spread" : true,
|
||||
"restParams" : true
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
2
|
||||
],
|
||||
"no-console": 0,
|
||||
"semi": ["error", "never"],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
env:
|
||||
node: true
|
||||
es2021: true
|
||||
mocha: true
|
||||
extends:
|
||||
- standard
|
||||
parserOptions:
|
||||
ecmaVersion: 12
|
||||
sourceType: module
|
||||
rules:
|
||||
indent: ["error", 2]
|
||||
no-console: 0
|
||||
semi: ["error", "never"]
|
||||
# linebreak-style: ["error", "unix"]
|
||||
quotes: ["error", "single"]
|
|
@ -1,3 +1,4 @@
|
|||
/node_modules/
|
||||
/coverage/
|
||||
*.yaml
|
||||
/example/example.log
|
||||
|
|
12
.travis.yml
12
.travis.yml
|
@ -1,12 +0,0 @@
|
|||
language: node_js
|
||||
|
||||
node_js:
|
||||
- '7.10'
|
||||
- 'node'
|
||||
|
||||
sudo: false
|
||||
|
||||
script: npm test
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports"
|
|
@ -1,47 +1,69 @@
|
|||
import logger from '../src/logger.js'
|
||||
import testsrc from './test.js'
|
||||
|
||||
let log = {}
|
||||
|
||||
class LogTest {
|
||||
constructor(opts) {
|
||||
log = logger(
|
||||
Object.assign({
|
||||
// pretty: {translateTime:true, colorize:true, levelFirst:true } // options for pino pretty printer
|
||||
// env:'', // 'dev' or 'pro' -- can be use to set/override UCI_ENV environment variable
|
||||
// enForce: false, // only used with .evn. if true will override UCI_ENV if it is set, otherwise no
|
||||
// level:'debug', // info is default level, set level to lowest visible
|
||||
// clear: false, // true for log files will clear the current log file on restart
|
||||
// logFileName:'test', // if not supplied log filename will be generated from timestamp
|
||||
// below are BASE properties which are optional and are passed to child logger instance and will be part of json log entry
|
||||
// libraryName: 'UCI', // will be logged as name: can be used to identify logs of related packages, can be set via UCI_LOG_NAME env variable
|
||||
appName:'uci-example-logger', //will be used for logging directory name if supplied and will be logged as well
|
||||
package: '@uci/test', // name of package with scope per package.json
|
||||
// repo: // will use scope-name from package prop if not supplied
|
||||
id: 'id set in package', // can pass a unique if for easy later search/filtering
|
||||
file: 'example/example.js', // path (to repo root) of actual file running this logger, default is ./src/<package without scope>.js
|
||||
class: 'LogTest', // The class that created this logger if any
|
||||
|
||||
/*----------------
|
||||
Can pass through additional props for every log by including this `additional` property object
|
||||
should not use any keys above or level,time,msg,pid,hostname,
|
||||
logPath,instanceCreatedHR,instanceCreated as keys in this object will be merged
|
||||
------------------*/
|
||||
// additional: {anotherprop:'test'}
|
||||
},opts)
|
||||
)
|
||||
const options = {
|
||||
// custom UCI logger options
|
||||
// noID: true,
|
||||
// IDKey: '_id' // default
|
||||
hide: ['meta', 'machine'], // array of properties to hide
|
||||
// pretty: {translateTime:true, colorize:true, levelFirst:true } // options for pino pretty printer
|
||||
// env:'', // 'dev' or 'pro' -- can be use to set/override UCI_ENV environment variable
|
||||
// enForce: false, // only used with .evn. if true will override UCI_ENV if it is set, otherwise no
|
||||
// clear: false, // true for log files will clear the current log file on restart
|
||||
// logFileName:'test', // if not supplied log filename will be generated from timestamp
|
||||
//
|
||||
// override logger default and or add any pino options
|
||||
pino: {
|
||||
// level:'info', // info is default level, overrides UCI_LOG_LEVEL, can be changed at runtime with .level method
|
||||
// name: either libraryName above or UCI_LOG_NAME or default 'UCI',
|
||||
// enabled: only if UCI_ENV is set
|
||||
// nestedKey: 'props' // nest the runtime custom log properties
|
||||
// safe: true,
|
||||
// timestamp: pino.stdTimeFunctions.epochTime,
|
||||
// serializers: {
|
||||
// req: pino.stdSerializers.req,
|
||||
// res: pino.stdSerializers.res
|
||||
// },
|
||||
// prettyPrint: pretty,
|
||||
// prettifier: filter // only call prefilter if some filter is supplied, otherwise see line 53
|
||||
}
|
||||
}
|
||||
|
||||
logit() {
|
||||
const meta = {
|
||||
// meta properties added to all log output
|
||||
// the following base meta props and will be generated with defaults if not set
|
||||
appName: 'uci-example-logger', // will be used for logging directory name if supplied and will be logged as well
|
||||
package: '@uci/test' // name of package with scope per package.json
|
||||
// library: 'uci', // will be stripped from @ organization of package if not supplied
|
||||
// repo: // will use scope-name from package prop if not supplied
|
||||
// file: 'example/example.js', // path (to repo root) of actual file running this logger, default is ./src/<package without scope>.js
|
||||
// file: import.meta.url // use this to get a dynmic absolute path to the file where logger is created
|
||||
// class: 'LogTest' // otherwise will be generated from package
|
||||
// class: false // set to false to disable meta class property
|
||||
// add any additional properties to meta data here
|
||||
// an example
|
||||
// id: // maybe a unique id to make is easier to search and/or filter these logs
|
||||
}
|
||||
|
||||
class LogTest {
|
||||
constructor () {
|
||||
log = logger(meta, options)
|
||||
} // end constructor
|
||||
|
||||
logit () {
|
||||
log.trace('this is a trace level logged message')
|
||||
log.debug({line:343,msg:'this is a debug level logged message with a line number'})
|
||||
log.info({runtimeprop:'some propetery in context', msg:'this is a info level logged message'})
|
||||
log.debug({ line: log.locate(), msg: 'this is a debug level logged message with a line number' })
|
||||
log.info({ runtimeprop: 'some propertey in context', msg: 'this is a info level logged message' })
|
||||
log.warn('this is a warn level logged message')
|
||||
log.error('this is a error level logged message')
|
||||
log.fatal('this is a fatal level logged message')
|
||||
// log.fatal('this is a fatal level logged message')
|
||||
}
|
||||
}
|
||||
|
||||
// let test = new LogTest({id:'id-via new instance', pretty:{include:'all'}})
|
||||
let test = new LogTest()
|
||||
const test = new LogTest()
|
||||
|
||||
log.div(`the default log level based on option or UCI_LOG_LEVEL ${log.level}`)
|
||||
test.logit()
|
||||
|
@ -54,4 +76,22 @@ test.logit()
|
|||
log.lvlset()
|
||||
log.div(`reset level back current default ${log.level}`)
|
||||
test.logit()
|
||||
log.clear('This call to log.clear could clear the file log when implemented')
|
||||
|
||||
console.log('\n-------- hide props------------')
|
||||
log.info({ test1: 'test1', test2: 'test2' }, 'testing')
|
||||
log.hide('test1')
|
||||
console.log('hiding test1')
|
||||
log.info({ test1: 'test1', test2: 'test2' }, 'hiding test1')
|
||||
log.hide('test2')
|
||||
console.log('hiding test2')
|
||||
log.info({ test1: 'test1', test2: 'test2' }, 'hiding test2')
|
||||
log.unhide(['test1', 'test2'])
|
||||
console.log('unhiding both')
|
||||
log.info({ test1: 'test1', test2: 'test2' }, 'hiding test2')
|
||||
|
||||
console.log('\n-------- include line and file ------------')
|
||||
log.info({ loc: log.locate() }, 'log line:file')
|
||||
log.info({ line: log.locate('n') }, 'log line')
|
||||
log.info({ file: log.locate('f') }, 'log file')
|
||||
log.info({ file: log.locate(1) }, 'log loc alternate stack')
|
||||
testsrc(log)
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
{"level":30,"time":1549418336924,"pid":12697,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-58-56-919Z","instanceCreated":1549418336923,"runtimeprop":"somevalue","msg":"this is a info level logged message","v":1}
|
||||
{"level":40,"time":1549418336924,"msg":"this is a warn level logged message","pid":12697,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-58-56-919Z","instanceCreated":1549418336923,"v":1}
|
||||
{"level":50,"time":1549418336924,"msg":"this is a error level logged message","pid":12697,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-58-56-919Z","instanceCreated":1549418336923,"v":1}
|
||||
{"level":60,"time":1549418336924,"msg":"this is a fatal level logged message","pid":12697,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-58-56-919Z","instanceCreated":1549418336923,"v":1}
|
||||
{"level":60,"time":1549418336924,"msg":"this is a fatal level logged message","pid":12697,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-58-56-919Z","instanceCreated":1549418336923,"v":1}
|
||||
{"level":30,"time":1549418336924,"pid":12697,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-58-56-919Z","instanceCreated":1549418336923,"runtimeprop":"somevalue","msg":"this is a info level logged message","v":1}
|
||||
{"level":40,"time":1549418336924,"msg":"this is a warn level logged message","pid":12697,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-58-56-919Z","instanceCreated":1549418336923,"v":1}
|
||||
{"level":50,"time":1549418336924,"msg":"this is a error level logged message","pid":12697,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-58-56-919Z","instanceCreated":1549418336923,"v":1}
|
||||
{"level":60,"time":1549418336924,"msg":"this is a fatal level logged message","pid":12697,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-58-56-919Z","instanceCreated":1549418336923,"v":1}
|
||||
{"level":30,"time":1549418345373,"pid":12734,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-59-05-370Z","instanceCreated":1549418345372,"runtimeprop":"somevalue","msg":"this is a info level logged message","v":1}
|
||||
{"level":40,"time":1549418345373,"msg":"this is a warn level logged message","pid":12734,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-59-05-370Z","instanceCreated":1549418345372,"v":1}
|
||||
{"level":50,"time":1549418345373,"msg":"this is a error level logged message","pid":12734,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-59-05-370Z","instanceCreated":1549418345372,"v":1}
|
||||
{"level":60,"time":1549418345373,"msg":"this is a fatal level logged message","pid":12734,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-59-05-370Z","instanceCreated":1549418345372,"v":1}
|
||||
{"level":60,"time":1549418345373,"msg":"this is a fatal level logged message","pid":12734,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-59-05-370Z","instanceCreated":1549418345372,"v":1}
|
||||
{"level":30,"time":1549418345373,"pid":12734,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-59-05-370Z","instanceCreated":1549418345372,"runtimeprop":"somevalue","msg":"this is a info level logged message","v":1}
|
||||
{"level":40,"time":1549418345373,"msg":"this is a warn level logged message","pid":12734,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-59-05-370Z","instanceCreated":1549418345372,"v":1}
|
||||
{"level":50,"time":1549418345373,"msg":"this is a error level logged message","pid":12734,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-59-05-370Z","instanceCreated":1549418345372,"v":1}
|
||||
{"level":60,"time":1549418345373,"msg":"this is a fatal level logged message","pid":12734,"hostname":"giskard","name":"UCI","logPath":"./example/example.log","appName":"uci-example-logger","repo":"uci-test","package":"@uci/test","file":"src/test.js","class":"Tuci/test","id":"logtest-via-new","instanceCreatedHR":"2019-02-06T01-59-05-370Z","instanceCreated":1549418345372,"v":1}
|
|
@ -0,0 +1,3 @@
|
|||
export default function test (log) {
|
||||
log.info({ location: log.locate() }, 'testing line from another file')
|
||||
}
|
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "@uci-utils/logger",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"description": "Parent Logger for all UCI modules",
|
||||
"main": "./src/logger.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"testd": "./node_modules/.bin/nodemon --exec './node_modules/.bin/mocha --timeout 30000' || exit 1",
|
||||
"test:dev": "./node_modules/.bin/nodemon --trace-warnings --exec './node_modules/.bin/mocha --timeout 30000' || exit 1",
|
||||
"test": "./node_modules/.bin/mocha --timeout 30000 || exit 0",
|
||||
"dev": "UCI_ENV=dev ./node_modules/.bin/nodemon example/example",
|
||||
"dev:verbose": "UCI_LOG_PRETTY='verbose' npm run dev",
|
||||
|
@ -18,7 +18,7 @@
|
|||
"dev:info:only": "UCI_LOG_SEARCH='level==`30`' npm run dev",
|
||||
"dev:fatal:only": "UCI_LOG_SEARCH='level==`60`' npm run dev",
|
||||
"dev:json": "UCI_LOG_LEVEL=trace UCI_LOG_JSON=true npm run dev",
|
||||
"pro": "UCI_ENV='pro' node example/example",
|
||||
"pro": "UCI_ENV='pro' nodemon example/example",
|
||||
"pro:path": "UCI_LOG_PATH=./example/example.log npm run pro"
|
||||
},
|
||||
"author": "David Kebler",
|
||||
|
@ -39,13 +39,19 @@
|
|||
"dependencies": {
|
||||
"env-paths": "^2.2.1",
|
||||
"make-dir": "^3.1.0",
|
||||
"pino": "^6.11.3",
|
||||
"pino-pretty": "^4.7.1"
|
||||
"pino": "^6.13.0",
|
||||
"pino-pretty": "^5.1.2",
|
||||
"uniqid": "^5.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.3.4",
|
||||
"mocha": "^8.3.2",
|
||||
"nodemon": "^2.0.7",
|
||||
"test-console": "^1.1.0"
|
||||
"eslint": "^7.31.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
"eslint-plugin-import": "^2.23.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"mocha": "^9.0.3",
|
||||
"nodemon": "^2.0.12",
|
||||
"test-console": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
|
176
src/logger.js
176
src/logger.js
|
@ -3,120 +3,190 @@ import envPaths from 'env-paths'
|
|||
import { sync as mkdir } from 'make-dir'
|
||||
import { dirname, basename } from 'path'
|
||||
import pinoPretty from 'pino-pretty'
|
||||
import uniqid from 'uniqid'
|
||||
|
||||
function child (opts) {
|
||||
// TODO add custom levels
|
||||
// is pro log to file working???
|
||||
|
||||
function child (bindings = {}, options = {}) {
|
||||
const pinoOpts = Object.assign({}, options.pino)
|
||||
const opts = Object.assign({}, options)
|
||||
delete opts.pino
|
||||
|
||||
const enabled = !!process.env.UCI_ENV
|
||||
|
||||
let pretty; let filter; let LOG_PATH; let DATE_TIME
|
||||
let pretty; let filter; let LOG_PATH; let DATE_TIME; let destination; let file
|
||||
|
||||
const PRETTY_DEFAULTS = {translateTime:true, colorize:true, levelFirst:true}
|
||||
const DEFAULT_FILTER_PROPS = ['level','time','pid','msg']
|
||||
const WHERE_FILTER_PROPS = ['package','file','class','method','function','line']
|
||||
let hidden = Array.isArray(opts.hide) ? opts.hide : [opts.hide]
|
||||
|
||||
let logOpts = {
|
||||
level:opts.level || process.env.UCI_LOG_LEVEL,
|
||||
logPath: LOG_PATH, // if logging to file
|
||||
appName: process.env.UCI_LOG_APP || opts.appName || opts.name,
|
||||
package: opts.package,
|
||||
repo: opts.repo || ((typeof opts.package==='string') ? opts.package.replace( /[@]+/g, '' ).replace( /[/]+/g, '-' ) : undefined),
|
||||
file: opts.file || ((typeof opts.package==='string') ? `src/${basename(opts.package)}.js` : undefined),
|
||||
class: opts.class || ( (typeof opts.package==='string') ? capitalize(basename(opts.package)) : undefined),
|
||||
id: opts.id || opts.name || 'none',
|
||||
instanceCreatedHR:DATE_TIME,
|
||||
instanceCreated:Date.now()
|
||||
}
|
||||
const PRETTY_DEFAULTS = { translateTime: true, colorize: true, levelFirst: true }
|
||||
const DEFAULT_FILTER_PROPS = ['level', 'time', 'pid', 'msg']
|
||||
const WHERE_FILTER_PROPS = ['package', 'file', 'class', 'method', 'function', 'line']
|
||||
|
||||
if (enabled) {
|
||||
if (opts.env) (opts.envForce) ? (process.env.UCI_ENV = opts.env) : (process.env.UCI_ENV = process.env.UCI_ENV || opts.env)
|
||||
if (process.env.UCI_ENV === 'node') process.env.UCI_ENV = process.env.NODE_ENV
|
||||
if((process.env.UCI_ENV.indexOf('dev')>-1 || process.env.UCI_LOG_PRETTY) && process.env.UCI_LOG_JSON !=='true' ) { // pretty is on
|
||||
if ((process.env.UCI_ENV.indexOf('dev') > -1 || process.env.UCI_LOG_PRETTY) && process.env.UCI_LOG_JSON !== 'true') { // pretty is on
|
||||
// process UCI_LOG_PRETTY
|
||||
try {
|
||||
pretty = JSON.parse(process.env.UCI_LOG_PRETTY)
|
||||
}
|
||||
catch (error) {
|
||||
} catch (error) {
|
||||
// console.log('LOGGER: could not JSON parse',process.env.UCI_LOG_PRETTY )
|
||||
}
|
||||
if (process.env.UCI_LOG_PRETTY==='verbose') pretty ={include:'all'}
|
||||
if (process.env.UCI_LOG_PRETTY === 'verbose') pretty = { include: 'all' }
|
||||
pretty = pretty || opts.pretty || {}
|
||||
pretty = Object.assign({},PRETTY_DEFAULTS,pretty)
|
||||
pretty = Object.assign({}, PRETTY_DEFAULTS, pretty)
|
||||
pretty.search = process.env.UCI_LOG_SEARCH
|
||||
pretty.include = pretty.include === 'all' ? 'all' : `level${pretty.include ? ','+ pretty.include : ''}`
|
||||
pretty.ignore = pretty.include === 'all' ? null : Object.keys(logOpts).filter(key => pretty.include.indexOf(key) === -1 ).join()
|
||||
|
||||
|
||||
if (process.env.UCI_LOG_PRETTY === 'terse' || process.env.UCI_LOG_PRETTY === 'where' || pretty.filter ) {
|
||||
filter = filterPretty // only call prefilter if some filter is supplied, otherwise
|
||||
pretty.filter = [...DEFAULT_FILTER_PROPS,...(process.env.UCI_LOG_PRETTY === 'where' ? WHERE_FILTER_PROPS : []),...(pretty.filter||[])]
|
||||
pretty.include = pretty.include === 'all' ? 'all' : `level${pretty.include ? ',' + pretty.include : ''}`
|
||||
pretty.ignore = pretty.include === 'all' ? null : Object.keys(opts).filter(key => pretty.include.indexOf(key) === -1).join()
|
||||
if (process.env.UCI_LOG_PRETTY === 'terse' || process.env.UCI_LOG_PRETTY === 'where' || pretty.filter) {
|
||||
filter = filterPretty // only call prefilter if some filter is supplied, otherwise
|
||||
pretty.filter = [...DEFAULT_FILTER_PROPS, ...(process.env.UCI_LOG_PRETTY === 'where' ? WHERE_FILTER_PROPS : []), ...(pretty.filter || [])]
|
||||
pretty.ignore = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DATE_TIME = new Date().toString()
|
||||
LOG_PATH = ( process.env.UCI_ENV.indexOf('pro') > -1 || process.env.UCI_ENV === 'logfile' )
|
||||
? ( process.env.UCI_LOG_PATH || `${envPaths(opts.appName || opts.name || 'default').log}/${opts.logFileName || DATE_TIME}.log`) : undefined
|
||||
LOG_PATH = (process.env.UCI_ENV.indexOf('pro') > -1 || process.env.UCI_ENV === 'logfile')
|
||||
? (process.env.UCI_LOG_PATH || `${envPaths(opts.appName || opts.name || 'default').log}/${opts.logFileName || DATE_TIME}.log`)
|
||||
: undefined
|
||||
if (LOG_PATH) {
|
||||
try { mkdir(dirname(LOG_PATH)) } // makes recursively for any missing parent directories
|
||||
catch(err) { throw err }
|
||||
mkdir(dirname(LOG_PATH)) // makes recursively for any missing parent directories
|
||||
destination = LOG_PATH
|
||||
}
|
||||
} // end enabled
|
||||
|
||||
// default bindings
|
||||
bindings.appName = process.env.UCI_LOG_APP || bindings.appName || bindings.name
|
||||
bindings.library = bindings.library || typeof bindings.package === 'string' ? (bindings.package.includes('@') ? (bindings.package.replace(/[@]+/g, '')).split('/')[0] : undefined) : undefined
|
||||
bindings.repo = bindings.repo || ((typeof bindings.package === 'string') ? bindings.package.replace(/[@]+/g, '').replace(/[/]+/g, '-') : undefined)
|
||||
bindings.file = bindings.file || ((typeof bindings.package === 'string') ? `src/${basename(bindings.package)}.js` : undefined)
|
||||
bindings.class = bindings.class || (bindings.class !== false && typeof bindings.package === 'string') ? capitalize(basename(bindings.package)) : undefined
|
||||
bindings.instanceCreatedHR = DATE_TIME
|
||||
bindings.instanceCreated = Date.now()
|
||||
|
||||
// console.dir(pretty)
|
||||
// console.dir(logOpts)
|
||||
|
||||
const logger = pino({
|
||||
name: opts.libraryName || process.env.UCI_LOG_NAME || 'UCI',
|
||||
if (pinoOpts.destination) {
|
||||
destination = pinoOpts.destination
|
||||
delete pinoOpts.destination
|
||||
}
|
||||
|
||||
const defaultLevel = pinoOpts.level || opts.level || process.env.UCI_LOG_LEVEL || 'info'
|
||||
|
||||
const defaultOpts = {
|
||||
enabled: enabled,
|
||||
safe: true,
|
||||
level: defaultLevel,
|
||||
formatters: {
|
||||
bindings (obj) {
|
||||
return { machine: obj }
|
||||
}
|
||||
},
|
||||
timestamp: pino.stdTimeFunctions.epochTime,
|
||||
serializers: {
|
||||
req: pino.stdSerializers.req,
|
||||
res: pino.stdSerializers.res
|
||||
},
|
||||
prettyPrint: pretty,
|
||||
prettifier: filter // only call prefilter if some filter is supplied, otherwise see line 53
|
||||
},
|
||||
// if production not enabled then LOG_PATH is empty and logs go to stdout/stderr and can be piped from there
|
||||
LOG_PATH
|
||||
}
|
||||
|
||||
const logger = pino(
|
||||
Object.assign({}, defaultOpts, pinoOpts),
|
||||
// if production not enabled then LOG_PATH is empty and logs go to stdout/stderr and can be piped from there
|
||||
destination
|
||||
)
|
||||
|
||||
let child = logger.child(logOpts)
|
||||
const child = logger.child({ meta: bindings }, {
|
||||
formatters: {
|
||||
log (obj) {
|
||||
// console.log('formatter', obj.level, child.level)
|
||||
obj.dateTime = new Date().toString()
|
||||
if (!pretty) {
|
||||
obj.label = child.level
|
||||
if (!opts.noID) obj[opts.keyID || '_id'] = uniqid()
|
||||
} else {
|
||||
obj.file = obj.file || file
|
||||
hidden.forEach(prop => {
|
||||
// console.log('hiding', prop, obj[prop])
|
||||
obj[prop] = undefined
|
||||
})
|
||||
}
|
||||
return obj
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
child.default = process.env.UCI_LOG_LEVEL || opts.level || 'info'
|
||||
child.default = defaultLevel
|
||||
child.clear = () => {
|
||||
if (enabled) {
|
||||
if (process.env.UCI_ENV.indexOf('pro') > -1) return null } // enable feature here
|
||||
if (process.env.UCI_ENV.indexOf('pro') > -1) return null
|
||||
} // enable feature here
|
||||
}
|
||||
child.div = value => {
|
||||
if (enabled) {
|
||||
if (process.env.UCI_ENV.indexOf('dev') > -1) console.log(`===== ${value} ========`)}
|
||||
if (process.env.UCI_ENV.indexOf('dev') > -1) console.log(`===== ${value} ========`)
|
||||
}
|
||||
}
|
||||
child.lvlset = (level) => { if (enabled) child.level = level || child.default }
|
||||
|
||||
child.hide = (props) => {
|
||||
hidden = arraysMerge(props, hidden)
|
||||
}
|
||||
|
||||
child.unhide = (props) => {
|
||||
hidden = arraysFilter(props, hidden)
|
||||
}
|
||||
|
||||
child.locate = locate
|
||||
|
||||
return child
|
||||
}
|
||||
|
||||
export default child
|
||||
const levels = pino.levels
|
||||
export {child as logger, levels}
|
||||
|
||||
function capitalize (s) { return s.charAt(0).toUpperCase() + s.slice(1)}
|
||||
export { child as logger, levels, locate, arraysMerge }
|
||||
|
||||
function filterPretty (options) {
|
||||
// console.log('filter options',options)
|
||||
return function prettifier (inputData) {
|
||||
// console.log('calling filter',inputData)
|
||||
let log
|
||||
let parsedData
|
||||
// let parsedData
|
||||
if (typeof inputData === 'string') {
|
||||
try { log = JSON.Parse(inputData)}
|
||||
catch(err){ return inputData }
|
||||
}
|
||||
else log = inputData
|
||||
let filteredLog = {}
|
||||
options.filter.forEach(prop => filteredLog[prop]= log[prop])
|
||||
try { log = JSON.Parse(inputData) } catch (err) { return inputData }
|
||||
} else log = inputData
|
||||
const filteredLog = {}
|
||||
options.filter.forEach(prop => { filteredLog[prop] = log[prop] })
|
||||
// console.log('filtered',options.filter, filteredLog)
|
||||
return pinoPretty(options)(filteredLog)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO move these to @uci-utils/helpers
|
||||
|
||||
function capitalize (s) { return s.charAt(0).toUpperCase() + s.slice(1) }
|
||||
|
||||
function locate (frame = 2, ret) {
|
||||
if (typeof frame === 'string') { ret = frame; frame = 2 }
|
||||
const e = new Error()
|
||||
const stack = e.stack.toString().split(/\r\n|\n/)
|
||||
const RE = /file:\/\/(.*):(\d+):(?:\d+)[^\d]*$/
|
||||
const reg = RE.exec(stack[frame])
|
||||
const str = ret ? (ret === 'n' ? reg[2] : reg[1]) : `${reg[2]}:${reg[1]}`
|
||||
return str // return line#:path
|
||||
}
|
||||
|
||||
function arraysMerge (els, arr) {
|
||||
els = Array.isArray(els) ? els : [els]
|
||||
return [...new Set([...arr, ...els])].filter(el => el != null)
|
||||
}
|
||||
|
||||
function arraysFilter (els, arr) {
|
||||
els = Array.isArray(els) ? els : [els]
|
||||
return arr.filter(function (item) {
|
||||
return !els.includes(item)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue