Compare commits
32 Commits
release-0.
...
v0.6.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8383dfc4f4 | ||
|
|
4e8fb26099 | ||
|
|
8492519e3b | ||
|
|
fdc9d253c9 | ||
|
|
18e21ca473 | ||
|
|
ab8c7ed89d | ||
|
|
aa4f7c071b | ||
|
|
dc632f4705 | ||
|
|
ac6284add1 | ||
|
|
2da01cc611 | ||
|
|
ad8229145e | ||
|
|
8c12c948d9 | ||
|
|
af6ae7af98 | ||
|
|
936ad4da8e | ||
|
|
097ae3d7f1 | ||
|
|
04de4ed8d3 | ||
|
|
29b02921b6 | ||
|
|
48ed5d1222 | ||
|
|
7844b0d2e4 | ||
|
|
8b49ba9f3d | ||
|
|
ed7462885f | ||
|
|
36c5175a55 | ||
|
|
22160f90b3 | ||
|
|
73437ecb40 | ||
|
|
107e33c0d1 | ||
|
|
0544342e9f | ||
|
|
1d1153d32f | ||
|
|
e58cf201ca | ||
|
|
83271e47fc | ||
|
|
f3271a3997 | ||
|
|
4b7cf589a2 | ||
|
|
c8f401c47d |
@@ -1,3 +1,5 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.10
|
||||
- "0.10"
|
||||
- "0.8"
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@ Out of the box it supports the following features:
|
||||
* configurable log message layout/patterns
|
||||
* different log levels for different log categories (make some parts of your app log as DEBUG, others only ERRORS, etc.)
|
||||
|
||||
NOTE: version 0.6.0 onwards will only work with node v0.10.x upwards, since it makes use of the new streams API. If you're using node 0.8 or lower, use log4js@0.5.7.
|
||||
|
||||
NOTE: from log4js 0.5 onwards you'll need to explicitly enable replacement of node's console.log functions. Do this either by calling `log4js.replaceConsole()` or configuring with an object or json file like this:
|
||||
|
||||
```javascript
|
||||
@@ -130,13 +128,13 @@ If you have already defined an absolute path for one of the FileAppenders in the
|
||||
]
|
||||
}
|
||||
```
|
||||
Documentation for most of the core appenders can be found on the [wiki](log4js-node/wiki/Appenders), otherwise take a look at the tests and the examples.
|
||||
Documentation for most of the core appenders can be found on the [wiki](https://github.com/nomiddlename/log4js-node/wiki/Appenders), otherwise take a look at the tests and the examples.
|
||||
|
||||
## Documentation
|
||||
See the [wiki](log4js-node/wiki). Improve the [wiki](log4js-node/wiki), please.
|
||||
See the [wiki](https://github.com/nomiddlename/log4js-node/wiki). Improve the [wiki](https://github.com/nomiddlename/log4js-node/wiki), please.
|
||||
|
||||
## Contributing
|
||||
Contributions welcome, but take a look at the [rules](log4js-node/wiki/Contributing) first.
|
||||
Contributions welcome, but take a look at the [rules](https://github.com/nomiddlename/log4js-node/wiki/Contributing) first.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,14 +1,46 @@
|
||||
var log4js = require('./lib/log4js');
|
||||
log4js.addAppender(log4js.fileAppender('cheese.log'), 'cheese');
|
||||
//The connect/express logger was added to log4js by danbell. This allows connect/express servers to log using log4js.
|
||||
//https://github.com/nomiddlename/log4js-node/wiki/Connect-Logger
|
||||
|
||||
var logger = log4js.getLogger('cheese');
|
||||
logger.setLevel('INFO');
|
||||
// load modules
|
||||
var log4js = require('log4js');
|
||||
var express = require("express");
|
||||
var app = express();
|
||||
|
||||
var app = require('express').createServer();
|
||||
//config
|
||||
log4js.configure({
|
||||
appenders: [
|
||||
{ type: 'console' },
|
||||
{ type: 'file', filename: 'logs/log4jsconnect.log', category: 'log4jslog' }
|
||||
]
|
||||
});
|
||||
|
||||
//define logger
|
||||
var logger = log4js.getLogger('log4jslog');
|
||||
|
||||
// set at which time msg is logged print like: only on error & above
|
||||
// logger.setLevel('ERROR');
|
||||
|
||||
//express app
|
||||
app.configure(function() {
|
||||
app.use(log4js.connectLogger(logger, { level: log4js.levels.INFO }));
|
||||
app.use(express.favicon(''));
|
||||
// app.use(log4js.connectLogger(logger, { level: log4js.levels.INFO }));
|
||||
// app.use(log4js.connectLogger(logger, { level: 'auto', format: ':method :url :status' }));
|
||||
|
||||
//### AUTO LEVEL DETECTION
|
||||
//http responses 3xx, level = WARN
|
||||
//http responses 4xx & 5xx, level = ERROR
|
||||
//else.level = INFO
|
||||
app.use(log4js.connectLogger(logger, { level: 'auto' }));
|
||||
});
|
||||
app.get('*', function(req,res) {
|
||||
res.send('hello world\n <a href="/cheese">cheese</a>\n');
|
||||
|
||||
//route
|
||||
app.get('/', function(req,res) {
|
||||
res.send('hello world');
|
||||
});
|
||||
|
||||
//start app
|
||||
app.listen(5000);
|
||||
|
||||
console.log('server runing at localhost:5000');
|
||||
console.log('Simulation of normal response: goto localhost:5000');
|
||||
console.log('Simulation of error response: goto localhost:5000/xxx');
|
||||
|
||||
43
examples/smtp-appender.js
Normal file
43
examples/smtp-appender.js
Normal file
@@ -0,0 +1,43 @@
|
||||
//Note that smtp appender needs nodemailer to work.
|
||||
//If you haven't got nodemailer installed, you'll get cryptic
|
||||
//"cannot find module" errors when using the smtp appender
|
||||
var log4js = require('../lib/log4js')
|
||||
, log
|
||||
, logmailer
|
||||
, i = 0;
|
||||
log4js.configure({
|
||||
"appenders": [
|
||||
{
|
||||
type: "console",
|
||||
category: "test"
|
||||
},
|
||||
{
|
||||
"type": "smtp",
|
||||
"recipients": "logfilerecipient@logging.com",
|
||||
"sendInterval": 5,
|
||||
"transport": "SMTP",
|
||||
"SMTP": {
|
||||
"host": "smtp.gmail.com",
|
||||
"secureConnection": true,
|
||||
"port": 465,
|
||||
"auth": {
|
||||
"user": "someone@gmail",
|
||||
"pass": "********************"
|
||||
},
|
||||
"debug": true
|
||||
},
|
||||
"category": "mailer"
|
||||
}
|
||||
]
|
||||
});
|
||||
log = log4js.getLogger("test");
|
||||
logmailer = log4js.getLogger("mailer");
|
||||
|
||||
function doTheLogging(x) {
|
||||
log.info("Logging something %d", x);
|
||||
logmailer.info("Logging something %d", x);
|
||||
}
|
||||
|
||||
for ( ; i < 500; i++) {
|
||||
doTheLogging(i);
|
||||
}
|
||||
@@ -19,10 +19,10 @@ process.on('exit', function() {
|
||||
* also used to check when to roll files - defaults to '.yyyy-MM-dd'
|
||||
* @layout layout function for log messages - defaults to basicLayout
|
||||
*/
|
||||
function appender(filename, pattern, layout) {
|
||||
function appender(filename, pattern, alwaysIncludePattern, layout) {
|
||||
layout = layout || layouts.basicLayout;
|
||||
|
||||
var logFile = new streams.DateRollingFileStream(filename, pattern);
|
||||
var logFile = new streams.DateRollingFileStream(filename, pattern, { alwaysIncludePattern: alwaysIncludePattern });
|
||||
openFiles.push(logFile);
|
||||
|
||||
return function(logEvent) {
|
||||
@@ -35,14 +35,18 @@ function configure(config, options) {
|
||||
var layout;
|
||||
|
||||
if (config.layout) {
|
||||
layout = layouts.layout(config.layout.type, config.layout);
|
||||
layout = layouts.layout(config.layout.type, config.layout);
|
||||
}
|
||||
|
||||
if (!config.alwaysIncludePattern) {
|
||||
config.alwaysIncludePattern = false;
|
||||
}
|
||||
|
||||
if (options && options.cwd && !config.absolute) {
|
||||
config.filename = path.join(options.cwd, config.filename);
|
||||
}
|
||||
|
||||
return appender(config.filename, config.pattern, layout);
|
||||
return appender(config.filename, config.pattern, config.alwaysIncludePattern, layout);
|
||||
}
|
||||
|
||||
exports.appender = appender;
|
||||
|
||||
@@ -38,31 +38,30 @@ function logServer(config) {
|
||||
var actualAppender = config.actualAppender,
|
||||
server = net.createServer(function serverCreated(clientSocket) {
|
||||
clientSocket.setEncoding('utf8');
|
||||
clientSocket.on('connect', function clientConnected() {
|
||||
var logMessage = '';
|
||||
var logMessage = '';
|
||||
|
||||
function logTheMessage(msg) {
|
||||
if (logMessage.length > 0) {
|
||||
actualAppender(deserializeLoggingEvent(clientSocket, msg));
|
||||
}
|
||||
function logTheMessage(msg) {
|
||||
if (logMessage.length > 0) {
|
||||
actualAppender(deserializeLoggingEvent(clientSocket, msg));
|
||||
}
|
||||
}
|
||||
|
||||
function chunkReceived(chunk) {
|
||||
var event;
|
||||
logMessage += chunk || '';
|
||||
if (logMessage.indexOf(END_MSG) > -1) {
|
||||
event = logMessage.substring(0, logMessage.indexOf(END_MSG));
|
||||
logTheMessage(event);
|
||||
logMessage = logMessage.substring(event.length + END_MSG.length) || '';
|
||||
//check for more, maybe it was a big chunk
|
||||
chunkReceived();
|
||||
}
|
||||
function chunkReceived(chunk) {
|
||||
var event;
|
||||
logMessage += chunk || '';
|
||||
if (logMessage.indexOf(END_MSG) > -1) {
|
||||
event = logMessage.substring(0, logMessage.indexOf(END_MSG));
|
||||
logTheMessage(event);
|
||||
logMessage = logMessage.substring(event.length + END_MSG.length) || '';
|
||||
//check for more, maybe it was a big chunk
|
||||
chunkReceived();
|
||||
}
|
||||
}
|
||||
|
||||
clientSocket.on('data', chunkReceived);
|
||||
clientSocket.on('end', chunkReceived);
|
||||
});
|
||||
clientSocket.on('data', chunkReceived);
|
||||
clientSocket.on('end', chunkReceived);
|
||||
});
|
||||
|
||||
server.listen(config.loggerPort || 5000, config.loggerHost || 'localhost');
|
||||
|
||||
return actualAppender;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
var layouts = require("../layouts"),
|
||||
mailer = require("nodemailer"),
|
||||
os = require('os');
|
||||
mailer = require("nodemailer"),
|
||||
os = require('os');
|
||||
|
||||
/**
|
||||
* SMTP Appender. Sends logging events using SMTP protocol.
|
||||
@@ -17,12 +17,13 @@ function smtpAppender(config, layout) {
|
||||
|
||||
var logEventBuffer = [];
|
||||
var sendTimer;
|
||||
var transport = mailer.createTransport(config.transport, config[config.transport]);
|
||||
|
||||
function sendBuffer() {
|
||||
if (logEventBuffer.length == 0)
|
||||
if (logEventBuffer.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var transport = mailer.createTransport(config.transport, config[config.transport]);
|
||||
var firstEvent = logEventBuffer[0];
|
||||
var body = "";
|
||||
while (logEventBuffer.length > 0) {
|
||||
@@ -35,29 +36,33 @@ function smtpAppender(config, layout) {
|
||||
text: body,
|
||||
headers: {"Hostname": os.hostname()}
|
||||
};
|
||||
if (config.sender)
|
||||
if (config.sender) {
|
||||
msg.from = config.sender;
|
||||
}
|
||||
transport.sendMail(msg, function(error, success) {
|
||||
if (error) {
|
||||
console.error("log4js.smtpAppender - Error happened ", error);
|
||||
}
|
||||
transport.close();
|
||||
});
|
||||
}
|
||||
|
||||
function scheduleSend() {
|
||||
if (!sendTimer)
|
||||
if (!sendTimer) {
|
||||
sendTimer = setTimeout(function() {
|
||||
sendTimer = null;
|
||||
sendBuffer();
|
||||
}, sendInterval);
|
||||
}
|
||||
}
|
||||
|
||||
return function(loggingEvent) {
|
||||
logEventBuffer.push(loggingEvent);
|
||||
if (sendInterval > 0)
|
||||
if (sendInterval > 0) {
|
||||
scheduleSend();
|
||||
else
|
||||
} else {
|
||||
sendBuffer();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ var levels = require("./levels");
|
||||
* Options:
|
||||
*
|
||||
* - `format` Format string, see below for tokens
|
||||
* - `level` A log4js levels instance.
|
||||
* - `level` A log4js levels instance. Supports also 'auto'
|
||||
*
|
||||
* Tokens:
|
||||
*
|
||||
@@ -26,64 +26,74 @@ var levels = require("./levels");
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function getLogger(logger4js, options) {
|
||||
if ('object' == typeof options) {
|
||||
options = options || {};
|
||||
} else if (options) {
|
||||
options = { format: options };
|
||||
} else {
|
||||
options = {};
|
||||
}
|
||||
function getLogger(logger4js, options) {
|
||||
if ('object' == typeof options) {
|
||||
options = options || {};
|
||||
} else if (options) {
|
||||
options = { format: options };
|
||||
} else {
|
||||
options = {};
|
||||
}
|
||||
|
||||
var thislogger = logger4js
|
||||
, level = levels.toLevel(options.level, levels.INFO)
|
||||
, fmt = options.format || ':remote-addr - - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"'
|
||||
, nolog = options.nolog ? createNoLogCondition(options.nolog) : null;
|
||||
var thislogger = logger4js
|
||||
, level = levels.toLevel(options.level, levels.INFO)
|
||||
, fmt = options.format || ':remote-addr - - ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"'
|
||||
, nolog = options.nolog ? createNoLogCondition(options.nolog) : null;
|
||||
|
||||
return function (req, res, next) {
|
||||
return function (req, res, next) {
|
||||
|
||||
// mount safety
|
||||
if (req._logging) return next();
|
||||
|
||||
// nologs
|
||||
if (nolog && nolog.test(req.originalUrl)) return next();
|
||||
// nologs
|
||||
if (nolog && nolog.test(req.originalUrl)) return next();
|
||||
if (thislogger.isLevelEnabled(level) || options.level === 'auto') {
|
||||
|
||||
if (thislogger.isLevelEnabled(level)) {
|
||||
var start = +new Date
|
||||
, statusCode
|
||||
, writeHead = res.writeHead
|
||||
, end = res.end
|
||||
, url = req.originalUrl;
|
||||
|
||||
var start = +new Date
|
||||
, statusCode
|
||||
, writeHead = res.writeHead
|
||||
, end = res.end
|
||||
, url = req.originalUrl;
|
||||
// flag as logging
|
||||
req._logging = true;
|
||||
|
||||
// flag as logging
|
||||
req._logging = true;
|
||||
// proxy for statusCode.
|
||||
res.writeHead = function(code, headers){
|
||||
res.writeHead = writeHead;
|
||||
res.writeHead(code, headers);
|
||||
res.__statusCode = statusCode = code;
|
||||
res.__headers = headers || {};
|
||||
|
||||
// proxy for statusCode.
|
||||
res.writeHead = function(code, headers){
|
||||
res.writeHead = writeHead;
|
||||
res.writeHead(code, headers);
|
||||
res.__statusCode = statusCode = code;
|
||||
res.__headers = headers || {};
|
||||
};
|
||||
//status code response level handling
|
||||
if(options.level === 'auto'){
|
||||
level = levels.INFO;
|
||||
if(code >= 300) level = levels.WARN;
|
||||
if(code >= 400) level = levels.ERROR;
|
||||
} else {
|
||||
level = levels.toLevel(options.level, levels.INFO)
|
||||
}
|
||||
};
|
||||
|
||||
// proxy end to output a line to the provided logger.
|
||||
res.end = function(chunk, encoding) {
|
||||
res.end = end;
|
||||
res.end(chunk, encoding);
|
||||
res.responseTime = +new Date - start;
|
||||
if ('function' == typeof fmt) {
|
||||
var line = fmt(req, res, function(str){ return format(str, req, res); });
|
||||
if (line) thislogger.log(level, line);
|
||||
} else {
|
||||
thislogger.log(level, format(fmt, req, res));
|
||||
// proxy end to output a line to the provided logger.
|
||||
res.end = function(chunk, encoding) {
|
||||
res.end = end;
|
||||
res.end(chunk, encoding);
|
||||
res.responseTime = +new Date - start;
|
||||
if (thislogger.isLevelEnabled(level)) {
|
||||
if (typeof fmt === 'function') {
|
||||
var line = fmt(req, res, function(str){ return format(str, req, res); });
|
||||
if (line) thislogger.log(level, line);
|
||||
} else {
|
||||
thislogger.log(level, format(fmt, req, res));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//ensure next gets always called
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,25 +106,25 @@ function getLogger(logger4js, options) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function format(str, req, res) {
|
||||
return str
|
||||
.replace(':url', req.originalUrl)
|
||||
function format(str, req, res) {
|
||||
return str
|
||||
.replace(':url', req.originalUrl)
|
||||
.replace(':method', req.method)
|
||||
.replace(':status', res.__statusCode || res.statusCode)
|
||||
.replace(':response-time', res.responseTime)
|
||||
.replace(':date', new Date().toUTCString())
|
||||
.replace(':referrer', req.headers['referer'] || req.headers['referrer'] || '')
|
||||
.replace(':http-version', req.httpVersionMajor + '.' + req.httpVersionMinor)
|
||||
.replace(':remote-addr', req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)))
|
||||
.replace(':user-agent', req.headers['user-agent'] || '')
|
||||
.replace(':content-length', (res._headers && res._headers['content-length']) || (res.__headers && res.__headers['Content-Length']) || '-')
|
||||
.replace(/:req\[([^\]]+)\]/g, function(_, field){ return req.headers[field.toLowerCase()]; })
|
||||
.replace(/:res\[([^\]]+)\]/g, function(_, field){
|
||||
return res._headers
|
||||
? (res._headers[field.toLowerCase()] || res.__headers[field])
|
||||
: (res.__headers && res.__headers[field]);
|
||||
});
|
||||
}
|
||||
.replace(':status', res.__statusCode || res.statusCode)
|
||||
.replace(':response-time', res.responseTime)
|
||||
.replace(':date', new Date().toUTCString())
|
||||
.replace(':referrer', req.headers['referer'] || req.headers['referrer'] || '')
|
||||
.replace(':http-version', req.httpVersionMajor + '.' + req.httpVersionMinor)
|
||||
.replace(':remote-addr', req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)))
|
||||
.replace(':user-agent', req.headers['user-agent'] || '')
|
||||
.replace(':content-length', (res._headers && res._headers['content-length']) || (res.__headers && res.__headers['Content-Length']) || '-')
|
||||
.replace(/:req\[([^\]]+)\]/g, function(_, field){ return req.headers[field.toLowerCase()]; })
|
||||
.replace(/:res\[([^\]]+)\]/g, function(_, field){
|
||||
return res._headers
|
||||
? (res._headers[field.toLowerCase()] || res.__headers[field])
|
||||
: (res.__headers && res.__headers[field]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return RegExp Object about nolog
|
||||
@@ -143,26 +153,26 @@ function format(str, req, res) {
|
||||
* 3.1 ["\\.jpg$", "\\.png", "\\.gif"]
|
||||
* SAME AS "\\.jpg|\\.png|\\.gif"
|
||||
*/
|
||||
function createNoLogCondition(nolog, type) {
|
||||
if(!nolog) return null;
|
||||
type = type || '';
|
||||
function createNoLogCondition(nolog, type) {
|
||||
if(!nolog) return null;
|
||||
type = type || '';
|
||||
|
||||
if(nolog instanceof RegExp){
|
||||
if(type === 'string')
|
||||
return nolog.source;
|
||||
return nolog;
|
||||
} else if(typeof nolog === 'string'){
|
||||
if(type === 'string')
|
||||
return nolog;
|
||||
try{
|
||||
return new RegExp(nolog);
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
} else if(nolog instanceof Array){
|
||||
var regexps = nolog.map(function(o){ return createNoLogCondition(o, 'string')});
|
||||
return new RegExp(regexps.join('|'));
|
||||
}
|
||||
}
|
||||
if(nolog instanceof RegExp){
|
||||
if(type === 'string')
|
||||
return nolog.source;
|
||||
return nolog;
|
||||
} else if(typeof nolog === 'string'){
|
||||
if(type === 'string')
|
||||
return nolog;
|
||||
try{
|
||||
return new RegExp(nolog);
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
} else if(nolog instanceof Array){
|
||||
var regexps = nolog.map(function(o){ return createNoLogCondition(o, 'string')});
|
||||
return new RegExp(regexps.join('|'));
|
||||
}
|
||||
}
|
||||
|
||||
exports.connectLogger = getLogger;
|
||||
exports.connectLogger = getLogger;
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
var fs = require('fs'),
|
||||
stream = require('stream'),
|
||||
util = require('util');
|
||||
stream,
|
||||
util = require('util'),
|
||||
semver = require('semver');
|
||||
|
||||
function debug(message) {
|
||||
// console.log(message);
|
||||
if (semver.satisfies(process.version, '>=0.10.0')) {
|
||||
stream = require('stream');
|
||||
} else {
|
||||
stream = require('readable-stream');
|
||||
}
|
||||
|
||||
var debug;
|
||||
if (process.env.NODE_DEBUG && /\blog4js\b/.test(process.env.NODE_DEBUG)) {
|
||||
debug = function(message) { console.error('LOG4JS: (BaseRollingFileStream) %s', message); };
|
||||
} else {
|
||||
debug = function() { };
|
||||
}
|
||||
|
||||
module.exports = BaseRollingFileStream;
|
||||
@@ -66,7 +76,7 @@ BaseRollingFileStream.prototype.openTheStream = function(cb) {
|
||||
|
||||
BaseRollingFileStream.prototype.closeTheStream = function(cb) {
|
||||
debug("closing the underlying stream");
|
||||
this.theStream.end(null, null, cb);
|
||||
this.theStream.end(cb);
|
||||
};
|
||||
|
||||
BaseRollingFileStream.prototype.shouldRoll = function() {
|
||||
|
||||
@@ -6,23 +6,39 @@ var BaseRollingFileStream = require('./BaseRollingFileStream'),
|
||||
|
||||
module.exports = DateRollingFileStream;
|
||||
|
||||
function debug(message) {
|
||||
// console.log(message);
|
||||
var debug;
|
||||
if (process.env.NODE_DEBUG && /\blog4js\b/.test(process.env.NODE_DEBUG)) {
|
||||
debug = function(message) { console.error('LOG4JS: (DateRollingFileStream) %s', message); };
|
||||
} else {
|
||||
debug = function() { };
|
||||
}
|
||||
|
||||
function DateRollingFileStream(filename, pattern, options, now) {
|
||||
debug("Now is " + now);
|
||||
if (pattern && typeof(pattern) === 'object') {
|
||||
now = options;
|
||||
options = pattern;
|
||||
pattern = null;
|
||||
debug("Now is " + now);
|
||||
if (pattern && typeof(pattern) === 'object') {
|
||||
now = options;
|
||||
options = pattern;
|
||||
pattern = null;
|
||||
}
|
||||
this.pattern = pattern || '.yyyy-MM-dd';
|
||||
this.now = now || Date.now;
|
||||
this.lastTimeWeWroteSomething = format.asString(this.pattern, new Date(this.now()));
|
||||
this.baseFilename = filename;
|
||||
this.alwaysIncludePattern = false;
|
||||
|
||||
if (options) {
|
||||
if (options.alwaysIncludePattern) {
|
||||
this.alwaysIncludePattern = true;
|
||||
filename = this.baseFilename + this.lastTimeWeWroteSomething;
|
||||
}
|
||||
this.pattern = pattern || '.yyyy-MM-dd';
|
||||
this.now = now || Date.now;
|
||||
this.lastTimeWeWroteSomething = format.asString(this.pattern, new Date(this.now()));
|
||||
debug("this.now is " + this.now + ", now is " + now);
|
||||
delete options.alwaysIncludePattern;
|
||||
if (Object.keys(options).length === 0) {
|
||||
options = null;
|
||||
}
|
||||
}
|
||||
debug("this.now is " + this.now + ", now is " + now);
|
||||
|
||||
DateRollingFileStream.super_.call(this, filename, options);
|
||||
DateRollingFileStream.super_.call(this, filename, options);
|
||||
}
|
||||
util.inherits(DateRollingFileStream, BaseRollingFileStream);
|
||||
|
||||
@@ -39,18 +55,26 @@ DateRollingFileStream.prototype.shouldRoll = function() {
|
||||
};
|
||||
|
||||
DateRollingFileStream.prototype.roll = function(filename, callback) {
|
||||
var that = this,
|
||||
newFilename = filename + this.previousTime;
|
||||
var that = this;
|
||||
|
||||
debug("Starting roll");
|
||||
|
||||
async.series([
|
||||
this.closeTheStream.bind(this),
|
||||
deleteAnyExistingFile,
|
||||
renameTheCurrentFile,
|
||||
this.openTheStream.bind(this)
|
||||
], callback);
|
||||
|
||||
if (this.alwaysIncludePattern) {
|
||||
this.filename = this.baseFilename + this.lastTimeWeWroteSomething;
|
||||
async.series([
|
||||
this.closeTheStream.bind(this),
|
||||
this.openTheStream.bind(this)
|
||||
], callback);
|
||||
} else {
|
||||
var newFilename = this.baseFilename + this.previousTime;
|
||||
async.series([
|
||||
this.closeTheStream.bind(this),
|
||||
deleteAnyExistingFile,
|
||||
renameTheCurrentFile,
|
||||
this.openTheStream.bind(this)
|
||||
], callback);
|
||||
}
|
||||
|
||||
function deleteAnyExistingFile(cb) {
|
||||
//on windows, you can get a EEXIST error if you rename a file to an existing file
|
||||
//so, we'll try to delete the file we're renaming to first
|
||||
|
||||
@@ -4,9 +4,11 @@ var BaseRollingFileStream = require('./BaseRollingFileStream'),
|
||||
fs = require('fs'),
|
||||
async = require('async');
|
||||
|
||||
function debug() {
|
||||
// util.debug(message);
|
||||
// console.log.apply(console, arguments);
|
||||
var debug;
|
||||
if (process.env.NODE_DEBUG && /\blog4js\b/.test(process.env.NODE_DEBUG)) {
|
||||
debug = function(message) { console.error('LOG4JS: (RollingFileStream) %s', message); };
|
||||
} else {
|
||||
debug = function() { };
|
||||
}
|
||||
|
||||
module.exports = RollingFileStream;
|
||||
|
||||
78
package.json
78
package.json
@@ -1,40 +1,42 @@
|
||||
{
|
||||
"name": "log4js",
|
||||
"version": "0.6.1",
|
||||
"description": "Port of Log4js to work with node.",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"log",
|
||||
"log4j",
|
||||
"node"
|
||||
],
|
||||
"main": "./lib/log4js",
|
||||
"author": "Gareth Jones <gareth.jones@sensis.com.au>",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nomiddlename/log4js-node.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/nomiddlename/log4js-node/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": "~0.10"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vows"
|
||||
},
|
||||
"directories": {
|
||||
"test": "test",
|
||||
"lib": "lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "0.1.15",
|
||||
"dequeue": "1.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vows": "0.7.0",
|
||||
"sandboxed-module": "0.1.3",
|
||||
"hook.io": "0.8.10",
|
||||
"underscore": "1.2.1"
|
||||
}
|
||||
"name": "log4js",
|
||||
"version": "0.6.6",
|
||||
"description": "Port of Log4js to work with node.",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"log",
|
||||
"log4j",
|
||||
"node"
|
||||
],
|
||||
"main": "./lib/log4js",
|
||||
"author": "Gareth Jones <gareth.jones@sensis.com.au>",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nomiddlename/log4js-node.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/nomiddlename/log4js-node/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vows"
|
||||
},
|
||||
"directories": {
|
||||
"test": "test",
|
||||
"lib": "lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "0.1.15",
|
||||
"dequeue": "1.0.3",
|
||||
"semver": "~1.1.4",
|
||||
"readable-stream": "~1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vows": "0.7.0",
|
||||
"sandboxed-module": "0.1.3",
|
||||
"hook.io": "0.8.10",
|
||||
"underscore": "1.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,27 +72,62 @@ vows.describe('../lib/appenders/dateFile').addBatch({
|
||||
|
||||
}
|
||||
}).addBatch({
|
||||
'configure': {
|
||||
'with dateFileAppender': {
|
||||
'configure': {
|
||||
'with dateFileAppender': {
|
||||
topic: function() {
|
||||
var log4js = require('../lib/log4js')
|
||||
, logger;
|
||||
//this config file defines one file appender (to ./date-file-test.log)
|
||||
//and sets the log level for "tests" to WARN
|
||||
log4js.configure('test/with-dateFile.json');
|
||||
logger = log4js.getLogger('tests');
|
||||
logger.info('this should not be written to the file');
|
||||
logger.warn('this should be written to the file');
|
||||
|
||||
fs.readFile(path.join(__dirname, 'date-file-test.log'), 'utf8', this.callback);
|
||||
var log4js = require('../lib/log4js')
|
||||
, logger;
|
||||
//this config file defines one file appender (to ./date-file-test.log)
|
||||
//and sets the log level for "tests" to WARN
|
||||
log4js.configure('test/with-dateFile.json');
|
||||
logger = log4js.getLogger('tests');
|
||||
logger.info('this should not be written to the file');
|
||||
logger.warn('this should be written to the file');
|
||||
|
||||
fs.readFile(path.join(__dirname, 'date-file-test.log'), 'utf8', this.callback);
|
||||
},
|
||||
teardown: removeFile('date-file-test.log'),
|
||||
|
||||
teardown: removeFile('date-file-test.log'),
|
||||
|
||||
'should load appender configuration from a json file': function(err, contents) {
|
||||
assert.include(contents, 'this should be written to the file\n');
|
||||
assert.equal(contents.indexOf('this should not be written to the file'), -1);
|
||||
assert.include(contents, 'this should be written to the file' + require('os').EOL);
|
||||
assert.equal(contents.indexOf('this should not be written to the file'), -1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
'with options.alwaysIncludePattern': {
|
||||
topic: function() {
|
||||
var log4js = require('../lib/log4js')
|
||||
, format = require('../lib/date_format')
|
||||
, logger
|
||||
, options = {
|
||||
"appenders": [
|
||||
{
|
||||
"category": "tests",
|
||||
"type": "dateFile",
|
||||
"filename": "test/date-file-test",
|
||||
"pattern": "-from-MM-dd.log",
|
||||
"alwaysIncludePattern": true,
|
||||
"layout": {
|
||||
"type": "messagePassThrough"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
, thisTime = format.asString(options.appenders[0].pattern, new Date());
|
||||
fs.writeFileSync(path.join(__dirname, 'date-file-test' + thisTime), "this is existing data" + require('os').EOL, 'utf8');
|
||||
log4js.clearAppenders();
|
||||
log4js.configure(options);
|
||||
logger = log4js.getLogger('tests');
|
||||
logger.warn('this should be written to the file with the appended date');
|
||||
this.teardown = removeFile('date-file-test' + thisTime);
|
||||
fs.readFile(path.join(__dirname, 'date-file-test' + thisTime), 'utf8', this.callback);
|
||||
},
|
||||
'should create file with the correct pattern': function(contents) {
|
||||
assert.include(contents, 'this should be written to the file with the appended date');
|
||||
},
|
||||
'should not overwrite the file on open (bug found in issue #132)': function(contents) {
|
||||
assert.include(contents, 'this is existing data');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}).exportTo(module);
|
||||
|
||||
@@ -30,24 +30,24 @@ function makeFakeNet() {
|
||||
};
|
||||
},
|
||||
createServer: function(cb) {
|
||||
var fakeNet = this;
|
||||
cb({
|
||||
remoteAddress: '1.2.3.4',
|
||||
remotePort: '1234',
|
||||
setEncoding: function(encoding) {
|
||||
fakeNet.encoding = encoding;
|
||||
},
|
||||
on: function(event, cb) {
|
||||
fakeNet.cbs[event] = cb;
|
||||
}
|
||||
});
|
||||
var fakeNet = this;
|
||||
cb({
|
||||
remoteAddress: '1.2.3.4',
|
||||
remotePort: '1234',
|
||||
setEncoding: function(encoding) {
|
||||
fakeNet.encoding = encoding;
|
||||
},
|
||||
on: function(event, cb) {
|
||||
fakeNet.cbs[event] = cb;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
listen: function(port, host) {
|
||||
fakeNet.port = port;
|
||||
fakeNet.host = host;
|
||||
}
|
||||
};
|
||||
return {
|
||||
listen: function(port, host) {
|
||||
fakeNet.port = port;
|
||||
fakeNet.host = host;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -183,7 +183,6 @@ vows.describe('Multiprocess Appender').addBatch({
|
||||
topic: function(net) {
|
||||
var logString = JSON.stringify({ level: { level: 10000, levelStr: 'DEBUG' }, data: ['some debug']}) + '__LOG4JS__';
|
||||
|
||||
net.cbs['connect']();
|
||||
net.cbs['data'](JSON.stringify({ level: { level: 40000, levelStr: 'ERROR' }, data: ['an error message'] }) + '__LOG4JS__');
|
||||
net.cbs['data'](logString.substring(0, 10));
|
||||
net.cbs['data'](logString.substring(10));
|
||||
|
||||
@@ -13,7 +13,8 @@ function setupLogging(category, options) {
|
||||
sendMail: function (msg, callback) {
|
||||
msgs.push(msg);
|
||||
callback(null, true);
|
||||
}
|
||||
},
|
||||
close: function() {}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
var vows = require('vows')
|
||||
, assert = require('assert')
|
||||
, streams = require('stream')
|
||||
, fs = require('fs')
|
||||
, DateRollingFileStream = require('../../lib/streams').DateRollingFileStream
|
||||
, semver = require('semver')
|
||||
, streams
|
||||
, DateRollingFileStream
|
||||
, testTime = new Date(2012, 8, 12, 10, 37, 11);
|
||||
|
||||
if (semver.satisfies(process.version, '>=0.10.0')) {
|
||||
streams = require('stream');
|
||||
} else {
|
||||
streams = require('readable-stream');
|
||||
}
|
||||
DateRollingFileStream = require('../../lib/streams').DateRollingFileStream
|
||||
|
||||
function cleanUp(filename) {
|
||||
return function() {
|
||||
fs.unlink(filename);
|
||||
@@ -68,8 +76,8 @@ vows.describe('DateRollingFileStream').addBatch({
|
||||
var that = this,
|
||||
stream = new DateRollingFileStream(__dirname + '/test-date-rolling-file-stream-5', '.yyyy-MM-dd', null, now);
|
||||
stream.write("First message\n", 'utf8', function() {
|
||||
that.callback(null, stream);
|
||||
});
|
||||
that.callback(null, stream);
|
||||
});
|
||||
},
|
||||
teardown: cleanUp(__dirname + '/test-date-rolling-file-stream-5'),
|
||||
|
||||
@@ -117,6 +125,63 @@ vows.describe('DateRollingFileStream').addBatch({
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'with alwaysIncludePattern': {
|
||||
topic: function() {
|
||||
var that = this,
|
||||
testTime = new Date(2012, 8, 12, 0, 10, 12),
|
||||
stream = new DateRollingFileStream(__dirname + '/test-date-rolling-file-stream-pattern', '.yyyy-MM-dd', {alwaysIncludePattern: true}, now);
|
||||
stream.write("First message\n", 'utf8', function() {
|
||||
that.callback(null, stream);
|
||||
});
|
||||
},
|
||||
teardown: cleanUp(__dirname + '/test-date-rolling-file-stream-pattern.2012-09-12'),
|
||||
|
||||
'should create a file with the pattern set': {
|
||||
topic: function(stream) {
|
||||
fs.readFile(__dirname + '/test-date-rolling-file-stream-pattern.2012-09-12', this.callback);
|
||||
},
|
||||
'file should contain first message': function(result) {
|
||||
assert.equal(result.toString(), "First message\n");
|
||||
}
|
||||
},
|
||||
|
||||
'when the day changes': {
|
||||
topic: function(stream) {
|
||||
testTime = new Date(2012, 8, 13, 0, 10, 12);
|
||||
stream.write("Second message\n", 'utf8', this.callback);
|
||||
},
|
||||
teardown: cleanUp(__dirname + '/test-date-rolling-file-stream-pattern.2012-09-13'),
|
||||
|
||||
|
||||
'the number of files': {
|
||||
topic: function() {
|
||||
fs.readdir(__dirname, this.callback);
|
||||
},
|
||||
'should be two': function(files) {
|
||||
assert.equal(files.filter(function(file) { return file.indexOf('test-date-rolling-file-stream-pattern') > -1; }).length, 2);
|
||||
}
|
||||
},
|
||||
|
||||
'the file with the later date': {
|
||||
topic: function() {
|
||||
fs.readFile(__dirname + '/test-date-rolling-file-stream-pattern.2012-09-13', this.callback);
|
||||
},
|
||||
'should contain the second message': function(contents) {
|
||||
assert.equal(contents.toString(), "Second message\n");
|
||||
}
|
||||
},
|
||||
|
||||
'the file with the date': {
|
||||
topic: function() {
|
||||
fs.readFile(__dirname + '/test-date-rolling-file-stream-pattern.2012-09-12', this.callback);
|
||||
},
|
||||
'should contain the first message': function(contents) {
|
||||
assert.equal(contents.toString(), "First message\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}).exportTo(module);
|
||||
|
||||
@@ -3,8 +3,16 @@ var vows = require('vows')
|
||||
, assert = require('assert')
|
||||
, events = require('events')
|
||||
, fs = require('fs')
|
||||
, streams = require('stream')
|
||||
, RollingFileStream = require('../../lib/streams').RollingFileStream;
|
||||
, semver = require('semver')
|
||||
, streams
|
||||
, RollingFileStream;
|
||||
|
||||
if (semver.satisfies(process.version, '>=0.10.0')) {
|
||||
streams = require('stream');
|
||||
} else {
|
||||
streams = require('readable-stream');
|
||||
}
|
||||
RollingFileStream = require('../../lib/streams').RollingFileStream;
|
||||
|
||||
function remove(filename) {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user