Download |
Bug Tracking |
Source |
Documentation |
Forum |
Latest Changes |
Home
In a complex application, you always end up with the need to log some information to keep runtime statistics or to debug.
Logging information has an overhead and one cannot escape it, one can only try to be wise and mitigate the consequences. The Pluf logging framework provide a set of tools allowing you to have different strategies depending of your requirements (always present logs, debugging, etc.).
The simple logging methods are what you can expect from a logging framework.
Pluf_Log::log('Whatever you want to log.');
Pluf_Log::info('Whatever you want to log.');
Pluf_Log::debug('Debug information.');
Pluf_Log::fatal('Runtime situation which may crash the app.');
Depending of your settings the information will be logged or not, and, you can have then log written on disk, in the database or displayed at the bottom of your page.
Delayed logging is the action not to log directly the message coming in the log queue. This is very practical for different reasons:
The negative side of the delayed logging is that your logs will not be written if your application dies before flushing. This is why you should not use this method when doing debugging leading to a crash of your application. As this is a very rare case, delayed logging is often a good solution.
To enable delayed logging, just set the log_delayed key to true
and run the flush static method at the point in time you want to
flush the logs.
Pluf_Log::log('This is not written to disk.');
Pluf_Log::flush(); // Here we write to disk
Of course, you can get the flushing to be handle automatically at the
end of the request. In that case, just listen to the
Pluf_Dispatcher::postDispatch signal:
Pluf_Signal::connect('Pluf_Dispatcher::postDispatch',
array('Pluf_Log', 'flushHandler'));
You can add this at the end of your configuration file or in your main
relations.php file. Be sure to connect to the
Pluf_Dispatcher::postDispatch only once and everything will be fine.
The drawback of the simple logging approach is that you are always
calling the corresponding Pluf_Log method and generating the message
even if you are not logging the message. Most of the time this will
not be that problematic, but in some particular cases, the performance
impact could be problematic.
The solution is to dynamically generate the log message only if logging is enabled. To do so, the assert function is used.
To log with the assert call, simply run:
$object = MyApp_Foo::complex();
assert('Pluf_Log::alog("My message: $object.")');
The difference is that instead of using the log method, you use the
alog method. You also have the ainfo, adebug, afatal methods.
You can see that the string passed as argument to assert is not evaluated, it is a single quoted string. The string encapsulate a valid code fragment.nnn
The very interesting point is that the string will be evaluated and
logged only if you ask for it, and it will be evaluated in the
local context. This means that $object will be defined. The assert
call also adds the file and line number to your message.
The positive side of assert logging:
The negative side:
The recommended usage is to use assert logging for the logs which are not going to be run that often. Typically, this will be for debugging information which you normally do not want to log in production.
If you are doing statistics logging, for example to track the database query time or other complex operations, it is better to directly use the simple logging calls as these are logging actions which are most likely to be running all the time in production.
Base activation of the assert logging is performed in your configuration file. Just add the following line at the end:
Pluf_Log::activeAssert();
This will setup the assert callbacks needed to have the assert logging running smoothly.
log_level (Pluf_Log::INFO): It will log everything. The available log levels are:
Pluf_Log::ALL: Log everything.Pluf_Log::DEBUG: Log debug information for the application.Pluf_Log::INFO: Log normal information (this is the default).Pluf_Log::WARN: Log events which can lead to harmful situations.Pluf_Log::ERROR: Log error allowing the application to keep running.Pluf_Log::FATAL: Log error which makes the application stop.Pluf_Log::OFF: Stop all logging.The log levels are taken from log4j.
Pluf_Log_FileThis is the default logger, by default it logs in a pluf.log file in
your temp folder. Set the pluf_log_file configuration setting to the
full path of your log file to change the path.
Pluf_Log_RemotePost the log to a remote host via HTTP POST. The payload is the JSON encoded stack of logs at flush time. It is recommended to activate delayed logging when using this logger to log once per request.
The settings are:
'log_remote_path': /'log_remote_server': localhost'log_remote_headers': An array of extra headers to send with the request,
you can put your authentication header in it, empty by default. For example,
array('My-Header' => 'foo').'log_remote_port': 8000If you use a Node.js based logger, you can get
up to 350 log/s. For example, copy/paste the following code as
logs.js file and run it like that node logs.js.
var sys = require("sys"),
posix = require("posix"),
http = require("http"),
filename = "./pluf.nodejs.log",
port = 8000,
fd = posix.open(filename,
process.O_WRONLY | process.O_APPEND | process.O_CREAT,
process.S_IRWXU | process.S_IRGRP | process.S_IROTH
).wait();
record_message = function(request, msg) {
posix.write(fd, msg+"\n");
};
http.createServer(function (request, response) {
var content = "";
request.addListener("body", function(chunk) {
content += chunk;
});
request.addListener("complete", function() {
record_message(request, content);
response.sendHeader(200, {"Content-Type": "text/plain"});
response.sendBody("stored message");
response.finish();
});
}).listen(port);
Inspired by log collection server with Node.js.
Report issues in the documentation
If you find errors or issues in the documentation, report a bug. We will update the documentation accordingly.
Pluf © 2005-2008 Loïc d'Anterroches, supported by Céondo Ltd.