Skip to content

Commit

Permalink
[api test] Allow dynamic buckets in Riak Transport. Support "colorize…
Browse files Browse the repository at this point in the history
…" option in File and Console transports. Buffer log messages to Loggly until input token is retreived
  • Loading branch information
indexzero committed Jan 21, 2011
1 parent 5375e03 commit 6a5dbb4
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 34 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Setting the level for your logging message can be accomplished in one of two way
Currently, winston only supports [npm][0] style logging levels, but it is on the roadmap to support customizable logging levels.
<pre>
// TODO: Make levels configurable
var levels = Logger.prototype.levels = {
var levels = {
silly: 0, // logger.silly('silly msg');
verbose: 1, // logger.verbose('verbose msg');
info: 2, // logger.info('info msg');
Expand Down
31 changes: 31 additions & 0 deletions lib/winston/levels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* levels.js: Default settings for all levels that winston knows about
*
* (C) 2010 Charlie Robbins
* MIT LICENCE
*
*/

var colors = require('colors');

exports.levels = {
silly: 0,
verbose: 1,
info: 2,
warn: 3,
debug: 4,
error: 5
};

exports.colors = {
silly: 'magenta',
verbose: 'cyan',
info: 'green',
warn: 'yellow',
debug: 'blue',
error: 'red'
};

var colorize = exports.colorize = function (level) {
return level[exports.colors[level]];
};
14 changes: 4 additions & 10 deletions lib/winston/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ require.paths.unshift(require('path').join(__dirname, '..'));

var util = require('util'),
events = require('events'),
winston = require('winston');
winston = require('winston'),
levels = require('./levels').levels;

function capitalize(str) {
return str && str[0].toUpperCase() + str.slice(1);
Expand Down Expand Up @@ -46,15 +47,8 @@ var Logger = exports.Logger = function (options) {

util.inherits(Logger, events.EventEmitter);

// TODO: Make levels configurable
var levels = Logger.prototype.levels = {
silly: 0,
verbose: 1,
info: 2,
warn: 3,
debug: 4,
error: 5
};
// Set the prototype levels to the global levels
Logger.prototype.levels = levels;

//
// Define prototype methods for each log level
Expand Down
5 changes: 2 additions & 3 deletions lib/winston/transports/console.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@ var util = require('util'),
var Console = exports.Console = function (options) {
options = options || {};

// TODO: Consume the colorize option
this.name = 'console';
this.level = options.level || 'info';
this.silent = options.silent || false;
this.colorize = options.colorize;
this.colorize = options.colorize || false;
};

//
Expand All @@ -30,7 +29,7 @@ var Console = exports.Console = function (options) {
//
Console.prototype.log = function (level, msg, meta, callback) {
if (!this.silent) {
var output = log(level, msg, meta);
var output = log(level, msg, meta, this.colorize);

if (level === 'error' || level === 'debug') {
util.error(output);
Expand Down
5 changes: 2 additions & 3 deletions lib/winston/transports/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ var File = exports.File = function (options) {
else if (options.stream) this.stream = options.stream;
else throw new Error('Cannot log to file without filename or stream.');

// TODO: Consume the colorize option
this.name = 'file';
this.level = options.level || 'info';
this.silent = options.silent || false;
this.colorize = options.colorize;
this.colorize = options.colorize || false;
};

//
Expand All @@ -35,7 +34,7 @@ var File = exports.File = function (options) {
//
File.prototype.log = function (level, msg, meta, callback) {
if (!this.silent) {
var output = log(level, msg, meta) + '\n';
var output = log(level, msg, meta, this.colorize) + '\n';
this.stream.write(output);
callback(null, true);
}
Expand Down
39 changes: 36 additions & 3 deletions lib/winston/transports/loggly.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ var loggly = require('loggly'),
//
var Loggly = exports.Loggly = function (options) {
options = options || {};
if (!options.auth) throw new Error('Loggly authentication is required');
if (!options.subdomain) throw new Error('Loggly Subdomain is required');
if (!options.inputToken && !options.inputName) throw new Error('Target input token or name is required.');
if (!options.auth && options.inputName) throw new Error('Loggly authentication is required');

this.name = 'loggly';
this.level = options.level || 'info';
this.logBuffer = [];

this.client = loggly.createClient({
subdomain: options.subdomain,
auth: options.auth
auth: options.auth || null
});

if (options.inputToken) {
Expand Down Expand Up @@ -53,6 +55,37 @@ Loggly.prototype.log = function (level, msg, meta, callback) {
message.level = level;
message.message = msg;

// TODO: Fix Race condition here if 'inputName' is provided to the constructor
// If we haven't gotten the input token yet
// add this message to the log buffer.
if (!this.ready) {
this.logBuffer.push(message);
return callback(null, true);
}

// Otherwise if we have buffered messages
// add this message to the buffer and flush them.
if (this.ready && this.logBuffer.length > 0) {
this.logBuffer.push(message);
return this.flush(callback);
}

// Otherwise just log the message as normal
this.client.log(this.inputToken, message, callback);
};

Loggly.prototype.flush = function (callback) {
var self = this, flushed = 0,
length = this.logBuffer.length;

// Close over each message
this.logBuffer.forEach(function (msg) {
process.nextTick(function () {
this.client.log(self.inputToken, msg, function () {
if (flushed++ === count) return callback(null, true);
});
});
});

// Then quickly truncate the list (thanks isaacs)
this.logBuffer.length = 0;
};
15 changes: 12 additions & 3 deletions lib/winston/transports/riak.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,26 @@ var Riak = exports.Riak = function (options) {
// TODO: Better support for dynamic bucket names
this.name = 'riak';
this.level = options.level || 'info';
this.bucketName = options.bucketName || Date.now();
this.bucket = options.bucket || Date.now();
this.generate = typeof this.bucket === 'function';
};

//
// function log (level, msg, [meta], callback)
// Core logging method exposed to Winston. Metadata is optional.
//
Riak.prototype.log = function (level, msg, meta, callback) {
var metac = utils.clone(meta);
var bucketName = this.bucket, metac = utils.clone(meta);

// Deep clone the object for adding to Riak
metac.level = level;
metac.contentType = msg instanceof Object ? 'application/json' : 'text/plain';

this.client.save(this.bucketName, Date.now(), msg, metac, callback);
if (this.generate) {
var nextBucket = this.bucket(level, msg, meta, Date.now());
if (this.lastBucket !== nextBucket) this.lastBucket = nextBucket;
bucketName = this.lastBucket;
}

this.client.save(bucketName, Date.now(), msg, metac, callback);
};
10 changes: 7 additions & 3 deletions lib/winston/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*
*/

var util = require('util');
var util = require('util'),
levels = require('./../levels');

//
// function clone (obj)
Expand Down Expand Up @@ -48,8 +49,11 @@ var timestamp = exports.timestamp = function () {
// function log (level, msg, meta)
// Generic logging function for returning timestamped strings
//
var log = exports.log = function (level, msg, meta) {
var output = timestamp() + ' - ' + level + ': ' + msg;
var log = exports.log = function (level, msg, meta, colorize) {
var output = timestamp() + ' - ';
targetLevel = colorize ? levels.colorize(level) : level;

output += targetLevel + ': ' + msg;

// TODO: Define color profile for eyes
if (meta && Object.keys(meta).length > 0) output += ' ' + util.inspect(meta);
Expand Down
35 changes: 27 additions & 8 deletions test/loggly-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,36 @@ var path = require('path'),
helpers = require('./helpers');

var config = helpers.loadConfig(),
transport = new (winston.transports.Loggly)(config.transports.loggly);
tokenTransport = new (winston.transports.Loggly)({
subdomain: config.transports.loggly.subdomain,
inputToken: config.transports.loggly.inputToken
}),
nameTransport = new (winston.transports.Loggly)({
subdomain: config.transports.loggly.subdomain,
inputName: config.transports.loggly.inputName,
auth: config.transports.loggly.auth
});

vows.describe('winston/transports/loggly').addBatch({
"An instance of the Loggly Transport": {
"should have the proper methods defined": function () {
helpers.assertLoggly(transport);
"when passed an input token": {
"should have the proper methods defined": function () {
helpers.assertLoggly(tokenTransport);
},
"the log() method": helpers.testLevels(tokenTransport, "should log messages to loggly", function (ign, err, result) {
assert.isNull(err);
assert.isObject(result);
assert.equal(result.response, 'ok');
})
},
"the log() method": helpers.testLevels(transport, "should log messages to loggly", function (ign, err, result) {
assert.isNull(err);
assert.isObject(result);
assert.equal(result.response, 'ok');
})
"when passed an input name": {
"should have the proper methods defined": function () {
helpers.assertLoggly(nameTransport);
},
"the log() method": helpers.testLevels(nameTransport, "should log messages to loggly", function (ign, err, result) {
assert.isNull(err);
assert.isTrue(result === true || result.response === 'ok');
})
}
}
}).export(module);
1 change: 1 addition & 0 deletions test/riak-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var path = require('path'),
vows = require('vows'),
assert = require('assert'),
winston = require('winston'),
utils = require('winston/utils'),
helpers = require('./helpers');

var config = helpers.loadConfig(),
Expand Down

0 comments on commit 6a5dbb4

Please sign in to comment.