From 1a9e712dbc0a48474f733a12a9e1d3a012a81adc Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Tue, 21 Aug 2012 11:04:33 -0700 Subject: [PATCH] [issue #34] `body` et al in request/response output by `bunyan` CLI Ensure `req.body`, `res.body` and other request/response fields are emitted by the `bunyan` CLI (mostly by Rob Gulewich). --- AUTHORS | 1 + CHANGES.md | 4 +- Makefile | 17 +++++---- bin/bunyan | 96 ++++++++++++++++++++++++++++++++++++++---------- test/cli.test.js | 8 ++-- 5 files changed, 95 insertions(+), 31 deletions(-) diff --git a/AUTHORS b/AUTHORS index 1562a13..ba2edfe 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,3 +3,4 @@ Mark Cavage (https://github.com/mcavage) Dave Pacheco (https://github.com/davepacheco) Michael Hart (https://github.com/mhart) Isaac Schlueter (https://github.com/isaacs) +Rob Gulewich (https://github.com/rgulewich) diff --git a/CHANGES.md b/CHANGES.md index e900642..bbe946d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,9 @@ ## bunyan 0.13.1 (not yet released) -(nothing yet) +- [issue #34] Ensure `req.body`, `res.body` and other request/response fields + are emitted by the `bunyan` CLI (mostly by Rob Gulewich). + ## bunyan 0.13.0 diff --git a/Makefile b/Makefile index cbf7572..961f64e 100644 --- a/Makefile +++ b/Makefile @@ -36,24 +36,27 @@ test: $(TAP) # Test will all node supported versions (presumes install locations I use on my machine). .PHONY: testall -testall: test06 test07 testmaster +testall: test08 test06 test09 testmaster .PHONY: testmaster testmaster: @echo "# Test node master (with node `$(HOME)/opt/node-master/bin/node --version`)" PATH="$(HOME)/opt/node-master/bin:$(PATH)" TAP=1 $(TAP) test/*.test.js - -.PHONY: test07 -test07: - @echo "# Test node 0.7.x (with node `$(HOME)/opt/node-0.7/bin/node --version`)" - PATH="$(HOME)/opt/node-0.7/bin:$(PATH)" TAP=1 $(TAP) test/*.test.js - +.PHONY: test09 +test09: + @echo "# Test node 0.9.x (with node `$(HOME)/opt/node-0.9/bin/node --version`)" + PATH="$(HOME)/opt/node-0.9/bin:$(PATH)" TAP=1 $(TAP) test/*.test.js +.PHONY: test08 +test08: + @echo "# Test node 0.8.x (with node `$(HOME)/opt/node-0.8/bin/node --version`)" + PATH="$(HOME)/opt/node-0.8/bin:$(PATH)" TAP=1 $(TAP) test/*.test.js .PHONY: test06 test06: @echo "# Test node 0.6.x (with node `$(HOME)/opt/node-0.6/bin/node --version`)" PATH="$(HOME)/opt/node-0.6/bin:$(PATH)" TAP=1 $(TAP) test/*.test.js + #---- check .PHONY: check-jsstyle diff --git a/bin/bunyan b/bin/bunyan index db15e06..c231c60 100755 --- a/bin/bunyan +++ b/bin/bunyan @@ -613,50 +613,108 @@ function emitRecord(rec, line, opts, stylize) { delete rec.msg; if (rec.req) { - var headers = rec.req.headers; - details.push(indent(format("%s %s HTTP/1.1%s", rec.req.method, - rec.req.url, + var req = rec.req; + var headers = req.headers; + var s = format("%s %s HTTP/%s%s", req.method, + req.url, + req.httpVersion || "1.1", (headers ? '\n' + Object.keys(headers).map( function (h) { return h + ': ' + headers[h]; }).join('\n') : '') - ))); + ); + delete req.url; + delete req.method; + delete req.httpVersion; + delete req.headers; + if (req.body) { + s += '\n\n' + req.body; + delete req.body; + } + if (req.trailers && Object.keys(req.trailers) > 0) { + s += '\n' + Object.keys(req.trailers).map( + function (t) { return t + ': ' + req.trailers[t]; }).join('\n'); + } + delete req.trailers; + details.push(indent(s)); + // E.g. for extra 'foo' field on 'req', add 'req.foo' at top-level. + // This *does* have the potential to stomp on a literal 'req.foo' key. + Object.keys(req).forEach(function (k) { + rec["req." + k] = req[k]; + }) } delete rec.req; if (rec.client_req) { - var headers = rec.client_req.headers; + var client_req = rec.client_req; + var headers = client_req.headers; var hostHeaderLine = ''; - if (rec.client_req.address) { - hostHeaderLine = 'Host: ' + rec.client_req.address; - if (rec.client_req.port) - hostHeaderLine += ':' + rec.client_req.port; + var s = ''; + if (client_req.address) { + hostHeaderLine = 'Host: ' + client_req.address; + if (client_req.port) + hostHeaderLine += ':' + client_req.port; hostHeaderLine += '\n'; } - details.push(indent(format("%s %s HTTP/1.1\n%s%s", rec.client_req.method, - rec.client_req.url, + delete client_req.headers; + delete client_req.address; + delete client_req.port; + s += format("%s %s HTTP/%s\n%s%s", client_req.method, + client_req.url, + req.client_req.httpVersion || "1.1", hostHeaderLine, Object.keys(headers).map( - function (h) { return h + ': ' + headers[h]; }).join('\n')))); + function (h) { return h + ': ' + headers[h]; }).join('\n')); + delete client_req.method; + delete client_req.url; + delete client_req.httpVersion; + if (client_req.body) { + s += '\n\n' + client_req.body + delete client_req.body; + } + // E.g. for extra 'foo' field on 'client_req', add 'client_req.foo' at + // top-level. This *does* have the potential to stomp on a literal + // 'client_req.foo' key. + Object.keys(client_req).forEach(function (k) { + rec["client_req." + k] = client_req[k]; + }) + details.push(indent(s)); } delete rec.client_req; if (rec.res) { + var res = rec.res; var s = ''; - if (rec.res.header) { - s += rec.res.header.trimRight(); - } else if (rec.res.headers) { - if (rec.res.statusCode) { - s += format("HTTP/1.1 %s %s\n", rec.res.statusCode, - http.STATUS_CODES[rec.res.statusCode]); + if (res.header) { + s += res.header.trimRight(); + } else if (res.headers) { + if (res.statusCode) { + s += format("HTTP/1.1 %s %s\n", res.statusCode, + http.STATUS_CODES[res.statusCode]); } - var headers = rec.res.headers; + var headers = res.headers; s += Object.keys(headers).map( function (h) { return h + ': ' + headers[h]; }).join('\n'); } + delete res.header; + delete res.headers; + delete res.statusCode; + if (res.body) { + s += '\n\n' + res.body + delete res.body; + } + if (res.trailer) { + s += '\n' + res.trailer; + } + delete res.trailer; if (s) { details.push(indent(s)); } + // E.g. for extra 'foo' field on 'res', add 'res.foo' at top-level. + // This *does* have the potential to stomp on a literal 'res.foo' key. + Object.keys(res).forEach(function (k) { + rec["res." + k] = res[k]; + }) } delete rec.res; diff --git a/test/cli.test.js b/test/cli.test.js index 6a7e65d..99bdfb5 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -33,7 +33,7 @@ test('--version', function (t) { test('--help', function (t) { exec(BUNYAN + ' --help', function (err, stdout, stderr) { t.error(err) - t.ok(stdout.indexOf('Options:') !== -1); + t.ok(stdout.indexOf('General options:') !== -1); t.end(); }); }); @@ -41,7 +41,7 @@ test('--help', function (t) { test('-h', function (t) { exec(BUNYAN + ' -h', function (err, stdout, stderr) { t.error(err) - t.ok(stdout.indexOf('Options:') !== -1); + t.ok(stdout.indexOf('General options:') !== -1); t.end(); }); }); @@ -279,7 +279,7 @@ test('multiple --conditions', function (t) { test('robust req handling', function (t) { var expect = [ '[2012-08-08T10:25:47.636Z] DEBUG: amon-master/12859 on 9724a190-27b6-4fd8-830b-a574f839c67d: headAgentProbes respond (req_id=cce79d15-ffc2-487c-a4e4-e940bdaac31e, route=HeadAgentProbes, contentMD5=11FxOYiYfpMxmANj4kGJzg==)', - '[2012-08-08T10:25:47.637Z] INFO: amon-master/12859 on 9724a190-27b6-4fd8-830b-a574f839c67d: HeadAgentProbes handled: 200 (req_id=cce79d15-ffc2-487c-a4e4-e940bdaac31e, 3ms, audit=true, remoteAddress=10.2.207.2, remotePort=50394, secure=false, _audit=true)', + '[2012-08-08T10:25:47.637Z] INFO: amon-master/12859 on 9724a190-27b6-4fd8-830b-a574f839c67d: HeadAgentProbes handled: 200 (req_id=cce79d15-ffc2-487c-a4e4-e940bdaac31e, 3ms, audit=true, remoteAddress=10.2.207.2, remotePort=50394, secure=false, _audit=true, req.version=*)', ' HEAD /agentprobes?agent=ccf92af9-0b24-46b6-ab60-65095fdd3037 HTTP/1.1', ' accept: application/json', ' content-type: application/json', @@ -302,7 +302,7 @@ test('robust req handling', function (t) { ' "name": "HeadAgentProbes",', ' "version": false', ' }', - '[2012-08-08T10:25:47.637Z] INFO: amon-master/12859 on 9724a190-27b6-4fd8-830b-a574f839c67d: HeadAgentProbes handled: 200 (req_id=cce79d15-ffc2-487c-a4e4-e940bdaac31e, 3ms, audit=true, remoteAddress=10.2.207.2, remotePort=50394, secure=false, _audit=true)', + '[2012-08-08T10:25:47.637Z] INFO: amon-master/12859 on 9724a190-27b6-4fd8-830b-a574f839c67d: HeadAgentProbes handled: 200 (req_id=cce79d15-ffc2-487c-a4e4-e940bdaac31e, 3ms, audit=true, remoteAddress=10.2.207.2, remotePort=50394, secure=false, _audit=true, req.version=*)', ' HEAD /agentprobes?agent=ccf92af9-0b24-46b6-ab60-65095fdd3037 HTTP/1.1', ' --', ' route: {',