[출처] 시대유감 블로그 http://chan180.tistory.com/164
최근 개인적으로 Node.js스터디를 진행하고 있습니다. 책을 한권 구해 차근차근 따라가던 중 express의 logger 미들웨어가 동작하지 않더군요. 우선 기본 개념은 인터넷 참조없이 책만으로 해결하려고 마음먹었는데 당황했습니다. 바로 아래와 같은 에러 메세지가 등장합니다.
간 단히 해석하면 "대부분의 미들웨어(로거와 같은)는 더 이상 익스프레스에 기본으로 제공되지 않으니 반드시 개별로 설치해라. 그리고 url을 봐라"라는군요. (express 4.x버전부터 삭제되었습니다.) logger뿐만 아니라 많은 미들웨어가 제거 되었나봅니다. 앞으로 몇번의 난관이 더 있을거라는 이야기군요.
우선은 express.logger()를 대체할 API를 찾다보니 morgan이라는 모듈이 검색이 됩니다. morgan의 사용법을 알아봅시다.
morgan module을 설치합니다.
아래 나오는 api는 https://github.com/expressjs/morgan을 참조하였습니다. 거의 없다시피한 영어 실력으로 번역하였으므로, 오역이 상당히 많을것으로 예상됩니다.
API
var morgan = require('morgan');morgan(format, options)
morgan 로거 미들웨어 함수는 주어진 format, options을 이용하여 생성합니다. format은 미리 정의된 이름의 문자열(아래 참조), 형식 문자열, 또는 로그 항목을 생성하는 함수가 될 수 있습니다.
Options
morgan은 다음과같은 속성을 옵션으로 받아들입니다.
immediate
response대신 request에 따라 로그를 작성합니다. 서버 크래시가 발생하여도 request들은 기록되지만, reponse(response code, 컨텐츠 길이 등등)의 데이터는 기록할 수 없기 때문입니다.
skip
로깅의 스킵여부를 결정하기 위한 함수입니다. 기본값은 false. 이 함수는 "skip(req, res)" 형식으로 호출됩니다.
// 예 : 에러 response만 기록합니다.
morgan('combined', {
skip : function(req, res) { return res.statusCode < 400 }
});실습 해봅시다! 간단히 예제코드 작성해봤습니다.
var http = require('http');
var express = require('express');
var morgan = require('morgan');
var app = express();
var router = express.Router();
// 이곳으로 접근하면 로그를 출력
router.get('/logging', function(req, res) {
console.log('access logging');
res.writeHead(404, { 'Content-Type' : 'text/html' });
res.end('error!!');
});
// 이곳으로 접근하면 로그 출력하지 않음
router.get('/skip', function(req, res) {
console.log('access skip');
res.writeHead(200, { 'Content-Type' : 'text/html' });
res.end('success!!');
});
// Create new Morgan
var myMorgan = morgan('combined', {
skip : function(req, res) { return res.statusCode < 400 }
});
app.use(myMorgan);
app.use('/', router);
// 서버 생성 및 리슨
http.createServer(app).listen(10000, function() {
console.log('Server Start!!');
});
위의 코드를 작성하고 서버를 띄운 후 http://localhost:10000/logging 과 http://localhost:10000/skip에 접근하여봅시다.
access skip
access logging
::1 - - [07/Apr/2015:05:23:26 +0000] "GET /logging HTTP/1.1" 404 - "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36"
stream
로그 작성을 위한 Output stream옵션입니다. 기본값은 process.stdout입니다.
정의된 포맷들
다양한 정의돈 포맷들이 제공됩니다:
combined
표준 Apache combined 로그 출력
:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
common
표준 Apache common 로그 출력.
:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]
dev
개발용을 위해 response에 따라 색상이 입혀진 축약된 로그를 출력합니다. :status값이 빨간색이면 서버 에러코드, 노란색이면 클라이언트 에러 코드, 청록색은 리다이렉션 코드, 그외 코드는 컬러가 입없습니다.
:method :url :status :response-time ms - :res[content-length]
short
기본 설정보다 짧은 로그를 출력하고, 응답 시간을 포함합니다.
:remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms
tiny
최소화된 로그를 출력합니다.
:method :url :status :res[content-length] - :response-time ms
Tokens
새 토큰 생성
토 큰을 정의하기 위해서는 단순히 morgan.toke()함수를 이름, 콜백함수와 함께 호출하면 됩니다. 이 콜백함수는 string값을 리턴할것이라고 예상합니다. 아래의 콜백함수에서 리턴하는 값은 ":type"으로 사용할 수 있습니다:
morgan.token('type', function(req, res){ return req.headers['content-type']; })
morgan.toke()함수를 호출할 때 같은 이름을 사용하면 기존 token정의는 덮어쓰여지게 됩니다.
:date[format]
현재의 UTC날짜/시간. 사용 가능한 포맷:
clf일반적인 로그 포맷 ("10/Oct/2000:13:55:36 +0000")iso공통 ISO 8601 날짜/시간 포맷 (2000-10-10T13:55:36.000Z)web공통 RFC 1123 날짜/시간 포맷 (Tue, 10 Oct 2000 13:55:36 GMT)
포맷을 설정하지 않을경우 기본값은 web입니다.
:http-version
request의 HTTP버전.
:method
request의 메소드(get,post.....).
:referrer
request의 Referer header.
:remote-addr
request의 remote address. 이 값은 req.ip를 사용한다, 그렇지 않으면 표준req.connection.remoteAddress 값을 사용 (socket address).
:remote-user
인증된 사용자.
:req[header]
The given header 정보.
:res[header]
The given header of the response.
:response-time
request가 morgan으로 들어오고 response header가 쓰여지기 까지의 시간(millis).
:status
reponse status code.
:url
request의 URL. req.originalUrl 이 존재하면 상용하고, 아닐경우 req.url을 사용한다.
:user-agent
User-Agent header의 내용.
Examples
express/connect
모든 요청에 대해서 Aapache combinded 포맷의 로그를 출력하는 간단한 앱 예제
var express = require('express')
var morgan = require('morgan')
var app = express()
app.use(morgan('combined'))
app.get('/', function (req, res) {
res.send('hello, world!')
})
아래는 express모듈을 사용하지 않은 앱의 예제
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!')
})
})
사용자 정의 토큰을 사용하기
모든 요청에 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()
}