From 79e5ded839886386e07d75f4ecab3fc92f24805e Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Thu, 1 Nov 2012 23:49:09 -0700 Subject: [PATCH] 'bunyan -p PID' support --- CHANGES.md | 7 +++-- TODO.md | 1 + bin/bunyan | 74 +++++++++++++++++++++++++++++++++++++++++++--- docs/bunyan.1 | 35 ++++++++++++++++++++-- docs/bunyan.1.html | 35 ++++++++++++++++++++-- docs/bunyan.1.ronn | 28 ++++++++++++++++++ lib/bunyan.js | 2 +- package.json | 2 +- 8 files changed, 172 insertions(+), 12 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d00ea81..929b7b0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,11 @@ # bunyan Changelog -## bunyan 0.15.1 (not yet released) +## bunyan 0.16.0 (not yet released) -(nothing yet) +- Add `bunyan -p PID` support. This is a convenience wrapper that effectively + calls: + + dtrace -x strsize=4k -qn 'bunyan$PID:::log-*{printf("%s", copyinstr(arg0))}' | bunyan ## bunyan 0.15.0 diff --git a/TODO.md b/TODO.md index 33c7c73..db1877e 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,4 @@ +- -p PID: proper handling of '-l level' - "all" or "off" levels? log4j? logging.py? logging.py has NOTSET === 0. I think that is only needed/used for multi-level hierarchical effective level. diff --git a/bin/bunyan b/bin/bunyan index 3f930b2..c4f3a57 100755 --- a/bin/bunyan +++ b/bin/bunyan @@ -5,7 +5,7 @@ // See . // -var VERSION = "0.15.1"; +var VERSION = "0.16.0"; var util = require('util'); var pathlib = require('path'); @@ -13,6 +13,7 @@ var vm = require('vm'); var http = require('http'); var fs = require('fs'); var warn = console.warn; +var spawn = require('child_process').spawn; @@ -134,6 +135,8 @@ function objCopy(obj) { function printHelp() { console.log("Usage:"); console.log(" bunyan [OPTIONS] [FILE ...]"); + console.log(" ... | bunyan [OPTIONS]"); + console.log(" bunyan [OPTIONS] -p PID"); console.log(""); console.log("Filter and pretty-print Bunyan log file content."); console.log(""); @@ -141,6 +144,10 @@ function printHelp() { console.log(" -h, --help print this help info and exit"); console.log(" --version print version of this command and exit"); console.log(""); + console.log("Dtrace options (only on dtrace-supporting platforms):"); + console.log(" -p PID Process bunyan:log-* probes from the process"); + console.log(" with the given PID."); + console.log(""); console.log("Filtering options:"); console.log(" -l, --level LEVEL"); console.log(" Only show messages at or above the specified level."); @@ -307,13 +314,14 @@ function parseArgv(argv) { jsonIndent: 2, level: null, conditions: null, - strict: false + strict: false, + pid: 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, 'c': true, 'l': true}; + var optTakesArg = {'d': true, 'o': true, 'c': true, 'l': true, 'p': 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(""); @@ -382,6 +390,14 @@ function parseArgv(argv) { case "-j": // output with JSON.stringify parsed.outputMode = OM_JSON; break; + case "-p": + var pidArg = args.shift(); + var pid = +(pidArg); + if (isNaN(pid)) { + throw new Error(format('invalid pid: "%s"', pidArg)); + } + parsed.pid = pid; + break; case "-l": case "--level": var levelArg = args.shift(); @@ -877,6 +893,48 @@ function processStdin(opts, stylize, callback) { } +/** + * Process bunyan:log-* probes from the given pid. + * + * @params opts {Object} Bunyan options object. + * @param stylize {Function} Output stylize function to use. + * @param callback {Function} `function (code)` + */ +function processPid(opts, stylize, callback) { + var leftover = ""; // Left-over partial line from last chunk. + var argv = ['dtrace', '-Z', '-x', 'strsize=4k', '-qn', + format('bunyan%d:::log-*{printf("%s", copyinstr(arg0))}', opts.pid)]; + var dtrace = spawn(argv[0], argv.slice(1)); + + dtrace.stderr.pipe(process.stderr); + + dtrace.stdout.setEncoding('utf8'); + dtrace.stdout.on('data', function (chunk) { + var lines = chunk.split(/\r\n|\n/); + var length = lines.length; + if (length === 1) { + leftover += lines[0]; + return; + } + if (length > 1) { + handleLogLine(null, leftover + lines[0], opts, stylize); + } + leftover = lines.pop(); + length -= 1; + for (var i=1; i < length; i++) { + handleLogLine(null, lines[i], opts, stylize); + } + }); + dtrace.on('exit', function (code) { + if (leftover) { + handleLogLine(null, leftover, opts, stylize); + leftover = ''; + } + callback(code); + }); +} + + /** * Process all input from the given log file. * @@ -1009,10 +1067,18 @@ function main(argv) { console.log("bunyan " + getVersion()); return; } + if (opts.pid && opts.args.length > 0) { + warn("bunyan: error: can't use both '-p PID' and file args"); + return drainStdoutAndExit(1); + } var stylize = (opts.color ? stylizeWithColor : stylizeWithoutColor); var retval = 0; - if (opts.args.length > 0) { + if (opts.pid) { + processPid(opts, stylize, function (code) { + process.exit(code); + }); + } else if (opts.args.length > 0) { var files = opts.args; files.forEach(function (file) { streams[file] = { stream: null, records: [], done: false } diff --git a/docs/bunyan.1 b/docs/bunyan.1 index 47c4040..48cf235 100644 --- a/docs/bunyan.1 +++ b/docs/bunyan.1 @@ -1,13 +1,13 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BUNYAN" "1" "October 2012" "" "bunyan manual" +.TH "BUNYAN" "1" "November 2012" "" "bunyan manual" . .SH "NAME" \fBbunyan\fR \- filter and pretty\-print Bunyan log file content . .SH "SYNOPSIS" -\fBbunyan\fR [OPTIONS] [LOOKUPS\.\.\.] +\fBbunyan\fR [OPTIONS] [LOOKUPS\.\.\.] \.\.\. | \fBbunyan\fR [OPTIONS] \fBbunyan\fR [OPTIONS] \-p PID . .SH "DESCRIPTION" "Bunyan" is \fBa simple and fast a JSON logging library\fR for node\.js services, a one\-JSON\-object\-per\-line log format, and \fBa \fBbunyan\fR CLI tool\fR for nicely viewing those logs\. This man page describes the latter\. @@ -96,6 +96,13 @@ Print version of this command and exit\. Don\'t warn if input isn\'t valid JSON\. . .P +Dtrace options (only on dtrace\-supporting platforms): +. +.TP +\fB\-p PID\fR +Process bunyan:log\-* probes from the process with the given PID\. +. +.P Filtering options: . .TP @@ -166,6 +173,30 @@ inspect Node\.js `util\.inspect` output\. . .fi . +.SH "DTRACE SUPPORT" +On systems that support DTrace (e\.g\., MacOS, FreeBSD, illumos derivatives like SmartOS and OmniOS), Bunyan will create a DTrace provider (\fBbunyan\fR) that makes available the following probes: +. +.IP "" 4 +. +.nf + +log\-trace +log\-debug +log\-info +log\-warn +log\-error +log\-fatal +. +.fi +. +.IP "" 0 +. +.P +Each of these probes has a single argument: the string that would be written to the log\. Note that when a probe is enabled, it will fire whenever the corresponding function is called, even if the level of the log message is less than that of any stream\. +. +.P +See \fIhttps://github\.com/trentm/node\-bunyan#dtrace\-support\fR for more details\. +. .SH "PROJECT & BUGS" \fBbunyan\fR is written in JavaScript and requires node\.js (\fBnode\fR)\. The project lives at \fIhttps://github\.com/trentm/node\-bunyan\fR and is published to npm as "bunyan"\. . diff --git a/docs/bunyan.1.html b/docs/bunyan.1.html index 2623bbd..ca48260 100644 --- a/docs/bunyan.1.html +++ b/docs/bunyan.1.html @@ -65,6 +65,7 @@ OPTIONS LOG LEVELS OUTPUT FORMATS + DTRACE SUPPORT PROJECT & BUGS LICENSE COPYRIGHT @@ -83,7 +84,9 @@

