Skip to content
Browse files

Initial commit.

  • Loading branch information...
0 parents commit 9d9864306c9eaecd0882c982ac2335d74f010d91 @mikeal committed Dec 13, 2011
Showing with 163 additions and 0 deletions.
  1. +68 −0 README.md
  2. +63 −0 main.js
  3. +13 −0 package.json
  4. +19 −0 test.js
68 README.md
@@ -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`.
+
63 main.js
@@ -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
+}
13 package.json
@@ -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": {}
+}
19 test.js
@@ -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')

0 comments on commit 9d98643

Please sign in to comment.
Something went wrong with that request. Please try again.