Skip to content

Commit

Permalink
Add :total-time token
Browse files Browse the repository at this point in the history
closes #165
  • Loading branch information
dougwilson committed Mar 20, 2020
1 parent ce15462 commit aa718d7
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 5 deletions.
1 change: 1 addition & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
unreleased
==========

* Add `:total-time` token
* Fix trailing space in colored status code for `dev` format
* deps: basic-auth@~2.0.1
- deps: safe-buffer@5.1.2
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ If the request/response cycle completes before a response was sent to the
client (for example, the TCP socket closed prematurely by a client aborting
the request), then the status will be empty (displayed as `"-"` in the log).

##### :total-time[digits]

The time between the request coming into `morgan` and when the response
has finished being written out to the connection, in milliseconds.

The `digits` argument is a number that specifies the number of digits to
include on the number, defaulting to `3`, which provides microsecond precision.

##### :url

The URL of the request. This will use `req.originalUrl` if exists, otherwise `req.url`.
Expand Down
20 changes: 20 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,26 @@ morgan.token('response-time', function getResponseTimeToken (req, res, digits) {
return ms.toFixed(digits === undefined ? 3 : digits)
})

/**
* total time in milliseconds
*/

morgan.token('total-time', function getTotalTimeToken (req, res, digits) {
if (!req._startAt || !res._startAt) {
// missing request and/or response start time
return
}

// time elapsed from request start
var elapsed = process.hrtime(req._startAt)

// cover to milliseconds
var ms = (elapsed[0] * 1e3) + (elapsed[1] * 1e-6)

// return truncated value
return ms.toFixed(digits === undefined ? 3 : digits)
})

/**
* current date
*/
Expand Down
186 changes: 181 additions & 5 deletions test/morgan.js
Original file line number Diff line number Diff line change
Expand Up @@ -641,12 +641,14 @@ describe('morgan()', function () {
.expect(200, cb)
})

it('should not include response latency', function (done) {
it('should not include response write time', function (done) {
var cb = after(2, function (err, res, line) {
if (err) return done(err)
var end = Date.now()
var ms = parseFloat(line)
assert.ok(ms > 0, 'positive milliseconds')
assert.ok(ms < end - start + 1, 'response time expected to be < ' + (end - start + 1) + ', but was ' + ms)
assert(ms > 0)
assert(ms < end - start + 1)
assert(ms < write - start + 1)
done()
})

Expand All @@ -656,15 +658,15 @@ describe('morgan()', function () {

var server = createServer(':response-time', { stream: stream }, function (req, res) {
res.write('hello, ')
end = Date.now()
write = Date.now()

setTimeout(function () {
res.end('world!')
}, 50)
})

var end
var start = Date.now()
var write = null

request(server)
.get('/')
Expand Down Expand Up @@ -796,6 +798,180 @@ describe('morgan()', function () {
})
})

describe(':total-time', function () {
it('should be in milliseconds', function (done) {
var cb = after(2, function (err, res, line) {
if (err) return done(err)
var end = Date.now()
var ms = parseFloat(line)
assert(ms > 0)
assert(ms < end - start + 1)
done()
})

var stream = createLineStream(function (line) {
cb(null, null, line)
})

var start = Date.now()

request(createServer(':total-time', { stream: stream }))
.get('/')
.expect(200, cb)
})

it('should have three digits by default', function (done) {
var cb = after(2, function (err, res, line) {
if (err) return done(err)
assert.ok(/^[0-9]+\.[0-9]{3}$/.test(line))
done()
})

var stream = createLineStream(function (line) {
cb(null, null, line)
})

request(createServer(':total-time', { stream: stream }))
.get('/')
.expect(200, cb)
})

it('should have five digits with argument "5"', function (done) {
var cb = after(2, function (err, res, line) {
if (err) return done(err)
assert.ok(/^[0-9]+\.[0-9]{5}$/.test(line))
done()
})

var stream = createLineStream(function (line) {
cb(null, null, line)
})

request(createServer(':total-time[5]', { stream: stream }))
.get('/')
.expect(200, cb)
})

it('should have no digits with argument "0"', function (done) {
var cb = after(2, function (err, res, line) {
if (err) return done(err)
assert.ok(/^[0-9]+$/.test(line))
done()
})

var stream = createLineStream(function (line) {
cb(null, null, line)
})

request(createServer(':total-time[0]', { stream: stream }))
.get('/')
.expect(200, cb)
})

it('should include response write time', function (done) {
var cb = after(2, function (err, res, line) {
if (err) return done(err)
var end = Date.now()
var ms = parseFloat(line)
assert(ms > 0)
assert(ms > write - start - 1)
assert(ms < end - start + 1)
done()
})

var stream = createLineStream(function (line) {
cb(null, null, line)
})

var server = createServer(':total-time', { stream: stream }, function (req, res) {
res.write('hello, ')
write = Date.now()

setTimeout(function () {
res.end('world!')
}, 50)
})

var start = Date.now()
var write = null

request(server)
.get('/')
.expect(200, cb)
})

it('should be empty without hidden property', function (done) {
var cb = after(2, function (err, res, line) {
if (err) return done(err)
assert.strictEqual(line, '-')
done()
})

var stream = createLineStream(function (line) {
cb(null, null, line)
})

var server = createServer(':total-time', { stream: stream }, function (req, res, next) {
delete req._startAt
next()
})

request(server)
.get('/')
.expect(200, cb)
})

it('should be empty before response', function (done) {
var cb = after(2, function (err, res, line) {
if (err) return done(err)
assert.strictEqual(line, '-')
done()
})

var stream = createLineStream(function (line) {
cb(null, null, line)
})

var server = createServer(':total-time', {
immediate: true,
stream: stream
})

request(server)
.get('/')
.expect(200, cb)
})

it('should be empty if morgan invoked after response sent', function (done) {
var cb = after(3, function (err, res, line) {
if (err) return done(err)
assert.strictEqual(line, '-')
done()
})

var stream = createLineStream(function (line) {
cb(null, null, line)
})

var logger = morgan(':total-time', {
immediate: true,
stream: stream
})

var server = http.createServer(function (req, res) {
setTimeout(function () {
logger(req, res, cb)
}, 10)

res.end()
})

request(server)
.get('/')
.expect(200, cb)
})
})

describe(':url', function () {
it('should get request URL', function (done) {
var cb = after(2, function (err, res, line) {
Expand Down

0 comments on commit aa718d7

Please sign in to comment.