SYNOPSIS

-

bunyan [OPTIONS] [LOOKUPS...]

+

bunyan [OPTIONS] [LOOKUPS...] +... | bunyan [OPTIONS] +bunyan [OPTIONS] -p PID

DESCRIPTION

@@ -146,6 +149,13 @@ record data. In the COND code, this refers to the record object:

+

Dtrace options (only on dtrace-supporting platforms):

+ +
+
-p PID
Process bunyan:log-* probes from the process with the given PID.
+
+ +

Filtering options:

@@ -199,6 +209,27 @@ json-N JSON output, N-space indentation, e.g. "json-0" inspect Node.js `util.inspect` output. +

DTRACE SUPPORT

+ +

On systems that support DTrace (e.g., MacOS, FreeBSD, illumos derivatives +like SmartOS and OmniOS), Bunyan will create a DTrace provider (bunyan) +that makes available the following probes:

+ +
log-trace
+log-debug
+log-info
+log-warn
+log-error
+log-fatal
+
+ +

Each of these probes has a single argument: the string that would be +written to the log. Note that when a probe is enabled, it will +fire whenever the corresponding function is called, even if the level of +the log message is less than that of any stream.

+ +

See https://github.com/trentm/node-bunyan#dtrace-support for more details.

+

PROJECT & BUGS

