Permalink
Browse files

Log, Log writer (file, console)

  • Loading branch information...
1 parent 860ca8c commit 2e2f321e25911b1f8e47408f0ea1c6f8155cc1da @vovazolotoy vovazolotoy committed Oct 17, 2011
View
15 application/bootstrap.js
@@ -8,15 +8,20 @@ Johana.init({
profile: false
});
-Johana.conf.attach(new ConfigFile());
-
+/**
+ * Attach the file write to logging. Multiple writers are supported.
+ */
+Johana.log.attach(new LogFile(APPPATH + 'logs'), Log.ERROR);
+Johana.log.attach(new LogConsole());
+Johana.conf.attach(new ConfigFile());
function testList(req, res) {
-
- console.log(Request.factory(req.url, req));
- console.log(req.url);
+ Johana.log.add(Log.DEBUG, 'Request: ' + req.url);
+ Johana.log.add(Log.ERROR, 'ERRO Request: ' + req.url);
+
+ //console.log(Request.factory(req.url, req));
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(View.factory('hello').render());
};
View
15 system/prototypes/johana/core.js
@@ -178,15 +178,6 @@ JohanaCore.init = function(settings)
Johana.errors = settings['errors'];
}
- if (Johana.errors === true)
- {
-// // Enable JohanaCore exception handling, adds stack traces and error source.
-// set_exception_handler(Object('JohanaCore_Exception', 'handler'));
-//
-// // Enable JohanaCore error handling, converts all PHP errors to exceptions.
-// set_error_handler(Object('JohanaCore', 'error_handler'));
- }
-
if (settings['expose'] !== undefined)
{
Johana.expose = settings['expose'];
@@ -268,9 +259,9 @@ JohanaCore.init = function(settings)
Johana.baseUrl = settings['baseUrl'].replace(/\/$/, '') + '/';
}
-// // Load the logger
-// Johana.log = Log.instance();
-//
+ // Load the logger
+ Johana.log = Log.instance();
+
// Load the config
Johana.conf = Config.instance();
};
View
209 system/prototypes/johana/log.js
@@ -0,0 +1,209 @@
+/**
+ * Message logging with observer-based log writing.
+ *
+ * @package Johana
+ * @category Logging
+ * @author Johana Team
+ * @copyright (c) 2011 Johana Team
+ * @license http://johanaframework.org/license
+ */
+JohanaLog = function()
+{
+};
+
+// Log message levels
+JohanaLog.EMERGENCY = 0;
+JohanaLog.ALERT = 1;
+JohanaLog.CRITICAL = 2;
+JohanaLog.ERROR = 3;
+JohanaLog.WARNING = 4;
+JohanaLog.NOTICE = 5;
+JohanaLog.INFO = 6;
+JohanaLog.DEBUG = 7;
+JohanaLog.STRACE = 8;
+
+/**
+ * @var Boolean immediately write when logs are added
+ */
+JohanaLog.writeOnAdd = true;
+
+/**
+ * @var Log Singleton instance container
+ */
+JohanaLog._instance = null;
+
+/**
+ * Get the singleton instance of this proto.
+ *
+ * var log = Log.instance();
+ *
+ * @return Log
+ */
+JohanaLog.instance = function()
+{
+ if (Log._instance === null)
+ {
+ // Create a new instance
+ Log._instance = new Log();
+
+ // Write the logs at shutdown
+ //register_shutdown_function(array(Log::$_instance, 'write'));
+ }
+
+ return Log._instance;
+};
+
+/**
+ * @var Array list of added messages
+ */
+JohanaLog.prototype._messages = [];
+
+/**
+ * @var Array list of log writers
+ */
+JohanaLog.prototype._writers = [];
+
+/**
+ * Attaches a log writer, and optionally limits the levels of messages that
+ * will be written by the writer.
+ *
+ * log.attach(writer);
+ *
+ * @param Object LogWriter instance
+ * @param mixed array of messages levels to write OR max level to write
+ * @param integer min level to write IF levels is not an array
+ * @return Log
+ */
+JohanaLog.prototype.attach = function(writer, levels, minLevel)
+{
+ minLevel = minLevel || 0;
+
+ if (levels === undefined)
+ {
+ levels = [];
+ }
+
+ if (levels.constructor != Array)
+ {
+ var lev = [];
+ for (var i = minLevel; i <= levels; i++)
+ {
+ lev.push(i);
+ }
+ levels = lev;
+ }
+
+ this._writers[writer.toString()] =
+ {
+ object: writer,
+ levels: levels
+ };
+
+ return this;
+};
+
+/**
+ * Detaches a log writer. The same writer object must be used.
+ *
+ * log.detach(writer);
+ *
+ * @param object LogWriter instance
+ * @return Log
+ */
+JohanaLog.prototype.detach = function(writer)
+{
+ // Remove the writer
+ delete this._writers[writer.toString()];
+
+ return this;
+};
+
+/**
+ * Adds a message to the log. Replacement values must be passed in to be
+ * replaced using mask
+ *
+ * log.add(Log.ERROR, 'Could not locate user: :user', {
+ * ':user' => username,
+ * });
+ *
+ * @param String level of message
+ * @param String message body
+ * @param Array values to replace in the message
+ * @return Log
+ */
+JohanaLog.prototype.add = function(level, message, values)
+{
+ if (values)
+ {
+ // Insert the values into the message
+ for (var v in values)
+ {
+ message = message.replace(v, values[v]);
+ }
+ }
+
+ // Create a new message and timestamp it
+ this._messages.push({
+ time: new Date().toString(),
+ level: level,
+ body: message
+ });
+
+ if (Log.writeOnAdd)
+ {
+ // Write logs as they are added
+ this.write();
+ }
+
+ return this;
+};
+
+/**
+ * Write and clear all of the messages.
+ *
+ * log.write();
+ *
+ * @return void
+ */
+JohanaLog.prototype.write = function()
+{
+ if ( ! this._messages.length)
+ {
+ // There is nothing to write, move along
+ return;
+ }
+
+ // Import all messages locally
+ var messages = this._messages;
+
+ // Reset the messages array
+ this._messages = [];
+
+ for (var w in this._writers)
+ {
+ if ( ! this._writers[w].levels.length)
+ {
+ // Write all of the messages
+ this._writers[w].object.write(messages);
+ }
+ else
+ {
+ // Filtered messages
+ var filtered = [];
+
+ for (var m in messages)
+ {
+ if (this._writers[w].levels.indexOf(messages[m].level) != -1)
+ {
+ // Writer accepts this kind of message
+ filtered.push(messages[m]);
+ }
+ }
+
+ // Write the filtered messages
+ this._writers[w].object.write(filtered);
+ }
+ }
+};
+
+module.exports = JohanaLog; // End
View
35 system/prototypes/johana/log/console.js
@@ -0,0 +1,35 @@
+/**
+ * Console log writer. Writes out messages to console
+ *
+ * @package Johana
+ * @category Logging
+ * @author Johana Team
+ * @copyright (c) 2011 Johana Team
+ * @license http://johanaframework.org/license
+ */
+JohanaLogFile = function()
+{
+ LogWriter.call(this);
+};
+
+// Inherits
+require('util').inherits(JohanaLogFile, LogWriter);
+
+/**
+ * Writes each of the messages to console
+ *
+ * writer.write(messages);
+ *
+ * @param Array messages
+ * @return void
+ */
+JohanaLogFile.prototype.write = function(messages)
+{
+ for (var m in messages)
+ {
+ var line = messages[m].time + ' --- ' + this._logLevels[messages[m].level] + ': ' + messages[m].body;
+ console.log(line);
+ }
+};
+
+exports = module.exports = JohanaLogFile; // End
View
93 system/prototypes/johana/log/file.js
@@ -0,0 +1,93 @@
+/**
+ * File log writer. Writes out messages and stores them in a YYYY/MM directory.
+ *
+ * @package Johana
+ * @category Logging
+ * @author Johana Team
+ * @copyright (c) 2011 Johana Team
+ * @license http://johanaframework.org/license
+ */
+JohanaLogFile = function(directory)
+{
+ LogWriter.call(this);
+
+ try
+ {
+ // Check if cache dir is writable
+ require('fs').chmodSync(directory, 0755);
+ }
+ catch (e)
+ {
+ throw new Error('Directory ' + directory + ' must be writable');
+ }
+
+ // Determine the directory path
+ this._directory = require('fs').realpathSync(directory) + '/';
+};
+
+// Inherits
+require('util').inherits(JohanaLogFile, LogWriter);
+
+/**
+ * @var String Directory to place log files in
+ */
+JohanaLogFile.prototype._directory;
+
+/**
+ * Writes each of the messages into the log file. The log file will be
+ * appended to the `YYYY/MM/DD.log` file, where YYYY is the current
+ * year, MM is the current month, and DD is the current day.
+ *
+ * writer.write(messages);
+ *
+ * @param Array messages
+ * @return void
+ */
+JohanaLogFile.prototype.write = function(messages)
+{
+ // Set the yearly directory name
+ var directory = this._directory + new Date().getFullYear();
+
+ if ( ! require('path').existsSync(directory))
+ {
+ require('fs').mkdirSync(directory, 02777);
+ }
+
+ // Add the month to the directory
+ var month = new Date().getMonth();
+
+ if (month < 10)
+ {
+ month = '0' + month;
+ }
+
+ directory += '/' + month;
+
+ if ( ! require('path').existsSync(directory))
+ {
+ // Create the monthly directory
+ require('fs').mkdirSync(directory, 02777);
+ }
+
+ // Set the name of the log file
+ var date = new Date().getDate();
+
+ if (date < 10)
+ {
+ date = '0' + date;
+ }
+
+ var filename = directory + '/' + date + '.log';
+
+ var file = require('fs').openSync(filename, 'a');
+
+ for (var m in messages)
+ {
+ // Write each message into the log file
+ // Format: time --- level: body
+ var line = '\n' + messages[m].time + ' --- ' + this._logLevels[messages[m].level] + ': ' + messages[m].body;
+ require('fs').writeSync(file, line);
+ }
+};
+
+exports = module.exports = JohanaLogFile; // End
View
40 system/prototypes/johana/log/writer.js
@@ -0,0 +1,40 @@
+/**
+ * Log writer abstract pproto. All [Log] writers must extend this prototype.
+ *
+ * @package Johana
+ * @category Logging
+ * @author Johana Team
+ * @copyright (c) 2011 Johana Team
+ * @license http://johanaframework.org/license
+ */
+JohanaLogWriter = function() {};
+
+/**
+ * Numeric log level to string lookup table.
+ * @var Object
+ */
+JohanaLogWriter.prototype._logLevels = {
+ 0: 'EMERGENCY',
+ 1: 'ALERT',
+ 2: 'CRITICAL',
+ 3: 'ERROR',
+ 4: 'WARNING',
+ 5: 'NOTICE',
+ 6: 'INFO',
+ 7: 'DEBUG',
+ 8: 'STRACE'
+};
+
+/**
+ * Allows the writer to have a unique key when stored.
+ *
+ * console.log(writer + '\n');
+ *
+ * @return String
+ */
+JohanaLogWriter.prototype.toString = function()
+{
+ return JSON.stringify(this);
+};
+
+exports = module.exports = JohanaLogWriter; // End
View
4 system/prototypes/log.js
@@ -0,0 +1,4 @@
+
+Log = JohanaLog;
+
+module.exports = Log;
View
4 system/prototypes/log/console.js
@@ -0,0 +1,4 @@
+
+LogConsole = JohanaLogConsole;
+
+module.exports = LogConsole;
View
4 system/prototypes/log/file.js
@@ -0,0 +1,4 @@
+
+LogFile = JohanaLogFile;
+
+module.exports = LogFile;
View
4 system/prototypes/log/writer.js
@@ -0,0 +1,4 @@
+
+LogWriter = JohanaLogWriter;
+
+module.exports = LogWriter;

0 comments on commit 2e2f321

Please sign in to comment.