Node.js ログ出力時に色と出力時間をつけて見やすくする

consoleに出力区分と時間を追加しただけですが、意外と見やすくなります。
自分がよく使う部分しか実装してません。(dirとかassertは未実装)
メモ書き程度に

## 参考
https://github.com/joyent/node/blob/master/lib/console.js


## code

```js:colorConsole.js
var 
	util = require('util'),
	red     = '\u001b[31m',
	green   = '\u001b[32m',
	yellow  = '\u001b[33m',
	blue    = '\u001b[34m',
	magenta = '\u001b[35m',
	cyan    = '\u001b[36m',
	reset   = '\u001b[0m';

function df(dt, format){
    var year 	= dt.getFullYear().toString(),
        month 	= ('0'+(dt.getMonth()+1)).slice(-2),
        date 	= ('0'+dt.getDate()).slice(-2),
        hour 	= ('0'+dt.getHours()).slice(-2),
        min 	= ('0'+dt.getMinutes()).slice(-2),
        sec 	= ('0'+dt.getSeconds()).slice(-2),
        misec 	= ('00'+dt.getMilliseconds()).slice(-3);
    if(format.match(/yyyy/g)) format = format.replace(/yyyy/g, year);
    else if(format.match(/yy/g)) format = format.replace(/yy/g, year.slice(-2));
    if(format.match(/MM/g)) format = format.replace(/MM/g, month);
    else if(format.match(/M/g)) format = format.replace(/M/g, month.slice(-1));
    if(format.match(/dd/g)) format = format.replace(/dd/g, date);
    else if(format.match(/d/g)) format = format.replace(/d/g, date.slice(-1));
    if(format.match(/hh/g)) format = format.replace(/hh/g, hour);
    else if(format.match(/h/g)) format = format.replace(/h/g, hour.slice(-1));
    if(format.match(/mm/g)) format = format.replace(/mm/g, min);
    else if(format.match(/m/g)) format = format.replace(/m/g, min.slice(-1));
    if(format.match(/ss/g)) format = format.replace(/ss/g, sec);
    else if(format.match(/s/g)) format = format.replace(/s/g, sec.slice(-1));
    if(format.match(/SSS/g)) format = format.replace(/SSS/g, misec);
    return format;
};

var ColorConsole = function(format){

	stdout = process.stdout;
	stderr = process.stderr;

	if (!(this instanceof ColorConsole)) {
		return new ColorConsole(stdout, stderr);
	}

	if (!stdout || !util.isFunction(stdout.write)) {
		throw new TypeError('Console expects a writable stream instance');
	}
	if (!stderr) {
		stderr = stdout;
	}
	var prop = {
		writable: true,
		enumerable: false,
		configurable: true
	};

	prop.value = stdout;
	Object.defineProperty(this, '_stdout', prop);
	prop.value = stderr;
	Object.defineProperty(this, '_stderr', prop);
	prop.value = {};
	Object.defineProperty(this, '_times', prop);

	Object.keys(ColorConsole.prototype).forEach(function(k) {
		this[k] = this[k].bind(this);
	}, this);

	this._fmt = format;
}

ColorConsole.prototype.log = function() {
	var s = magenta + '[LOG]';
	if(this._fmt)
		s += df(new Date(), this._fmt);
	s+=reset + ' ';


	this._stdout.write(s + util.format.apply(this, arguments) + '\n');
};
ColorConsole.prototype.info = function() {
	var s = green + '[INFO]';
	if(this._fmt)
		s += df(new Date(), this._fmt);
	s+=reset + ' ';


	this._stdout.write(s + util.format.apply(this, arguments) + '\n');
};

ColorConsole.prototype.warn = function() {
	var s = yellow + '[WARN]';
	if(this._fmt)
		s += df(new Date(), this._fmt);
	s+=reset + ' ';


	this._stderr.write(s + util.format.apply(this, arguments) + '\n');
};
ColorConsole.prototype.error = function() {
	var s = red + '[ERROR]';
	if(this._fmt)
		s += df(new Date(), this._fmt);
	s+=reset + ' ';

	this._stderr.write(s + util.format.apply(this, arguments) + '\n');
};

ColorConsole.prototype.trace = function() {
  var err = new Error;
  err.name = 'Trace';
  err.message = util.format.apply(this, arguments);
  Error.captureStackTrace(err, arguments.callee);
  var s = cyan + '[TRACE]';
  if(this._fmt)
    s += df(new Date(), this._fmt);
  s+=reset + ' ';
  this._stderr.write(s + '\n' + err.stack + '\n');
};


ColorConsole.prototype.time = function(label) {
  this._times[label] = Date.now();
};

ColorConsole.prototype.timeEnd = function(label) {
  var time = this._times[label];
  if (!time) {
    throw new Error('No such label: ' + label);
  }
  var duration = Date.now() - time;
  this.log('%s: %dms', label, duration);
};

module.exports = ColorConsole;

```

## DEMO

```js
var ColorConsole = new require('./colorConsole.js');
var logger = new ColorConsole('yy-MM-dd hh:mm:ss.SSS');

logger.log('%s world', 'hello');

logger.info('pid = %d', process.pid);

logger.warn('warn');

logger.error('error', [1,2,3,4]);

logger.trace('Error Name');

logger.time('time');

setTimeout(logger.timeEnd, 1000, 'time');

```

出力結果

![out.png](https://qiita-image-store.s3.amazonaws.com/0/34919/ddc69d6b-c81f-0243-f359-c4476a038911.png)