From 755b1567d349a64020b73a03d5d000a181f9bfd7 Mon Sep 17 00:00:00 2001 From: Alan Plum Date: Tue, 27 Jan 2015 12:37:25 +0100 Subject: [PATCH] Rewrote all the logging. --- js/common/bootstrap/modules.js | 2 +- .../modules/org/arangodb/foxx/logging.js | 158 +++++++++++++++++- .../org/arangodb/foxx/logging/console.js | 119 ------------- 3 files changed, 155 insertions(+), 124 deletions(-) delete mode 100644 js/server/modules/org/arangodb/foxx/logging/console.js diff --git a/js/common/bootstrap/modules.js b/js/common/bootstrap/modules.js index 5dde65898c..0354ccb8a7 100644 --- a/js/common/bootstrap/modules.js +++ b/js/common/bootstrap/modules.js @@ -1733,7 +1733,7 @@ function require (path) { sandbox.__filename = full; sandbox.__dirname = normalizeModuleName(full + "/.."); sandbox.module = appContext.appModule; - sandbox.console = require("org/arangodb/foxx/logging/console").for(appContext.mount); + sandbox.console = require("org/arangodb/foxx/logging")(appContext.mount, true); sandbox.applicationContext = appContext; sandbox.require = function (path) { diff --git a/js/server/modules/org/arangodb/foxx/logging.js b/js/server/modules/org/arangodb/foxx/logging.js index 7ed0c81964..d471465010 100644 --- a/js/server/modules/org/arangodb/foxx/logging.js +++ b/js/server/modules/org/arangodb/foxx/logging.js @@ -1,9 +1,9 @@ /*jshint globalstrict: true */ -/*global module */ +/*global require, module */ 'use strict'; //////////////////////////////////////////////////////////////////////////////// -/// @brief Foxx logging manager +/// @brief Foxx logging /// /// @file /// @@ -29,6 +29,156 @@ /// @author Copyright 2015, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// -// TODO implement this. +var util = require('util'); +var extend = require('underscore').extend; +var AssertionError = require('assert').AssertionError; +var db = require('org/arangodb').db; -module.exports = {}; \ No newline at end of file +var Console = function (mount, tracing) { + this._mount = mount; + this._timers = Object.create(null); + this._tracing = Boolean(tracing); + this._logLevel = -999; + this._logLevels = {TRACE: -2}; + + Object.keys(Console.prototype).forEach(function (name) { + if (typeof this[name] === 'function') { + this[name] = this[name].bind(this); + } + }.bind(this)); + + this.debug = this._withLevel('DEBUG', -1); + this.info = this._withLevel('INFO', 0); + this.warn = this._withLevel('WARN', 1); + this.error = this._withLevel('ERROR', 2); + + this.assert._level = 'ERROR'; + this.dir._level = 'INFO'; + this.log._level = 'INFO'; + this.time._level = 'INFO'; + this.trace._level = 'TRACE'; +}; + +extend(Console.prototype, { + _log: function (level, message, callee) { + if (!this._logLevels.hasOwnProperty(level)) { + throw new Error('Unknown log level: ' + level); + } + + if (this._logLevels[level] < this._logLevel) { + // Don't log this. + return; + } + + var doc = { + mount: this._mount, + level: level, + levelNum: this._logLevels[level], + created: Date.now(), + message: message + }; + + if (this._tracing) { + var e = new Error(); + Error.captureStackTrace(e, callee || this._log); + doc.stack = e.stack.replace(/\n$/, '').split('\n').slice(2) + .map(function (line) { + var tokens = line.replace(/^\s*at\s+/, '').split(':'); + return { + fileName: tokens.slice(0, tokens.length - 2).join(':'), + lineNumber: Number(tokens[tokens.length - 2]), + columnNumber: Number(tokens[tokens.length - 1]) + }; + }); + } + + if (!db._foxxlog) { + db._create('_foxxlog', {isSystem: true}); + db._foxxlog.ensureSkiplist('mount', 'created'); + db._foxxlog.ensureSkiplist('level', 'created'); + db._foxxlog.ensureSkiplist('levelNum', 'created'); + db._foxxlog.ensureSkiplist('stack[0].fileName'); + db._foxxlog.ensureFulltextIndex('message'); + } + + db._foxxlog.save(doc); + }, + + assert: function (condition, message) { + if (!condition) { + this._log(this.assert._level, new AssertionError({ + message: message, + actual: condition, + expected: true, + operator: '==', + stackStartFunction: this.assert + }).stack, + this.assert); + } + }, + + dir: function (obj) { + this._log(this.dir._level, util.inspect(obj)); + }, + + log: function () { + this._log(this.log._level, util.format.apply(null, arguments)); + }, + + time: function (label) { + this._timers[label] = Date.now(); + }, + + timeEnd: function (label) { + if (!this._timers.hasOwnProperty(label)) { + throw new Error('No such label: ' + label); + } + this._log( + this.time._level, + util.format('%s: %dms', label, Date.now() - this._timers[label]), + this.time + ); + delete this._timers[label]; + }, + + trace: function (message) { + var trace = new Error(message); + trace.name = 'Trace'; + Error.captureStackTrace(trace, this.trace); + this._log(this.trace._level, trace.stack); + }, + + _withLevel: function (level, weight) { + level = String(level); + weight = Number(weight); + weight = weight === weight ? weight : 999; + this._logLevels[level] = weight; + var logWithLevel = function() { + this._log(level, util.format.apply(null, arguments), logWithLevel); + }.bind(this); + return logWithLevel; + }, + + _setLogLevel: function (level) { + if (typeof level === 'string') { + if (!this._logLevels.hasOwnProperty(level)) { + throw new Error('Unknown log level: ' + level); + } + level = this._logLevels[level]; + } + this._logLevel = typeof level === 'number' ? level : -999; + return this._logLevel; + }, + + _setTracing: function (tracing) { + this._tracing = Boolean(tracing); + return this._tracing; + } +}); + +module.exports = extend( + function (mount, tracing) { + return new Console(mount, tracing); + }, + {Console: Console} +); \ No newline at end of file diff --git a/js/server/modules/org/arangodb/foxx/logging/console.js b/js/server/modules/org/arangodb/foxx/logging/console.js deleted file mode 100644 index f3ab59152c..0000000000 --- a/js/server/modules/org/arangodb/foxx/logging/console.js +++ /dev/null @@ -1,119 +0,0 @@ -/*jshint globalstrict: true */ -/*global exports, require, Symbol */ -'use strict'; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief Foxx logging console -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2015 triAGENS GmbH, Cologne, Germany -/// -/// Licensed 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. -/// -/// Copyright holder is triAGENS GmbH, Cologne, Germany -/// -/// @author Alan Plum -/// @author Copyright 2015, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -var util = require('util'); -var extend = require('underscore').extend; -var AssertionError = require('assert').AssertionError; - -exports.for = function (mount, traceAll) { - traceAll = Boolean(traceAll); - - var console = {}; - var timers = Object.create(null); - - function log(level, message, trace) { - var doc = { - mount: mount, - level: level, - created: Date.now(), - message: message - }; - - if (trace) { - var e = new Error(); - Error.captureStackTrace(e, log); - var stack = e.stack.replace(/\n$/, '').split('\n').slice(2); - var tokens = stack[0].replace(/^\s*at\s+/, '').split(':'); - extend(doc, { - fileName: tokens.slice(0, tokens.length - 2).join(':'), - lineNumber: Number(tokens[tokens.length - 2]), - columnNumber: Number(tokens[tokens.length - 1]), - stack: stack.join('\n').replace(/(^|\n)\s+/g, '$1') - }); - } - - // TODO write to collection - require('console').log(doc); - } - - console.assert = function (condition, message) { - if (!condition) { - log('error', new AssertionError({ - message: message, - actual: condition, - expected: true, - operator: '==', - stackStartFunction: console.assert - }).stack, traceAll); - } - }; - - console.dir = function (obj) { - log('info', util.inspect(obj), traceAll); - }; - - console.time = function (label) { - var symbol = Symbol.for(label); - timers[symbol] = Date.now(); - }; - - console.timeEnd = function (label) { - var symbol = Symbol.for(label); - if (!timers.hasOwnProperty(symbol)) { - throw new Error('No such label: ' + label); - } - log('info', util.format('%s: %dms', label, Date.now() - timers[symbol]), traceAll); - delete timers[symbol]; - }; - - console.trace = function (message) { - var trace = new Error(message); - trace.name = 'Trace'; - Error.captureStackTrace(trace, console.trace); - log('trace', trace.stack, traceAll); - }; - - console._level = function (level, trace) { - level = String(level); - trace = Boolean(trace); - return function () { - log(level, util.format.apply(null, arguments), trace); - }; - }; - - console.debug = console._level('debug', traceAll); - console.info = console._level('info', traceAll); - console.warn = console._level('warn', traceAll); - console.error = console._level('error', traceAll); - console.log = console.info; - - return console; -}; \ No newline at end of file