Moved so single main environment variable UCI_ENV
now checks for development and production. Production will write a file to default location if none given Example can be run in numerous ways from npm scripts add readme.md documenatation. need to add mocha testsmaster
parent
88c5886a58
commit
893f88b20d
|
@ -1,19 +1,44 @@
|
||||||
import logger from '../src/logger'
|
import logger from '../src/logger'
|
||||||
let log = {}
|
let log = {}
|
||||||
|
|
||||||
class LOGTEST {
|
class LogTest {
|
||||||
constructor(opts) {
|
constructor(opts) {
|
||||||
log = logger({
|
log = logger({
|
||||||
name: 'test',
|
// pretty: {translateTime:true, colorize:true, levelFirst:true } // options for pino pretty printer
|
||||||
id: opts.id,
|
// env:'', // 'dev' or 'pro' -- can be use to set/override UCI_ENV environment variable
|
||||||
file: 'example/example.js',
|
// enForce: false, // only used with .evn. if true will override UCI_ENV if it is set, otherwise no
|
||||||
class: 'LOGTEST'
|
// level:'info', // 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 properties 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/logger', // name of package with scope per package.json
|
||||||
|
// repo: // will use scope-name from package prop if not supplied
|
||||||
|
id: opts.id, // 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
|
||||||
|
// one can pass through additional props to log for every log
|
||||||
|
// should not use any keys above or
|
||||||
|
// level,time,msg,pid,hostname
|
||||||
|
// logPath,instanceCreatedHR,instanceCreated as keys will be merged
|
||||||
|
// NOTE: more props can be added at run time by passing an object of props
|
||||||
|
additional: {anotherprop:'test'} // should do not use any keys above or 'level,logPath,package,instanceCreatedHR,instanceCreated' as keys will be merged
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logit() {
|
||||||
|
log.trace('this is a trace level logged message')
|
||||||
|
log.debug('this is a debug level logged message')
|
||||||
|
log.info({runtimeprop:'somevalue', 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.clear('This would clear the log')
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let test = new LOGTEST({id:'process-test1'})
|
let test = new LogTest({id:'logtest-via-new'})
|
||||||
|
|
||||||
log.info({test:'filter', msg:'this is a logged message'})
|
test.logit()
|
||||||
log.fatal('this is a fatal logged message')
|
|
||||||
|
|
21
package.json
21
package.json
|
@ -4,13 +4,16 @@
|
||||||
"description": "Parent Logger for all UCI modules",
|
"description": "Parent Logger for all UCI modules",
|
||||||
"main": "src/logger",
|
"main": "src/logger",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"testw": "mocha -r esm test/*.test.mjs --watch --recurse --watch-extensions mjs",
|
"testd": "./node_modules/.bin/nodemon --exec './node_modules/.bin/mocha -r esm --timeout 30000'",
|
||||||
"test": "mocha -r esm test/*.test.mjs",
|
"test": "./node_modules/.bin/mocha -r esm --timeout 30000 || exit 0",
|
||||||
"testci": "istanbul cover ./node_modules/.bin/_mocha --report lcovonly -- -R spec --recursive && codecov || true",
|
"testci": "istanbul cover ./node_modules/.bin/_mocha --report lcovonly -- -R spec --recursive && codecov || true",
|
||||||
"example": "node -r esm example/example",
|
"none": "node -r esm example/example",
|
||||||
"dev": "UCI_DEV=true ./node_modules/.bin/nodemon -r esm example/example",
|
"dev": "UCI_ENV=dev ./node_modules/.bin/nodemon -r esm example/example",
|
||||||
"log": "UCI_LOG=true ./node_modules/.bin/nodemon -r esm example/example",
|
"dev:info": "UCI_ENV=dev UCI_LOG_SEARCH='level==`30`' ./node_modules/.bin/nodemon -r esm example/example",
|
||||||
"pro": "UCI_PROD=./test/logs/uci.log node -r esm example/example"
|
"dev:fatal": "UCI_ENV=dev UCI_LOG_SEARCH='level==`60`' ./node_modules/.bin/nodemon -r esm example/example",
|
||||||
|
"json": "UCI_ENV=dev UCI_LOG_JSON=true ./node_modules/.bin/nodemon -r esm example/example",
|
||||||
|
"pro": "UCI_ENV='pro' node -r esm example/example",
|
||||||
|
"pro:alt": "UCI_ENV='pro' UCI_LOG_PATH=./example/example.log node -r esm example/example"
|
||||||
},
|
},
|
||||||
"author": "David Kebler",
|
"author": "David Kebler",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -28,16 +31,18 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/uCOMmandIt/uci-changeme#readme",
|
"homepage": "https://github.com/uCOMmandIt/uci-changeme#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"env-paths": "^2.0.0",
|
||||||
|
"make-dir": "^1.3.0",
|
||||||
"pino": "^5.11.1",
|
"pino": "^5.11.1",
|
||||||
"pino-pretty": "^2.5.0"
|
"pino-pretty": "^2.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"chai-as-promised": "^7.1.1",
|
|
||||||
"codecov": "^3.1.0",
|
"codecov": "^3.1.0",
|
||||||
"esm": "^3.1.2",
|
"esm": "^3.1.2",
|
||||||
"istanbul": "^0.4.5",
|
"istanbul": "^0.4.5",
|
||||||
"mocha": "^5.2.0",
|
"mocha": "^5.2.0",
|
||||||
"nodemon": "^1.18.9"
|
"nodemon": "^1.18.9",
|
||||||
|
"test-console": "^1.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
88
readme.md
88
readme.md
|
@ -1,17 +1,87 @@
|
||||||
# uCOMmandIt JSON Logger
|
`# uCOMmandIt JSON Logger
|
||||||
|
|
||||||
runtime module logger based on pino
|
### json logger based on pino.
|
||||||
|
|
||||||
run example as either
|
## How to by Example
|
||||||
|
|
||||||
`npm run log`
|
see [example](./example/example.js) for explanation of options and use in a es6 class allowing logging in any method of the class
|
||||||
for json logging
|
|
||||||
|
|
||||||
or for pretty output `npm run dev`
|
```javascript
|
||||||
|
// 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:'info', // 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 properties 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/logger', // name of package with scope per package.json
|
||||||
|
// repo: // will use scope-name from package prop if not supplied
|
||||||
|
id: opts.id, // 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
|
||||||
|
// one can pass through additional props to log for every log
|
||||||
|
// should not use any keys above or
|
||||||
|
// level,time,msg,pid,hostname
|
||||||
|
// logPath,instanceCreatedHR,instanceCreated as keys will be merged
|
||||||
|
// NOTE: more props can be added at run time by passing an object of props
|
||||||
|
additional: {anotherprop:'test'} // should do not use any keys above or 'level,logPath,package,instanceCreatedHR,instanceCreated' as keys will be merged
|
||||||
|
```
|
||||||
|
|
||||||
|
to run the example clone reop and then `npm install` from root
|
||||||
|
|
||||||
|
then
|
||||||
|
|
||||||
|
`npm run [script]`
|
||||||
|
|
||||||
|
available scripts for example file
|
||||||
|
|
||||||
|
- `none`: no logs to console or file
|
||||||
|
- `dev`: all levels pretty printed to console/stdout
|
||||||
|
- `dev:info`: show/filter only level 30 (info) logs pretty printed to console
|
||||||
|
- `dev:fatal`: show/filer only level 60 (fatal) logs pretty printed to console
|
||||||
|
- `json`: log to console but as raw json
|
||||||
|
- `pro`: log to a file in the userspace default log directory location
|
||||||
|
- `pro:alt`: log to a supplied/alternate file (path) location in this case `./example/example.log`
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
- `UCI_ENV='dev'|'pro'|'node'`, `dev` outputs to console, `pro` outputs to file, `node` will follow whatever `NODE_ENV` is set to.
|
||||||
|
- `UCI_LOG_PATH=<some file path>` force logging to go to some particular file, also setable via options, see above
|
||||||
|
- `UCI_LOG_JSON=true` will not pretty output to console but rather as raw json. Useful for piping to a json log processor such as pino-colada
|
||||||
|
- `UCI_LOG_PRETTY`={} the pretty option for pino pretty, also setable via options, see above
|
||||||
|
- `UCI_LOG_SEARCH='key == `\``value`\``'` will filter pretty/dev logs. _note:_ ALL search values regardless of type MUST be escaped with ``
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
standalone (not in a class constructor as in example)
|
||||||
|
lilke this.
|
||||||
|
|
||||||
|
import logger from '../src/logger'
|
||||||
|
opts = {} // see above
|
||||||
|
let log = logger(opts)
|
||||||
|
|
||||||
|
once you have created a Logger as a `global` in your module you can log per http://getpino.io/#/docs/api?id=logger
|
||||||
|
|
||||||
|
like so
|
||||||
|
```javascript
|
||||||
|
log.trace('this is a trace level logged message')
|
||||||
|
log.debug('this is a debug level logged message')
|
||||||
|
log.info({runtimeprop:'somevalue', 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')
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
for search/filter use environment variable
|
you can change visible levels on the fly http://getpino.io/#/docs/api?id=level
|
||||||
|
|
||||||
`UCI_LOG_SEARCH='key == `\`value\``' npm run dev`
|
like so
|
||||||
|
|
||||||
note: ALL search values regardless of type MUST be escaped with ``
|
`log.level('debug')` or in the options, see above
|
||||||
|
|
||||||
|
|
||||||
|
## More Help
|
||||||
|
|
||||||
|
this package/model being a simple extension of the pino json logger check their documentation http://getpino.io/#/
|
||||||
|
|
|
@ -1,39 +1,65 @@
|
||||||
import pino from 'pino'
|
import pino from 'pino'
|
||||||
import { homedir } from 'os'
|
import envPaths from 'env-paths'
|
||||||
|
import { sync as mkdir } from 'make-dir'
|
||||||
|
import { dirname, basename } from 'path'
|
||||||
|
|
||||||
let pretty = false
|
function child (opts) {
|
||||||
if(process.env.UCI_DEV) {
|
|
||||||
pretty = process.env.UCI_LOG_PRETTY || {translateTime:true, colorize:true, levelFirst:true }
|
|
||||||
pretty.search = process.env.UCI_LOG_SEARCH
|
|
||||||
}
|
|
||||||
|
|
||||||
let LOG = process.env.UCI_LOG || process.env.UCI_DEV || process.env.UCI_PROD
|
if (opts.env) (opts.envForce) ? (process.env.UCI_ENV = opts.env) : (process.env.UCI_ENV = process.env.UCI_ENV || opts.env)
|
||||||
let LOG_PATH = (process.env.UCI_PROD===true) ? homedir()+'/logs/uci.log' : process.env.UCI_PROD
|
|
||||||
|
|
||||||
const logger = pino({
|
if (process.env.UCI_ENV === 'node') process.env.UCI_ENV = process.env.NODE_ENV
|
||||||
name: 'UCI',
|
|
||||||
enabled: !!LOG,
|
let pretty = false
|
||||||
safe: true,
|
if(process.env.UCI_ENV === 'dev' || process.env.UCI_ENV === 'development') {
|
||||||
serializers: {
|
if (process.env.UCI_LOG_JSON !=='true') {
|
||||||
req: pino.stdSerializers.req,
|
pretty = process.env.UCI_LOG_PRETTY || opts.pretty || {translateTime:true, colorize:true, levelFirst:true }
|
||||||
res: pino.stdSerializers.res
|
pretty.search = process.env.UCI_LOG_SEARCH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DATE_TIME = new Date(Date.now()).toISOString().replace( /[:.]+/g, '-' )
|
||||||
|
|
||||||
|
const LOG_PATH = (process.env.UCI_ENV=== 'production' || process.env.UCI_ENV=== 'pro' || process.env.UCI_ENV=== 'logfile' )
|
||||||
|
? ( process.env.UCI_LOG_PATH || `${envPaths(opts.appName || opts.name || 'default').log}/${opts.logFileName || DATE_TIME}.log`) : null
|
||||||
|
|
||||||
|
if (LOG_PATH) {
|
||||||
|
try { mkdir(dirname(LOG_PATH)) }
|
||||||
|
catch(err) { throw err }
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('making logger (env,json,pretty,pretty-search,path)',process.env.UCI_ENV,process.env.UCI_LOG_JSON,pretty,process.env.UCI_LOG_SEARCH,LOG_PATH)
|
||||||
|
const logger = pino({
|
||||||
|
name: opts.libraryName || process.env.UCI_LOG_NAME || 'UCI',
|
||||||
|
enabled: !!process.env.UCI_ENV,
|
||||||
|
safe: true,
|
||||||
|
serializers: {
|
||||||
|
req: pino.stdSerializers.req,
|
||||||
|
res: pino.stdSerializers.res
|
||||||
|
},
|
||||||
|
prettyPrint: pretty
|
||||||
},
|
},
|
||||||
prettyPrint: pretty
|
// if production not enabled then LOG_PATH is empty and logs go to stdout/stderr and can be piped from there
|
||||||
},
|
LOG_PATH
|
||||||
// if production not enabled then LOG_PATH is empty and logs go to stdout/stderr and can be piped from there
|
)
|
||||||
LOG_PATH
|
|
||||||
)
|
|
||||||
|
|
||||||
function child (opts) {
|
logger.clear = value => {console.log(value)}
|
||||||
const LOG_OPTS = {
|
|
||||||
repo: opts.repo || 'uci-'+ opts.name,
|
let logOpts = {
|
||||||
package: opts.package || '@uci/'+ opts.name,
|
level:opts.level,
|
||||||
file: opts.file || `src/${opts.name}.js`,
|
logPath: LOG_PATH, // if logging to file
|
||||||
|
appName: opts.appName,
|
||||||
|
repo: opts.repo || (opts.package) ? opts.package.replace( /[@]+/g, '' ).replace( /[/]+/g, '-' ) : null,
|
||||||
|
package: opts.package,
|
||||||
|
file: opts.file || `src/${basename(opts.package)}.js`,
|
||||||
class: opts.class || (opts.name.charAt(0).toUpperCase() + opts.name.slice(1)),
|
class: opts.class || (opts.name.charAt(0).toUpperCase() + opts.name.slice(1)),
|
||||||
id: opts.id || opts.name || 'none',
|
id: opts.id || opts.name || 'none',
|
||||||
instance_created:new Date().getTime()
|
instanceCreatedHR:DATE_TIME,
|
||||||
|
instanceCreated:new Date().getTime()
|
||||||
}
|
}
|
||||||
return logger.child(LOG_OPTS)
|
|
||||||
|
logOpts = Object.assign(logOpts,opts.additional)
|
||||||
|
|
||||||
|
return logger.child(logOpts)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default child
|
export default child
|
||||||
|
|
Loading…
Reference in New Issue