From 4ec81b68057c8ccb59a59981308b2727f8b5b5fa Mon Sep 17 00:00:00 2001 From: rjrodger Date: Mon, 2 Sep 2019 16:08:00 +0100 Subject: [PATCH] test and quiet interaction tests --- lib/api.js | 63 +++-- lib/logging.js | 408 +++++++++++++-------------- lib/options.js | 26 +- lib/outward.js | 6 +- lib/plugins.js | 5 +- package.json | 2 +- seneca.js | 111 ++++---- test/logging.test.js | 546 ++++++++++++++++++++++++++++++++---- test/seneca-options.test.js | 7 +- 9 files changed, 793 insertions(+), 381 deletions(-) diff --git a/lib/api.js b/lib/api.js index 1d5449b5..40209dc0 100644 --- a/lib/api.js +++ b/lib/api.js @@ -199,12 +199,12 @@ exports.delegate = function(fixedargs, fixedmeta) { delegate.did = (delegate.did ? delegate.did + '/' : '') + self.private$.didnid() - - delegate.log = function log() { return root.log.apply(delegate, arguments)} - Object.assign(delegate.log,root.log) + delegate.log = function log() { + return root.log.apply(delegate, arguments) + } + Object.assign(delegate.log, root.log) delegate.log.self = () => delegate - var strdesc delegate.toString = function toString() { if (strdesc) return strdesc @@ -285,17 +285,27 @@ exports.export = function(key) { return exportval } -// TODO: logging needs to be able to support this without reload awkwardness! -// TODO: boolean to turn on/off -exports.quiet = function() { - this.options({ +exports.quiet = function(flags) { + flags = flags || {} + + var quiet_opts = { + test: false, quiet: true, - log: 'warn' - }) + log: 'none', + reload$: true + } - this.private$.logging.build_log(this) - - return this + var opts = this.options(quiet_opts) + + // An override from env or args is possible. + // Only flip to test mode if called from test() method + if (opts.test && 'test' !== flags.from) { + return this.test() + } else { + this.private$.logging.build_log(this) + + return this + } } exports.test = function(errhandler, logspec) { @@ -313,23 +323,32 @@ exports.test = function(errhandler, logspec) { errhandler = null } + logspec = true === logspec || 'true' === logspec ? 'test' : logspec + var test_opts = { errhandler: null == errhandler ? null : errhandler, test: true, - log: logspec || 'test', + quiet: false, + reload$: true, + log: logspec || 'test' } - this.options(test_opts) + var set_opts = this.options(test_opts) + + // An override from env or args is possible. + if (set_opts.quiet) { + return this.quiet({ from: 'test' }) + } else { + this.private$.logging.build_log(this) - this.private$.logging.build_log(this) + // Manually set logger to test_logger (avoids infecting options structure), + // unless there was an external logger defined by the options + if (!this.private$.logger.from_options$) { + this.root.private$.logger = this.private$.logging.test_logger + } - // Manually set logger to test_logger (avoids infecting options structure), - // unless there was an external logger defined by the options - if(!this.private$.logger.from_options$) { - this.root.private$.logger = this.private$.logging.test_logger + return this } - - return this } // use('pluginname') - built-in, or provide calling code 'require' as seneca opt diff --git a/lib/logging.js b/lib/logging.js index d3948436..bc1707db 100644 --- a/lib/logging.js +++ b/lib/logging.js @@ -1,14 +1,11 @@ /* Copyright © 2016-2019 Richard Rodger and other contributors, MIT License. */ 'use strict' - // NOTES // Valid log level values range from 100 to 999 inclusive only. - const Util = require('util') - // REMOVE //var _ = require('lodash') @@ -16,8 +13,6 @@ const Stringify = require('fast-safe-stringify') const Print = require('./print') const Common = require('./common') - - const default_logspec = { level: 'info', default_level: 'debug', @@ -28,7 +23,7 @@ const default_logspec = { 400: 'warn', 500: 'error', 600: 'fatal', - 999: 'none', + 999: 'none' }, logger: json_logger } @@ -46,10 +41,9 @@ const level_abbrev = { const internal_loggers = { flat_logger, test_logger, - json_logger, + json_logger } - function make_logging() { const logging = { default_logspec: Common.deep(default_logspec), @@ -59,68 +53,69 @@ function make_logging() { build_log, flat_logger, test_logger, - json_logger, + json_logger } return logging } - module.exports = make_logging - - - - - // TODO: create concise production flat format function flat_logger(entry) { - - var level_str = entry.level_name.toUpperCase() - if(level_str.length < 5) { - level_str += '_'.repeat(5-level_str.length) + var level_str = (entry.level_name+'').toUpperCase() + if (level_str.length < 5) { + level_str += '_'.repeat(5 - level_str.length) } - level_str = level_str.substring(0,5) + level_str = level_str.substring(0, 5) var da = - null != entry.err ? [entry.err.message, entry.err.callpoint] : - null != entry.res ? [entry.res] : - null != entry.msg ? [entry.msg] : - Array.isArray(entry.data) ? entry.data : - null != entry.data ? [entry.data] : - [] - - for(var i = 0; i < da.length; i++) { - da[i] = 'object' === typeof(da[i]) ? Common.clean(da[i]) : da[i] - da[i] = Util.inspect(da[i],{ - compact:true, - depth:(entry.depth||3), - breakLength:Infinity + null != entry.err + ? [entry.err.message, entry.err.callpoint] + : null != entry.res + ? [entry.res] + : null != entry.msg + ? [entry.msg] + : Array.isArray(entry.data) + ? entry.data + : null != entry.data + ? [entry.data] + : [] + + for (var i = 0; i < da.length; i++) { + da[i] = 'object' === typeof da[i] ? Common.clean(da[i]) : da[i] + da[i] = Util.inspect(da[i], { + compact: true, + depth: entry.depth$ || 3, + breakLength: Infinity }) } - + var data_str = da.join(' ') - var plugin_str = null==entry.plugin_name?'': - (entry.plugin_name+ - ((null==entry.plugin_tag||'-'==entry.plugin_tag)?'':'$'+entry.plugin_tag)) - + var plugin_str = + null == entry.plugin_name + ? '' + : entry.plugin_name + + (null == entry.plugin_tag || '-' == entry.plugin_tag + ? '' + : '$' + entry.plugin_tag) + var sb = [ entry.isot, entry.seneca_id, level_str, - (null==entry.kind?'log':entry.kind), - (null==entry.case?'LOG':entry.case), + null == entry.kind ? 'log' : entry.kind, + null == entry.case ? 'LOG' : entry.case, plugin_str, - (null==entry.pattern?'':entry.pattern), - (null==entry.action?'':entry.action), - (null==entry.idpath?'':entry.idpath), + null == entry.pattern ? '' : entry.pattern, + null == entry.action ? '' : entry.action, + null == entry.idpath ? '' : entry.idpath, data_str, entry.callpoint ? Util.inspect(entry.callpoint) : '' ] - - console.log(sb.join(' ').substring(0,entry.maxlen||11111)) -} + console.log(sb.join(' ').substring(0, entry.maxlen$ || 11111)) +} // TODO: make default function json_logger(entry) { @@ -128,7 +123,6 @@ function json_logger(entry) { Print.log(logstr) } - function test_logger(entry) { try { var logstr = build_test_log(this, entry) @@ -138,23 +132,22 @@ function test_logger(entry) { } } - function load_logger(instance, log_plugin) { log_plugin = log_plugin || json_logger var logger = log_plugin - - if('string' === typeof(logger)) { - logger = internal_loggers[logger+'_logger'] + + if ('string' === typeof logger) { + logger = internal_loggers[logger + '_logger'] } - + // The logger is actually a seneca plugin that generates a logger function - if(log_plugin.preload) { + if (log_plugin.preload) { logger = log_plugin.preload.call(instance).extend.logger logger.from_options$ = log_plugin.from_options$ } - - if(2 == logger.length) { + + if (2 == logger.length) { var lla = function logger_legacy_adapter(entry) { return logger(this, entry) } @@ -162,14 +155,11 @@ function load_logger(instance, log_plugin) { lla.from_options$ = logger.from_options$ return lla - } - else { + } else { return logger } } - - //function build_log_spec(self,flags) { //flags = flags || {} @@ -177,81 +167,76 @@ function build_log_spec(self) { var options = self.options() var orig_logspec = options.log + //var es; try { throw new Error() } catch(e) { es = e.stack }; + //console.log('ORIG LOGSPEC', {v:orig_logspec}, es) + // Canonize logspec into a standard object structure var logspec = Common.deep( - { text_level:{} }, - 'object' === typeof(orig_logspec) ? orig_logspec : default_logspec) + { text_level: {} }, + 'object' === typeof orig_logspec ? orig_logspec : default_logspec + ) // Define reverse lookup of log level values by name Object.keys(logspec.level_text).forEach(val => { - logspec.text_level[logspec.level_text[val]] = parseInt(val,10) + logspec.text_level[logspec.level_text[val]] = parseInt(val, 10) }) var text_level = logspec.text_level var level_text = logspec.level_text // logger can be set at top level as a convenience - var logger = (options.internal && options.internal.logger) || - options.logger || - logspec.logger + var logger = + (options.internal && options.internal.logger) || + options.logger || + logspec.logger // level can be set by abbreviation if ('string' === typeof orig_logspec) { let level_value = NaN let found_logger = null - + // abbreviation could be an actual log level name or value - if(text_level[orig_logspec]) { + if (text_level[orig_logspec]) { logspec.level = orig_logspec } // otherwise resolve abbreviation to log level name - else if(level_abbrev[orig_logspec]) { + else if (level_abbrev[orig_logspec]) { logspec.level = level_abbrev[orig_logspec] - } - - else if(!isNaN(level_value = parseInt(orig_logspec,10))) { + } else if (!isNaN((level_value = parseInt(orig_logspec, 10)))) { logspec.level = level_value } // set logger by name - else if('function' === typeof(found_logger = internal_loggers[orig_logspec+'_logger'])) { + else if ( + 'function' === + typeof (found_logger = internal_loggers[orig_logspec + '_logger']) + ) { logger = found_logger - } - - else { - throw Common.error('bad-logspec-string', {logspec: orig_logspec}) + } else { + throw Common.error('bad_logspec_string', { logspec: orig_logspec }) } } // level value can be set directly - else if('number' === typeof orig_logspec) { - logspec.level = parseInt(orig_logspec,10) - } - - else if('function' === typeof orig_logspec) { + else if ('number' === typeof orig_logspec) { + logspec.level = parseInt(orig_logspec, 10) + } else if ('function' === typeof orig_logspec) { logger = orig_logspec - } - - else if('object' !== typeof orig_logspec && null != orig_logspec) { - throw Common.error('bad-logspec', {logspec: orig_logspec}) + } else if ('object' !== typeof orig_logspec && null != orig_logspec) { + throw Common.error('bad_logspec', { logspec: orig_logspec }) } // If level was a known level value, replace with level text, // otherwise leave as value (as string). - logspec.level = level_text[logspec.level] || ''+logspec.level + logspec.level = level_text[logspec.level] || '' + logspec.level // Set live log level value from log level name, and ensure in valid range - var live_level = - text_level[logspec.level] || parseInt(logspec.level,10) - live_level = - live_level < 100 ? 100 : - 999 < live_level ? 999 : - live_level + var live_level = text_level[logspec.level] || parseInt(logspec.level, 10) + live_level = live_level < 100 ? 100 : 999 < live_level ? 999 : live_level logspec.live_level = live_level - - if(logger) { + if (logger) { logspec.logger = logger } @@ -264,110 +249,110 @@ function build_log_spec(self) { self.options(logopts) } */ - + return logspec } - //function build_log(self,flags) { // var logspec = build_log_spec(self,flags) function build_log(self) { var logspec = build_log_spec(self) - + // shortcut for direct access (avoids seneca.options() call) self.private$.logspec = logspec var logger = load_logger(self, logspec.logger) - + self.private$.logger = logger - + self.log = function log(entry) { var instance = this - - // Handle legacy entity call - if(instance.entity$) { + + // Handle legacy entity call + if (instance.entity$) { instance = instance.private$.get_instance() - entry = {data:Array.prototype.slice.call(arguments)} - } - else if('string' === typeof(entry)) { - entry = {data:Array.prototype.slice.call(arguments)} + entry = { data: Array.prototype.slice.call(arguments) } + } else if ('string' === typeof entry) { + entry = { data: Array.prototype.slice.call(arguments) } } - + var logspec = instance.private$.logspec entry.level = entry.level || logspec.default_level - if('number' !== typeof(entry.level)) { - entry.level = logspec.text_level[entry.level] || + if ('number' !== typeof entry.level) { + entry.level = + logspec.text_level[entry.level] || logspec.text_level[logspec.default_level] } - - + var now = new Date() // NOTE: don't overwrite entry data! - + entry.isot = entry.isot || now.toISOString() entry.when = entry.when || now.getTime() entry.level_name = entry.level_name || logspec.level_text[entry.level] entry.seneca_id = entry.seneca_id || instance.id - if(instance.did) { + if (instance.did) { entry.seneca_did = entry.seneca_did || instance.did } - if(instance.fixedargs.plugin$) { + if (instance.fixedargs.plugin$) { entry.plugin_name = entry.plugin_name || instance.fixedargs.plugin$.name entry.plugin_tag = entry.plugin_tag || instance.fixedargs.plugin$.tag } - if(instance.private$.act) { + if (instance.private$.act) { entry.kind = entry.kind || 'act' entry.actid = entry.actid || instance.private$.act.meta.id entry.pattern = entry.pattern || instance.private$.act.meta.pattern entry.action = entry.action || instance.private$.act.def.id entry.idpath = instance.private$.act.meta.tx - for(var i = 0; i < (instance.private$.act.meta.parents || []).length; i++) { - entry.idpath += '.'+(instance.private$.act.meta.parents[i][1].split('/')[0]) + for ( + var i = 0; + i < (instance.private$.act.meta.parents || []).length; + i++ + ) { + entry.idpath += + '.' + instance.private$.act.meta.parents[i][1].split('/')[0] } - entry.idpath += '.'+instance.private$.act.meta.mi + entry.idpath += '.' + instance.private$.act.meta.mi } - - - // Log event is called on all logs - they are not filtered by level instance.emit('log', entry) var level_match = logspec.live_level <= entry.level - if(level_match) { + // console.log('LOG', level_match, entry) + + if (level_match) { instance.private$.logger.call(this, entry) } - + return this } self.log.self = () => self - Object.keys(logspec.text_level).forEach((level_name)=>{ - self.log[level_name] = - make_log_level(level_name,logspec) - }) + Object.keys(logspec.text_level).forEach(level_name => { + self.log[level_name] = make_log_level(level_name, logspec) + }) return logspec } - function make_log_level(level_name, logspec) { var level = logspec.text_level[level_name] var log_level = function(entry) { var self = this.self() - if('object' !== typeof(entry)) { + if ('object' !== typeof entry) { entry = { - data:Array.prototype.slice.call(arguments) + data: Array.prototype.slice.call(arguments) } } @@ -375,12 +360,11 @@ function make_log_level(level_name, logspec) { return self.log(entry) } - Object.defineProperty(log_level, "name", { value: "log_"+level_name }); - + Object.defineProperty(log_level, 'name', { value: 'log_' + level_name }) + return log_level } - //function build_test_log(seneca, origspec, data) { function build_test_log(seneca, data) { var logstr @@ -388,96 +372,92 @@ function build_test_log(seneca, data) { var datalen = seneca.private$.exports.options.debug.datalen //if ('test' === origspec || 'print' === origspec) { - var logb = [ - time + - '/' + - seneca.id.substring(0, 2) + - '/' + - seneca.tag + - ' ' + - data.level_name.toUpperCase(), - (data.kind || 'data') + - (data.case ? '/' + data.case : '') + - (data.meta ? (data.meta.sync ? '/s' : '/a') : '') - ] - - if ('act' === data.kind) { - if (data.meta) { - logb.push( - data.meta.id - .split('/') - .map(function(s) { - return s.substring(0, 2) - }) - .join('/') - ) - - logb.push(data.meta.pattern) - } - - if(data.res || data.result || data.msg) { - logb.push( - Util.inspect(seneca.util.clean(data.res || data.result || data.msg)) - .replace(/\s+/g, '') - .substring(0, datalen) - ) - } - - if(data.actdef) { - logb.push(data.actdef.id) - } - - if (data.notice) { - logb.push(data.notice) - } - - - if (data.data) { - logb.push(data.data) - } - - // TODO: err log should show err code + var logb = [ + time + + '/' + + seneca.id.substring(0, 2) + + '/' + + seneca.tag + + ' ' + + (data.level_name+'').toUpperCase(), + (data.kind || 'data') + + (data.case ? '/' + data.case : '') + + (data.meta ? (data.meta.sync ? '/s' : '/a') : '') + ] - if ('ERR' === data.case) { - logb.push('\n\n' + data.err.stack + '\n' + data.caller + '\n') - } - } else if ('add' === data.kind) { - logb.push(data.pattern) - logb.push(data.name) - } else if ('ready' === data.kind) { - logb.push(data.name) - } else if ('plugin' === data.kind) { + if ('act' === data.kind) { + if (data.meta) { logb.push( - data.plugin_name + (data.plugin_tag ? '$' + data.plugin_tag : '') + data.meta.id + .split('/') + .map(function(s) { + return s.substring(0, 2) + }) + .join('/') ) - } else if ('options' === data.kind) { - // deliberately omit - } else if ('notice' === data.kind) { - logb.push(data.notice) - } else if ('listen' === data.kind || 'client' === data.kind) { - var config = data.options && data.options[0] - logb.push( - [ - config.type, - config.pin, - config.host, - 'function' === typeof(config.port) ? '' : config.port - ].join(';') - ) - } else { + + logb.push(data.meta.pattern) + } + + if (data.res || data.result || data.msg) { logb.push( - Util.inspect(data) - .replace(/\n/g, ' ') + Util.inspect(seneca.util.clean(data.res || data.result || data.msg)) + .replace(/\s+/g, '') .substring(0, datalen) ) } - if (data.did) { - logb.push(data.did) + if (data.actdef) { + logb.push(data.actdef.id) + } + + if (data.notice) { + logb.push(data.notice) + } + + if (data.data) { + logb.push(data.data) + } + + // TODO: err log should show err code + + if ('ERR' === data.case) { + logb.push('\n\n' + data.err.stack + '\n' + data.caller + '\n') } + } else if ('add' === data.kind) { + logb.push(data.pattern) + logb.push(data.name) + } else if ('ready' === data.kind) { + logb.push(data.name) + } else if ('plugin' === data.kind) { + logb.push(data.plugin_name + (data.plugin_tag ? '$' + data.plugin_tag : '')) + } else if ('options' === data.kind) { + // deliberately omit + } else if ('notice' === data.kind) { + logb.push(data.notice) + } else if ('listen' === data.kind || 'client' === data.kind) { + var config = data.options && data.options[0] + logb.push( + [ + config.type, + config.pin, + config.host, + 'function' === typeof config.port ? '' : config.port + ].join(';') + ) + } else { + logb.push( + Util.inspect(data) + .replace(/\n/g, ' ') + .substring(0, datalen) + ) + } + + if (data.did) { + logb.push(data.did) + } + + logstr = logb.join('\t') - logstr = logb.join('\t') - return logstr } - diff --git a/lib/options.js b/lib/options.js index 0fb11528..7b6420c3 100644 --- a/lib/options.js +++ b/lib/options.js @@ -52,7 +52,8 @@ module.exports = function(callmodule, defaults, orig_initial) { sourcemap.loaded = load_options(from) } - // options debug.argv allows for testing + // Option debug.argv allows for testing. + // First two elements are stripped! var argv = Minimist( ((initial && initial.debug && initial.debug.argv) || process.argv).slice( 2 @@ -96,6 +97,10 @@ module.exports = function(callmodule, defaults, orig_initial) { sourcemap.env.test = env.SENECA_TEST } + if (env.SENECA_QUIET) { + sourcemap.env.quiet = env.SENECA_QUIET + } + if (argv.seneca) { if (_.isObject(argv.seneca.options)) { sourcemap.argv = argv.seneca.options @@ -155,9 +160,6 @@ module.exports = function(callmodule, defaults, orig_initial) { // boolean corrections out.legacy.logging = Common.boolify(out.legacy.logging) - - //console.log('LOAD OPTS LOG', out.log) - return out } @@ -169,29 +171,19 @@ module.exports = function(callmodule, defaults, orig_initial) { function parse_command_line_log(spec, parsedSpec) { var logSpec = _.isArray(spec) ? spec[0] : spec - //console.log('PCLL logSpec', logSpec) - if (_.isString(logSpec)) { try { parsedSpec.log = Jsonic(logSpec) } catch (e) { - console.log(e.message) parsedSpec.log = logSpec } - - //console.log('PCLL str', parsedSpec) - - } - - else if (_.isObject(logSpec)) { + } else if (_.isObject(logSpec)) { parsedSpec.log = {} var logType = Object.keys(logSpec.level || logSpec) if (logType.length > 0) { parsedSpec.log = { level: logType[0] } } } - - //console.log('PCLL obj', parsedSpec) } function set_options(input) { @@ -200,10 +192,12 @@ module.exports = function(callmodule, defaults, orig_initial) { // DEPRECATED: Remove when Seneca >= 4.x if (_.isString(input)) { options = prepare(basemodule, defaults, input) + } else if (input.reload$) { + options = prepare(basemodule, defaults, input) } else { options = Common.deepextend(options, input) } - + return options } diff --git a/lib/outward.js b/lib/outward.js index 86c34702..13ba08c7 100644 --- a/lib/outward.js +++ b/lib/outward.js @@ -135,11 +135,11 @@ function outward_announce(ctxt, data) { // if (!ctxt.actdef) return var meta = data.meta - - if(meta.error) { + + if (meta.error) { return } - + if (_.isFunction(ctxt.seneca.on_act_out)) { ctxt.seneca.on_act_out(ctxt.actdef, data.res, data.meta) } diff --git a/lib/plugins.js b/lib/plugins.js index 2f925e71..3775134d 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -28,7 +28,7 @@ module.exports.register = function(callpoint) { var so = seneca.options() var define_callpoint = callpoint(true) - + // NOTE: `define` is the property for the plugin definition action. // The property `init` will be deprecated in 4.x plugin.define = plugin.define || plugin.init @@ -301,7 +301,7 @@ function make_delegate(instance, plugin) { } ) */ - + delegate.die = Common.makedie(delegate, { type: 'plugin', plugin: plugin.name @@ -436,7 +436,6 @@ function resolve_plugin_exports(seneca, fullname, meta) { seneca.private$.action_modifiers.push(meta.extend.action_modifier) } - // FIX: needs to use logging.load_logger if (_.isFunction(meta.extend.logger)) { if ( diff --git a/package.json b/package.json index 516caa59..0efac2d2 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ }, "main": "seneca.js", "scripts": { - "test": "lab -v -P test -L -t 85 ", + "test": "lab -v -P test -L -t 90", "coveralls": "lab -s -P test -r lcov | coveralls", "coverage": "lab -v -P test -L -t 85 -r html > docs/coverage.html", "smoke": "node test/stubs/launch.js", diff --git a/seneca.js b/seneca.js index 90106643..2c18604c 100644 --- a/seneca.js +++ b/seneca.js @@ -32,7 +32,6 @@ const Print = require('./lib/print') const Actions = require('./lib/actions') const Transport = require('./lib/transport') - // Shortcuts. const errlog = Common.make_standard_err_log_entry const actlog = Common.make_standard_act_log_entry @@ -68,7 +67,7 @@ const option_defaults = { // Custom logger function, optional - see lib/logging.js logger: null, - + // Wait time for plugins to close gracefully. death_delay: 11111, @@ -405,9 +404,7 @@ function make_seneca(initial_options) { // Setup event handlers, if defined var event_names = ['log', 'act_in', 'act_out', 'act_err', 'ready', 'close'] - event_names.forEach(function( - event_name - ) { + event_names.forEach(function(event_name) { if ('function' === typeof start_opts.events[event_name]) { root$.on(event_name, start_opts.events[event_name]) } @@ -421,10 +418,14 @@ function make_seneca(initial_options) { private$.next_action_id = Common.autoincr() // These need to come from options as required during construction. - start_opts.internal.actrouter = start_opts.internal.actrouter || Patrun({ gex: true }) - start_opts.internal.subrouter = start_opts.internal.subrouter || Patrun({ gex: true }) + start_opts.internal.actrouter = + start_opts.internal.actrouter || Patrun({ gex: true }) + start_opts.internal.subrouter = + start_opts.internal.subrouter || Patrun({ gex: true }) - var callpoint = private$.callpoint = make_callpoint(start_opts.debug.callpoint) + var callpoint = (private$.callpoint = make_callpoint( + start_opts.debug.callpoint + )) // Define public member variables. root$.start_time = Date.now() @@ -472,7 +473,9 @@ function make_seneca(initial_options) { root$.inward = API.inward // Add a modifier function for messages inward root$.outward = API.outward // Add a modifier function for responses outward root$.error = API.error // Set global error handler, or generate Seneca Error - root$.fail = start_opts.legacy.fail ? Legacy.make_legacy_fail(start_opts) : API.fail // Throw a Seneca error + root$.fail = start_opts.legacy.fail + ? Legacy.make_legacy_fail(start_opts) + : API.fail // Throw a Seneca error root$.explain = API.explain // Toggle top level explain capture root$.decorate = API.decorate // Decorate seneca object with functions root$.seneca = API.seneca @@ -506,7 +509,8 @@ function make_seneca(initial_options) { // Identifier generator. root$.idgen = Nid({ length: start_opts.idlen }) start_opts.tag = start_opts.tag || option_defaults.tag - start_opts.tag = start_opts.tag === 'undefined' ? option_defaults.tag : start_opts.tag + start_opts.tag = + start_opts.tag === 'undefined' ? option_defaults.tag : start_opts.tag // Create a unique identifer for this instance. root$.id = @@ -544,7 +548,7 @@ function make_seneca(initial_options) { private$.exports = { options: start_opts } private$.decorations = {} - + //root$.make_log = make_log //root$.log = make_log(root$)//, make_default_log_modifier(root$)) @@ -635,18 +639,19 @@ function make_seneca(initial_options) { .add(Outward.announce) .add(Outward.act_error) - // Configure logging // Mark logger as being externally defined from options - if(start_opts.logger && 'object' === typeof(start_opts.logger)) { + if (start_opts.logger && 'object' === typeof start_opts.logger) { start_opts.logger.from_options$ = true } // Load logger and update log options var logspec = private$.logging.build_log(root$) - start_opts = private$.exports.options = private$.optioner.set({log:logspec}) - + start_opts = private$.exports.options = private$.optioner.set({ + log: logspec + }) + if (start_opts.test) { root$.test('string' === typeof start_opts.test ? start_opts.test : null) } @@ -695,7 +700,6 @@ function make_seneca(initial_options) { return root$ } - function api_add() { var self = this var private$ = self.private$ @@ -706,10 +710,10 @@ function api_add() { var pattern = self.util.clean(raw_pattern) var action = - args.action || - function default_action(msg, done, meta) { - done.call(this, null, meta.dflt || null) - } + args.action || + function default_action(msg, done, meta) { + done.call(this, null, meta.dflt || null) + } var actdef = self.util.deepextend(args.actdef) || {} @@ -720,11 +724,11 @@ function api_add() { actdef.plugin_fullname = actdef.plugin_fullname || actdef.plugin_name + - ((actdef.plugin_tag === '-' + ((actdef.plugin_tag === '-' ? void 0 : actdef.plugin_tag) - ? '$' + actdef.plugin_tag - : '') + ? '$' + actdef.plugin_tag + : '') actdef.plugin = { name: actdef.plugin_name, @@ -747,7 +751,7 @@ function api_add() { actdef.custom = Jsonic(raw_pattern.custom$ || {}) var strict_add = - raw_pattern.strict$ && raw_pattern.strict$.add !== null + raw_pattern.strict$ && raw_pattern.strict$.add !== null ? !!raw_pattern.strict$.add : !!opts.strict.add @@ -758,7 +762,7 @@ function api_add() { } var action_name = - null == action.name || '' === action.name ? 'action' : action.name + null == action.name || '' === action.name ? 'action' : action.name actdef.id = action_name + '_' + private$.next_action_id() actdef.name = action_name actdef.func = action @@ -782,8 +786,8 @@ function api_add() { // pattern does not submit all patterns into the handle if ( 'function' === typeof priordef.handle && - ((priordef.client && actdef.client) || - (!priordef.client && !actdef.client)) + ((priordef.client && actdef.client) || + (!priordef.client && !actdef.client)) ) { //priordef.handle(args.pattern, action) priordef.handle(actdef) @@ -831,7 +835,6 @@ function api_add() { return self } - function make_action_stats(actdef) { return { id: actdef.id, @@ -858,8 +861,6 @@ function deferred_modify_action(seneca, actdef) { }) } - - // Private member variables of Seneca object. function make_private() { return { @@ -886,19 +887,18 @@ function make_private() { // Callpoint resolver. Indicates location in calling code. function make_callpoint(active) { return function callpoint(override) { - if(active || override) { + if (active || override) { return error.callpoint(new Error(), [ '/seneca/seneca.js', '/seneca/lib/', '/lodash.js' ]) - } - else { + } else { return void 0 } } } - + intern.make_act_delegate = function(instance, opts, meta, actdef) { meta = meta || {} actdef = actdef || {} @@ -925,11 +925,10 @@ intern.make_act_delegate = function(instance, opts, meta, actdef) { if (meta.tx) { delegate.fixedargs.tx$ = meta.tx } - + return delegate } - // Perform an action. The properties of the first argument are matched against // known patterns, and the most specific one wins. function api_act() { @@ -948,10 +947,10 @@ function api_act() { msg.caller$ = '\n Action call arguments and location: ' + (new Error(Util.inspect(msg).replace(/\n/g, '')).stack + '\n') - .replace(/Error: /, '') - .replace(/.*\/gate-executor\.js:.*\n/g, '') - .replace(/.*\/seneca\.js:.*\n/g, '') - .replace(/.*\/seneca\/lib\/.*\.js:.*\n/g, '') + .replace(/Error: /, '') + .replace(/.*\/gate-executor\.js:.*\n/g, '') + .replace(/.*\/seneca\.js:.*\n/g, '') + .replace(/.*\/seneca\/lib\/.*\.js:.*\n/g, '') } do_act(self, opts, msg, reply) @@ -974,7 +973,6 @@ function api_wrap(pin, actdef, wrapper) { return this } - function do_act(instance, opts, origmsg, origreply) { var timedout = false var actmsg = intern.make_actmsg(origmsg) @@ -1040,9 +1038,6 @@ function do_act(instance, opts, origmsg, origreply) { instance.private$.ge.add(execspec) } - - - function api_fix(patargs, msgargs, custom) { var self = this @@ -1053,11 +1048,11 @@ function api_fix(patargs, msgargs, custom) { fix_delegate.add = function fix_add() { var args = Common.parsePattern(this, arguments, 'rest:.*', patargs) var addargs = [args.pattern] - .concat({ - fixed$: Object.assign({}, msgargs, args.pattern.fixed$), - custom$: Object.assign({}, custom, args.pattern.custom$) - }) - .concat(args.rest) + .concat({ + fixed$: Object.assign({}, msgargs, args.pattern.fixed$), + custom$: Object.assign({}, custom, args.pattern.custom$) + }) + .concat(args.rest) return self.add.apply(this, addargs) } @@ -1068,11 +1063,11 @@ function api_fix(patargs, msgargs, custom) { function api_options(options, chain) { var self = this var private$ = self.private$ - - if(null == options) { + + if (null == options) { return private$.optioner.get() } - + // self.log may not exist yet as .options() used during construction if (null != options && self.log) { self.log.debug({ @@ -1082,12 +1077,14 @@ function api_options(options, chain) { }) } - var out_opts = private$.exports.options = private$.optioner.set(options) - + var out_opts = (private$.exports.options = private$.optioner.set(options)) + // Update logging configuration - if(null != options && options.log) { + if (null != options && options.log) { var logspec = private$.logging.build_log(self) - out_opts = private$.exports.options = private$.optioner.set({log:logspec}) + out_opts = private$.exports.options = private$.optioner.set({ + log: logspec + }) } // DEPRECATED @@ -1105,8 +1102,6 @@ function api_options(options, chain) { return chain ? self : out_opts } - - intern.execute_action = function( execspec, act_instance, diff --git a/test/logging.test.js b/test/logging.test.js index 76d473ca..db907cec 100644 --- a/test/logging.test.js +++ b/test/logging.test.js @@ -14,7 +14,6 @@ var it = Shared.make_it(lab) var Seneca = require('..') var Logging = require('../lib/logging') - describe('logging', function() { it('happy', function(fin) { var capture = make_log_capture() @@ -38,7 +37,7 @@ describe('logging', function() { }) it('happy-ng', function(fin) { - var capture = make_log_capture({legacy:false}) + var capture = make_log_capture({ legacy: false }) Seneca({ log: 'all', internal: { logger: capture } }) .error(fin) @@ -59,58 +58,61 @@ describe('logging', function() { }) it('level-text-values', function(fin) { - var capture = make_log_capture({legacy:false}) + var capture = make_log_capture({ legacy: false }) var options = Seneca() - .test(fin) - .options() + .test(fin) + .options() // console.log('OPTS', options) - + // ensure text-level mapping is reversible - Object.keys(options.log.text_level).forEach(text=>{ + Object.keys(options.log.text_level).forEach(text => { expect(options.log.level_text[options.log.text_level[text]]).equal(text) }) - + fin() }) - it('build_log_spec', function(fin) { - var msi = (opts)=>{return {options:()=>{return opts}}} + var msi = opts => { + return { + options: () => { + return opts + } + } + } var out var logging = Logging() - - out = logging.build_log_spec(msi({log:'test'})) - expect(out).contains({level:'warn', live_level:400}) - out = logging.build_log_spec(msi({log:'quiet'})) - expect(out).contains({level:'none', live_level:999}) + out = logging.build_log_spec(msi({ log: 'test' })) + expect(out).contains({ level: 'warn', live_level: 400 }) - out = logging.build_log_spec(msi({log:'any'})) - expect(out).contains({level:'all', live_level:100}) + out = logging.build_log_spec(msi({ log: 'quiet' })) + expect(out).contains({ level: 'none', live_level: 999 }) - out = logging.build_log_spec(msi({log:'debug'})) - expect(out).contains({level:'debug', live_level:200}) + out = logging.build_log_spec(msi({ log: 'any' })) + expect(out).contains({ level: 'all', live_level: 100 }) - out = logging.build_log_spec(msi({log:'fatal'})) - expect(out).contains({level:'fatal', live_level:600}) + out = logging.build_log_spec(msi({ log: 'debug' })) + expect(out).contains({ level: 'debug', live_level: 200 }) + out = logging.build_log_spec(msi({ log: 'fatal' })) + expect(out).contains({ level: 'fatal', live_level: 600 }) - out = logging.build_log_spec(msi({log:'300'})) - expect(out).contains({level:'info', live_level:300}) + out = logging.build_log_spec(msi({ log: '300' })) + expect(out).contains({ level: 'info', live_level: 300 }) - out = logging.build_log_spec(msi({log:300})) - expect(out).contains({level:'info', live_level:300}) + out = logging.build_log_spec(msi({ log: 300 })) + expect(out).contains({ level: 'info', live_level: 300 }) - out = logging.build_log_spec(msi({log:301})) - expect(out).contains({level:'301', live_level:301}) + out = logging.build_log_spec(msi({ log: 301 })) + expect(out).contains({ level: '301', live_level: 301 }) fin() }) - it('event', function(fin) { var loga = [] var logb = [] @@ -144,7 +146,6 @@ describe('logging', function() { }) }) - it('quiet', function(fin) { Seneca() .quiet() @@ -152,7 +153,16 @@ describe('logging', function() { .ready(fin) }) - + it('bad_logspec', function(fin) { + try { + Seneca({ log: true }) + Code.fail() + } catch (e) { + expect(e.code).equal('bad_logspec') + fin() + } + }) + // DEPRECATED it('basic', function(fin) { var capture = make_log_capture() @@ -164,7 +174,7 @@ describe('logging', function() { }) .act('a:1', function() { expect(this.seneca).to.exist() - this.log({ seen: 'a:1', level:'info' }) + this.log({ seen: 'a:1', level: 'info' }) }) .ready(function() { var log = capture.log.filter(function(entry) { @@ -175,10 +185,138 @@ describe('logging', function() { }) }) + it('logger-output', function(fin) { + var log + + var stdout_write = process.stdout.write + // Note: comment out to see logs to debug test + process.stdout.write = function(data) { + log.push(data.toString()) + } + + function restore(err) { + console.log('RESTORE', err) + if (err && err.message && !err.message.includes('a1')) { + console.log('FLAT LOGGER ERROR', err, log) + process.stdout.write = stdout_write + fin(err) + } else if (true === err) { + process.stdout.write = stdout_write + } + } + + // NOTE: call func directly to debug test + // NOTE: tests: [flat, test] (hardcoded in `error`) + basic('flat') + + function basic(logger) { + log = [] + Seneca({ + log: { level: 'debug', logger: logger }, + legacy: { transport: false } + }) + .error(restore) + .add('a:1', a1) + .act('a:1') + .use(function foo() { + this.add('b:1', function b1(m, r) { + r({ x: 1 }) + }) + }) + .act('b:1') + .ready(function() { + expect(log.length).above(20) + + entry(logger) + }) + } + + function entry(logger) { + log = [] + Seneca({ + log: { level: 'debug', logger: logger }, + legacy: { transport: false } + }) + .error(restore) + .add('a:1', function a1(m, r) { + this.log({ + maxlen$: 111, + depth$: 4, + a: { b: { c: { d: { e: { f: 1 } } } } } + }) + this.log.debug( + 'foo', + ['bar'], + { zed: 1 }, + true, + 101, + NaN, + /re/, + new Date(), + null, + void 0 + ) + this.log.info('eek!', m, r) + this.log({ + isot: 1, + when: 2, + level_name: 3, + seneca_id: 4, + seneca_did: 5, + plugin_name: 6, + pugin_tag: 7, + kind: 8, + actid: 9, + pattern: 10, + action: 11, + idpath: 12 + }) + r({ x: 1 }) + }) + .act('a:1') + .use(function foo$t0() { + this.add('b:1', function b1(m, r) { + r({ y: 1 }) + }) + }) + .act('b:1') + .ready(function() { + expect(log.length).above(20) + + error(logger) + }) + } + + // TODO: why are there spurious lines to actual stdout? + function error(logger) { + log = [] + Seneca({ + log: { level: 'debug', logger: logger }, + legacy: { transport: false } + }) + .error(restore) + .add('a:1', function(m, r) { + r(new Error('a1')) + }) + .act('a:1') + .ready(function() { + expect(log.length).above(10) + + if ('flat' === logger) { + basic('test') + } else { + restore(true) + fin() + } + }) + } + }) it('shortcuts', function(fin) { var log + var stdout_write = process.stdout.write + // Note: comment out to see logs to debug test process.stdout.write = function(data) { log.push(data.toString()) } @@ -186,13 +324,14 @@ describe('logging', function() { function restore(err) { process.stdout.write = stdout_write - if(err) { - console.log('ERROR', log) + if (err) { + console.log('SHORTCUTS ERROR', log) } - + fin(err) } + // NOTE: call shortcut directly to debug test nothing() function nothing() { @@ -281,6 +420,47 @@ describe('logging', function() { // remove legacy-transport entry in 4.x expect(log.length).to.equal(2) + json() + }) + } + + // DEPRECATED DEFAULT = 4.x will change to 'flat' + function json() { + log = [] + Seneca() + // Seneca( {log:'json'}) - change to this in 4.x + .error(restore) + .add('a:1', a1) + .act('a:1') + .ready(function() { + expect(log.length).to.equal(2) + + flat() + }) + } + + function flat() { + log = [] + Seneca({ log: 'flat' }) // should not be needed in 4.x + .error(restore) + .add('a:1', a1) + .act('a:1') + .ready(function() { + expect(log.length).to.equal(2) + + logger_test() + }) + } + + function logger_test() { + log = [] + Seneca({ logger: 'test' }) + .error(restore) + .add('a:1', a1) + .act('a:1') + .ready(function() { + expect(log.length).to.equal(2) + do_test() }) } @@ -298,12 +478,11 @@ describe('logging', function() { } }) - it('test-mode-basic', function(fin) { var capture = make_log_capture() // Note: capture logger is marked from_options$ so overrides test_logger - Seneca({logger:capture}) + Seneca({ logger: capture }) .test() .add('a:1', function a1(msg, reply) { // test mode log level is warn @@ -313,17 +492,16 @@ describe('logging', function() { .act('a:1') .ready(function() { // only warn should appear - expect(capture.log.map(x=>x.data[0])).equal(['a1']) + expect(capture.log.map(x => x.data[0])).equal(['a1']) fin() }) }) - it('test-mode-option', function(fin) { var capture = make_log_capture() // Note: capture logger is marked from_options$ so overrides test_logger - Seneca({logger:capture, test:true}) + Seneca({ logger: capture, test: true }) .add('a:2', function a2(msg, reply) { // test mode log level is warn this.log.warn('a2') @@ -332,50 +510,299 @@ describe('logging', function() { .act('a:2') .ready(function() { // only warn should appear - expect(capture.log.map(x=>x.data[0])).equal(['a2']) + expect(capture.log.map(x => x.data[0])).equal(['a2']) fin() }) }) + it('test-mode-argv', function(fin) { + var capture = make_log_capture() + Seneca({ logger: capture, debug: { argv: ['', '', '--seneca.test'] } }) + .add('a:1', function a1(msg, reply) { + this.log.warn('a1') + reply() + }) + .act('a:1') + .ready(function() { + expect(capture.log.map(x => x.data[0])).equal(['a1']) + fin() + }) + }) + // FIX: this should work + it('test-mode-argv-opts', function(fin) { + var capture = make_log_capture() + Seneca({ + logger: capture, + debug: { argv: ['', '', '--seneca.options.test'] } + }) + .add('a:1', function a1(msg, reply) { + this.log.warn('a1') + reply() + }) + .act('a:1') + .ready(function() { + //console.log(this.options().log) + //console.log(capture.log) + expect(capture.log.map(x => x.data[0])).equal(['a1']) + fin() + }) + }) + it('test-mode-env', function(fin) { + var capture = make_log_capture() + Seneca({ logger: capture, debug: { env: { SENECA_TEST: 'test' } } }) + .add('a:1', function a1(msg, reply) { + this.log.warn('a1') + reply() + }) + .act('a:1') + .ready(function() { + expect(capture.log.map(x => x.data[0])).equal(['a1']) + fin() + }) + }) + it('quiet-mode-basic', function(fin) { + var capture = make_log_capture() + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture }) + .quiet() + .add('a:1', function a1(msg, reply) { + this.log.warn('a1') + reply() + }) + .act('a:1') + .ready(function() { + expect(capture.log.length).equal(0) + fin() + }) + }) - /* FIX - it('test-mode-argv', function(fin) { + it('quiet-mode-option', function(fin) { var capture = make_log_capture() - Seneca({logger:capture, debug:{argv:['--seneca.test']}}) + + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture, quiet: true }) .add('a:1', function a1(msg, reply) { this.log.warn('a1') reply() }) .act('a:1') .ready(function() { - console.log(capture.log) - expect(capture.log.map(x=>x.data[0])).equal(['a1']) + expect(capture.log.length).equal(0) fin() }) }) - */ - - /* - it('test-mode-env', function(fin) { + + it('quiet-mode-argv', function(fin) { + var capture = make_log_capture() + Seneca({ logger: capture, debug: { argv: ['', '', '--seneca.quiet'] } }) + .add('a:1', function a1(msg, reply) { + this.log.warn('a1') + reply() + }) + .act('a:1') + .ready(function() { + expect(capture.log.length).equal(0) + fin() + }) + }) + + it('quiet-mode-argv-opts', function(fin) { + var capture = make_log_capture() + Seneca({ + logger: capture, + debug: { argv: ['', '', '--seneca.options.quiet'] } + }) + .add('a:1', function a1(msg, reply) { + this.log.warn('a1') + reply() + }) + .act('a:1') + .ready(function() { + expect(capture.log.length).equal(0) + fin() + }) + }) + + it('quiet-mode-env', function(fin) { + var capture = make_log_capture() + Seneca({ logger: capture, debug: { env: { SENECA_QUIET: 'true' } } }) + .add('a:1', function a1(msg, reply) { + this.log.warn('a1') + reply() + }) + .act('a:1') + .ready(function() { + expect(capture.log.length).equal(0) + fin() + }) + }) + + it('test-quiet-mode-basic', function(fin) { + var capture = make_log_capture() + + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture }) + .test() + .add('a:1', function a1(msg, reply) { + // test mode log level is warn + this.log.warn('a1') + reply() + }) + .act('a:1') + .quiet() + .act('a:1') + .ready(function() { + // NO LOGS - quiet called synchronously! + expect(capture.log.length).equal(0) + fin() + }) + }) + + it('quiet-test-mode-basic', function(fin) { var capture = make_log_capture() - Seneca({logger:capture, debug:{env:{SENECA_TEST:'true'}}}) + + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture }) + .quiet() .add('a:1', function a1(msg, reply) { + // test mode log level is warn this.log.warn('a1') reply() }) .act('a:1') + .test() + .act('a:1') .ready(function() { - console.log(capture.log) - expect(capture.log.map(x=>x.data[0])).equal(['a1']) + // BOTH LOGGED - test called synchronously! + expect(capture.log.length).equal(2) + fin() + }) + }) + + it('test-ready-quiet-mode-basic', function(fin) { + var capture = make_log_capture() + + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture }) + .test() + .add('a:1', function a1(msg, reply) { + // test mode log level is warn + this.log.warn('a1x' + msg.x) + reply() + }) + .act('a:1,x:1') + .ready(function() { + this.quiet().ready(function() { + this.act('a:1,x:2') + + expect(capture.log.length).equal(1) + expect(capture.log[0].data).equal(['a1x1']) + fin() + }) + }) + }) + + it('quiet-ready-test-mode-basic', function(fin) { + var capture = make_log_capture() + + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture }) + .quiet() + .add('a:1', function a1(msg, reply) { + // test mode log level is warn + this.log.warn('a1x' + msg.x) + reply() + }) + .act('a:1,x:1') + .ready(function() { + this.test() + + this.act('a:1,x:2').ready(function() { + expect(capture.log.length).equal(1) + expect(capture.log[0].data).equal(['a1x2']) + + fin() + }) + }) + }) + + it('quiet-argv-override', function(fin) { + var capture = make_log_capture() + + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture, debug: { argv: ['', '', '--seneca.test'] } }) + .quiet() + .add('a:1', function a1(msg, reply) { + // test mode log level is warn + this.log.warn('a1x' + msg.x) + reply() + }) + .act('a:1,x:1') + .ready(function() { + expect(capture.log.length).equal(1) + expect(capture.log[0].data).equal(['a1x1']) + fin() + }) + }) + + it('test-argv-override', function(fin) { + var capture = make_log_capture() + + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture, debug: { argv: ['', '', '--seneca.quiet'] } }) + .test() + .add('a:1', function a1(msg, reply) { + // test mode log level is warn + this.log.warn('a1x' + msg.x) + reply() + }) + .act('a:1,x:1') + .ready(function() { + expect(capture.log.length).equal(0) + fin() + }) + }) + + it('quiet-env-override', function(fin) { + var capture = make_log_capture() + + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture, debug: { env: { SENECA_TEST: 'true' } } }) + .quiet() + .add('a:1', function a1(msg, reply) { + // test mode log level is warn + this.log.warn('a1x' + msg.x) + reply() + }) + .act('a:1,x:1') + .ready(function() { + expect(capture.log.length).equal(1) + expect(capture.log[0].data).equal(['a1x1']) + fin() + }) + }) + + it('test-env-override', function(fin) { + var capture = make_log_capture() + + // Note: capture logger is marked from_options$ so overrides test_logger + Seneca({ logger: capture, debug: { env: { SENECA_QUIET: 'true' } } }) + .test() + .add('a:1', function a1(msg, reply) { + // test mode log level is warn + this.log.warn('a1x' + msg.x) + reply() + }) + .act('a:1,x:1') + .ready(function() { + expect(capture.log.length).equal(0) fin() }) }) - */ - }) function a1(msg, reply) { @@ -390,30 +817,29 @@ function make_log_capture(flags) { return capture } - function Capture(flags) { var self = this self.id = Math.random() self.log = [] - + self.preload = function() { var seneca = this var so = seneca.options() self.spec = so.log - + var legacy_logger = function(seneca, entry) { self.log.push(entry) } - + var nextgen_logger = function(entry) { self.log.push(entry) } - + var capture_logger = false === flags.legacy ? nextgen_logger : legacy_logger //console.log(capture_logger) capture_logger.id = self.id - + return { extend: { logger: capture_logger diff --git a/test/seneca-options.test.js b/test/seneca-options.test.js index ef693e9d..7edc86c3 100644 --- a/test/seneca-options.test.js +++ b/test/seneca-options.test.js @@ -88,13 +88,12 @@ describe('seneca --seneca.log arguments tests: ', function() { try { Seneca(opts) Code.fail() - } - catch(e) { + } catch (e) { console.log(e) - expect(e.code).equal('bad-logspec-string') + expect(e.code).equal('bad_logspec_string') fin() } - + done() })