[PATCH] Re: [PEAR-DEV] Log_file behavior in long running apps

From: Date: Sat, 05 Jul 2003 19:44:24 +0000
Subject: [PATCH] Re: [PEAR-DEV] Log_file behavior in long running apps
References: 1 2 3 4 5 6  Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-18037@lists.php.net to get a copy of this message
# jon@php.net / 2003-07-04 19:37:45 -0400: > On Fri, Jul 04, 2003 at 08:45:22PM +0200, Roman Neuhauser wrote: > > > > > > When I find the time to rewrite the Log_file class, I'll make the > > > > > output buffering optional. > > > > > > > > What are the other changes you want to make? > > > > > > People have been asking for configurable timestamp and output formats. > > > > Add reverting to fwrite() right in log() to that list, please. :) > > Feel free to submit your own version, as well. Ok, here's a patch. Log_file::log() now writes the line straight away which should speed it up by ~20% compared to using the _logLines array. witeOut() is now a noop because of the above change. dontLog() only affects further log() calls (same reason). I haven't added resumeLogging() or anything like that. (I don't believe this class should have such behavior at all. It's supposed to log stuff, right? Why bother with dontLog()?) The constructor now looks for lineFormat index in the $conf array(), possible escapes are %{time}, %{ident}, %{prio}, %{msg}. This allows for arbitrarily structured log format. Defaults to '%{time} %{ident} [%{prio}] %{msg}' (no change). The constructor now looks for eof index in the $conf array(), allowing the user choose the preferred eol string. Defaults to "\r\n" for BC. There's other stuff that could be improved, but I don't want to stuff it all in one patch, it contains two unrelated changes already. Let me know what you think. NB this patch has some rough edges as I don't want to spend too much time on it if you decide it's not good enough. If/when I know this is the way to go I'll polish it. Or you can do it. :) -- If you cc me or remove the list(s) completely I'll most likely ignore your message. see http://www.eyrie.org./~eagle/faqs/questions.html

Index: Log/Log/file.php =================================================================== RCS file: /repository/pear/Log/Log/file.php,v retrieving revision 1.25 diff -u -u -r1.25 file.php --- Log/Log/file.php 17 Jun 2003 05:35:24 -0000 1.25 +++ Log/Log/file.php 5 Jul 2003 19:27:32 -0000 @@ -71,16 +71,34 @@ var $_timeFormat = '%b %d %H:%M:%S'; /** - * Array holding the lines to log + * The log line format. + * @var string + */ + var $_lineFormat = '%1$s %2$s [%3$s] %4$s'; + + /** + * Available line format escapes and printf() escapes + * the'll get translated into. * @var array */ - var $_logLines; + var $_formatfu = array('%{time}' => '%1$s', + '%{ident}' => '%2$s', + '%{prio}' => '%3$s', + '%{msg}' => '%4$s', + '%\{' => '%%{', + ); + + /** + * EOL string. + * @var string + */ + var $_eol = "\r\n"; /** * Boolean which if true will mean * the lines are *NOT* written out. */ - var $_writeOut; + var $_dontLog; /** * Creates a new logfile object. @@ -102,44 +120,45 @@ if (!empty($conf['timeFormat'])) { $this->_timeFormat = $conf['timeFormat']; } + if (!empty($conf['lineFormat'])) { + $this->_lineFormat = str_replace(array_keys($this->_formatfu), + array_values($this->_formatfu), + $conf['lineFormat']); + } - if (!file_exists($name)) { - touch($name); - chmod($name, $this->_mode); + /* Here we use isset() instead of empty() because the user + * might have eol embeded in logged messages */ + if (isset($conf['eol'])) { + $this->_eol = $conf['eol']; } $this->_id = md5(microtime()); $this->_filename = realpath($name); $this->_ident = $ident; $this->_mask = Log::UPTO($maxLevel); - - $this->_logLines = array(); - $this->_writeOut = true; + + /* FIXME: return value is ignored. what should be done + * if the fopen() fails? */ + $this->_openLogfile(); register_shutdown_function(array(&$this, '_Log_file')); } - + /** - * Destructor. This will write out any lines to the logfile, UNLESS the dontLog() - * method has been called, in which case it won't. + * Destructor. Closes the file handle if it hasn't been already closed. * * @access private */ function _Log_file() { - if (!empty($this->_logLines) AND $this->_writeOut AND $this->_openLogfile()) { - - foreach ($this->_logLines as $line) { - $this->_writeLine($line['message'], $line['ident'], $line['priority'], $line['time']); - } - + if (is_resource($this->_fp)) { $this->_closeLogfile(); } } /** - * Adds a line to be logged. Adds it to the internal array and will only - * get written out when the destructor is called. + * If the specified priority is at or below the maximum level, + * appends the message to the log file. * * @param string $message The textual message to be logged. * @param string $priority The priority of the message. Valid @@ -152,12 +171,15 @@ function log($message, $priority = PEAR_LOG_INFO) { // Abort early if the priority is above the maximum logging level. - if (!$this->_isMasked($priority)) { + if ($this->_dontLog || !$this->_isMasked($priority)) { return false; } - // Add to loglines array - $this->_logLines[] = array('message' => $message, 'ident' => $this->_ident, 'priority' => $priority, 'time' => strftime($this->_timeFormat)); + fwrite($this->_fp, sprintf($this->_lineFormat, + strftime($this->_timeFormat), + $this->_ident, + $this->priorityToString($priority), + $message . $this->_eol)); // Notify observers $this->_announce(array('message' => $message, 'priority' => $priority)); @@ -172,29 +194,18 @@ */ function dontLog() { - $this->_writeOut = false; + $this->_dontLog = true; } /** - * Function to force writing out of log *now*. Will clear the queue. - * Using this function does not cancel the writeout in the destructor. - * Handy for long running processes. + * A noop. Kept for backwards-compatibility. * * @access public */ function writeOut() { - if (!empty($this->_logLines) AND $this->_openLogfile()) { - - foreach ($this->_logLines as $line) { - $this->_writeLine($line['message'], $line['ident'], $line['priority'], $line['time']); - } - - $this->_logLines = array(); - $this->_closeLogfile(); - } } - + /** * Opens the logfile for appending. File should always exist, as * constructor will create it if it doesn't. @@ -203,11 +214,14 @@ */ function _openLogfile() { - if (($this->_fp = @fopen($this->_filename, 'a')) == false) { - return false; + if (!file_exists($this->_filename)) { + touch($this->_filename); + chmod($this->_filename, $this->_mode); } - @chmod($this->_filename, $this->_mode); + if (($this->_fp = @fopen($this->_filename, 'a')) === false) { + return false; + } return true; } @@ -222,19 +236,6 @@ return fclose($this->_fp); } - /** - * Writes a line to the logfile - * - * @param string $line The line to write - * @param string $ident The ident string of this line - * @param integer $priority The priority of this line/msg - * @return integer Number of bytes written or -1 on error - * @access private - */ - function _writeLine($line, $ident, $priority, $time) - { - return fwrite($this->_fp, sprintf("%s %s [%s] %s\r\n", $time, $ident, $this->priorityToString($priority), $line)); - } } // End of class ?>
« previous php.pear.dev (#18037) next »