Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9d98643
Showing
4 changed files
with
163 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,68 @@ | |||
# Logging | |||
|
|||
This is a considerable departure from the traditional logger. | |||
|
|||
This logger is meant for use in third party modules and packages. It's so that modules can have a very simple way to offer optional visibility in to the modules inner workings. | |||
|
|||
To this end, it does not have log levels like *info*, *warn*, etc. It simply allows the creation of a logger for your module (with a name) and offer a single function to take messages and a context for those messages. | |||
|
|||
This module is both an implementation and a light specification. Loggers can be quite opinionated and the creators of modules are unlikely to solidify around a single implementation of anything. | |||
|
|||
## Spec | |||
|
|||
A logging library should be a single function that returns logger functions. | |||
|
|||
```javascript | |||
var logging = require('logging') | |||
, log = logging('mymodulename') | |||
; | |||
``` | |||
|
|||
When running an application in a production environment, logging is the one of the few things you need to be global that is outside of node core. | |||
|
|||
Users of this specification should require **the user** to set the process.logging to the desired module. A library **must never** set this property automatically as it will override any other logger the user may want to use. | |||
|
|||
**server.js** | |||
```javascript | |||
process.logging = require('logging') | |||
var request = require('request') | |||
``` | |||
|
|||
Notice that this line comes **before** loading **any** other module. This is important, modules will likely check for process.logging as soon as they are required. | |||
|
|||
Using the logger is quite easy within a module. | |||
|
|||
```javascript | |||
if (process.logging) var log = process.logging('mymodule') | |||
else var log = function () {} | |||
|
|||
... | |||
module.exports = fancy (options) { | |||
log('new fancy %method for %url', options) | |||
} | |||
... | |||
fancy({method:'GET', url:'http://www.google.com'}) | |||
``` | |||
|
|||
The final piece of this spec is visible in the last example. | |||
|
|||
Log functions take two arguments, a message and a context. | |||
|
|||
Named string interpolation from the context **should** be supported. This prevents many errors related to using the + operator in building the message string. | |||
|
|||
## logging API | |||
|
|||
The rest of this documentation covers features which should not be considered part of the specification. | |||
|
|||
Enabling stdout or stderr printing of logs. | |||
|
|||
``` | |||
require('logging').stdout() | |||
``` | |||
|
|||
``` | |||
require('logging').stderr() | |||
``` | |||
|
|||
All will print `[mymodule] new fancy GET for http://www.google.com`. | |||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,63 @@ | |||
var events = require('events') | |||
, util = require('util') | |||
, global = new events.EventEmitter() | |||
; | |||
|
|||
function formatter (msg, ctx) { | |||
while (msg.indexOf('%') !== -1) { | |||
var start = msg.indexOf('%') | |||
, end = msg.indexOf(' ', start) | |||
; | |||
if (end === -1) end = msg.length | |||
msg = msg.slice(0, start) + ctx[msg.slice(start+1, end)] + msg.slice(end) | |||
} | |||
return msg | |||
} | |||
global.formatter = formatter | |||
|
|||
function Logger (name) { | |||
var self = this | |||
self.name = name | |||
self.on('log', function (msg, ctx) { | |||
if (self.listeners('msg').length) { | |||
msg = (self.formatter || global.formatter) (msg, ctx) | |||
self.emit('msg', msg, ctx) | |||
} | |||
}) | |||
} | |||
util.inherits(Logger, events.EventEmitter) | |||
|
|||
module.exports = function (name) { | |||
var logger = new Logger(name) | |||
function log (msg, ctx) { | |||
if (!msg) throw new Error('msg is a required argument.') | |||
if (!ctx) ctx = {} | |||
logger.emit('log', msg, ctx) | |||
} | |||
log.error = function (e) { | |||
logger.emit('error', e) | |||
} | |||
logger.log = log | |||
log.logger = logger | |||
global.emit('logger', logger) | |||
return log | |||
} | |||
|
|||
module.exports.stderr = function () { | |||
global.on('logger', function (logger) { | |||
logger.on('msg', function (msg, ctx) { | |||
console.error('['+logger.name+'] '+msg) | |||
}) | |||
}) | |||
} | |||
module.exports.stdout = function () { | |||
global.on('logger', function (logger) { | |||
logger.on('msg', function (msg, ctx) { | |||
console.log('['+logger.name+'] '+msg) | |||
}) | |||
}) | |||
} | |||
module.exports.formatter = function (f) { | |||
if (f) global.formatter = f | |||
return global.formatter | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,13 @@ | |||
{ | |||
"author": "Mikeal Rogers <mikeal.rogers@gmail.com>", | |||
"name": "logging", | |||
"description": "Simple and extensible logging.", | |||
"version": "0.0.0", | |||
"repository": { | |||
"url": "" | |||
}, | |||
"scripts": {"test":"node test.js"}, | |||
"main": "main.js", | |||
"dependencies": {}, | |||
"devDependencies": {} | |||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,19 @@ | |||
var logging = require('./main') | |||
, assert = require('assert') | |||
, f = logging.formatter() | |||
; | |||
|
|||
assert.equal(f('%start with', {start:'starts'}), 'starts with') | |||
assert.equal(f('in %the middle', {the:'the'}), 'in the middle') | |||
assert.equal(f('at %end', {end:'end'}), 'at end') | |||
assert.equal(f('%has %many %reps', {has:'has',many:'many',reps:'reps'}), 'has many reps') | |||
|
|||
|
|||
process.logging = logging | |||
logging.stdout() | |||
|
|||
process.stdout.write = function (chunk) { | |||
assert.equal(chunk.toString(), '[test] a test line\n') | |||
} | |||
var log = logging('test') | |||
log('a test line') |