bunyan is written in JavaScript and requires node.js (node). The project @@ -224,7 +255,7 @@ All rights reserved.

  1. -
  2. October 2012
  3. +
  4. November 2012
  5. bunyan(1)
diff --git a/docs/bunyan.1.ronn b/docs/bunyan.1.ronn index ec72989..1c77be8 100644 --- a/docs/bunyan.1.ronn +++ b/docs/bunyan.1.ronn @@ -4,6 +4,8 @@ ## SYNOPSIS `bunyan` \[OPTIONS\] \[LOOKUPS...\] +... | `bunyan` \[OPTIONS\] +`bunyan` \[OPTIONS\] -p PID ## DESCRIPTION @@ -68,6 +70,11 @@ record data. In the COND code, `this` refers to the record object: * `-q`, `--quiet`: Don't warn if input isn't valid JSON. +Dtrace options (only on dtrace-supporting platforms): + + * `-p PID`: + Process bunyan:log-* probes from the process with the given PID. + Filtering options: * `-l`, `--level LEVEL`: @@ -128,6 +135,27 @@ scripts, uppercase symbols like "DEBUG" are defined for convenience. inspect Node.js `util.inspect` output. +## DTRACE SUPPORT + +On systems that support DTrace (e.g., MacOS, FreeBSD, illumos derivatives +like SmartOS and OmniOS), Bunyan will create a DTrace provider (`bunyan`) +that makes available the following probes: + + log-trace + log-debug + log-info + log-warn + log-error + log-fatal + +Each of these probes has a single argument: the string that would be +written to the log. Note that when a probe is enabled, it will +fire whenever the corresponding function is called, even if the level of +the log message is less than that of any stream. + +See for more details. + + ## PROJECT & BUGS `bunyan` is written in JavaScript and requires node.js (`node`). The project diff --git a/lib/bunyan.js b/lib/bunyan.js index 2eec0c6..856fcad 100644 --- a/lib/bunyan.js +++ b/lib/bunyan.js @@ -4,7 +4,7 @@ * The bunyan logging library for node.js. */ -var VERSION = '0.15.1'; +var VERSION = '0.16.0'; // Bunyan log format version. This becomes the 'v' field on all log records. // `0` is until I release a version '1.0.0' of node-bunyan. Thereafter, diff --git a/package.json b/package.json index f53b256..5da6a46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bunyan", - "version": "0.15.1", + "version": "0.16.0", "description": "a JSON Logger library for node.js services", "author": "Trent Mick (http://trentm.com)", "main": "./lib/bunyan.js",