Commit 70a7da47 authored by Bryan Tong's avatar Bryan Tong
Browse files

Merge branch 'improveLogging' into 'master'

Improve logging.

Closes #108

See merge request kado/kado!309
parents 1658f9c9 c1444c5e
Pipeline #8442 passed with stage
in 2 minutes and 28 seconds
# Changelog
### 4.3.3
*Pending*
* Log now writes to console synchronously when toConsole is on.
* Improved log dump to work with all variable types.
* Better log dumping on errors.
* Added `log.print(msg)` which is an alias for `log.info(msg)`
* Added `log.log(msg)` which is an alias for `log.info(msg)`
### 4.3.2
*Released 7/7/21*
* Restore main field, with proper value. Ensured compliance.
......
......@@ -21,6 +21,7 @@
const dgram = require('dgram')
const Connect = require('./Connect')
const fs = require('./FileSystem')
const Format = require('./Format')
const Stream = require('./Stream')
class Log extends Connect {
static getInstance (options) { return new Log(options) }
......@@ -34,6 +35,8 @@ class Log extends Connect {
error (msg = '', opts = {}) { this.message(Log.levels[0], msg, opts) }
warning (msg = '', opts = {}) { this.message(Log.levels[1], msg, opts) }
info (msg = '', opts = {}) { this.message(Log.levels[2], msg, opts) }
print (msg = '', opts = {}) { this.message(Log.levels[2], msg, opts) }
log (msg = '', opts = {}) { this.message(Log.levels[2], msg, opts) }
verbose (msg = '', opts = {}) { this.message(Log.levels[3], msg, opts) }
debug (msg = '', opts = {}) { this.message(Log.levels[4], msg, opts) }
extra (msg = '', opts = {}) { this.message(Log.levels[5], msg, opts) }
......@@ -82,7 +85,6 @@ class LogEngine extends Stream.Readable {
this.name = (options.name || 'Kado').toUpperCase()
this.toConsole = true
if (options.toConsole !== undefined) this.toConsole = options.toConsole
if (this.toConsole === true) this.pipe(process.stdout)
}
// keep the stream open, even though we write to the consumer when we want
......@@ -103,16 +105,32 @@ class LogEngine extends Stream.Readable {
message (level = Log.levels[2], msg = '', opts = {}) {
const now = new Date()
const date = this.formatDate(now)
let chunk = Buffer.from(
`[${date} ${this.name}-${level.title}] ${msg}\n`
)
if (opts.wrap === false) chunk = msg
let chunk = msg
if (msg instanceof Error) {
chunk = '' + Format.color(msg.stack, 'Red')
} else {
if (!(msg instanceof String)) {
let color = 'Yellow'
if (typeof msg === 'number') color = 'Green'
if (msg === null) color = 'Cyan'
chunk = Format.color(`${msg}`, color)
}
if (opts.wrap !== false) {
chunk = Buffer.from(
`[${date} ${this.name}-${level.title}] ${msg}`
)
}
}
chunk = `${chunk}\n`
this.push(chunk)
if (this.toConsole === true) process.stdout.write(chunk)
}
error (msg = '', opts = {}) { this.message(Log.levels[0], msg, opts) }
warning (msg = '', opts = {}) { this.message(Log.levels[1], msg, opts) }
info (msg = '', opts = {}) { this.message(Log.levels[2], msg, opts) }
print (msg = '', opts = {}) { this.message(Log.levels[2], msg, opts) }
log (msg = '', opts = {}) { this.message(Log.levels[2], msg, opts) }
verbose (msg = '', opts = {}) { this.message(Log.levels[3], msg, opts) }
debug (msg = '', opts = {}) { this.message(Log.levels[4], msg, opts) }
extra (msg = '', opts = {}) { this.message(Log.levels[5], msg, opts) }
......
......@@ -55,5 +55,5 @@
"scripts": {
"test": "standard && node ./test/index.js"
},
"version": "4.3.2"
"version": "4.3.3"
}
......@@ -23,38 +23,73 @@ const Assert = require('../lib/Assert')
const Log = require('../lib/Log')
runner.suite('Log', (it) => {
const logName = 'kado'
const log = new Log.LogEngine({ name: logName })
const logEngine = new Log(null, log)
const log = new Log()
const logEngine = new Log.LogEngine({ name: logName, toConsole: false })
log.addEngine('test', logEngine)
/* additional test code
const l = new Log()
const engine = new Log.LogEngine()
l.addEngine('test', engine)
l.info('foo')
l.error('bad')
const err = new Error('test')
l.dump(err)
l.dump(2)
l.dump(false)
l.dump({ foo: 'foo' })
*/
it('should construct', () => {
Assert.isType('Log', new Log())
Assert.isType('Log', log)
})
it('should dump variables', () => {
log.dump(true)
})
it('should dump errors', () => {
const error = new Error('testing')
log.dump(error)
})
it('should dump objects', () => {
const obj = { foo: 'foo' }
log.dump(obj)
})
it('should dump null', () => {
log.dump(null)
})
it('should dump numbers', () => {
log.dump(35)
})
it('should print', () => {
log.print('foo')
})
it('should log', () => {
log.log('foo')
})
it('should have no logger', () => {
console.log(logEngine.listEngines())
Assert.eq(logEngine.listEngines().length, 0)
Assert.eq(log.listEngines().length, 1)
})
it('should have no handlers', () => {
Assert.eq(logEngine.listEngines().length, 0)
Assert.eq(log.listEngines().length, 1)
})
it('should add an engine', () => {
Assert.isType('LogEngine', logEngine.addEngine(logName, log))
Assert.isType('LogEngine', log.addEngine(logName, logEngine))
})
it('should get the handler', () => {
Assert.isType('LogEngine', logEngine.getEngine(logName))
Assert.isType('LogEngine', log.getEngine(logName))
})
it('should activate the handler', () => {
Assert.isType('LogEngine', logEngine.activateEngine(logName))
Assert.isType('LogEngine', log.activateEngine(logName))
})
it('should return the active handler', () => {
Assert.isType('LogEngine', logEngine.getActiveEngine())
Assert.isType('LogEngine', log.getActiveEngine())
})
it('should remove the handler', () => {
Assert.eq(logEngine.removeEngine(logName), true)
Assert.eq(log.removeEngine(logName), true)
})
it('should no longer have the handler', () => {
Assert.eq(logEngine.getEngine(logName), false)
Assert.eq(log.getEngine(logName), false)
})
it('should now not have a logger', () => {
Assert.eq(logEngine.getActiveEngine(), null)
Assert.eq(log.getActiveEngine(), null)
})
})
if (require.main === module) runner.execute().then(code => process.exit(code))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment