Skip to content

Loading…

Add colors to log messages #10

Open
wants to merge 8 commits into from

3 participants

@Couto

I was in need for a small and useful utility that allowed different types of log messages, and I found yours… however since I log a lot of messages I needed colorful outputs to ease the task of looking for the right messages, since Log.js is so simple I decided to add colors to stdout messages.

My changes only affect stdout messages, I'm predicting that logging colors into files would be quite troublesome if they weren't parsed with the read method, also, I've added the colorful() method to turn colors on/off and edit your own colors, depending on the argument given.

Anyway, thanks for this small utility, is quite useful and simple to use =)

@atian25

hi, @visionmedia will this merge to master?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 12, 2012
  1. Fix credits

    Couto committed
  2. Update docs

    Couto committed
Commits on Mar 20, 2012
  1. Add trace level for compatibility purposes

    Couto committed
Commits on Aug 3, 2012
  1. @neekey
Commits on Aug 5, 2012
  1. @neekey

    update readme.md

    neekey committed
  2. Merge pull request #1 from neekey/master

    Luís Couto committed
    add `customLevels` to customize levels
Showing with 343 additions and 201 deletions.
  1. +45 −0 Readme.md
  2. +66 −0 examples/stdout-color.js
  3. +232 −201 lib/log.js
View
45 Readme.md
@@ -34,6 +34,51 @@ Instead of the log level constants, you may also supply a string:
log.error('oh no, failed to send mail to %s.', user.email);
+Turn colors on:
+
+ log.colorful();
+
+Turn colors off:
+
+ log.colorful(false);
+
+Setting up our own colors :
+
+ log.colorful({
+ 'EMERGENCY' : "\033[0;31m",
+ 'ALERT' : "\033[0;33m",
+ 'CRITICAL' : "\033[0;31m",
+ 'ERROR' : "\033[1;31m",
+ 'WARNING' : "\033[0;33m",
+ 'NOTICE' : "\033[0;36m",
+ 'INFO' : "\033[0;35m",
+ 'DEBUG' : "\033[0m"
+ });
+
+ You don't have to specify all levels, when defining colors, if you only want to specify certain levels, you just write those:
+
+ log.colorful({
+ 'INFO' : "\033[0;35m",
+ 'DEBUG' : "\033[0m"
+ })
+
+Setting up your own log levels:
+
+ log.customLevels([ 'COMMAND', 'DATA' ] );
+
+Which will simple add methods `command` and `data` to the `Log` object, and you can use them as the way that default log methods be used, like `log.command( "a command message")`.
+
+Also, you can setting up your own log levels and their colors at the same time:
+
+ log.customLevels({
+ COMMAND: '\033[0;31m',
+ DATA: '\033[0;31m'
+ });
+
+
+
+
+
## Reader
To stream a log, simply pass a readable stream instead of a writable:
View
66 examples/stdout-color.js
@@ -0,0 +1,66 @@
+
+/**
+ * Module dependencies.
+ */
+
+var Log = require('../lib/log')
+ , log = new Log('trace').colorful();
+
+/**
+ * Default log.
+ */
+log.trace( 'Below is default logs.');
+log.debug('a debug message');
+log.info('a info message');
+log.notice('a notice message');
+log.warning('a warning message');
+log.error('a error message');
+log.critical('a critical message');
+log.alert('a alert message');
+log.emergency('a emergency %s', 'message');
+
+/**
+ * Setup our own colors
+ */
+log.colorful({
+ ERROR : "\033[0;37m",
+ CRITICAL : "\033[1;36m"
+});
+
+log.trace( 'Below is color-customed logs.');
+log.debug('a debug message');
+log.info('a info message');
+log.notice('a notice message');
+log.warning('a warning message');
+log.error('a error message');
+log.critical('a critical message');
+log.alert('a alert message');
+log.emergency('a emergency %s', 'message');
+
+/**
+ * Turn off color.
+ */
+log.colorful( false );
+log.trace( 'Below is color-offed logs.');
+log.debug('a debug message');
+log.info('a info message');
+log.notice('a notice message');
+log.warning('a warning message');
+log.error('a error message');
+log.critical('a critical message');
+log.alert('a alert message');
+log.emergency('a emergency %s', 'message');
+
+/**
+ * Customize levels and colors
+ */
+log.customLevels({
+ COMMAND: "\x1b[0;35m",
+ DATA: "\x1b[0;33m",
+ RESULT: "\x1b[0;36m"
+}).colorful( true).setLevel( 'result' );
+
+log.command( 'a command message' );
+log.data( 'a data message' );
+log.result( 'a result message' );
+
View
433 lib/log.js
@@ -2,6 +2,23 @@
* Log.js
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
+ *
+ * Colorful stdout messages by Couto <lcouto87@gmail.com>
+ *
+ * CustomLevel by Neekey<ni184775761@gmail.com>
+ */
+
+/**
+ * Colors Cheat-sheet
+ * white : "\033[1;37m", black : "\033[0;30m",
+ * red : "\033[0;31m", light_red : "\033[1;31m",
+ * green : "\033[0;32m", light_green : "\033[1;32m",
+ * yellow : "\033[0;33m", light_yellow : "\033[1;33m",
+ * blue : "\033[0;34m", light_blue : "\033[1;34m",
+ * purple : "\033[0;35m", light_purple : "\033[1;35m",
+ * cyan : "\033[0;36m", light_cyan : "\033[1;36m",
+ * gray : "\033[1;30m", light_gray : "\033[0;37m",
+ * reset : "\033[0m"
*/
/**
@@ -13,240 +30,254 @@ var EventEmitter = require('events').EventEmitter;
/**
* Initialize a `Loggeer` with the given log `level` defaulting
* to __DEBUG__ and `stream` defaulting to _stdout_.
- *
- * @param {Number} level
- * @param {Object} stream
+ *
+ * @param {Number} level
+ * @param {Object} stream
* @api public
*/
-var Log = exports = module.exports = function Log(level, stream){
- if ('string' == typeof level) level = exports[level.toUpperCase()];
- this.level = level || exports.DEBUG;
- this.stream = stream || process.stdout;
- if (this.stream.readable) this.read();
+var Log = exports = module.exports = function Log(level, stream, custom) {
+
+ // Add custom levels.
+ if( custom ) this.customLevels( custom );
+ this.setLevel( level );
+ this.stream = stream || process.stdout;
+ if (this.stream.readable) this.read();
};
/**
- * System is unusable.
- *
- * @type Number
+ * Define Levels for levels.
*/
-
-exports.EMERGENCY = 0;
+exports.colors = {
+ /**
+ * System is unusable.
+ */
+ 'EMERGENCY':"\033[0;31m",
+ /**
+ * Action must be taken immediately.
+ */
+ 'ALERT':"\033[0;33m",
+ /**
+ * Critical condition.
+ */
+ 'CRITICAL':"\033[0;31m",
+ /**
+ * Error condition.
+ */
+ 'ERROR':"\033[1;31m",
+ /**
+ * Warning condition.
+ */
+ 'WARNING':"\033[0;33m",
+ /**
+ * Normal but significant condition.
+ */
+ 'NOTICE':"\033[0;36m",
+ /**
+ * Purely informational message.
+ */
+ 'INFO':"\033[0;35m",
+ /**
+ * Application debug messages.
+ */
+ 'DEBUG':"\033[0m",
+ /**
+ * Application debug messages.
+ */
+ 'TRACE':"\033[1;30m",
+ /**
+ * Reset log color.
+ */
+ 'reset':"\033[0m"
+}
/**
- * Action must be taken immediately.
- *
- * @type Number
+ * The latest enum value for level.
+ *
+ * @type {Number}
*/
-
-exports.ALERT = 1;
+var enumCount = 0;
/**
- * Critical condition.
+ * Add an new log level to exports, and assign an new enum value to it.
*
- * @type Number
+ * @param levelName
*/
+var addLevelEnumerable = function (levelName) {
-exports.CRITICAL = 2;
-
-/**
- * Error condition.
- *
- * @type Number
- */
+ if (!( levelName in exports )) {
+ exports[ levelName ] = ++enumCount;
+ }
-exports.ERROR = 3;
+ var lowCaseLevelName = levelName.toLowerCase();
-/**
- * Warning condition.
- *
- * @type Number
- */
+ if(!( lowCaseLevelName in Log.prototype )) {
-exports.WARNING = 4;
+ Log.prototype[ lowCaseLevelName ] = function(msg){
+ this.log(levelName, arguments);
+ }
+ }
+};
/**
- * Normal but significant condition.
- *
- * @type Number
+ * prototype.
*/
-exports.NOTICE = 5;
+Log.prototype = {
-/**
- * Purely informational message.
- *
- * @type Number
- */
+ /**
+ * Start emitting "line" events.
+ *
+ * @api public
+ */
+
+ read:function () {
+ var buf = ''
+ , self = this
+ , stream = this.stream;
+
+ stream.setEncoding('ascii');
+ stream.on('data', function (chunk) {
+ buf += chunk;
+ if ('\n' != buf[buf.length - 1]) return;
+ buf.split('\n').map(function (line) {
+ if (!line.length) return;
+ try {
+ var captures = line.match(/^\[([^\]]+)\] (\w+) (.*)/);
+ var obj = {
+ date:new Date(captures[1]), level:exports[captures[2]], levelString:captures[2], msg:captures[3]
+ };
+ self.emit('line', obj);
+ } catch (err) {
+ // Ignore
+ }
+ });
+ buf = '';
+ });
+
+ stream.on('end', function () {
+ self.emit('end');
+ });
+ },
+
+ /**
+ * Log output message.
+ *
+ * @param {String} levelStr
+ * @param {Array} args
+ * @api private
+ */
+
+ log:function (levelStr, args) {
+ if (exports[levelStr] <= this.level) {
+ var i = 1;
+ var msg = args[0].replace(/%s/g, function () {
+ return args[i++];
+ });
+ if (this.stream === process.stdout &&
+ this.useColors &&
+ exports.colors[levelStr]) {
+
+ this.stream.write(
+ exports.colors[levelStr]
+ + '[' + new Date + ']'
+ + ' ' + levelStr
+ + ' ' + msg
+ + exports.colors.reset
+ + '\n'
+ );
+ } else {
+ this.stream.write(
+ '[' + new Date + ']'
+ + ' ' + levelStr
+ + ' ' + msg
+ + '\n'
+ );
+ }
+ }
+ },
+
+ /**
+ * Customize colors for stout.
+ *
+ * @param {Object|Boolean} colors
+ * @return {*}
+ * @example
+ * `colorful({ DEBUG: "\033[0m"});` set level `DEBUG` color to `\033[0m`.
+ * `colorful(false)` turn off color.
+ * `colorful()` or `colorful(true)` turn on color.
+ *
+ */
+ colorful:function (colors) {
+ var k;
+ if (Object.prototype.toString.call(colors) === '[object Object]') {
+ for (k in colors) {
+ if (colors.hasOwnProperty(k)) {
+ exports.colors[k] = colors[k];
+ }
+ }
+ this.useColors = true;
+ } else if (colors === false) {
+ this.useColors = false;
+ }
+ else {
+ this.useColors = true;
+ }
+ return this;
+ },
-exports.INFO = 6;
+ /**
+ * Customize Levels and Colors.
+ *
+ * @param {Object|Array} levels
+ * @example
+ * `customLevels([ 'DEBUG', 'ERROR', 'WARNING' ]);`
+ * `customLevels({ DEBUG: "\033[0m"});`
+ */
+ customLevels: function( levels ){
-/**
- * Application debug messages.
- *
- * @type Number
- */
+ var k;
-exports.DEBUG = 7;
+ if( Object.prototype.toString.call( levels ) === '[object Array]' ){
-/**
- * prototype.
- */
+ for( k = 0; k < levels.length; k++ ){
-Log.prototype = {
-
- /**
- * Start emitting "line" events.
- *
- * @api public
- */
-
- read: function(){
- var buf = ''
- , self = this
- , stream = this.stream;
-
- stream.setEncoding('ascii');
- stream.on('data', function(chunk){
- buf += chunk;
- if ('\n' != buf[buf.length - 1]) return;
- buf.split('\n').map(function(line){
- if (!line.length) return;
- try {
- var captures = line.match(/^\[([^\]]+)\] (\w+) (.*)/);
- var obj = {
- date: new Date(captures[1])
- , level: exports[captures[2]]
- , levelString: captures[2]
- , msg: captures[3]
- };
- self.emit('line', obj);
- } catch (err) {
- // Ignore
+ addLevelEnumerable( levels[ k ] );
+ }
}
- });
- buf = '';
- });
-
- stream.on('end', function(){
- self.emit('end');
- });
- },
-
- /**
- * Log output message.
- *
- * @param {String} levelStr
- * @param {Array} args
- * @api private
- */
-
- log: function(levelStr, args) {
- if (exports[levelStr] <= this.level) {
- var i = 1;
- var msg = args[0].replace(/%s/g, function(){
- return args[i++];
- });
- this.stream.write(
- '[' + new Date + ']'
- + ' ' + levelStr
- + ' ' + msg
- + '\n'
- );
+ else if( Object.prototype.toString.call( levels ) === '[object Object]' ){
+ this.colorful( levels );
+
+ for( k in levels ){
+ addLevelEnumerable( k );
+ }
+ }
+
+ return this;
+ },
+
+ /**
+ * Set log level
+ *
+ * @param level
+ * @return {*}
+ */
+ setLevel: function( level ){
+
+ if ('string' == typeof level) level = exports[level.toUpperCase()];
+ this.level = level || this.level || exports.DEBUG;
+
+ return this;
}
- },
-
- /**
- * Log emergency `msg`.
- *
- * @param {String} msg
- * @api public
- */
-
- emergency: function(msg){
- this.log('EMERGENCY', arguments);
- },
-
- /**
- * Log alert `msg`.
- *
- * @param {String} msg
- * @api public
- */
-
- alert: function(msg){
- this.log('ALERT', arguments);
- },
-
- /**
- * Log critical `msg`.
- *
- * @param {String} msg
- * @api public
- */
-
- critical: function(msg){
- this.log('CRITICAL', arguments);
- },
-
- /**
- * Log error `msg`.
- *
- * @param {String} msg
- * @api public
- */
-
- error: function(msg){
- this.log('ERROR', arguments);
- },
-
- /**
- * Log warning `msg`.
- *
- * @param {String} msg
- * @api public
- */
-
- warning: function(msg){
- this.log('WARNING', arguments);
- },
-
- /**
- * Log notice `msg`.
- *
- * @param {String} msg
- * @api public
- */
-
- notice: function(msg){
- this.log('NOTICE', arguments);
- },
-
- /**
- * Log info `msg`.
- *
- * @param {String} msg
- * @api public
- */
-
- info: function(msg){
- this.log('INFO', arguments);
- },
-
- /**
- * Log debug `msg`.
- *
- * @param {String} msg
- * @api public
- */
-
- debug: function(msg){
- this.log('DEBUG', arguments);
- }
+
};
/**
+ * Add Default levels to exports and add methods to Log.prototype.
+ */
+Log.prototype.customLevels( exports.colors );
+
+/**
* Inherit from `EventEmitter`.
*/
Something went wrong with that request. Please try again.