summaryrefslogtreecommitdiff
path: root/framework/Log/EventLog/writers
diff options
context:
space:
mode:
Diffstat (limited to 'framework/Log/EventLog/writers')
-rw-r--r--framework/Log/EventLog/writers/writer_database.php216
-rw-r--r--framework/Log/EventLog/writers/writer_file.php273
-rw-r--r--framework/Log/EventLog/writers/writer_unix_file.php100
3 files changed, 589 insertions, 0 deletions
diff --git a/framework/Log/EventLog/writers/writer_database.php b/framework/Log/EventLog/writers/writer_database.php
new file mode 100644
index 00000000..6908a770
--- /dev/null
+++ b/framework/Log/EventLog/writers/writer_database.php
@@ -0,0 +1,216 @@
+<?php
+/**
+ * File containing the ezcLogWriterDatabase class.
+ *
+ * @package EventLog
+ * @version //autogentag//
+ * @copyright Copyright (C) 2005, 2006 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ */
+
+/**
+ * Writes log messages to the database.
+ *
+ * @package EventLog
+ * @version //autogentag//
+ */
+class ezcLogWriterDatabase implements ezcLogWriter
+{
+ private $db = null;
+
+ private $properties = array();
+ private $defaultColumns = array();
+ private $additionalColumns = array();
+
+ private $map;
+ private $defaultTable = false;
+
+ /**
+ * Construct a new database log-writer.
+ *
+ * You can set the default table to write to with the $defaultTable parameter.
+ * If $databaseInstance is given, that instance will be used for writing. If it
+ * is ommitted the default database instance will be retrieved.
+ *
+ * This constructor is a tie-in.
+ *
+ * @param string $defaultTable
+ * @param ezcDbHandler $databaseInstance
+ *
+ */
+ public function __construct( ezcDbHandler $databaseInstance, $defaultTable = false )
+ {
+ $this->db = $databaseInstance;
+
+ $this->map = new ezcLogMap();
+ $this->defaultTable = $defaultTable;
+
+ $this->message = "message";
+ $this->datetime = "time";
+ $this->severity = "severity";
+ $this->source = "source";
+ $this->category = "category";
+ }
+
+ /**
+ * Sets the property $name to $value.
+ *
+ * @throws ezcBasePropertyNotFoundException if the property does not exist.
+ * @param string $name
+ * @param mixed $value
+ * @return void
+ */
+ public function __set( $name, $value )
+ {
+ switch ( $name )
+ {
+ case 'table': $this->properties['table'] = $value; break;
+ case 'message':
+ case 'datetime':
+ case 'severity':
+ case 'source':
+ case 'category': $this->defaultColumns[ $name ] = $value; break;
+ default: $this->additionalColumns[ $name ] = $value; break;
+ }
+ }
+
+ /**
+ * Returns the property $name.
+ *
+ * @throws ezcBasePropertyNotFoundException if the property does not exist.
+ * @param string $name
+ * @return mixed
+ */
+ public function __get( $name )
+ {
+ switch ( $name )
+ {
+ case 'table': return $this->properties['table']; break;
+ case 'message':
+ case 'datetime':
+ case 'severity':
+ case 'source':
+ case 'category': return $this->defaultColumns[ $name ]; break;
+
+ default: return $this->additionalColumns[ $name ]; break;
+ }
+ }
+
+ /**
+ * Writes the message $message to the log.
+ *
+ * The writer can use the severity, source, and category to filter the
+ * incoming messages and determine the location where the messages should
+ * be written.
+ *
+ * $optional may contain extra information that can be added to the log. For example:
+ * line numbers, file names, usernames, etc.
+ *
+ * @throws ezcLogWriterException when the log writer was unable to write
+ * the log message.
+ * @param string $message
+ * @param int $severity
+ * ezcLog:: DEBUG, SUCCES_AUDIT, FAILED_AUDIT, INFO, NOTICE, WARNING, ERROR or FATAL.
+ *
+ * $param string $source
+ * @param string $category
+ * @param array(string=>string) $optional
+ * @return void
+ */
+ public function writeLogMessage( $message, $severity, $source, $category, $optional = array() )
+ {
+ $severityName = ezcLog::translateSeverityName( $severity );
+
+ $colStr = "";
+ $valStr = "";
+
+ if ( is_array( $optional ) )
+ {
+ foreach ( $optional as $key => $val )
+ {
+ $colStr .= ", " . ( isset( $this->additionalColumns[$key] ) ? $this->additionalColumns[$key] : $key );
+ $valStr .= ", " . $this->db->quote( $val );
+ }
+ }
+
+ $tables = $this->map->get( $severity, $source, $category );
+
+ $query = $this->db->createSelectQuery();
+ if ( count( $tables ) > 0)
+ {
+ foreach ( $tables as $t )
+ {
+ try
+ {
+ $this->db->exec( "INSERT INTO `{$t}` ( {$this->message}, {$this->severity}, {$this->source}, {$this->category}, {$this->datetime} $colStr ) ".
+ "VALUES( ".$this->db->quote( $message ).", ".$this->db->quote( $severityName ).", ".$this->db->quote( $source ).", ".
+ $this->db->quote( $category ).", ".$query->expr->now()." $valStr )" );
+ }
+ catch ( PDOException $e )
+ {
+ throw new ezcLogWriterException( "SQL query failed in ezcLogWriterDatabase.\n". $e->getMessage() );
+ }
+ }
+ }
+ else
+ {
+ if ( $this->defaultTable !== false )
+ {
+ try
+ {
+ $this->db->exec( "INSERT INTO `{$this->defaultTable}` ( {$this->message}, {$this->severity}, {$this->source}, {$this->category}, {$this->datetime} $colStr ) ".
+ "VALUES( ".$this->db->quote( $message ).", ".$this->db->quote( $severityName ).", ".$this->db->quote( $source ).", ".
+ $this->db->quote( $category ).", ".$query->expr->now()." $valStr )" );
+ }
+ catch ( PDOException $e )
+ {
+ throw new ezcLogWriterException( "SQL query failed in ezcLogWriterDatabase.\n". $e->getMessage() );
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns an array that describes the coupling between the logMessage
+ * information and the columns in the database.
+ *
+ * @return array(string=>string)
+ */
+ public function getColumnTranslations()
+ {
+ return array_merge( $this->defaultColumns, $this->additionalColumns );
+ }
+
+
+ /**
+ * Maps the table $tableName to the messages specified by the {@link ezcLogFilter} $logFilter.
+ *
+ * Log messages that matches with the filter are written to the table $tableName.
+ * This method works the same as {@link ezclog::map()}.
+ *
+ * @param ezcLogFilter $logFilter
+ * @param string $tableName
+ * @return void
+ */
+ public function map( ezcLogFilter $logFilter, $tableName )
+ {
+ $this->map->map( $logFilter->severity, $logFilter->source, $logFilter->category, $tableName );
+ }
+
+ /**
+ * Unmaps the table $tableName from the messages specified by the {@link ezcLogFilter} $logFilter.
+ *
+ * Log messages that matches with the filter are no longer written to the table $tableName.
+ * This method works the same as {@link ezclog::unmap()}.
+ *
+ * @param ezcLogFilter $logFilter
+ * @param string $fileName
+ * @return void
+ */
+ public function unmap( ezcLogFilter $logFilter, $tableName )
+ {
+ $this->map->unmap( $logFilter->severity, $logFilter->source, $logFilter->category, $tableName );
+ }
+}
+
+?>
diff --git a/framework/Log/EventLog/writers/writer_file.php b/framework/Log/EventLog/writers/writer_file.php
new file mode 100644
index 00000000..46ecf13e
--- /dev/null
+++ b/framework/Log/EventLog/writers/writer_file.php
@@ -0,0 +1,273 @@
+<?php
+/**
+ * File containing the ezcLogWriterFile class.
+ *
+ * @package EventLog
+ * @version //autogentag//
+ * @copyright Copyright (C) 2005, 2006 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ */
+
+/**
+ * The ezcLogWriterFile class provides functionality to write log files to the file
+ * system.
+ *
+ * The main purpose is to keep track of the various log files and support
+ * log rotation. The file format of the log should be implemented in a subclass.
+ *
+ * The following example implements a new log writer that writes the output in ({@link print_r()} format)
+ * to a file:
+ * <code>
+ * class MyLogWriter extends ezcLogWriterFile
+ * {
+ * // Call parent constructor. (In this case, it possible to omit the constructor.)
+ * public function __construct($dir, $file = null, $maxSize = 204800, $maxFiles = 3 )
+ * {
+ * parent::__construct($dir, $file, $maxSize, $maxFiles);
+ * }
+ *
+ * // Implement the ezcLogWriter interface:
+ * public function writeLogMessage( $message, $type, $source, $category, $extraInfo = array() )
+ * {
+ * // Create a message
+ * $res = print_r( array( "message" => $message, "type" => $type, "source" => $source, "category" => $category ), true );
+ *
+ * // And call the parent class
+ * $this->write( $type, $source, $category, $res );
+ * }
+ *}
+ * </code>
+ *
+ * @package EventLog
+ * @version //autogentag//
+ */
+abstract class ezcLogWriterFile implements ezcLogWriter
+{
+ /**
+ * Contains all the open files. The first file in the
+ * array is always the default file.
+ *
+ * @var array(resource)
+ */
+ protected $openFiles = array();
+
+
+ /**
+ * Keeps track of which group of messages should be stored
+ * in what file.
+ *
+ * @var ezcLogMap
+ */
+ protected $fileMap;
+
+ /**
+ * Directory where the log files should be placed.
+ *
+ * @var string
+ */
+ protected $logDirectory;
+
+ /**
+ * Maximum file size before rotation.
+ *
+ * @var int
+ */
+ protected $maxSize;
+
+ /**
+ * Maximum log rotation files with the same name.
+ *
+ * When rotating and the max limit is reached, the oldest log
+ * is discarded.
+ *
+ * @var int
+ */
+ protected $maxFiles;
+
+
+ /**
+ * Constructs an ezcLogFileWriter.
+ *
+ * The log files will be placed in the directory $logDirectory.
+ *
+ * If the file $defaultFile is not null, log messages that are not {@link map() mapped}
+ * to any file are written to this $defaultFile. If $defaultFile is null, then
+ * log messages are discarded.
+
+ *
+ * Set $maxLogRotationSize to specify the maximum size of a logfile. When the
+ * maximum size is reached, the log will be rotated. $maxLogFiles sets the maximum
+ * number of rotated log files. The oldest rotated log will be removed when the
+ * maxLogFiles exceeds.
+ *
+ * @param string $logDirectory
+ * @param string $defaultFile
+ * @param string $maxLogRotationSize
+ * @param string $maxLogFiles
+ */
+ public function __construct( $logDirectory, $defaultFile = null, $maxLogRotationSize = 204800, $maxLogFiles = 3 )
+ {
+ $this->maxSize = $maxLogRotationSize;
+ $this->maxFiles = $maxLogFiles;
+ $this->logDirectory = $logDirectory;
+ $this->defaultFile = $defaultFile;
+
+ if ( !is_null( $defaultFile ) )
+ {
+ $this->openFile( $defaultFile );
+ }
+
+ $this->fileMap = new ezcLogMap();
+ }
+
+ /**
+ * Destructs the object and closes all open file handles.
+ */
+ public function __destruct()
+ {
+ foreach ( $this->openFiles as $fh )
+ {
+ fclose( $fh );
+ }
+ }
+
+
+ /**
+ * This method writes the $string to a file.
+ *
+ * The file to which the string will be written depends on the $eventType, $eventSource, and
+ * $eventCategory.
+ *
+ * @throws ezcLogWriterException if it was not possible to write to the log file.
+ * @param int $eventType
+ * @param string $eventSource
+ * @param string $eventCategory
+ * @param string $string
+ * @return void
+ */
+ protected function write( $eventType, $eventSource, $eventCategory, $string )
+ {
+ $fileHandles = $this->fileMap->get( $eventType, $eventSource, $eventCategory );
+
+ if ( count( $fileHandles ) > 0 )
+ {
+ foreach ( $fileHandles as $fh )
+ {
+ if ( fwrite( $fh, $string ) === false)
+ {
+ throw ezcLogWriterException( "Cannot write to the attached log file.", ezcLogWriterException::FILE_NOT_WRITABLE );
+ }
+ }
+ }
+ else
+ {
+ if ( !is_null( $this->defaultFile ) )
+ {
+ if ( fwrite( $this->openFiles[$this->defaultFile], $string ) === false )
+ {
+ throw ezcLogWriterException( "Cannot write to the default log file.", ezcLogWriterException::FILE_NOT_WRITABLE );
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the filehandle of the $fileName.
+ *
+ * If the maximum file size is exceeded, the file will be rotated before opening.
+ *
+ * @return resource
+ */
+ protected function openFile( $fileName )
+ {
+ if ( isset( $this->openFiles[$fileName] ) )
+ {
+ return $this->openFiles[$fileName];
+ }
+
+ clearstatcache();
+ if ( file_exists( $this->logDirectory . "/". $fileName ) &&
+ ( filesize( $this->logDirectory . "/". $fileName ) >= $this->maxSize ) )
+ {
+ $this->rotateLog( $fileName );
+ }
+
+ $fh = @fopen( $this->logDirectory ."/". $fileName, "w" );
+ if ( $fh === false )
+ {
+ // throw exception.
+ throw new ezcLogFileException( "Cannot open the file <{$fileName}> for writing", ezcLogFileException::FILE_NOT_FOUND );
+ }
+
+ $this->openFiles[$fileName] = $fh;
+ return $fh;
+ }
+
+ /**
+ * Rotates a log and returns true upon success.
+ *
+ * @return bool
+ */
+ protected function rotateLog( $fileName )
+ {
+ $file = $this->logDirectory . "/" . $fileName;
+
+ for ( $i = $this->maxFiles; $i > 0; --$i )
+ {
+ $logRotateName = $file. '.' . $i;
+ if ( file_exists( $logRotateName ) )
+ {
+ if ( $i == $this->maxFiles )
+ {
+ unlink( $logRotateName );
+ }
+ else
+ {
+ $newLogRotateName = $file . '.' . ( $i + 1 );
+ rename( $logRotateName, $newLogRotateName );
+ }
+ }
+ }
+ if ( file_exists( $file ) )
+ {
+ $newLogRotateName = $file . '.' . 1;
+ rename( $file, $newLogRotateName );
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Maps the filename $fileName to the messages specified by the {@link ezcLogFilter} $logFilter.
+ *
+ * Log messages that matches with the filter are written to the file $fileName.
+ * This method works the same as {@link ezclog::map()}.
+ *
+ * @param ezcLogFilter $logFilter
+ * @param string $fileName
+ * @return void
+ */
+ public function map( ezcLogFilter $logFilter, $fileName )
+ {
+ $fh = $this->openFile( $fileName );
+ $this->fileMap->map( $logFilter->severity, $logFilter->source, $logFilter->category, $fh );
+ }
+
+ /**
+ * Unmaps the filename $fileName from the messages specified by the {@link ezcLogFilter} $logFilter.
+ *
+ * Log messages that matches with the filter are no longer written to the file $fileName.
+ * This method works the same as {@link ezclog::unmap()}.
+ *
+ * @param ezcLogFilter $logFilter
+ * @param string $fileName
+ * @return void
+ */
+ public function unmap( $logFilter, $fileName )
+ {
+ $this->fileMap->unmap( $logFilter->severity, $logFilter->source, $logFilter->category, $this->openFiles[ $fileName ] );
+ }
+
+}
+?>
diff --git a/framework/Log/EventLog/writers/writer_unix_file.php b/framework/Log/EventLog/writers/writer_unix_file.php
new file mode 100644
index 00000000..a2045217
--- /dev/null
+++ b/framework/Log/EventLog/writers/writer_unix_file.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * File containing the ezcLogWriterUnix class.
+ *
+ * @package EventLog
+ * @version //autogentag//
+ * @copyright Copyright (C) 2005, 2006 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ */
+
+/**
+ * Writes the log messages to a file in a format that is frequently used on the Unix operating system.
+ *
+ * @package EventLog
+ * @version //autogentag//
+ */
+class ezcLogWriterUnixFile extends ezcLogWriterFile
+{
+ /**
+ * Write the logEntries to a file.
+ *
+ * Each line in the log file represents a log message. The log
+ * messages have the following style:
+ * <pre>
+ * MMM dd HH:mm:ss [Severity] [Source] [Category] Message (ExtraInfo)
+ * </pre>
+ *
+ * With:
+ * - MMM: The 3 letter abbreviation of the month.
+ * - dd: The day of the month.
+ * - HH: The hour.
+ * - mm: The minutes.
+ * - ss: The seconds.
+ *
+ * Example:
+ * <pre>
+ * Jan 24 15:32:56 [Debug] [Paynet] [Shop] Connecting to the paynet server (file: paynet_server.php, line: 224).
+ * Jan 24 15:33:01 [Debug] [Paynet] [Shop] Connected with the server (file: paynet_server.php, line: 710).
+ * </pre>
+ *
+ * This method will be called by the {@link ezcLog} class. The $eventSource and $eventCategory are either given
+ * in the {@link ezcLog::log()} method or are the defaults from the {@link ezcLog} class.
+ *
+ * @param string $message
+ * @param int $eventType
+ * @param string $eventType
+ * @param string $eventCategory
+ * @param array(string=>string) $extraInfo
+ */
+ public function writeLogMessage( $message, $eventType, $eventSource, $eventCategory, $extraInfo = array() )
+ {
+ $extra = $this->implodeWithKey( ", ", ": ", $extraInfo );
+
+ if ( $eventCategory == false )
+ {
+ $eventCategory = "";
+ }
+ $logMsg = @date( "M d H:i:s" ) .
+ " [".ezcLog::translateSeverityName( $eventType ) .
+ "] [$eventSource] [$eventCategory] $message ($extra)\n";
+
+ $this->write( $eventType, $eventSource, $eventCategory, $logMsg );
+ }
+
+ /**
+ * Returns a string from the hash $data.
+ *
+ * The string $splitEntry specifies the string that will be inserted between the pairs.
+ * The string $splitKeyVal specifies the string that will be inserted in each pair.
+ *
+ * Example:
+ * <code>
+ * $this->implodeWithKey( ", ", ": ", array( "Car" => "red", "Curtains" => "blue" );
+ * </code>
+ *
+ * Will create the following string:
+ * <pre>
+ * Car: red, Curtains: blue
+ * </pre>
+ *
+ * @param string $splitEntry
+ * @param string $splitKeyVal
+ * @param array(mixed=>mixed) $data
+ * @return string
+ */
+ protected function implodeWithKey( $splitEntry, $splitKeyVal, $data)
+ {
+ $total = "";
+ if ( is_array( $data ) )
+ {
+ foreach ( $data as $key => $val )
+ {
+ $total .= $splitEntry . $key . $splitKeyVal . $val;
+ }
+ }
+
+ return substr( $total, strlen( $splitEntry ) );
+ }
+}
+?>