Skip to content

Commit

Permalink
Add colored status token
Browse files Browse the repository at this point in the history
Coloring status makes sense for whatever format user wants, not just the internal `dev` one. So using `:status-colored` gives that ability.

Memoization for `dev` format is collaterally removed since now `dev` format is just a string and coloring is compiled as the `status-colored` token.

resolves expressjs#171
  • Loading branch information
st-sloth authored and ryhinchey committed Mar 26, 2020
1 parent c68d2ea commit 76746de
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 31 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,13 @@ Standard Apache common log output.

##### dev

Concise output colored by response status for development use. The `:status`
Concise output colored by response status for development use. The `:status-colored`
token will be colored green for success codes, red for server error codes,
yellow for client error codes, cyan for redirection codes, and uncolored
for information codes.

```
:method :url :status :response-time ms - :res[content-length]
:method :url :status-colored :response-time ms - :res[content-length]
```

##### short
Expand Down Expand Up @@ -220,6 +220,18 @@ 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.

##### :status-colored

Same as `:status` but the output will be colored red for server error codes,
yellow for client error codes, cyan for redirection codes, green for success codes,
and uncolored for all other codes.

This token also adds a reset escape code to ensure color will only be applied to the status code. The escape code removes any existing colors in your logs that come after the `:status-colored` token. For something like a background color that's applied to the entire log string, you must add it back after the `:status-colored` token.

For example, this log format sets a magenta background color to the entire log string. Notice that it's added at the beginning of the log and immediately after the `:status-colored` token.

`morgan('\x1b[45m:method :url :status-colored\x1b[45m :res[content-length]\x1b[0m')`

##### :url

The URL of the request. This will use `req.originalUrl` if exists, otherwise `req.url`.
Expand Down
75 changes: 46 additions & 29 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ var CLF_MONTH = [

var DEFAULT_BUFFER_DURATION = 1000

/**
* Placeholder that replaces empty token values in resulting log line
* @private
*/

var EMPTY_TOKEN_VALUE_PLACEHOLDER = '-'

/**
* Create a logger middleware.
*
Expand Down Expand Up @@ -180,30 +187,7 @@ morgan.format('tiny', ':method :url :status :res[content-length] - :response-tim
* dev (colored)
*/

morgan.format('dev', function developmentFormatLine (tokens, req, res) {
// get the status code if response written
var status = headersSent(res)
? res.statusCode
: undefined

// get status color
var color = status >= 500 ? 31 // red
: status >= 400 ? 33 // yellow
: status >= 300 ? 36 // cyan
: status >= 200 ? 32 // green
: 0 // no color

// get colored function
var fn = developmentFormatLine[color]

if (!fn) {
// compile
fn = developmentFormatLine[color] = compile('\x1b[0m:method :url \x1b[' +
color + 'm:status\x1b[0m :response-time ms - :res[content-length]\x1b[0m')
}

return fn(tokens, req, res)
})
morgan.format('dev', '\x1b[0m:method :url :status-colored :response-time ms - :res[content-length]\x1b[0m')

/**
* request url
Expand Down Expand Up @@ -280,10 +264,26 @@ morgan.token('date', function getDateToken (req, res, format) {
* response status code
*/

morgan.token('status', function getStatusToken (req, res) {
return headersSent(res)
? String(res.statusCode)
: undefined
morgan.token('status', getStatusToken)

/**
* colored response status code
*/

morgan.token('status-colored', function getStatusColoredToken (req, res) {
var status = getStatusToken(req, res)

// get status color
var color = status >= 500 ? 31 // red
: status >= 400 ? 33 // yellow
: status >= 300 ? 36 // cyan
: status >= 200 ? 32 // green
: 0 // no color

// using placeholder here since `compile` adds it if token function returns falsy,
// but this coloring token returns color data anyway (as per tests) and
// value won't be eligible for substitute
return '\x1b[' + color + 'm' + (status || EMPTY_TOKEN_VALUE_PLACEHOLDER) + '\x1b[0m'
})

/**
Expand Down Expand Up @@ -404,7 +404,9 @@ function compile (format) {
tokenArguments += ', ' + String(JSON.stringify(arg))
}

return '" +\n (' + tokenFunction + '(' + tokenArguments + ') || "-") + "'
return '" +\n (' +
tokenFunction + '(' + tokenArguments + ') || "' + EMPTY_TOKEN_VALUE_PLACEHOLDER +
'") + "'
})

// eslint-disable-next-line no-new-func
Expand Down Expand Up @@ -474,6 +476,21 @@ function getFormatFunction (name) {
: fmt
}

/**
* Get value for status token
*
* @param {IncomingMessage} req
* @param {OutgoingMessage} res
* @return {string | undefined}
* @public
*/

function getStatusToken (req, res) {
return headersSent(res)
? String(res.statusCode)
: undefined
}

/**
* Get request IP address.
*
Expand Down

0 comments on commit 76746de

Please sign in to comment.