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 |
|
9 | HTTP 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 | ```js
|
16 | var morgan = require('morgan')
|
17 | ```
|
18 |
|
19 | ### morgan(format, options)
|
20 |
|
21 | Create a new morgan logger middleware function using the given `format` and `options`.
|
22 | The `format` argument may be a string of a predefined name (see below for the names),
|
23 | a string of a format string, or a function that will produce a log entry.
|
24 |
|
25 | #### Options
|
26 |
|
27 | Morgan accepts these properties in the options object.
|
28 |
|
29 | #### immediate
|
30 |
|
31 | Write log line on request instead of response. This means that a requests will
|
32 | be logged even if the server crashes, _but data from the response (like the
|
33 | response code, content length, etc.) cannot be logged_.
|
34 |
|
35 | ##### skip
|
36 |
|
37 | Function to determine if logging is skipped, defaults to `false`. This function
|
38 | will be called as `skip(req, res)`.
|
39 |
|
40 | ```js
|
41 | // EXAMPLE: only log error responses
|
42 | morgan('combined', {
|
43 | skip: function (req, res) { return res.statusCode < 400 }
|
44 | })
|
45 | ```
|
46 |
|
47 | ##### stream
|
48 |
|
49 | Output stream for writing log lines, defaults to `process.stdout`.
|
50 |
|
51 | #### Predefined Formats
|
52 |
|
53 | There are various pre-defined formats provided:
|
54 |
|
55 | ##### combined
|
56 |
|
57 | Standard Apache combined log output.
|
58 |
|
59 | ```
|
60 | :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
|
61 | ```
|
62 |
|
63 | ##### common
|
64 |
|
65 | Standard Apache common log output.
|
66 |
|
67 | ```
|
68 | :remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]
|
69 | ```
|
70 |
|
71 | ##### dev
|
72 |
|
73 | Concise output colored by response status for development use. The `:status`
|
74 | token will be colored red for server error codes, yellow for client error
|
75 | codes, cyan for redirection codes, and uncolored for all other codes.
|
76 |
|
77 | ```
|
78 | :method :url :status :response-time ms - :res[content-length]
|
79 | ```
|
80 |
|
81 | ##### short
|
82 |
|
83 | Shorter than default, also including response time.
|
84 |
|
85 | ```
|
86 | :remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms
|
87 | ```
|
88 |
|
89 | ##### tiny
|
90 |
|
91 | The minimal output.
|
92 |
|
93 | ```
|
94 | :method :url :status :res[content-length] - :response-time ms
|
95 | ```
|
96 |
|
97 | #### Tokens
|
98 |
|
99 | ##### Creating new tokens
|
100 |
|
101 | To define a token, simply invoke `morgan.token()` with the name and a callback function. This callback function is expected to return a string value. The value returned is then available as ":type" in this case:
|
102 | ```js
|
103 | morgan.token('type', function(req, res){ return req.headers['content-type']; })
|
104 | ```
|
105 |
|
106 | Calling `morgan.token()` using the same name as an existing token will overwrite that token definition.
|
107 |
|
108 | ##### :date[format]
|
109 |
|
110 | The current date and time in UTC. The available formats are:
|
111 |
|
112 | - `clf` for the common log format (`"10/Oct/2000:13:55:36 +0000"`)
|
113 | - `iso` for the common ISO 8601 date time format (`2000-10-10T13:55:36.000Z`)
|
114 | - `web` for the common RFC 1123 date time format (`Tue, 10 Oct 2000 13:55:36 GMT`)
|
115 |
|
116 | If no format is given, then the default is `web`.
|
117 |
|
118 | ##### :http-version
|
119 |
|
120 | The HTTP version of the request.
|
121 |
|
122 | ##### :method
|
123 |
|
124 | The HTTP version of the request.
|
125 |
|
126 | ##### :referrer
|
127 |
|
128 | The Referrer header of the request. This will use the standard mis-spelled Referer header if exists, otherwise Referrer.
|
129 |
|
130 | ##### :remote-addr
|
131 |
|
132 | The remote address of the request. This will use `req.ip`, otherwise the standard `req.connection.remoteAddress` value (socket address).
|
133 |
|
134 | ##### :remote-user
|
135 |
|
136 | The user authenticated as part of Basic auth for the request.
|
137 |
|
138 | ##### :req[header]
|
139 |
|
140 | The given `header` of the request.
|
141 |
|
142 | ##### :res[header]
|
143 |
|
144 | The given `header` of the response.
|
145 |
|
146 | ##### :response-time
|
147 |
|
148 | The time between the request coming into `morgan` and when the response headers are written, in milliseconds.
|
149 |
|
150 | ##### :status
|
151 |
|
152 | The status code of the response.
|
153 |
|
154 | ##### :url
|
155 |
|
156 | The URL of the request. This will use `req.originalUrl` if exists, otherwise `req.url`.
|
157 |
|
158 | ##### :user-agent
|
159 |
|
160 | The contents of the User-Agent header of the request.
|
161 |
|
162 | ## Examples
|
163 |
|
164 | ### express/connect
|
165 |
|
166 | Simple app that will log all request in the Apache combined format to STDOUT
|
167 |
|
168 | ```js
|
169 | var express = require('express')
|
170 | var morgan = require('morgan')
|
171 |
|
172 | var app = express()
|
173 |
|
174 | app.use(morgan('combined'))
|
175 |
|
176 | app.get('/', function (req, res) {
|
177 | res.send('hello, world!')
|
178 | })
|
179 | ```
|
180 |
|
181 | ### vanilla http server
|
182 |
|
183 | Simple app that will log all request in the Apache combined format to STDOUT
|
184 |
|
185 | ```js
|
186 | var finalhandler = require('finalhandler')
|
187 | var http = require('http')
|
188 | var morgan = require('morgan')
|
189 |
|
190 | // create "middleware"
|
191 | var logger = morgan('combined')
|
192 |
|
193 | http.createServer(function (req, res) {
|
194 | var done = finalhandler(req, res)
|
195 | logger(req, res, function (err) {
|
196 | if (err) return done(err)
|
197 |
|
198 | // respond to request
|
199 | res.setHeader('content-type', 'text/plain')
|
200 | res.end('hello, world!')
|
201 | })
|
202 | })
|
203 | ```
|
204 |
|
205 | ### write logs to a file
|
206 |
|
207 | #### single file
|
208 |
|
209 | Simple app that will log all requests in the Apache combined format to the file
|
210 | `access.log`.
|
211 |
|
212 | ```js
|
213 | var express = require('express')
|
214 | var fs = require('fs')
|
215 | var morgan = require('morgan')
|
216 |
|
217 | var app = express()
|
218 |
|
219 | // create a write stream (in append mode)
|
220 | var accessLogStream = fs.createWriteStream(__dirname + '/access.log', {flags: 'a'})
|
221 |
|
222 | // setup the logger
|
223 | app.use(morgan('combined', {stream: accessLogStream}))
|
224 |
|
225 | app.get('/', function (req, res) {
|
226 | res.send('hello, world!')
|
227 | })
|
228 | ```
|
229 |
|
230 | #### log file rotation
|
231 |
|
232 | Simple app that will log all requests in the Apache combined format to one log
|
233 | file per date in the `log/` directory using the
|
234 | [file-stream-rotator module](https://www.npmjs.com/package/file-stream-rotator).
|
235 |
|
236 | ```js
|
237 | var FileStreamRotator = require('file-stream-rotator')
|
238 | var express = require('express')
|
239 | var fs = require('fs')
|
240 | var morgan = require('morgan')
|
241 |
|
242 | var app = express()
|
243 | var logDirectory = __dirname + '/log'
|
244 |
|
245 | // ensure log directory exists
|
246 | fs.existsSync(logDirectory) || fs.mkdirSync(logDirectory)
|
247 |
|
248 | // create a rotating write stream
|
249 | var accessLogStream = FileStreamRotator.getStream({
|
250 | filename: logDirectory + '/access-%DATE%.log',
|
251 | frequency: 'daily',
|
252 | verbose: false
|
253 | })
|
254 |
|
255 | // setup the logger
|
256 | app.use(morgan('combined', {stream: accessLogStream}))
|
257 |
|
258 | app.get('/', function (req, res) {
|
259 | res.send('hello, world!')
|
260 | })
|
261 | ```
|
262 |
|
263 | ### use custom token formats
|
264 |
|
265 | Sample app that will use custom token formats. This adds an ID to all requests and displays it using the `:id` token.
|
266 |
|
267 | ```js
|
268 | var express = require('express')
|
269 | var morgan = require('morgan')
|
270 | var uuid = require('node-uuid')
|
271 |
|
272 | morgan.token('id', function getId(req) {
|
273 | return req.id
|
274 | })
|
275 |
|
276 | var app = express()
|
277 |
|
278 | app.use(assignId)
|
279 | app.use(morgan(':id :method :url :response-time'))
|
280 |
|
281 | app.get('/', function (req, res) {
|
282 | res.send('hello, world!')
|
283 | })
|
284 |
|
285 | function assignId(req, res, next) {
|
286 | req.id = uuid.v4()
|
287 | next()
|
288 | }
|
289 | ```
|
290 |
|
291 | ## License
|
292 |
|
293 | [MIT](LICENSE)
|
294 |
|
295 | [npm-image]: https://img.shields.io/npm/v/morgan.svg
|
296 | [npm-url]: https://npmjs.org/package/morgan
|
297 | [travis-image]: https://img.shields.io/travis/expressjs/morgan/master.svg
|
298 | [travis-url]: https://travis-ci.org/expressjs/morgan
|
299 | [coveralls-image]: https://img.shields.io/coveralls/expressjs/morgan/master.svg
|
300 | [coveralls-url]: https://coveralls.io/r/expressjs/morgan?branch=master
|
301 | [downloads-image]: https://img.shields.io/npm/dm/morgan.svg
|
302 | [downloads-url]: https://npmjs.org/package/morgan
|
303 | [gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg
|
304 | [gratipay-url]: https://www.gratipay.com/dougwilson/
|