├── .gitignore ├── README.md ├── index.js ├── lib └── date_format.js ├── package.json └── test └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | koa-log4js 2 | ========== 3 | 4 | [Log4js](https://github.com/nomiddlename/log4js-node) logger middleware for koa. 5 | 6 | 7 | ## Install 8 | ``` 9 | npm install koa-log4js 10 | ``` 11 | 12 | 13 | ## Example 14 | ``` 15 | var koa = require('koa'); 16 | var logger = require('koa-log4js'); 17 | 18 | 19 | var app = koa(); 20 | 21 | app.use(logger()); // 使用默认console logger 22 | 23 | app.use(function* (){ 24 | this.body = "Hello koa-log4js"; 25 | }); 26 | app.listen(3000); 27 | 28 | 29 | // or 30 | app.use(logger({ 31 | "filename": "relative/path/to/log_file.log" 32 | })); 33 | 34 | 35 | 36 | ``` 37 | 38 | 39 | ## TODO 40 | 41 | * make the options better 42 | * make the log format configurable -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var log4js = require('log4js'); 2 | var util = require('util'); 3 | var date = require('./lib/date_format.js'); 4 | 5 | // date, addr, method, url, HTTP/version, content-length, user-agent 6 | var DEFAULT = "%s %s -- %s %s HTTP/%s, %s %s"; 7 | /* 8 | * middleware 9 | */ 10 | module.exports = function(opts){ 11 | var logger; 12 | if(!opts){ 13 | logger = log4js.getLogger(); // 默认使用 console logger 14 | }else{ 15 | var loggerName = 'normal'; 16 | log4js.configure({ 17 | appenders: [ 18 | { 19 | type: 'console' 20 | }, 21 | { 22 | type: 'file', 23 | filename: opts.file || opts.filename, 24 | maxLogSize: opts.size || 10*1024*1024, 25 | backups: opts.backups || 4, 26 | category: loggerName 27 | } 28 | ], 29 | replaceConsole: true 30 | }); 31 | logger = log4js.getLogger(loggerName); 32 | } 33 | 34 | return function* (next){ 35 | var req = this.request, header = req.header, nodeReq = this.req; 36 | var str = util.format(DEFAULT, date.asString(new Date), req.ip, req.method, req.url, nodeReq.httpVersion, req.length || null, header['user-agent']); 37 | 38 | logger.debug(str); 39 | yield next; 40 | } 41 | } 42 | 43 | 44 | // where to get status, referer 45 | // add more info 46 | // 解析配置选项, 创建file logger, 支持log 内容配置 47 | // 从其他middleware中可以获取到 logger 48 | // 日志格式可参看 log4js的 connetct-logger 49 | -------------------------------------------------------------------------------- /lib/date_format.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.ISO8601_FORMAT = "yyyy-MM-dd hh:mm:ss.SSS"; 3 | exports.ISO8601_WITH_TZ_OFFSET_FORMAT = "yyyy-MM-ddThh:mm:ssO"; 4 | exports.DATETIME_FORMAT = "dd MM yyyy hh:mm:ss.SSS"; 5 | exports.ABSOLUTETIME_FORMAT = "hh:mm:ss.SSS"; 6 | 7 | function padWithZeros(vNumber, width) { 8 | var numAsString = vNumber + ""; 9 | while (numAsString.length < width) { 10 | numAsString = "0" + numAsString; 11 | } 12 | return numAsString; 13 | } 14 | 15 | function addZero(vNumber) { 16 | return padWithZeros(vNumber, 2); 17 | } 18 | 19 | /** 20 | * Formats the TimeOffest 21 | * Thanks to http://www.svendtofte.com/code/date_format/ 22 | * @private 23 | */ 24 | function offset(date) { 25 | // Difference to Greenwich time (GMT) in hours 26 | var os = Math.abs(date.getTimezoneOffset()); 27 | var h = String(Math.floor(os/60)); 28 | var m = String(os%60); 29 | if (h.length == 1) { 30 | h = "0" + h; 31 | } 32 | if (m.length == 1) { 33 | m = "0" + m; 34 | } 35 | return date.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m; 36 | } 37 | 38 | exports.asString = function(/*format,*/ date) { 39 | var format = exports.ISO8601_FORMAT; 40 | if (typeof(date) === "string") { 41 | format = arguments[0]; 42 | date = arguments[1]; 43 | } 44 | 45 | var vDay = addZero(date.getDate()); 46 | var vMonth = addZero(date.getMonth()+1); 47 | var vYearLong = addZero(date.getFullYear()); 48 | var vYearShort = addZero(date.getFullYear().toString().substring(2,4)); 49 | var vYear = (format.indexOf("yyyy") > -1 ? vYearLong : vYearShort); 50 | var vHour = addZero(date.getHours()); 51 | var vMinute = addZero(date.getMinutes()); 52 | var vSecond = addZero(date.getSeconds()); 53 | var vMillisecond = padWithZeros(date.getMilliseconds(), 3); 54 | var vTimeZone = offset(date); 55 | var formatted = format 56 | .replace(/dd/g, vDay) 57 | .replace(/MM/g, vMonth) 58 | .replace(/y{1,4}/g, vYear) 59 | .replace(/hh/g, vHour) 60 | .replace(/mm/g, vMinute) 61 | .replace(/ss/g, vSecond) 62 | .replace(/SSS/g, vMillisecond) 63 | .replace(/O/g, vTimeZone); 64 | return formatted; 65 | 66 | }; 67 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "koa-log4js", 3 | "version": "0.0.0", 4 | "description": "log4js middleware for koa", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "npm test" 8 | }, 9 | "keywords": [ 10 | "koa", 11 | "logger" 12 | ], 13 | "author": "Pana", 14 | "license": "MIT", 15 | "dependencies": { 16 | "log4js": "~0.6.9" 17 | }, 18 | "devDependencies": { 19 | "koa": "~0.2.1", 20 | "mocha": "~1.17.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var koa = require('koa'); 2 | var app = koa(); 3 | var logger = require('../index.js'); 4 | 5 | 6 | var file = __dirname + '/normal.log' 7 | app.use(logger({ 8 | file: file 9 | })); 10 | 11 | app.use(function* (){ 12 | this.body = 'Hello world'; 13 | }); 14 | 15 | app.listen(3000); 16 | console.log("Koa app listen at 3000"); --------------------------------------------------------------------------------