Merge pull request #154 from pfmooney/GH-87
Fix #87 - nuke vm.runInNewContext condition filtering
This commit is contained in:
commit
02c1d042e9
3 changed files with 116 additions and 51 deletions
61
bin/bunyan
61
bin/bunyan
|
@ -276,9 +276,16 @@ function filterRecord(rec, opts)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.conditions) {
|
if (opts.condFuncs) {
|
||||||
for (var i = 0; i < opts.conditions.length; i++) {
|
var recCopy = objCopy(rec);
|
||||||
var pass = opts.conditions[i].runInNewContext(rec);
|
for (var i = 0; i < opts.condFuncs.length; i++) {
|
||||||
|
var pass = opts.condFuncs[i].call(recCopy);
|
||||||
|
if (!pass)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (opts.condVm) {
|
||||||
|
for (var i = 0; i < opts.condVm.length; i++) {
|
||||||
|
var pass = opts.condVm[i].runInNewContext(rec);
|
||||||
if (!pass)
|
if (!pass)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -348,6 +355,33 @@ function emitNextRecord(opts, stylize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a function for the given JS code that returns.
|
||||||
|
*
|
||||||
|
* If no 'return' in the given javascript snippet, then assume we are a single
|
||||||
|
* statement and wrap in 'return (...)'. This is for convenience for short
|
||||||
|
* '-c ...' snippets.
|
||||||
|
*/
|
||||||
|
function funcWithReturnFromSnippet(js) {
|
||||||
|
// auto-"return"
|
||||||
|
if (js.indexOf('return') === -1) {
|
||||||
|
if (js.substring(js.length - 1) === ';') {
|
||||||
|
js = js.substring(0, js.length - 1);
|
||||||
|
}
|
||||||
|
js = 'return (' + js + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose level definitions to condition func context
|
||||||
|
var varDefs = [];
|
||||||
|
Object.keys(upperNameFromLevel).forEach(function (lvl) {
|
||||||
|
varDefs.push(format('var %s = %d;',
|
||||||
|
upperNameFromLevel[lvl], lvl));
|
||||||
|
});
|
||||||
|
varDefs = varDefs.join('\n') + '\n';
|
||||||
|
|
||||||
|
return (new Function(varDefs + js));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the command-line options and arguments into an object.
|
* Parse the command-line options and arguments into an object.
|
||||||
*
|
*
|
||||||
|
@ -400,6 +434,7 @@ function parseArgv(argv) {
|
||||||
}
|
}
|
||||||
args = newArgs;
|
args = newArgs;
|
||||||
|
|
||||||
|
// Expose level definitions to condition vm context
|
||||||
var condDefines = [];
|
var condDefines = [];
|
||||||
Object.keys(upperNameFromLevel).forEach(function (lvl) {
|
Object.keys(upperNameFromLevel).forEach(function (lvl) {
|
||||||
condDefines.push(
|
condDefines.push(
|
||||||
|
@ -495,18 +530,21 @@ function parseArgv(argv) {
|
||||||
case '-c':
|
case '-c':
|
||||||
case '--condition':
|
case '--condition':
|
||||||
var condition = args.shift();
|
var condition = args.shift();
|
||||||
parsed.conditions = parsed.conditions || [];
|
if (Boolean(process.env.JSON_EXEC &&
|
||||||
var scriptName = 'bunyan-condition-'+parsed.conditions.length;
|
process.env.JSON_EXEC === 'vm')) {
|
||||||
|
parsed.condVm = parsed.condVm || [];
|
||||||
|
var scriptName = 'bunyan-condition-'+parsed.condVm.length;
|
||||||
var code = condDefines + condition;
|
var code = condDefines + condition;
|
||||||
|
var script;
|
||||||
try {
|
try {
|
||||||
var script = vm.createScript(code, scriptName);
|
script = vm.createScript(code, scriptName);
|
||||||
} catch (compileErr) {
|
} catch (complErr) {
|
||||||
throw new Error(format('illegal CONDITION code: %s\n'
|
throw new Error(format('illegal CONDITION code: %s\n'
|
||||||
+ ' CONDITION script:\n'
|
+ ' CONDITION script:\n'
|
||||||
+ '%s\n'
|
+ '%s\n'
|
||||||
+ ' Error:\n'
|
+ ' Error:\n'
|
||||||
+ '%s',
|
+ '%s',
|
||||||
compileErr, indent(code), indent(compileErr.stack)));
|
complErr, indent(code), indent(complErr.stack)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure this is a reasonably safe CONDITION.
|
// Ensure this is a reasonably safe CONDITION.
|
||||||
|
@ -527,8 +565,11 @@ function parseArgv(argv) {
|
||||||
indent(condErr.stack)
|
indent(condErr.stack)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
parsed.condVm.push(script);
|
||||||
parsed.conditions.push(script);
|
} else {
|
||||||
|
parsed.condFuncs = parsed.condFuncs || [];
|
||||||
|
parsed.condFuncs.push(funcWithReturnFromSnippet(condition));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default: // arguments
|
default: // arguments
|
||||||
if (!endOfOptions && arg.length > 0 && arg[0] === '-') {
|
if (!endOfOptions && arg.length > 0 && arg[0] === '-') {
|
||||||
|
|
|
@ -18,19 +18,24 @@ if (fs.statSync(FILENAME).mode & S_IWUSR) {
|
||||||
fs.chmodSync(FILENAME, 0444);
|
fs.chmodSync(FILENAME, 0444);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.warn('- Create logger.')
|
console.warn('- Create logger.');
|
||||||
var log = bunyan.createLogger({name: 'handle-fs-error', streams: [{path: FILENAME}]});
|
var log = bunyan.createLogger({
|
||||||
|
name: 'handle-fs-error',
|
||||||
|
streams: [
|
||||||
|
{path: FILENAME}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
log.on('error', function (err) {
|
log.on('error', function (err) {
|
||||||
console.warn('- The logger emitted an error:', err);
|
console.warn('- The logger emitted an error:', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.warn('- Call log.info(...).')
|
console.warn('- Call log.info(...).');
|
||||||
log.info('info log message');
|
log.info('info log message');
|
||||||
console.warn('- Called log.info(...).')
|
console.warn('- Called log.info(...).');
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
console.warn('- Call log.warn(...).')
|
console.warn('- Call log.warn(...).');
|
||||||
log.warn('warn log message');
|
log.warn('warn log message');
|
||||||
console.warn('- Called log.warn(...).')
|
console.warn('- Called log.warn(...).');
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
|
@ -280,7 +280,7 @@ test('--level 40', function (t) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('--condition "level === 10 && pid === 123"', function (t) {
|
test('--condition "this.level === 10 && this.pid === 123"', function (t) {
|
||||||
var expect = [
|
var expect = [
|
||||||
'# levels\n',
|
'# levels\n',
|
||||||
/* JSSTYLED */
|
/* JSSTYLED */
|
||||||
|
@ -292,14 +292,14 @@ test('--condition "level === 10 && pid === 123"', function (t) {
|
||||||
'not a JSON line\n',
|
'not a JSON line\n',
|
||||||
'{"hi": "there"}\n'
|
'{"hi": "there"}\n'
|
||||||
].join('');
|
].join('');
|
||||||
var cmd = _('%s -c "level === 10 && pid === 123" %s/corpus/all.log',
|
var cmd = _('%s -c "this.level === 10 && this.pid === 123"'
|
||||||
BUNYAN, __dirname);
|
+ ' %s/corpus/all.log', BUNYAN, __dirname);
|
||||||
exec(cmd, function (err, stdout, stderr) {
|
exec(cmd, function (err, stdout, stderr) {
|
||||||
t.ifError(err);
|
t.ifError(err);
|
||||||
t.equal(stdout, expect);
|
t.equal(stdout, expect);
|
||||||
var cmd = _(
|
var cmd = _(
|
||||||
'%s --condition "level === 10 && pid === 123" %s/corpus/all.log',
|
'%s --condition "this.level === 10 && this.pid === 123"'
|
||||||
BUNYAN, __dirname);
|
+ ' %s/corpus/all.log', BUNYAN, __dirname);
|
||||||
exec(cmd, function (err, stdout, stderr) {
|
exec(cmd, function (err, stdout, stderr) {
|
||||||
t.ifError(err);
|
t.ifError(err);
|
||||||
t.equal(stdout, expect);
|
t.equal(stdout, expect);
|
||||||
|
@ -308,13 +308,34 @@ test('--condition "level === 10 && pid === 123"', function (t) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('--condition "this.level === TRACE', function (t) {
|
||||||
|
var expect = [
|
||||||
|
'# levels\n',
|
||||||
|
/* JSSTYLED */
|
||||||
|
'[2012-02-08T22:56:50.856Z] TRACE: myservice/123 on example.com: My message\n',
|
||||||
|
'\n',
|
||||||
|
'# extra fields\n',
|
||||||
|
'\n',
|
||||||
|
'# bogus\n',
|
||||||
|
'not a JSON line\n',
|
||||||
|
'{"hi": "there"}\n'
|
||||||
|
].join('');
|
||||||
|
var cmd = _('%s -c "this.level === TRACE" %s/corpus/all.log',
|
||||||
|
BUNYAN, __dirname);
|
||||||
|
exec(cmd, function (err, stdout, stderr) {
|
||||||
|
t.ifError(err);
|
||||||
|
t.equal(stdout, expect);
|
||||||
|
t.done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// multiple
|
// multiple
|
||||||
// not sure if this is a bug or a feature. let's call it a feature!
|
// not sure if this is a bug or a feature. let's call it a feature!
|
||||||
test('multiple --conditions', function (t) {
|
test('multiple --conditions', function (t) {
|
||||||
var expect = [
|
var expect = [
|
||||||
'# levels\n',
|
'# levels\n',
|
||||||
/* JSSTYLED */
|
/* JSSTYLED */
|
||||||
'[2012-02-08T22:56:53.856Z] WARN: myservice/1 on example.com: My message\n',
|
'[2012-02-08T22:56:53.856Z] WARN: myservice/123 on example.com: My message\n',
|
||||||
'\n',
|
'\n',
|
||||||
'# extra fields\n',
|
'# extra fields\n',
|
||||||
'\n',
|
'\n',
|
||||||
|
@ -322,10 +343,8 @@ test('multiple --conditions', function (t) {
|
||||||
'not a JSON line\n',
|
'not a JSON line\n',
|
||||||
'{"hi": "there"}\n'
|
'{"hi": "there"}\n'
|
||||||
].join('');
|
].join('');
|
||||||
exec(_('%s %s/corpus/all.log ' +
|
exec(_('%s %s/corpus/all.log -c "this.level === 40" -c "this.pid === 123"',
|
||||||
'-c "if (level === 40) pid = 1; true" ' +
|
BUNYAN, __dirname), function (err, stdout, stderr) {
|
||||||
'-c "pid === 1"', BUNYAN, __dirname),
|
|
||||||
function (err, stdout, stderr) {
|
|
||||||
t.ifError(err);
|
t.ifError(err);
|
||||||
t.equal(stdout, expect);
|
t.equal(stdout, expect);
|
||||||
t.end();
|
t.end();
|
||||||
|
|
Loading…
Reference in a new issue