This is not too easy. At Log4PHP we have exactly that problem right now. Somebody is using the FileAppender and figured out, that one Apache process was waiting looong time before it could write. Reason: the logger locked the Logfile for the whole time of the request. If you have lots of requests, you can think what it means. Performance is past, in the case.
Time for me to think about the different options to write to log files.
I figured out, that I have to compare the following options:
1) Not closing the file while the whole request is running. This is not an option in a live system, but will give me a good idea whats currently the case
$fp = fopen($file, 'a+');
while($count < $loop) {
fwrite($fp, $text);
}
fclose($fp);
2) Closing the file directly after fwrite is called
while($count < $loop) {
$fp = fopen($file, 'a+');
fwrite($fp, $text);
fclose($fp);
}
3) Use file_put_contents, which is known as an alias to fopen, fwrite and fclose
while($count < $loop) {
file_put_contents($file, $text, FILE_APPEND);
}
4) Leave the file open while the whole request, but unlock it with flock and flock it again, when the next log event occurs
$fp = fopen($file, 'a+');
flock($fp, LOCK_UN);
while($count < $loop) {
if (flock($fp, LOCK_EX)) {
fwrite($fp, $text);
}
flock($fp, LOCK_UN);
}
fclose($fp);
5) Use a nonblocking stream for this and flock
$fp = fopen($file, 'a+');
stream_set_blocking($fp, 0);
while($count < $loop) {
if (flock($fp, LOCK_EX)) {
fwrite($fp, $text);
}
flock($fp, LOCK_UN);
}
fclose($fp);
6) Use the error_log method, which my friend Kevin Horst brought up
while($count < $loop) {
error_log($text, 3, $file);
}
For each of this options I wrote a simple function which wrote 10000 times 100 characters inĀ a freshly created log file. I measured before opening and after closing. Additionally I tried out with 2 seperated threads if the write access is nonblocking. Good thing is, option 2 to 6 are actually nonblocking. And here are the timing results:
1) Execution with NOT closing the log file took 0.0668561458588 seconds
2) Execution with CLOSING the log after each write file took 30.1630220413 seconds
3) Execution with file_put_content took 30.153963089 seconds
4) Execution with leaving the file open, but LOCKING and UNLOCKING it took 0.148998975754 seconds
5) Execution with nonblocking stream took 0.149605989456 seconds
6) Execution with the error_log method took 30.069578886 seconds
Let’s see what it means.
Not closing the file until the 10000 fwrite calls are handled as actually the fastest. No surprise. It just took 0.0668 seconds but this one is not really an option, cause other threads have to wait until this request has been finished.
If you close the file after each fwrite and make it available to other threads and then reopen it, is hell. For 10000 calls of this kind I needed 30 seconds! It’s insane to have this in a productive system. The same goes with file_put_contents. Well, I allready knew (its in the php docs) that this method is nothing else then a wrapper for fopen, fwrite and fclose. Times are so similar that I say it’s exactly the same. Sometimes the one is some millis faster, sometimes the other.
If you open the file, unlock it with flock and flock it again it works very well. Just 0.14 ms for the 10000 fwrite calls. Thats the double amount of option 1, but yeah, here we do some more stuff. The interpreter cares about who is allowed to write, together with the OS. flock works that way, that a call to this function blocks until the requestor gets the actual lock. You can be sure that only one thread is actually writing.
Same goes to the nonblocking stream. This works with stream_set_blocking($fp, 0);. The file stream is nonblocking, means each thread could write at it the same time. That no mess happens, we need an flock here too. That brings us to the nearly same results as fopen, flock, fwrite, flock, fclose option above. But looking at the logfiles of this one and option 4, this one looks more nice to me. This is just subjective, but it looks like the lock is shared more nicely between both threads.
Last one is the error_log method. It didn’t had any idea what to expect, but… 30 seconds! This one behaviours like a wrapper for fopen, fwrite and fclose, like file_put_content. No guys, this is not really a method enabled for logging! If one would use this in a framework like Log4PHP, that would be hell to performance. I would think that this should better removed out. The name suggests a good logging method, but this is not the case.
Having that all said, Log4PHP will get the lock and unlock option number 4. I feel good with it, since it’s quite straightforward. I don’t have too much expierence with the non blocking stream and don’t want to have this in a framework like log4php is.
However, Logging must be used carefully at all. I thnk on a system with 10000 request a second. Enabling logging into one file could bring the system down. I think a live system should have the option to log exactly one request. Maybe triggered by an url param. Think carefully what you log and how you configure your live system.
The complete script can be found here.
Tags: Apache Log4PHP, PHP
Are these Apache processes that are waiting a looong time on windows? I don’t think Linux blocks concurrent writes to open files by default.
This isn’t blocked by the OS, even when the issue itself has been reported for Linux, Windows and Mac.
Please see: https://issues.apache.org/jira/browse/LOG4PHP-71
I think the guy identified the issue cause Log4PHP did explicitly set the LOCK flag to the file. This blocked other Apache processes before writing. If we wouldn’t have set this flag, we might have corrupted the file when two processes write at the same time. This is, why I wrote “nonblocking”.
I wonder when we can download and start to use log4php?
Is there any defined release date?
I looked download page (http://incubator.apache.org/log4php/download.html) but it says no release yet.
Thanks
We are in the “clean up and make it stable” phase. I think we will have Log4PHP 2.0 out before christmas.
Cheers
thanks for info Christian
Hello Christian.
I wanna ask if you know any good log software as an alternative to log4php. I just need one and I see that first release of log4php will not come till december..
Another question is there problems I mean may first release be late than december?
regards
Antoine, I am afraid to say that I don’t know any other option for logging in PHP at the moment. Maybe Zend Framework has something in it or PEAR, but they might not be so flexible like Log4PHP. However, if I were you, I would checkout the log4php code from SVN. Its pretty stable and we are really thinking about releasing it in near future, maybe start of november. So, if you have a chance, go for SVN (and share your expierences
)
Christian
thanks for answer Christian,
I go to SVN, and see the files, but I couldn’t download them. (sorry I’m new to SVN), could you send me the link, or explain me howto?
BTW I found the coverage report at log4php site and see that everything almost 100% finished. Should we expect 1st release soon?
regards
Yes, you can expect a release quite soon. Actually I am struggelling with the maven stuff for it. Hope to get that sorted out this week, then the votings need to pass on. However, if you are on windows, you can try tortoise: http://tortoisesvn.tigris.org/
You need to check out the sourcecode – going to the website alone will not help.
We (DBpedia) have been using http://svn.apache.org/repos/asf/incubator/log4php/tags/apache-log4php-2.0.0-incubating-RC1 for a while now without any problems. Highly recommended!
thanks Christopher,
do you know any tutorial about log4php about Installation and using?
Regards
Hi Antoine,
there is a complete manual online at:
http://incubator.apache.org/log4php/install.html