UNPKG

10 kBMarkdownView Raw
1# morgan
2
3[![NPM Version][npm-image]][npm-url]
4[![NPM Downloads][downloads-image]][downloads-url]
5[![Build Status][travis-image]][travis-url]
6[![Test Coverage][coveralls-image]][coveralls-url]
7[![Gratipay][gratipay-image]][gratipay-url]
8
9HTTP request logger middleware for node.js
10
11> Named after [Dexter](http://en.wikipedia.org/wiki/Dexter_Morgan), a show you should not watch until completion.
12
13## API
14
15<!-- eslint-disable no-unused-vars -->
16
17```js
18var morgan = require('morgan')
19```
20
21### morgan(format, options)
22
23Create a new morgan logger middleware function using the given `format` and `options`.
24The `format` argument may be a string of a predefined name (see below for the names),
25a string of a format string, or a function that will produce a log entry.
26
27The `format` function will be called with three arguments `tokens`, `req`, and `res`,
28where `tokens` is object with all defined tokens, `req` is the HTTP request and `res`
29is the HTTP response. The function is expected to return a string that will be the log
30line, or `undefined` / `null` to skip logging.
31
32#### Using a predefined format string
33
34<!-- eslint-disable no-undef -->
35
36```
37morgan('tiny')
38```
39
40#### Using format string of predefined tokens
41
42<!-- eslint-disable no-undef -->
43
44```js
45morgan(':method :url :status :res[content-length] - :response-time ms')
46```
47
48#### Using a custom format function
49
50<!-- eslint-disable no-undef -->
51
52``` js
53morgan(function (tokens, req, res) {
54 return [
55 tokens.method(req, res),
56 tokens.url(req, res),
57 tokens.status(req, res),
58 tokens.res(req, res, 'content-length'), '-',
59 tokens['response-time'](req, res), 'ms'
60 ].join(' ')
61})
62```
63
64#### Options
65
66Morgan accepts these properties in the options object.
67
68##### immediate
69
70Write log line on request instead of response. This means that a requests will
71be logged even if the server crashes, _but data from the response (like the
72response code, content length, etc.) cannot be logged_.
73
74##### skip
75
76Function to determine if logging is skipped, defaults to `false`. This function
77will be called as `skip(req, res)`.
78
79<!-- eslint-disable no-undef -->
80
81```js
82// EXAMPLE: only log error responses
83morgan('combined', {
84 skip: function (req, res) { return res.statusCode < 400 }
85})
86```
87
88##### stream
89
90Output stream for writing log lines, defaults to `process.stdout`.
91
92#### Predefined Formats
93
94There are various pre-defined formats provided:
95
96##### combined
97
98Standard Apache combined log output.
99
100```
101:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
102```
103
104##### common
105
106Standard Apache common log output.
107
108```
109:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]
110```
111
112##### dev
113
114Concise output colored by response status for development use. The `:status`
115token will be colored red for server error codes, yellow for client error
116codes, cyan for redirection codes, and uncolored for all other codes.
117
118```
119:method :url :status :response-time ms - :res[content-length]
120```
121
122##### short
123
124Shorter than default, also including response time.
125
126```
127:remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms
128```
129
130##### tiny
131
132The minimal output.
133
134```
135:method :url :status :res[content-length] - :response-time ms
136```
137
138#### Tokens
139
140##### Creating new tokens
141
142To define a token, simply invoke `morgan.token()` with the name and a callback function.
143This callback function is expected to return a string value. The value returned is then
144available as ":type" in this case:
145
146<!-- eslint-disable no-undef -->
147
148```js
149morgan.token('type', function (req, res) { return req.headers['content-type'] })
150```
151
152Calling `morgan.token()` using the same name as an existing token will overwrite that
153token definition.
154
155The token function is expected to be called with the arguments `req` and `res`, representing
156the HTTP request and HTTP response. Additionally, the token can accept further arguments of
157it's choosing to customize behavior.
158
159##### :date[format]
160
161The current date and time in UTC. The available formats are:
162
163 - `clf` for the common log format (`"10/Oct/2000:13:55:36 +0000"`)
164 - `iso` for the common ISO 8601 date time format (`2000-10-10T13:55:36.000Z`)
165 - `web` for the common RFC 1123 date time format (`Tue, 10 Oct 2000 13:55:36 GMT`)
166
167If no format is given, then the default is `web`.
168
169##### :http-version
170
171The HTTP version of the request.
172
173##### :method
174
175The HTTP method of the request.
176
177##### :referrer
178
179The Referrer header of the request. This will use the standard mis-spelled Referer header if exists, otherwise Referrer.
180
181##### :remote-addr
182
183The remote address of the request. This will use `req.ip`, otherwise the standard `req.connection.remoteAddress` value (socket address).
184
185##### :remote-user
186
187The user authenticated as part of Basic auth for the request.
188
189##### :req[header]
190
191The given `header` of the request.
192
193##### :res[header]
194
195The given `header` of the response.
196
197##### :response-time[digits]
198
199The time between the request coming into `morgan` and when the response
200headers are written, in milliseconds.
201
202The `digits` argument is a number that specifies the number of digits to
203include on the number, defaulting to `3`, which provides microsecond precision.
204
205##### :status
206
207The status code of the response.
208
209If the request/response cycle completes before a response was sent to the
210client (for example, the TCP socket closed prematurely by a client aborting
211the request), then the status will be empty (displayed as `"-"` in the log).
212
213##### :url
214
215The URL of the request. This will use `req.originalUrl` if exists, otherwise `req.url`.
216
217##### :user-agent
218
219The contents of the User-Agent header of the request.
220
221### morgan.compile(format)
222
223Compile a format string into a `format` function for use by `morgan`. A format string
224is a string that represents a single log line and can utilize token syntax.
225Tokens are references by `:token-name`. If tokens accept arguments, they can
226be passed using `[]`, for example: `:token-name[pretty]` would pass the string
227`'pretty'` as an argument to the token `token-name`.
228
229The function returned from `morgan.compile` takes three arguments `tokens`, `req`, and
230`res`, where `tokens` is object with all defined tokens, `req` is the HTTP request and
231`res` is the HTTP response. The function will return a string that will be the log line,
232or `undefined` / `null` to skip logging.
233
234Normally formats are defined using `morgan.format(name, format)`, but for certain
235advanced uses, this compile function is directly available.
236
237## Examples
238
239### express/connect
240
241Simple app that will log all request in the Apache combined format to STDOUT
242
243```js
244var express = require('express')
245var morgan = require('morgan')
246
247var app = express()
248
249app.use(morgan('combined'))
250
251app.get('/', function (req, res) {
252 res.send('hello, world!')
253})
254```
255
256### vanilla http server
257
258Simple app that will log all request in the Apache combined format to STDOUT
259
260```js
261var finalhandler = require('finalhandler')
262var http = require('http')
263var morgan = require('morgan')
264
265// create "middleware"
266var logger = morgan('combined')
267
268http.createServer(function (req, res) {
269 var done = finalhandler(req, res)
270 logger(req, res, function (err) {
271 if (err) return done(err)
272
273 // respond to request
274 res.setHeader('content-type', 'text/plain')
275 res.end('hello, world!')
276 })
277})
278```
279
280### write logs to a file
281
282#### single file
283
284Simple app that will log all requests in the Apache combined format to the file
285`access.log`.
286
287```js
288var express = require('express')
289var fs = require('fs')
290var morgan = require('morgan')
291var path = require('path')
292
293var app = express()
294
295// create a write stream (in append mode)
296var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), {flags: 'a'})
297
298// setup the logger
299app.use(morgan('combined', {stream: accessLogStream}))
300
301app.get('/', function (req, res) {
302 res.send('hello, world!')
303})
304```
305
306#### log file rotation
307
308Simple app that will log all requests in the Apache combined format to one log
309file per day in the `log/` directory using the
310[rotating-file-stream module](https://www.npmjs.com/package/rotating-file-stream).
311
312```js
313var express = require('express')
314var fs = require('fs')
315var morgan = require('morgan')
316var path = require('path')
317var rfs = require('rotating-file-stream')
318
319var app = express()
320var logDirectory = path.join(__dirname, 'log')
321
322// ensure log directory exists
323fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory)
324
325// create a rotating write stream
326var accessLogStream = rfs('access.log', {
327 interval: '1d', // rotate daily
328 path: logDirectory
329})
330
331// setup the logger
332app.use(morgan('combined', {stream: accessLogStream}))
333
334app.get('/', function (req, res) {
335 res.send('hello, world!')
336})
337```
338
339### use custom token formats
340
341Sample app that will use custom token formats. This adds an ID to all requests and displays it using the `:id` token.
342
343```js
344var express = require('express')
345var morgan = require('morgan')
346var uuid = require('node-uuid')
347
348morgan.token('id', function getId (req) {
349 return req.id
350})
351
352var app = express()
353
354app.use(assignId)
355app.use(morgan(':id :method :url :response-time'))
356
357app.get('/', function (req, res) {
358 res.send('hello, world!')
359})
360
361function assignId (req, res, next) {
362 req.id = uuid.v4()
363 next()
364}
365```
366
367## License
368
369[MIT](LICENSE)
370
371[npm-image]: https://img.shields.io/npm/v/morgan.svg
372[npm-url]: https://npmjs.org/package/morgan
373[travis-image]: https://img.shields.io/travis/expressjs/morgan/master.svg
374[travis-url]: https://travis-ci.org/expressjs/morgan
375[coveralls-image]: https://img.shields.io/coveralls/expressjs/morgan/master.svg
376[coveralls-url]: https://coveralls.io/r/expressjs/morgan?branch=master
377[downloads-image]: https://img.shields.io/npm/dm/morgan.svg
378[downloads-url]: https://npmjs.org/package/morgan
379[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg
380[gratipay-url]: https://www.gratipay.com/dougwilson/