logger: truncate log files.

This commit is contained in:
Christopher Jeffrey 2017-03-13 18:36:55 -07:00
parent b372715c88
commit a266391f1b
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
6 changed files with 216 additions and 59 deletions

View File

@ -528,6 +528,7 @@ CPUJob.prototype.destroy = function destroy() {
/** /**
* Calculate number of hashes. * Calculate number of hashes.
* @param {Number} nonce
* @returns {Number} * @returns {Number}
*/ */
@ -537,6 +538,7 @@ CPUJob.prototype.getHashes = function getHashes(nonce) {
/** /**
* Calculate hashrate. * Calculate hashrate.
* @param {Number} nonce
* @returns {Number} * @returns {Number}
*/ */

View File

@ -210,9 +210,9 @@ Miner.prototype.updateTime = function updateTime(attempt) {
* @returns {Promise} Returns {@link CPUJob}. * @returns {Promise} Returns {@link CPUJob}.
*/ */
Miner.prototype.createJob = co(function* createJob(tip, address) { Miner.prototype.createJob = function createJob(tip, address) {
return yield this.cpu.createJob(tip, address); return this.cpu.createJob(tip, address);
}); };
/** /**
* Mine a single block. * Mine a single block.
@ -222,9 +222,9 @@ Miner.prototype.createJob = co(function* createJob(tip, address) {
* @returns {Promise} Returns {@link Block}. * @returns {Promise} Returns {@link Block}.
*/ */
Miner.prototype.mineBlock = co(function* mineBlock(tip, address) { Miner.prototype.mineBlock = function mineBlock(tip, address) {
return yield this.cpu.mineBlock(tip, address); return this.cpu.mineBlock(tip, address);
}); };
/** /**
* Add an address to the address list. * Add an address to the address list.

View File

@ -477,16 +477,16 @@ Pool.prototype.discoverGateway = co(function* discoverGateway() {
this.logger.debug('Discovering internet gateway (upnp).'); this.logger.debug('Discovering internet gateway (upnp).');
wan = yield UPNP.discover(); wan = yield UPNP.discover();
} catch (e) { } catch (e) {
this.logger.debug('UPNP error:'); this.logger.debug('Could not discover internet gateway (upnp).');
this.logger.error(e); this.logger.debug(e);
return false; return false;
} }
try { try {
host = yield wan.getExternalIP(); host = yield wan.getExternalIP();
} catch (e) { } catch (e) {
this.logger.debug('Could not find external IP.'); this.logger.debug('Could not find external IP (upnp).');
this.logger.error(e); this.logger.debug(e);
return false; return false;
} }
@ -500,8 +500,8 @@ Pool.prototype.discoverGateway = co(function* discoverGateway() {
try { try {
yield wan.addPortMapping(host, src, dest); yield wan.addPortMapping(host, src, dest);
} catch (e) { } catch (e) {
this.logger.debug('Could not add port mapping.'); this.logger.debug('Could not add port mapping (upnp).');
this.logger.error(e); this.logger.debug(e);
return false; return false;
} }
@ -572,8 +572,8 @@ Pool.prototype.discoverExternal = co(function* discoverExternal() {
try { try {
host = yield this.getIP(); host = yield this.getIP();
} catch (e) { } catch (e) {
this.logger.debug('Could not find external IP.'); this.logger.debug('Could not find external IP (http).');
this.logger.error(e); this.logger.debug(e);
return; return;
} }

View File

@ -10,6 +10,7 @@ var assert = require('assert');
var fs = require('../utils/fs'); var fs = require('../utils/fs');
var util = require('../utils/util'); var util = require('../utils/util');
var co = require('../utils/co'); var co = require('../utils/co');
var Lock = require('../utils/lock');
/** /**
* Basic stdout and file logger. * Basic stdout and file logger.
@ -27,9 +28,13 @@ function Logger(options) {
this.level = Logger.levels.NONE; this.level = Logger.levels.NONE;
this.colors = Logger.HAS_TTY; this.colors = Logger.HAS_TTY;
this.console = true; this.console = true;
this.shrink = true;
this.closed = true;
this.closing = false;
this.filename = null; this.filename = null;
this.stream = null; this.stream = null;
this.contexts = {}; this.contexts = {};
this.locker = new Lock();
this.init(options); this.init(options);
} }
@ -41,6 +46,14 @@ function Logger(options) {
Logger.HAS_TTY = !!(process.stdout && process.stdout.isTTY); Logger.HAS_TTY = !!(process.stdout && process.stdout.isTTY);
/**
* Maximum file size.
* @const {Number}
* @default
*/
Logger.MAX_FILE_SIZE = 20 << 20;
/** /**
* Available log levels. * Available log levels.
* @enum {Number} * @enum {Number}
@ -91,7 +104,7 @@ Logger.prefixByVal = [
* @default * @default
*/ */
Logger.colors = [ Logger.styles = [
'0', '0',
'1;31', '1;31',
'1;33', '1;33',
@ -100,6 +113,23 @@ Logger.colors = [
'90' '90'
]; ];
/**
* Default CSI colors for modules.
* @const {String[]}
* @default
*/
Logger.colors = [
'32',
'92',
'34',
'94',
'35',
'95',
'36',
'96'
];
/** /**
* Initialize the logger. * Initialize the logger.
* @private * @private
@ -130,6 +160,11 @@ Logger.prototype.init = function init(options) {
this.console = options.console; this.console = options.console;
} }
if (options.shrink != null) {
assert(typeof options.shrink === 'boolean');
this.shrink = options.shrink;
}
if (options.filename != null) { if (options.filename != null) {
assert(typeof options.filename === 'string', 'Bad file.'); assert(typeof options.filename === 'string', 'Bad file.');
this.filename = options.filename; this.filename = options.filename;
@ -138,35 +173,122 @@ Logger.prototype.init = function init(options) {
/** /**
* Open the logger. * Open the logger.
* @method
* @returns {Promise} * @returns {Promise}
*/ */
Logger.prototype.open = co(function* open() { Logger.prototype.open = co(function* open() {
var unlock = yield this.locker.lock();
try {
return yield this._open();
} finally {
unlock();
}
});
/**
* Open the logger (no lock).
* @method
* @returns {Promise}
*/
Logger.prototype._open = co(function* open() {
if (fs.unsupported) if (fs.unsupported)
return; return;
if (!this.filename) if (!this.filename)
return; return;
if (this.stream)
return;
if (this.shrink)
yield this.truncate();
this.stream = yield openStream(this.filename); this.stream = yield openStream(this.filename);
this.stream.once('error', this.handleError.bind(this)); this.stream.once('error', this.handleError.bind(this));
this.closed = false;
}); });
/** /**
* Destroy the write stream. * Destroy the write stream.
* @method
* @returns {Promise} * @returns {Promise}
*/ */
Logger.prototype.close = co(function* close() { Logger.prototype.close = co(function* close() {
var unlock = yield this.locker.lock();
try {
return yield this._close();
} finally {
unlock();
}
});
/**
* Destroy the write stream (no lock).
* @method
* @returns {Promise}
*/
Logger.prototype._close = co(function* close() {
if (this.timer != null) { if (this.timer != null) {
co.clearTimeout(this.timer); co.clearTimeout(this.timer);
this.timer = null; this.timer = null;
} }
if (this.stream) { if (this.stream) {
yield closeStream(this.stream); try {
this.closing = true;
yield closeStream(this.stream);
} finally {
this.closing = false;
}
this.stream = null; this.stream = null;
} }
this.closed = true;
});
/**
* Truncate the log file to the last 20mb.
* @method
* @private
* @returns {Promise}
*/
Logger.prototype.truncate = co(function* truncate() {
var maxSize = Logger.MAX_FILE_SIZE;
var stat, data, fd;
if (!this.filename)
return;
if (fs.unsupported)
return;
assert(!this.stream);
try {
stat = yield fs.stat(this.filename);
} catch (e) {
if (e.code === 'ENOENT')
return;
throw e;
}
if (stat.size <= maxSize + (maxSize / 10))
return;
this.debug('Truncating log file to %d bytes.', maxSize);
fd = yield fs.open(this.filename, 'r+');
data = new Buffer(maxSize);
yield fs.read(fd, data, 0, maxSize, stat.size - maxSize);
yield fs.ftruncate(fd, maxSize);
yield fs.write(fd, data, 0, maxSize, 0);
yield fs.close(fd);
}); });
/** /**
@ -193,12 +315,35 @@ Logger.prototype.handleError = function handleError(err) {
*/ */
Logger.prototype.reopen = co(function* reopen() { Logger.prototype.reopen = co(function* reopen() {
var unlock = yield this.locker.lock();
try {
return yield this._reopen();
} finally {
unlock();
}
});
/**
* Try to reopen the logger (no lock).
* @method
* @private
* @returns {Promise}
*/
Logger.prototype._reopen = co(function* reopen() {
if (this.stream)
return;
if (this.closed)
return;
try { try {
this.stream = yield openStream(this.filename); this.stream = yield openStream(this.filename);
} catch (e) { } catch (e) {
this.retry(); this.retry();
return; return;
} }
this.stream.once('error', this.handleError.bind(this)); this.stream.once('error', this.handleError.bind(this));
}); });
@ -210,6 +355,7 @@ Logger.prototype.reopen = co(function* reopen() {
*/ */
Logger.prototype.retry = function* retry() { Logger.prototype.retry = function* retry() {
assert(this.timer == null);
this.timer = co.setTimeout(function() { this.timer = co.setTimeout(function() {
this.timer = null; this.timer = null;
this.reopen(); this.reopen();
@ -399,7 +545,7 @@ Logger.prototype.context = function context(module) {
Logger.prototype.writeConsole = function writeConsole(level, module, args) { Logger.prototype.writeConsole = function writeConsole(level, module, args) {
var name = Logger.prefixByVal[level]; var name = Logger.prefixByVal[level];
var msg = ''; var msg = '';
var fmt, color; var fmt, color, ch;
assert(name, 'Invalid log level.'); assert(name, 'Invalid log level.');
@ -407,16 +553,18 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
return; return;
if (util.isBrowser) { if (util.isBrowser) {
fmt = args[0];
msg += '[' + name + '] '; msg += '[' + name + '] ';
if (module) if (module)
msg += '(' + module + ') '; msg += '(' + module + ') ';
if (typeof args[0] !== 'object') if (typeof args[0] === 'object') {
fmt = util.format(args, false); return level === Logger.levels.ERROR
? console.error(msg, args[0])
: console.log(msg, args[0]);
}
msg += fmt; msg += util.format(args, false);
return level === Logger.levels.ERROR return level === Logger.levels.ERROR
? console.error(msg) ? console.error(msg)
@ -424,20 +572,33 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
} }
if (this.colors) { if (this.colors) {
color = Logger.colors[level]; color = Logger.styles[level];
assert(color);
msg += '\x1b[' + color + 'm'; msg += '\x1b[' + color + 'm';
msg += '[' + name + '] '; msg += '[' + name + '] ';
msg += '\x1b[m'; msg += '\x1b[m';
if (module) {
ch = module.charCodeAt(0) + module.length;
color = Logger.colors[ch % Logger.colors.length];
msg += '\x1b[' + color + 'm';
msg += '(' + module + ') ';
msg += '\x1b[m';
}
} else {
msg += '[' + name + '] ';
if (module)
msg += '(' + module + ') ';
} }
if (module)
msg += '(' + module + ') ';
msg += util.format(args, this.colors); msg += util.format(args, this.colors);
msg += '\n';
return level === Logger.levels.ERROR return level === Logger.levels.ERROR
? process.stderr.write(msg + '\n') ? process.stderr.write(msg)
: process.stdout.write(msg + '\n'); : process.stdout.write(msg);
}; };
/** /**
@ -449,12 +610,14 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
Logger.prototype.writeStream = function writeStream(level, module, args) { Logger.prototype.writeStream = function writeStream(level, module, args) {
var name = Logger.prefixByVal[level]; var name = Logger.prefixByVal[level];
var stream = this.stream;
var msg = ''; var msg = '';
assert(name, 'Invalid log level.'); assert(name, 'Invalid log level.');
if (!stream) if (!this.stream)
return;
if (this.closing)
return; return;
msg += '['; msg += '[';
@ -468,7 +631,7 @@ Logger.prototype.writeStream = function writeStream(level, module, args) {
msg += util.format(args, false); msg += util.format(args, false);
msg += '\n'; msg += '\n';
stream.write(msg); this.stream.write(msg);
}; };
/** /**
@ -486,14 +649,16 @@ Logger.prototype.logError = function logError(level, module, err) {
if (this.closed) if (this.closed)
return; return;
if (util.isBrowser && this.console && level >= Logger.levels.DEBUG) if (util.isBrowser && this.console) {
console.error(err); if (level <= Logger.levels.WARNING)
console.error(err);
}
msg = (err.message + '').replace(/^ *Error: */, ''); msg = (err.message + '').replace(/^ *Error: */, '');
this.log(level, module, [msg]); this.log(level, module, [msg]);
if (this.level >= Logger.levels.DEBUG) { if (level <= Logger.levels.WARNING) {
if (this.stream) if (this.stream)
this.stream.write(err.stack + '\n'); this.stream.write(err.stack + '\n');
} }
@ -505,19 +670,15 @@ Logger.prototype.logError = function logError(level, module, err) {
*/ */
Logger.prototype.memory = function memory(module) { Logger.prototype.memory = function memory(module) {
var mem; var mem = util.memoryUsage();
if (!process.memoryUsage) this.log(Logger.levels.DEBUG, module, [
return; 'Memory: rss=%dmb, js-heap=%d/%dmb native-heap=%dmb',
mem.total,
mem = process.memoryUsage(); mem.jsHeap,
mem.jsHeapTotal,
this.log(Logger.levels.DEBUG, module, mem.nativeHeap
['Memory: rss=%dmb, js-heap=%d/%dmb native-heap=%dmb', ]);
util.mb(mem.rss),
util.mb(mem.heapUsed),
util.mb(mem.heapTotal),
util.mb(mem.rss - mem.heapTotal)]);
}; };
/** /**

View File

@ -74,7 +74,7 @@ Node.prototype.initOptions = function initOptions() {
this.logger = config.obj('logger'); this.logger = config.obj('logger');
if (config.bool('log-file')) if (config.bool('log-file'))
this.logger.setFile(this.location('debug.log')); this.logger.setFile(config.location('debug.log'));
if (config.has('log-level')) if (config.has('log-level'))
this.logger.setLevel(config.str('log-level')); this.logger.setLevel(config.str('log-level'));
@ -82,6 +82,9 @@ Node.prototype.initOptions = function initOptions() {
if (config.has('log-console')) if (config.has('log-console'))
this.logger.console = config.bool('log-console'); this.logger.console = config.bool('log-console');
if (config.bool('debug'))
this.logger.shrink = false;
this.logger = this.logger.context('node'); this.logger = this.logger.context('node');
}; };
@ -251,17 +254,6 @@ Node.prototype.error = function error(err) {
this.emit('error', err); this.emit('error', err);
}; };
/**
* Create a file path from a name
* as well as the node's prefix.
* @param {String} name
* @returns {String}
*/
Node.prototype.location = function location(name) {
return this.config.prefix + '/' + name;
};
/** /**
* Get node uptime in seconds. * Get node uptime in seconds.
* @returns {Number} * @returns {Number}

View File

@ -1051,7 +1051,8 @@ util.memoryUsage = function memoryUsage() {
total: 0, total: 0,
jsHeap: 0, jsHeap: 0,
jsHeapTotal: 0, jsHeapTotal: 0,
nativeHeap: 0 nativeHeap: 0,
external: 0
}; };
} }
@ -1061,6 +1062,7 @@ util.memoryUsage = function memoryUsage() {
total: util.mb(mem.rss), total: util.mb(mem.rss),
jsHeap: util.mb(mem.heapUsed), jsHeap: util.mb(mem.heapUsed),
jsHeapTotal: util.mb(mem.heapTotal), jsHeapTotal: util.mb(mem.heapTotal),
nativeHeap: util.mb(mem.rss - mem.heapTotal) nativeHeap: util.mb(mem.rss - mem.heapTotal),
external: util.mb(mem.external)
}; };
}; };