diff --git a/bin/bunyan b/bin/bunyan index 0a36cef..11045dd 100755 --- a/bin/bunyan +++ b/bin/bunyan @@ -147,10 +147,14 @@ function printHelp() { util.puts(" -l, --level LEVEL"); util.puts(" Only show messages at or above the specified level."); util.puts(" (See 'Log Levels' below.)"); + util.puts(" -c, --condition CONDITION"); + util.puts(" Run each log message through the condition"); + util.puts(" and only show those that resolve to a truish value."); util.puts(""); util.puts("Log Levels:"); util.puts(" Either numeric values or their associated strings are valid for the"); - util.puts(" -l --level argument."); + util.puts(" -l --level argument. However, --condition scripts will see a numeric"); + util.puts(" 'level' value, not a string."); util.puts(""); Object.keys(levelFromName).forEach(function(name) { var n = name; @@ -196,6 +200,14 @@ function filterRecord(rec, opts) return false; } + if (opts.conditions) { + for (var i = 0; i < opts.conditions.length; i++) { + var pass = opts.conditions[i].runInNewContext(rec); + if (!pass) + return false; + } + } + return true; } @@ -276,13 +288,14 @@ function parseArgv(argv) { color: process.stdout.isTTY, outputMode: OM_PAUL, jsonIndent: 2, - level: -Infinity + level: -Infinity, + conditions: null }; // Turn '-iH' into '-i -H', except for argument-accepting options. var args = argv.slice(2); // drop ['node', 'scriptname'] var newArgs = []; - var optTakesArg = {'d': true, 'o': true, 'l': true}; + var optTakesArg = {'d': true, 'o': true, 'c': true, 'l': true}; for (var i = 0; i < args.length; i++) { if (args[i].charAt(0) === "-" && args[i].charAt(1) !== '-' && args[i].length > 2) { var splitOpts = args[i].slice(1).split(""); @@ -353,6 +366,14 @@ function parseArgv(argv) { } parsed.level = level; break; + case "-c": + case "--condition": + var condition = args.shift(); + parsed.conditions = parsed.conditions || [] + var scriptName = 'bunyan-condition-'+parsed.conditions.length; + var script = vm.createScript(condition, scriptName); + parsed.conditions.push(script); + break default: // arguments if (!endOfOptions && arg.length > 0 && arg[0] === '-') { throw new Error("unknown option '"+arg+"'"); diff --git a/test/cli.test.js b/test/cli.test.js index 89cf860..2a7ac09 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -226,3 +226,51 @@ test('--level 40', function (t) { }); }); }); + +test('--condition "level === 10 && pid === 123"', function (t) { + var expect = [ + '# levels\n', + '[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(''); + exec(BUNYAN + ' -c "level === 10 && pid === 123" corpus/all.log', + function (err, stdout, stderr) { + t.error(err); + t.equal(stdout, expect); + t.end(); + exec(BUNYAN + ' --condition "level === 10 && pid === 123" corpus/all.log', + function (err, stdout, stderr) { + t.error(err); + t.equal(stdout, expect); + t.end(); + }); + }); +}); + +// multiple +// not sure if this is a bug or a feature. let's call it a feature! +test('multiple --conditions', function (t) { + var expect = [ + '# levels\n', + '[2012-02-08T22:56:53.856Z] WARN: myservice/1 on example.com: My message\n', + '\n', + '# extra fields\n', + '\n', + '# bogus\n', + 'not a JSON line\n', + '{"hi": "there"}\n' + ].join(''); + t.end(); + exec(BUNYAN + ' test/corpus/all.log ' + + '-c "if (level === 40) pid = 1; true" ' + + '-c "pid === 1"', function (err, stdout, stderr) { + t.error(err); + t.equal(stdout, expect); + t.end(); + }); +});