node.js 用の HTTP リクエストロガーミドルウェア
最後まで見てはいけない番組 デクスター にちなんで名付けられました。
これは Node.js モジュールであり、npm レジストリ から入手できます。インストールは npm install
コマンド を使用して行います。
$ npm install morgan
var morgan = require('morgan')
指定された format
と options
を使用して、新しい morgan ロガーミドルウェア関数を作成します。format
引数は、定義済みの名前の文字列(名前については以下を参照)、フォーマット文字列の文字列、またはログエントリを生成する関数のいずれかです。
format
関数は、3 つの引数 tokens
、req
、および res
を使用して呼び出されます。ここで、tokens
は定義されたすべてのトークンを含むオブジェクト、req
は HTTP リクエスト、res
は HTTP レスポンスです。関数は、ログ行となる文字列、またはロギングをスキップするための undefined
/ null
を返すことが期待されます。
morgan('tiny')
morgan(':method :url :status :res[content-length] - :response-time ms')
morgan(function (tokens, req, res) {
return [
tokens.method(req, res),
tokens.url(req, res),
tokens.status(req, res),
tokens.res(req, res, 'content-length'), '-',
tokens['response-time'](req, res), 'ms'
].join(' ')
})
Morgan は、オプションオブジェクトでこれらのプロパティを受け入れます。
レスポンスではなくリクエスト時にログ行を書き込みます。これは、サーバーがクラッシュした場合でもリクエストがログに記録されることを意味しますが、レスポンスからのデータ(レスポンスコード、コンテンツの長さなど)はログに記録できません。
ロギングをスキップするかどうかを決定する関数。デフォルトは false
です。この関数は skip(req, res)
として呼び出されます。
// EXAMPLE: only log error responses
morgan('combined', {
skip: function (req, res) { return res.statusCode < 400 }
})
ログ行を書き込むための出力ストリーム。デフォルトは process.stdout
です。
さまざまな定義済みフォーマットが提供されています
標準の Apache combined ログ出力。
:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
標準の Apache common ログ出力。
:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]
開発用にレスポンスステータスで色分けされた簡潔な出力。:status
トークンは、成功コードの場合は緑、サーバーエラーコードの場合は赤、クライアントエラーコードの場合は黄色、リダイレクトコードの場合はシアン、情報コードの場合は無色になります。
:method :url :status :response-time ms - :res[content-length]
デフォルトよりも短く、レスポンスタイムも含まれています。
:remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms
最小限の出力。
:method :url :status :res[content-length] - :response-time ms
トークンを定義するには、名前とコールバック関数を使用して morgan.token()
を呼び出します。このコールバック関数は、文字列値を返すことが期待されます。返された値は、この場合は「:type」として使用できます。
morgan.token('type', function (req, res) { return req.headers['content-type'] })
既存のトークンと同じ名前を使用して morgan.token()
を呼び出すと、そのトークン定義が上書きされます。
トークン関数は、HTTP リクエストと HTTP レスポンスを表す引数 req
と res
を使用して呼び出されることが期待されます。さらに、トークンは動作をカスタマイズするために、選択したさらなる引数を受け入れることができます。
UTC での現在の日時。使用可能な形式は次のとおりです。
clf
("10/Oct/2000:13:55:36 +0000"
)iso
(2000-10-10T13:55:36.000Z
)web
(Tue, 10 Oct 2000 13:55:36 GMT
)形式が指定されていない場合、デフォルトは web
です。
リクエストの HTTP バージョン。
リクエストの HTTP メソッド。
リクエストの Referrer ヘッダー。Referer ヘッダーが存在する場合は、標準のスペルミスのある Referer ヘッダーが使用され、それ以外の場合は Referrer が使用されます。
リクエストのリモートアドレス。req.ip
が使用され、それ以外の場合は標準の req.connection.remoteAddress
値(ソケットアドレス)が使用されます。
リクエストの基本認証の一部として認証されたユーザー。
リクエストの指定された header
。ヘッダーが存在しない場合、値はログに "-"
として表示されます。
レスポンスの指定された header
。ヘッダーが存在しない場合、値はログに "-"
として表示されます。
リクエストが morgan
に到着してからレスポンスヘッダーが書き込まれるまでの時間(ミリ秒)。
digits
引数は、数値に含める桁数を指定する数値です。デフォルトは 3
で、マイクロ秒の精度が提供されます。
レスポンスのステータスコード。
クライアントにレスポンスが送信される前にリクエスト/レスポンスサイクルが完了した場合(たとえば、クライアントがリクエストを中止したために TCP ソケットが途中で閉じられた場合)、ステータスは空になります(ログに "-"
として表示されます)。
リクエストが morgan
に到着してからレスポンスが接続に書き込まれるのが完了するまでの時間(ミリ秒)。
digits
引数は、数値に含める桁数を指定する数値です。デフォルトは 3
で、マイクロ秒の精度が提供されます。
リクエストの URL。req.originalUrl
が存在する場合はそれが使用され、それ以外の場合は req.url
が使用されます。
リクエストの User-Agent ヘッダーの内容。
フォーマット文字列を、morgan
で使用するための format
関数にコンパイルします。フォーマット文字列は、単一のログ行を表す文字列であり、トークン構文を使用できます。トークンは :token-name
で参照されます。トークンが引数を受け入れる場合、[]
を使用して渡すことができます。たとえば、:token-name[pretty]
は文字列 'pretty'
をトークン token-name
に引数として渡します。
morgan.compile
から返された関数は、3 つの引数 tokens
、req
、および res
を取ります。ここで、tokens
は定義されたすべてのトークンを含むオブジェクト、req
は HTTP リクエスト、res
は HTTP レスポンスです。関数は、ログ行となる文字列、またはロギングをスキップするための undefined
/ null
を返します。
通常、フォーマットは morgan.format(name, format)
を使用して定義されますが、特定の高度な用途では、このコンパイル関数を直接使用できます。
すべてのリクエストを Apache combined 形式で STDOUT に記録するサンプルアプリ
var express = require('express')
var morgan = require('morgan')
var app = express()
app.use(morgan('combined'))
app.get('/', function (req, res) {
res.send('hello, world!')
})
すべてのリクエストを Apache combined 形式で STDOUT に記録するサンプルアプリ
var finalhandler = require('finalhandler')
var http = require('http')
var morgan = require('morgan')
// create "middleware"
var logger = morgan('combined')
http.createServer(function (req, res) {
var done = finalhandler(req, res)
logger(req, res, function (err) {
if (err) return done(err)
// respond to request
res.setHeader('content-type', 'text/plain')
res.end('hello, world!')
})
})
すべてのリクエストを Apache combined 形式でファイル access.log
に記録するサンプルアプリ。
var express = require('express')
var fs = require('fs')
var morgan = require('morgan')
var path = require('path')
var app = express()
// create a write stream (in append mode)
var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' })
// setup the logger
app.use(morgan('combined', { stream: accessLogStream }))
app.get('/', function (req, res) {
res.send('hello, world!')
})
rotating-file-stream モジュール を使用して、すべてのリクエストを Apache combined 形式で log/
ディレクトリに 1 日 1 つのログファイルに記録するサンプルアプリ。
var express = require('express')
var morgan = require('morgan')
var path = require('path')
var rfs = require('rotating-file-stream') // version 2.x
var app = express()
// create a rotating write stream
var accessLogStream = rfs.createStream('access.log', {
interval: '1d', // rotate daily
path: path.join(__dirname, 'log')
})
// setup the logger
app.use(morgan('combined', { stream: accessLogStream }))
app.get('/', function (req, res) {
res.send('hello, world!')
})
morgan
ミドルウェアは必要な回数だけ使用できるため、次のような組み合わせが可能です。
すべてのリクエストを Apache 形式を使用してファイルに記録するが、エラーレスポンスはコンソールに記録するサンプルアプリ
var express = require('express')
var fs = require('fs')
var morgan = require('morgan')
var path = require('path')
var app = express()
// log only 4xx and 5xx responses to console
app.use(morgan('dev', {
skip: function (req, res) { return res.statusCode < 400 }
}))
// log all requests to access.log
app.use(morgan('common', {
stream: fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' })
}))
app.get('/', function (req, res) {
res.send('hello, world!')
})
カスタムトークン形式を使用するサンプルアプリ。これはすべてのリクエストに ID を追加し、:id
トークンを使用して表示します。
var express = require('express')
var morgan = require('morgan')
var uuid = require('node-uuid')
morgan.token('id', function getId (req) {
return req.id
})
var app = express()
app.use(assignId)
app.use(morgan(':id :method :url :response-time'))
app.get('/', function (req, res) {
res.send('hello, world!')
})
function assignId (req, res, next) {
req.id = uuid.v4()
next()
}