Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Start on a graylog-style json logger

  • Loading branch information...
commit 9fcac72c10e8289bdbb1830dff211054ff8f6bd8 1 parent eee5928
@pquerna authored
Showing with 115 additions and 9 deletions.
  1. +98 −0 lib/graylog.js
  2. +17 −9 lib/logmagic.js
View
98 lib/graylog.js
@@ -0,0 +1,98 @@
+/*
+ * Licensed to Paul Querna under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * Paul Querna licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var os = require('os');
+
+var logobj = {
+ version: "1.0",
+ host: os.hostname(),
+ timestamp: null,
+ short_message: null,
+ full_message: null,
+ timestamp: null,
+ level: null,
+ facility: null,
+};
+
+var logcache = {};
+
+function clone(obj) {
+ /* Shallow object clone */
+ var target = {};
+ for (var i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ target[i] = obj[i];
+ }
+ }
+ return target;
+}
+
+exports.logstr = function(module, level, message, obj) {
+
+ if (level > 7) {
+ level = 7;
+ }
+
+ var l = null;
+
+ if (obj) {
+ /* begin fucking voodoo */
+
+ /**
+ * The 'easy' way to do this, is to create a new
+ * object every time:
+ * l = clone(logobj);
+ *
+ * But because of how node stores things in its slots,
+ * this is about 50% as fast as this hack using the keys
+ * of an object to store only one instance of it....
+ *
+ * The observation we make is that most applications have a
+ * limited set of parameters that they pass into be logged,
+ * and the 'key' to this log object is almost always a static
+ * string.
+ */
+ var keys = "";
+ /* This is faster than Object.keys(obj).join(""); */
+ for (var i in obj) {
+ keys += i;
+ }
+
+ l = logcache[keys];
+ if (!l) {
+ l = clone(logobj);
+ logcache[keys] = l;
+ }
+
+ for (var i in obj) {
+ if (obj.hasOwnProperty(i)) {
+ l["_" + i] = obj[i];
+ }
+ }
+ }
+ else {
+ l = logobj;
+ }
+
+
+ l.facility = module;
+ l.timestamp = (new Date().getTime()) / 1000;
+ l.short_message = message;
+ l.level = level;
+
+ return JSON.stringify(l);
+}
View
26 lib/logmagic.js
@@ -15,6 +15,8 @@
* limitations under the License.
*/
+var graylog = require('./graylog');
+
function LoggerProxy(modulename) {
this.modulename = modulename;
this.loglevel = -1;
@@ -65,9 +67,9 @@ var known_sinks = {};
var known_loggers = [];
var known_routes = [];
-function buildLogMethod(level, callback) {
+function buildLogMethod(modulename, level, callback) {
return function (msg, extra) {
- callback(level, msg, extra)
+ callback(modulename, level, msg, extra)
}
}
@@ -75,14 +77,14 @@ function nullLogger() {
/* Intentionally blank. */
}
-function applyRoute(route, logger) {
+function applyRoute(route, logger, modulename) {
logger.loglevel = route.loglevel;
for(var i=0; i<log_levels.length; i++) {
var level = log_levels[i];
var v = exports[level];
if (v <= route.loglevel) {
- logger[level.toLowerCase()] = buildLogMethod(v, route.callback);
+ logger[level.toLowerCase()] = buildLogMethod(modulename, v, route.callback);
}
else {
logger[level.toLowerCase()] = nullLogger;
@@ -126,10 +128,10 @@ function applyRoutes(logger) {
for(var i=0; i < known_routes.length; i++) {
var r = known_routes[i];
if (r.route == "__root__") {
- applyRoute(r, logger);
+ applyRoute(r, logger, "__root__");
}
else if (routeMatch(r.route, logger.modulename)) {
- applyRoute(r, logger);
+ applyRoute(r, logger, logger.modulename);
}
}
}
@@ -168,16 +170,22 @@ exports.route = function(match, loglevel, sinkname) {
/* Default Sinks */
/* This is just here for initial dev work, REMOVE ME */
- exports.registerSink("console", function(level, message, obj) {
+ exports.registerSink("console", function(modulename, level, message, obj) {
if (obj) {
/* TODO: improve */
- console.log(message + " " + JSON.stringify(obj));
+ console.log(modulename +": "+ message + " " + JSON.stringify(obj));
}
else {
- console.log(message);
+ console.log(modulename +": "+ message);
}
});
+ exports.registerSink("graylog2-stderr", function(modulename, level, message, obj) {
+ /* Outputs a GLEF-style JSON to stderr */
+ var str = graylog.logstr(modulename, level, message, obj);
+ process.stderr.write(str + "\n");
+ });
+
/* Default loggers */
exports.route("__root__", exports.INFO, "console");
})();

0 comments on commit 9fcac72

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