Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

More sinks and refactoring #5

Open
wants to merge 8 commits into from

1 participant

Mario Gutierrez
Mario Gutierrez

Consider merging

Refactoring and lots of changes

  • Refactored sinks to be instances. Was needed for multiple file logs.
  • Added Recipients multiple sink router
  • Added File sink
  • Added ColorConsole sink
  • Added factory functions for simpler registration
  • Updated readme
  • Added dependency to my colors library which is very light
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
3  .gitignore
... ... @@ -0,0 +1,3 @@
  1 +node_modules/
  2 +.DS_Store
  3 +file.log
4 NOTICE
... ... @@ -1,5 +1,7 @@
1 1 Log Magic
2 2 Copyright (c) 2011, Paul Querna
3 3
4   -This product includes software developed by
  4 +This product includes software developed by
  5 +
5 6 Paul Querna (http://paul.querna.org).
  7 +Mario Gutierrez (http://mgutz.com).
72 README.md
Source Rendered
@@ -7,9 +7,10 @@ The goal is to have a fast and easy to use logging subsystem that can be dynamic
7 7 reconfigured to provide insight into production systems.
8 8
9 9 Logmagic does its magic by generating objects with generated functions that are only modified
10   -when the logging system is reconfigured, thus your entire logging path is contained within
  10 +when the logging system is reconfigured, thus your entire logging path is contained within
11 11 long-lived functions that V8 is able to JIT.
12 12
  13 +
13 14 Getting Started
14 15 ====================
15 16
@@ -26,25 +27,74 @@ Then inside bar.js, you would just use the logger like any normal logger:
26 27 In any other part of your application, you can reconfigure the logging subsystem at runtime,
27 28 making it easy to change log levels for specific modules dynamically.
28 29
  30 + /* Register an ad-hoc sink */
29 31 var logmagic = require('logmagic');
30   - logmagic.registerSink("mysink", function(module, level, message) { console.log(message); });
31   -
  32 + logmagic.registerSink("ad-hoc", function(module, level, message) { console.log(message); });
  33 +
32 34 /* Send Info an higher in the root logger to stdout */
33   - logmagic.route("__root__", logmagic.INFO, "stdout")
34   -
  35 + logmagic.route("__root__", logmagic.INFO, "console")
  36 +
35 37 /* Reconfigure all children of mylib to log all debug messages to your custom sink */
36   - logmagic.route("mylib.*", logmagic.DEBUG, "mysink")
  38 + logmagic.route("mylib.*", logmagic.DEBUG, "ad-hoc")
  39 +
  40 +
  41 +Sinks
  42 +===============
  43 +
  44 +Sink modules should have this interface
  45 +
  46 + {
  47 + /* the log message callback */
  48 + callback: function(modulename, level, message, obj) {}
  49 +
  50 + /* sets options for sink */
  51 + setOptions: function(options) {}
  52 +
  53 + /* dispose of resources */
  54 + dispose: function() {}
  55 + }
  56 +
  57 +Registering a sink instance with full control
  58 +
  59 + var fileLog = new logmagic.sinks.File({filename: "/var/log/myapp.log"});
  60 + logmagic.registerSink("main", fileLog);
37 61
38 62
39   -Builtin sinks include:
  63 +Registering the easy way for `ColorConsole`, `File` and `Recipients`
40 64
41   -* stderr
42   -* Graylog2-style JSON to stderr
  65 + logmagic.registerFileSink("fileLog", "/var/log/myapp.log");
  66 + logmagic.registerConsoleSink("colorConsole", "dark");
  67 +
  68 +
  69 +Setting options on a sink instance
  70 +
  71 + logmagic.setSinkOptions("colorConsole", {plain: true});
  72 + logmagic.setSinkOptions("colorConsole", {scheme: "light"});
  73 +
  74 +Routing to multiple sinks
  75 +
  76 + logmagic.registerRecipientsSink("multi", ["fileLog", "colorConsole"]);
  77 + logmagic.route("__root__", logmagic.INFO, "multi")
  78 +
  79 +Pre-registered sinks
  80 +
  81 +* `"colorConsole"`
  82 +* `"console"`
  83 +* `"grayLog2-stderr"`
  84 +
  85 +Built-in sinks
  86 +
  87 +* `ColorConsole`: log to console with colors (may be disabled)
  88 +* `Console`: log to console (lightweight)
  89 +* `GrayLog2`: Graylog2-style JSON to stderr
  90 +* `File`: log to a file
  91 +* `Recipients`: log to multiple registered sinks
43 92
44 93 Future features:
45 94
46   -* Standard Out
47 95 * Facebook Scribe: https://github.com/facebook/scribe
48   -* File
49 96 * Unix Socket
50 97 * Syslog
  98 +
  99 +
  100 +See `tests/t.js` for an example.
155 lib/logmagic.js
@@ -15,7 +15,9 @@
15 15 * limitations under the License.
16 16 */
17 17
18   -var graylog = require('./graylog');
  18 +var fs = require('fs'),
  19 + path = require('path'),
  20 + util = require('util');
19 21
20 22 function LoggerProxy(modulename) {
21 23 this.modulename = modulename;
@@ -84,7 +86,7 @@ function buildLogMethod(modulename, level, callback) {
84 86 }
85 87 extra['full_message'] = new Error('Backtrace').stack;
86 88 extra = applyRewrites(modulename, level, msg, extra);
87   - callback(modulename, level, msg, extra)
  89 + callback(modulename, level, msg, extra);
88 90 }
89 91 }
90 92 else {
@@ -93,7 +95,7 @@ function buildLogMethod(modulename, level, callback) {
93 95 extra = {};
94 96 }
95 97 extra = applyRewrites(modulename, level, msg, extra);
96   - callback(modulename, level, msg, extra)
  98 + callback(modulename, level, msg, extra);
97 99 }
98 100 }
99 101 }
@@ -121,7 +123,7 @@ function buildFormattedLogMethod(modulename, level, callback) {
121 123 extra['full_message'] = new Error('Backtrace').stack;
122 124 extra = applyRewrites(modulename, level, msg, extra);
123 125 msg = applyFormatString(msg, extra);
124   - callback(modulename, level, msg, extra)
  126 + callback(modulename, level, msg, extra);
125 127 }
126 128 }
127 129 else {
@@ -131,7 +133,7 @@ function buildFormattedLogMethod(modulename, level, callback) {
131 133 }
132 134 extra = applyRewrites(modulename, level, msg, extra);
133 135 msg = applyFormatString(msg, extra);
134   - callback(modulename, level, msg, extra)
  136 + callback(modulename, level, msg, extra);
135 137 }
136 138 }
137 139 }
@@ -211,8 +213,36 @@ exports.local = function(modulename) {
211 213 return logger;
212 214 };
213 215
214   -exports.registerSink = function(sinkname, callback) {
215   - known_sinks[sinkname] = callback;
  216 +
  217 +/* from coffee-script :) */
  218 +var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  219 +
  220 +
  221 +/**
  222 + * Registers a sink.
  223 + *
  224 + * @param {String} instanceName
  225 + * @param {Object|Function} sink If the sink is a function, then an ad-hoc
  226 + * sink is created with the `sink` as the callback. Otherwise, `sink` is
  227 + * assumed to be an object that has a `sink` interface.
  228 + */
  229 +exports.registerSink = function(instanceName, sink) {
  230 + if (typeof sink === 'function') {
  231 + sink = {
  232 + name: "ad-hoc",
  233 + callback: sink
  234 + }
  235 + }
  236 +
  237 + known_sinks[instanceName] = sink;
  238 + sink.instanceName = instanceName;
  239 +
  240 + /* ad-hoc sinks will likely only have a callback, so default others */
  241 + if (!sink.setOptions) sink.setOptions = function() {};
  242 + if (!sink.dispose) sink.dispose = function() {};
  243 +
  244 + /* ensure callback is bound to sink */
  245 + sink.callback = __bind(sink.callback, sink);
216 246 };
217 247
218 248 exports.route = function(match, loglevel, sinkname) {
@@ -226,7 +256,7 @@ exports.route = function(match, loglevel, sinkname) {
226 256 throw new Error("Invalid Sink: " + sinkname);
227 257 }
228 258
229   - known_routes.push({route: match, loglevel: loglevel, callback: known_sinks[sinkname]});
  259 + known_routes.push({route: match, loglevel: loglevel, callback: known_sinks[sinkname].callback});
230 260
231 261 for(var i=0; i<known_loggers.length; i++) {
232 262 var logger = known_loggers[i];
@@ -242,27 +272,102 @@ exports.clearRewriter = function(func) {
242 272 rewriters.pop(func);
243 273 };
244 274
245   -(function() {
246   - /* Default Sinks */
247   -
248   - /* This is just here for initial dev work, REMOVE ME */
249   - exports.registerSink("console", function(modulename, level, message, obj) {
250   - if (obj && Object.keys(obj).length !== 0) {
251   - /* TODO: improve */
252   - var fm = obj['full_message'] ? "\n " + obj['full_message'] : "";
253   - obj['full_message'] = undefined;
254   - console.log(modulename +": "+ message + " " + JSON.stringify(obj) + fm);
  275 +
  276 +exports.setSinkOptions = function(instanceName, options) {
  277 + known_sinks[instanceName].setOptions(options);
  278 +};
  279 +
  280 +
  281 +/**
  282 + * The built-in sink classes.
  283 + */
  284 +var sinks = exports.sinks = {};
  285 +
  286 +
  287 +/**
  288 + * Get sink instances by name.
  289 + *
  290 + * @param {String|Array} names The instance names of sinks.
  291 + * @return Returns an array of sink instances.
  292 + */
  293 +exports.getSinkInstances = function(names) {
  294 + if (typeof names === 'string')
  295 + return [known_sinks[names]];
  296 + else if (util.isArray(names)) {
  297 + var result = [];
  298 + for (var i = 0; i < names.length; i++) {
  299 + result.push(known_sinks[names[i]]);
255 300 }
  301 + return result;
  302 + }
  303 +};
  304 +
  305 +
  306 +/* LogMagic looks way too complicated. Create simple factory functions. */
  307 +
  308 +/* Creates and registers a new FileSink */
  309 +exports.registerFileSink = function(instanceName, filename) {
  310 + var instance = new sinks.File({filename: filename});
  311 + exports.registerSink(instanceName, instance);
  312 + return instance;
  313 +};
  314 +
  315 +/* Creates and registers a new Recipients sink */
  316 +exports.registerRecipientsSink = function(instanceName, sinkInstances) {
  317 + var list = [],
  318 + name;
  319 +
  320 + for (var i = 0; i < sinkInstances.length; i++) {
  321 + name = sinkInstances[i];
  322 + if (typeof name === 'string')
  323 + list.push(known_sinks[name]);
256 324 else {
257   - console.log(modulename +": "+ message);
  325 + if (!name.callback) throw new Error("Invalid sink instance: " + name);
  326 + list.push(name);
258 327 }
259   - });
  328 + }
  329 +
  330 + var instance = new sinks.Recipients({list: list});
  331 + exports.registerSink(instanceName, instance);
  332 +
  333 + return instance;
  334 +};
  335 +
  336 +/* Creates and registers a new ColorConsoleSink */
  337 +exports.registerConsoleSink = function(instanceName, scheme) {
  338 + var instance = new sinks.ColorConsole({scheme: scheme});
  339 + exports.registerSink(instanceName, instance);
  340 + return instance;
  341 +};
  342 +
  343 +
  344 +(function() {
  345 + var file, name, sink;
  346 +
  347 + var files = fs.readdirSync(__dirname + "/sinks");
  348 +
  349 + /* Export sinks */
  350 + for (var i = 0; i < files.length; i++) {
  351 + file = files[i];
  352 + if (file.match(/\.js$/)) {
  353 + name = path.basename(file, '.js');
  354 + sink = require("./sinks/" + name);
  355 +
  356 + /* export the class with first letter capitalized */
  357 + klass = name.charAt(0).toUpperCase() + name.slice(1);
  358 + exports.sinks[klass] = sink;
  359 +
  360 + /* Sinks starting to have too many properties, add defaults for missing */
  361 + if (!sink.prototype.name) sink.prototype.name = klass;
  362 + if (!sink.prototype.setOptions) sink.prototype.setOptions = function() {};
  363 + if (!sink.prototype.dispose) sink.prototype.dispose = function() {};
  364 + }
  365 + }
260 366
261   - exports.registerSink("graylog2-stderr", function(modulename, level, message, obj) {
262   - /* Outputs a GLEF-style JSON to stderr */
263   - var str = graylog.logstr(modulename, level, message, obj);
264   - process.stderr.write(str + "\n");
265   - });
  367 + /* Register sinks whom do not need options */
  368 + exports.registerSink("console", new exports.sinks.Console);
  369 + exports.registerSink("colorConsole", new exports.sinks.ColorConsole);
  370 + exports.registerSink("graylog2-stderr", new exports.sinks.GrayLog2);
266 371
267 372 /* Default loggers */
268 373 exports.route("__root__", exports.INFO, "console");
156 lib/sinks/colorConsole.js
... ... @@ -0,0 +1,156 @@
  1 +/*============================================================================
  2 + * Copyright(c) 2010 Mario L Gutierrez <mario@mgutz.com>
  3 + * MIT Licensed
  4 + *==========================================================================*/
  5 +
  6 +var colors = require('mgutz-colors');
  7 +
  8 +
  9 +/**
  10 + * Logs to the console using colors (which may be disabled).
  11 + *
  12 + * @param {Object} options See `ColorConsole#setOptions`.
  13 + */
  14 +function ColorConsole(options) {
  15 + this.schemes = {
  16 + dark: {
  17 + nsColor: "black+h",
  18 + warnColor: "yellow+h",
  19 + infoColor: "cyan+h",
  20 + errorColor: "red+h",
  21 + traceColor: "white+h"
  22 + },
  23 +
  24 + light: {
  25 + nsColor: "black+h",
  26 + warnColor: "magenta",
  27 + infoColor: "cyan",
  28 + errorColor: "red",
  29 + traceColor: "black"
  30 + }
  31 + };
  32 +
  33 + if (!options) options = {};
  34 +
  35 + if (!options.scheme) options.scheme = "dark";
  36 + this.setOptions(options);
  37 + return this;
  38 +}
  39 +
  40 +
  41 +/**
  42 + * Uses a color scheme, setting color functions based on the scheme.
  43 + *
  44 + * @param {String|Object} scheme The name of an existing scheme or the
  45 + * definition.
  46 + */
  47 +ColorConsole.prototype.useColorScheme = function(scheme) {
  48 + if (typeof scheme === 'string') {
  49 + this.schemeName = scheme;
  50 + scheme = this.schemes[scheme];
  51 + if (!scheme) throw new Error("Scheme not found: "+scheme);
  52 + } else if (scheme.name && !this.schemes[scheme.name]) {
  53 + this.schemeName = scheme.name;
  54 + this.schemes[scheme.name] = scheme;
  55 + }
  56 + else {
  57 + this.schemeName = "unknown";
  58 + }
  59 +
  60 + // using scheme so must be allowing colors
  61 + colors.plain = false;
  62 +
  63 + var nsColor = colors.fn(scheme.nsColor ? scheme.nsColor : ""),
  64 + warnColor = colors.fn(scheme.warnColor ? scheme.warnColor : ""),
  65 + infoColor = colors.fn(scheme.infoColor ? scheme.infoColor : ""),
  66 + errorColor = colors.fn(scheme.errorColor ? scheme.errorColor : ""),
  67 + traceColor = colors.fn(scheme.traceColor ? scheme.traceColor : "");
  68 +
  69 + this.levels = [
  70 + ['EMG', errorColor], // emergency
  71 + ['ALT', errorColor], // alert
  72 + ['CRL', errorColor], // critical
  73 + ['ERR', errorColor],
  74 + ['WRN', warnColor],
  75 + ['NTC', warnColor], // notice
  76 + ['INF', infoColor],
  77 + ['DBG', traceColor],
  78 + ['TR1', traceColor],
  79 + ['TR2', traceColor],
  80 + ['TR3', traceColor],
  81 + ['TR4', traceColor],
  82 + ['TR5', traceColor],
  83 + ['TR6', traceColor],
  84 + ['TR7', traceColor]
  85 + ];
  86 +
  87 + this.nsColor = nsColor;
  88 + this.warnColor = warnColor;
  89 + this.infoColor = infoColor;
  90 + this.errorColor = errorColor;
  91 + this.traceColor = traceColor;
  92 +}
  93 +
  94 +
  95 +/**
  96 + * Invoked whenever a message needs to be logged.
  97 + *
  98 + * @param {String} modulename The modulename or namespace.
  99 + * @param {Integer} level The level of this message.
  100 + * @param {String} message The message to be logged.
  101 + * @param {String} obj ???
  102 + */
  103 +ColorConsole.prototype.callback = function(modulename, level, message, obj) {
  104 + /* TODO: improve */
  105 + if (obj && typeof obj == 'object') {
  106 + for(var prop in obj) {
  107 + if(obj.hasOwnProperty(prop) && prop !== 'full_message')
  108 + message += "\n " + prop + ": " + obj[prop];
  109 + }
  110 + var fm = obj['full_message'] ? "\n " + obj['full_message'] : "";
  111 + message += fm;
  112 + }
  113 +
  114 + var prefix = "["+this.levels[level][0]+"] ";
  115 + modulename += ": ";
  116 + var messageColor = this.levels[level][1];
  117 + console.log(messageColor(prefix) + this.nsColor(modulename) + messageColor(message));
  118 +};
  119 +
  120 +
  121 +/**
  122 + * Sets the options for this color-console sink.
  123 + *
  124 + * @param {Object} options An object { plain: boolean, setScheme: string|object }
  125 + * plain: Set to true to disable colors.
  126 + * setScheme Can be "dark", "light" or an object
  127 + * {
  128 + * nsColor: "",
  129 + * warnColor: "",
  130 + * infoColor: "",
  131 + * errorColor: "",
  132 + * traceColor: ""
  133 + * }
  134 + *
  135 + * @example
  136 + *
  137 + * // disable colors
  138 + * setOptions({plain: true});
  139 + *
  140 + * // use predefined or previously set scheme
  141 + * setOptions({scheme: "dark"});
  142 + *
  143 + * // customize colors
  144 + * setOptions({scheme: { name: "custom", nsColor: "black", warnColor: "red+h",
  145 + * infoColor: "blue+h", errorColor: "red", traceColor: "cyan" });
  146 + */
  147 +ColorConsole.prototype.setOptions = function(options) {
  148 + if (options.plain)
  149 + colors.plain = options.plain;
  150 + else if (options.scheme)
  151 + this.useColorScheme(options.scheme);
  152 +};
  153 +
  154 +
  155 +module.exports = ColorConsole;
  156 +
23 lib/sinks/console.js
... ... @@ -0,0 +1,23 @@
  1 +function Console() {
  2 + return this;
  3 +};
  4 +
  5 +
  6 +Console.prototype.setOptions = function(options) {
  7 + // nothing todo
  8 +};
  9 +
  10 +Console.prototype.callback = function(modulename, level, message, obj) {
  11 + if (obj && typeof obj == 'object') {
  12 + for(var prop in obj) {
  13 + if(obj.hasOwnProperty(prop) && prop !== 'full_message')
  14 + message += "\n " + prop + ": " + obj[prop];
  15 + }
  16 + var fm = obj['full_message'] ? "\n " + obj['full_message'] : "";
  17 + message += fm;
  18 + }
  19 + console.log(modulename +": "+ message);
  20 +};
  21 +
  22 +
  23 +module.exports = Console;
102 lib/sinks/file.js
... ... @@ -0,0 +1,102 @@
  1 +/*============================================================================
  2 + * Copyright(c) 2010 Mario L Gutierrez <mario@mgutz.com>
  3 + * MIT Licensed
  4 + *==========================================================================*/
  5 +
  6 +var fs = require("fs");
  7 +var levels = [
  8 + 'EMG', // emergency
  9 + 'ALT', // alert
  10 + 'CRL', // critical
  11 + 'ERR',
  12 + 'WRN',
  13 + 'NTC', // notice
  14 + 'INF',
  15 + 'DBG',
  16 + 'TR1',
  17 + 'TR2',
  18 + 'TR3',
  19 + 'TR4',
  20 + 'TR5',
  21 + 'TR6',
  22 + 'TR7'
  23 +];
  24 +
  25 +
  26 +/**
  27 + * Creates an instance of this sink.
  28 + *
  29 + * @param {Object} options The options. `options.filename` is REQUIRED.
  30 + */
  31 +function FileSink(options) {
  32 + this.setOptions(options);
  33 + return this;
  34 +};
  35 +
  36 +
  37 +/**
  38 + * Invoked whenever a message needs to be logged.
  39 + *
  40 + * @param {String} modulename The modulename or namespace.
  41 + * @param {Integer} level The level of this message.
  42 + * @param {String} message The message to be logged.
  43 + * @param {String} obj ???
  44 + */
  45 +FileSink.prototype.callback = function(modulename, level, message, obj) {
  46 + if (obj && typeof obj == 'object') {
  47 + for(var prop in obj) {
  48 + if(obj.hasOwnProperty(prop) && prop !== 'full_message')
  49 + message += "\n " + prop + ": " + obj[prop];
  50 + }
  51 + var fm = obj['full_message'] ? "\n " + obj['full_message'] : "";
  52 + message += fm;
  53 + }
  54 +
  55 + var prefix = "\n["+levels[level]+"] ";
  56 + modulename += ": ";
  57 + this.writer.write(prefix + modulename + message);
  58 +};
  59 +
  60 +
  61 +/**
  62 + * Sets the options for this sink.
  63 + *
  64 + * @param {Object} options The options `{filename: "path to log file"}`
  65 + *
  66 + * @example
  67 + * setOptions({file: "/var/log/myapp.log"});
  68 + */
  69 +FileSink.prototype.setOptions = function(options) {
  70 + if (options.filename) this.useFile(options.filename);
  71 +};
  72 +
  73 +
  74 +/**
  75 + * Disposes of resources used by this sink.
  76 + */
  77 +FileSink.prototype.dispose = function() {
  78 + if (this.writer) {
  79 + this.writer.end();
  80 + this.writer.destroySoon();
  81 + this.writer = null;
  82 + }
  83 +}
  84 +
  85 +
  86 +/**
  87 + * Creates a write stream and keeps it open until `dispose` is called.
  88 + *
  89 + * @param {String} filename The output file.
  90 + */
  91 +FileSink.prototype.useFile = function(filename) {
  92 + this.dispose();
  93 + this.filename = filename;
  94 + this.writer = fs.createWriteStream(filename, {
  95 + flags: "a",
  96 + encoding: "utf8",
  97 + mode: 0666
  98 + });
  99 +}
  100 +
  101 +
  102 +module.exports = FileSink;
18 lib/sinks/grayLog2.js
... ... @@ -0,0 +1,18 @@
  1 +var graylog = require("../graylog.js");
  2 +
  3 +function GrayLog2() {
  4 + return this;
  5 +}
  6 +
  7 +GrayLog2.prototype.setOptions = function(options) {
  8 + // nothing yet
  9 +};
  10 +
  11 +GrayLog2.prototype.callback = function(modulename, level, message, obj) {
  12 + /* Outputs a GLEF-style JSON to stderr */
  13 + var str = graylog.logstr(modulename, level, message, obj);
  14 + process.stderr.write(str + "\n");
  15 +};
  16 +
  17 +module.exports = GrayLog2;
  18 +
34 lib/sinks/recipients.js
... ... @@ -0,0 +1,34 @@
  1 +/*============================================================================
  2 + * Copyright(c) 2010 Mario L Gutierrez <mario@mgutz.com>
  3 + * MIT Licensed
  4 + *==========================================================================*/
  5 +
  6 +function Recipients(options) {
  7 + this.setOptions(options);
  8 + return this;
  9 +};
  10 +
  11 +
  12 +Recipients.prototype.setOptions = function(options) {
  13 + var instanceName, sink;
  14 + this.sinks = [];
  15 +
  16 + for (var i = 0; i < options.list.length; i++) {
  17 + sink = options.list[i];
  18 + this.sinks.push(sink);
  19 + }
  20 +};
  21 +
  22 +Recipients.prototype.callback = function(modulename, level, message, obj) {
  23 + var sink;
  24 +
  25 + // Need to synchronize this (performance hit), otherwise messages WILL
  26 + // LIKELY BE OUT OF ORDER
  27 + for (var i = 0; i < this.sinks.length; i++) {
  28 + sink = this.sinks[i];
  29 + sink.callback(modulename, level, message, obj);
  30 + }
  31 +};
  32 +
  33 +
  34 +module.exports = Recipients;
5 package.json
@@ -14,5 +14,8 @@
14 14 },
15 15 "engines": {
16 16 "node": "*"
  17 + },
  18 + "dependencies": {
  19 + "mgutz-colors": "~0.1"
17 20 }
18   -}
  21 +}
2  tests/bench.js
@@ -10,4 +10,4 @@ var end = (new Date().getTime());
10 10
11 11 var ms = (end - start);
12 12
13   -console.log(ops + " logstr operations in " + ms + "ms, " + (ops/ms) * 1000 + " (logstr/second)");
  13 +console.log(ops + " logstr operations in " + ms + "ms, " + (ops/ms) * 1000 + " (logstr/second)");
42 tests/t.js
@@ -8,6 +8,8 @@ log.trace("testing trace v0");
8 8
9 9 logmagic.route("__root__", logmagic.TRACE1, "console");
10 10 logmagic.route("__root__", logmagic.TRACE1, "graylog2-stderr");
  11 +logmagic.route("__root__", logmagic.TRACE1, "colorConsole");
  12 +
11 13 log.trace("testing trace v1", {slug: 1});
12 14
13 15 log = logmagic.local('mylib.foo.cars');
@@ -21,8 +23,44 @@ logmagic.addRewriter(function(modulename, level, msg, extra) {
21 23 return extra;
22 24 });
23 25
24   -log.trace("hello baksdfnsdf", {special: 'aaa', account_id: 42, txnid: "fxxxxx", full_message: "loooong message"});
  26 +function tryIt(header, log) {
  27 + console.log("\n" + header);
  28 + console.log("===============================================================================");
  29 +
  30 + log.trace("hello baksdfnsdf", {special: 'aaa', account_id: 42, txnid: "fxxxxx", full_message: "loooong message"});
  31 +
  32 + log.debug("hello debug", {request: {account: {id: 45}, txtId: "XXXXXXXXXXXXX"}});
  33 +
  34 + log.warn("hello warn", {request: {account: {id: 45}, txtId: "XXXXXXXXXXXXX"}});
  35 +
  36 + log.info("hello info", {request: {account: {id: 45}, txtId: "XXXXXXXXXXXXX"}});
  37 +
  38 + log.error("hello error", {request: {account: {id: 45}, txtId: "XXXXXXXXXXXXX"}});
  39 +}
  40 +
  41 +tryIt("Colorful", log);
  42 +
  43 +logmagic.setSinkOptions("colorConsole", {plain: true});
  44 +tryIt("Plain", log);
  45 +
  46 +logmagic.setSinkOptions("colorConsole", {scheme: "light"});
  47 +tryIt("Light", log);
  48 +
  49 +
  50 +logmagic.setSinkOptions("colorConsole", {scheme: {nsColor: "green"}});
  51 +tryIt("Custom colors", log);
  52 +
  53 +
  54 +logmagic.registerFileSink("fileLog", "file.log");
  55 +logmagic.route("__root__", logmagic.TRACE1, "fileLog");
  56 +tryIt("File > file.log", log);
  57 +
  58 +logmagic.registerRecipientsSink("recipients", ["fileLog", "colorConsole"]);
  59 +logmagic.route("__root__", logmagic.TRACE1, "recipients");
  60 +tryIt("Route to colorConsole and file", log);
25 61
26   -log.dbg("hello xxxx", {request: {account: {id: 45}, txtId: "XXXXXXXXXXXXX"}});
  62 +logmagic.registerSink("ad-hoc", function(module, level, message) { console.log(message); });
  63 +logmagic.route("__root__", logmagic.TRACE1, "ad-hoc");
  64 +tryIt("ad-hoc", log);
27 65
28 66 //console.log(log);

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.