diff options
author | Dan Horrigan <dan@dhorrigan.com> | 2014-03-17 16:44:44 -0400 |
---|---|---|
committer | Dan Horrigan <dan@dhorrigan.com> | 2014-03-17 16:44:44 -0400 |
commit | f8c8918e84a55bb342079117d22aa006de178dac (patch) | |
tree | 1629ad38c5aa0dbed8ec6be9c33ecd8ef2116f88 | |
parent | 85bd0d67aa1a388fc54f67d04b9522840682953c (diff) | |
download | KLogger-f8c8918e84a55bb342079117d22aa006de178dac.zip KLogger-f8c8918e84a55bb342079117d22aa006de178dac.tar.gz KLogger-f8c8918e84a55bb342079117d22aa006de178dac.tar.bz2 |
Major overhaul. It is not PSR-3 compatible and the output is prettier.
-rwxr-xr-x | example/example.php | 25 | ||||
-rwxr-xr-x | src/Logger.php | 414 |
2 files changed, 117 insertions, 322 deletions
diff --git a/example/example.php b/example/example.php index 3a4c4b9..4714021 100755 --- a/example/example.php +++ b/example/example.php @@ -3,18 +3,19 @@ # Should log to the same directory as this file require dirname(__FILE__).'/../vendor/autoload.php'; -$log = Katzgrau\KLogger\Logger::instance(dirname(__FILE__), Katzgrau\KLogger\Logger::DEBUG); -$args1 = array('a' => array('b' => 'c'), 'd'); +$obj = new stdClass(); +$obj->foo = 'bar'; +$log = new Katzgrau\KLogger\Logger(dirname(__FILE__), Psr\Log\LogLevel::DEBUG); +$args1 = array('a' => array('b' => 'c'), 'd' => null, 'e' => $obj); $args2 = NULL; -$log->logInfo('Info Test'); -$log->logNotice('Notice Test'); -$log->logWarn('Warn Test'); -$log->logError('Error Test'); -$log->logFatal('Fatal Test'); -$log->logAlert('Alert Test'); -$log->logCrit('Crit test'); -$log->logEmerg('Emerg Test'); +$log->emergency('Emergency Test'); +$log->alert('Alert Test'); +$log->critical('Critical Test'); +$log->error('Error Test'); +$log->warning('Warning Test'); +$log->notice('Notice Test'); +$log->info('Info Test'); +$log->debug('Debug Test'); -$log->logInfo('Testing passing an array or object', $args1); -$log->logWarn('Testing passing a NULL value', $args2); +$log->info('Testing passing an array or object', $args1); diff --git a/src/Logger.php b/src/Logger.php index 4b9993c..3fba93f 100755 --- a/src/Logger.php +++ b/src/Logger.php @@ -1,16 +1,21 @@ <?php
namespace Katzgrau\KLogger;
+use DateTime;
+use RuntimeException;
+use Psr\Log\AbstractLogger;
+use Psr\Log\LogLevel;
+
/**
* Finally, a light, permissions-checking logging class.
*
* Originally written for use with wpSearch
*
* Usage:
- * $log = new Katzgrau\KLogger\Logger('/var/log/', Katzgrau\KLogger\Logger::INFO);
- * $log->logInfo('Returned a million search results'); //Prints to the log file
- * $log->logFatal('Oh dear.'); //Prints to the log file
- * $log->logDebug('x = 5'); //Prints nothing due to current severity threshhold
+ * $log = new Katzgrau\KLogger\Logger('/var/log/', Psr\Log\LogLevel::INFO);
+ * $log->info('Returned a million search results'); //Prints to the log file
+ * $log->error('Oh dear.'); //Prints to the log file
+ * $log->debug('x = 5'); //Prints nothing due to current severity threshhold
*
* @author Kenny Katzgrau <katzgrau@gmail.com>
* @since July 26, 2008 — Last update July 1, 2012
@@ -21,173 +26,73 @@ namespace Katzgrau\KLogger; /**
* Class documentation
*/
-class Logger
+class Logger extends AbstractLogger
{
/**
- * Error severity, from low to high. From BSD syslog RFC, secion 4.1.1
- * @link http://www.faqs.org/rfcs/rfc3164.html
- */
- const EMERG = 0; // Emergency: system is unusable
- const ALERT = 1; // Alert: action must be taken immediately
- const CRIT = 2; // Critical: critical conditions
- const ERR = 3; // Error: error conditions
- const WARN = 4; // Warning: warning conditions
- const NOTICE = 5; // Notice: normal but significant condition
- const INFO = 6; // Informational: informational messages
- const DEBUG = 7; // Debug: debug messages
-
- //custom logging level
- /**
- * Log nothing at all
- */
- const OFF = 8;
- /**
- * Alias for CRIT
- * @deprecated
- */
- const FATAL = 2;
-
- /**
- * Internal status codes
- */
- const STATUS_LOG_OPEN = 1;
- const STATUS_OPEN_FAILED = 2;
- const STATUS_LOG_CLOSED = 3;
-
- /**
- * We need a default argument value in order to add the ability to easily
- * print out objects etc. But we can't use NULL, 0, FALSE, etc, because those
- * are often the values the developers will test for. So we'll make one up.
- */
- const NO_ARGUMENTS = 'KLogger::NO_ARGUMENTS';
-
- /**
- * Current status of the log file
- * @var integer
- */
- private $_logStatus = self::STATUS_LOG_CLOSED;
- /**
- * Holds messages generated by the class
- * @var array
- */
- private $_messageQueue = array();
- /**
* Path to the log file
* @var string
*/
- private $_logFilePath = null;
+ private $logFilePath = null;
+
/**
* Current minimum logging threshold
* @var integer
*/
- private $_severityThreshold = self::INFO;
+ private $logLevelThreshold = LogLevel::DEBUG;
+
+ private $logLevels = array(
+ LogLevel::EMERGENCY => 0,
+ LogLevel::ALERT => 1,
+ LogLevel::CRITICAL => 2,
+ LogLevel::ERROR => 3,
+ LogLevel::WARNING => 4,
+ LogLevel::NOTICE => 5,
+ LogLevel::INFO => 6,
+ LogLevel::DEBUG => 7,
+ );
+
/**
* This holds the file handle for this instance's log file
* @var resource
*/
- private $_fileHandle = null;
-
- /**
- * Standard messages produced by the class. Can be modified for il8n
- * @var array
- */
- private $_messages = array(
- //'writefail' => 'The file exists, but could not be opened for writing. Check that appropriate permissions have been set.',
- 'writefail' => 'The file could not be written to. Check that appropriate permissions have been set.',
- 'opensuccess' => 'The log file was opened successfully.',
- 'openfail' => 'The file could not be opened. Check permissions.',
- );
+ private $fileHandle = null;
/**
- * Default severity of log messages, if not specified
- * @var integer
- */
- private static $_defaultSeverity = self::DEBUG;
- /**
* Valid PHP date() format string for log timestamps
* @var string
*/
- private static $_dateFormat = 'Y-m-d G:i:s';
+ private $dateFormat = 'Y-m-d G:i:s.u';
+
/**
* Octal notation for default permissions of the log file
* @var integer
*/
- private static $_defaultPermissions = 0777;
- /**
- * Array of KLogger instances, part of Singleton pattern
- * @var array
- */
- private static $instances = array();
-
- /**
- * Partially implements the Singleton pattern. Each $logDirectory gets one
- * instance.
- *
- * @param string $logDirectory File path to the logging directory
- * @param integer $severity One of the pre-defined severity constants
- * @return KLogger
- */
- public static function instance($logDirectory = false, $severity = false)
- {
- if ($severity === false) {
- $severity = self::$_defaultSeverity;
- }
-
- if ($logDirectory === false) {
- if (count(self::$instances) > 0) {
- return current(self::$instances);
- } else {
- $logDirectory = dirname(__FILE__);
- }
- }
-
- if (in_array($logDirectory, self::$instances)) {
- return self::$instances[$logDirectory];
- }
-
- self::$instances[$logDirectory] = new self($logDirectory, $severity);
-
- return self::$instances[$logDirectory];
- }
+ private $defaultPermissions = 0777;
/**
* Class constructor
*
- * @param string $logDirectory File path to the logging directory
- * @param integer $severity One of the pre-defined severity constants
+ * @param string $logDirectory File path to the logging directory
+ * @param integer $logLevelThreshold The LogLevel Threshold
* @return void
*/
- public function __construct($logDirectory, $severity)
+ public function __construct($logDirectory, $logLevelThreshold = LogLevel::DEBUG)
{
- $logDirectory = rtrim($logDirectory, '\\/');
+ $this->logLevelThreshold = $logLevelThreshold;
- if ($severity === self::OFF) {
- return;
- }
-
- $this->_logFilePath = $logDirectory
- . DIRECTORY_SEPARATOR
- . 'log_'
- . date('Y-m-d')
- . '.txt';
-
- $this->_severityThreshold = $severity;
- if (!file_exists($logDirectory)) {
- mkdir($logDirectory, self::$_defaultPermissions, true);
+ $logDirectory = rtrim($logDirectory, '\\/');
+ if (! file_exists($logDirectory)) {
+ mkdir($logDirectory, $this->defaultPermissions, true);
}
- if (file_exists($this->_logFilePath) && !is_writable($this->_logFilePath)) {
- $this->_logStatus = self::STATUS_OPEN_FAILED;
- $this->_messageQueue[] = $this->_messages['writefail'];
- return;
+ $this->logFilePath = $logDirectory.DIRECTORY_SEPARATOR.'log_'.date('Y-m-d').'.txt';
+ if (file_exists($this->logFilePath) && !is_writable($this->logFilePath)) {
+ throw new RuntimeException('The file could not be written to. Check that appropriate permissions have been set.');
}
-
- if (($this->_fileHandle = fopen($this->_logFilePath, 'a'))) {
- $this->_logStatus = self::STATUS_LOG_OPEN;
- $this->_messageQueue[] = $this->_messages['opensuccess'];
- } else {
- $this->_logStatus = self::STATUS_OPEN_FAILED;
- $this->_messageQueue[] = $this->_messages['openfail'];
+
+ $this->fileHandle = fopen($this->logFilePath, 'a');
+ if ( ! $this->fileHandle) {
+ throw new RuntimeException('The file could not be opened. Check permissions.');
}
}
@@ -196,216 +101,105 @@ class Logger */
public function __destruct()
{
- if ($this->_fileHandle) {
- fclose($this->_fileHandle);
+ if ($this->fileHandle) {
+ fclose($this->fileHandle);
}
}
- /**
- * Writes a $line to the log with a severity level of DEBUG
- *
- * @param string $line Information to log
- * @return void
- */
- public function logDebug($line, $args = self::NO_ARGUMENTS)
- {
- $this->log($line, self::DEBUG);
- }
-
- /**
- * Returns (and removes) the last message from the queue.
- * @return string
- */
- public function getMessage()
- {
- return array_pop($this->_messageQueue);
- }
-
- /**
- * Returns the entire message queue (leaving it intact)
- * @return array
- */
- public function getMessages()
- {
- return $this->_messageQueue;
- }
-
- /**
- * Empties the message queue
- * @return void
- */
- public function clearMessages()
- {
- $this->_messageQueue = array();
- }
/**
* Sets the date format used by all instances of KLogger
*
* @param string $dateFormat Valid format string for date()
*/
- public static function setDateFormat($dateFormat)
- {
- self::$_dateFormat = $dateFormat;
- }
-
- /**
- * Writes a $line to the log with a severity level of INFO. Any information
- * can be used here, or it could be used with E_STRICT errors
- *
- * @param string $line Information to log
- * @return void
- */
- public function logInfo($line, $args = self::NO_ARGUMENTS)
- {
- $this->log($line, self::INFO, $args);
- }
-
- /**
- * Writes a $line to the log with a severity level of NOTICE. Generally
- * corresponds to E_STRICT, E_NOTICE, or E_USER_NOTICE errors
- *
- * @param string $line Information to log
- * @return void
- */
- public function logNotice($line, $args = self::NO_ARGUMENTS)
- {
- $this->log($line, self::NOTICE, $args);
- }
-
- /**
- * Writes a $line to the log with a severity level of WARN. Generally
- * corresponds to E_WARNING, E_USER_WARNING, E_CORE_WARNING, or
- * E_COMPILE_WARNING
- *
- * @param string $line Information to log
- * @return void
- */
- public function logWarn($line, $args = self::NO_ARGUMENTS)
- {
- $this->log($line, self::WARN, $args);
- }
-
- /**
- * Writes a $line to the log with a severity level of ERR. Most likely used
- * with E_RECOVERABLE_ERROR
- *
- * @param string $line Information to log
- * @return void
- */
- public function logError($line, $args = self::NO_ARGUMENTS)
+ public function setDateFormat($dateFormat)
{
- $this->log($line, self::ERR, $args);
+ $this->dateFormat = $dateFormat;
}
/**
- * Writes a $line to the log with a severity level of FATAL. Generally
- * corresponds to E_ERROR, E_USER_ERROR, E_CORE_ERROR, or E_COMPILE_ERROR
+ * Logs with an arbitrary level.
*
- * @param string $line Information to log
- * @return void
- * @deprecated Use logCrit
+ * @param mixed $level
+ * @param string $message
+ * @param array $context
+ * @return null
*/
- public function logFatal($line, $args = self::NO_ARGUMENTS)
+ public function log($level, $message, array $context = array())
{
- $this->log($line, self::FATAL, $args);
+ if ($this->logLevels[$this->logLevelThreshold] < $this->logLevels[$level]) {
+ return;
+ }
+ $message = $this->formatMessage($level, $message, $context);
+ $this->write($message);
}
/**
- * Writes a $line to the log with a severity level of ALERT.
+ * Writes a line to the log without prepending a status or timestamp
*
- * @param string $line Information to log
+ * @param string $line Line to write to the log
* @return void
*/
- public function logAlert($line, $args = self::NO_ARGUMENTS)
+ public function write($message)
{
- $this->log($line, self::ALERT, $args);
+ if (! is_null($this->fileHandle)) {
+ if (fwrite($this->fileHandle, $message) === false) {
+ throw new RuntimeException('The file could not be written to. Check that appropriate permissions have been set.');
+ }
+ }
}
/**
- * Writes a $line to the log with a severity level of CRIT.
+ * Formats the message for logging.
*
- * @param string $line Information to log
- * @return void
+ * @param string $level The Log Level of the message
+ * @param string $message The message to log
+ * @param array $context The context
+ * @return string
*/
- public function logCrit($line, $args = self::NO_ARGUMENTS)
+ private function formatMessage($level, $message, $context)
{
- $this->log($line, self::CRIT, $args);
+ $originalTime = microtime(true);
+ $micro = sprintf("%06d", ($originalTime - floor($originalTime)) * 1000000);
+ $date = new DateTime(date('Y-m-d H:i:s.'.$micro, $originalTime));
+ $time = $date->format($this->dateFormat);
+ $level = strtoupper($level);
+ if (! empty($context)) {
+ $message .= PHP_EOL.$this->indent($this->contextToString($context)).PHP_EOL;
+ }
+ return "[{$time}] [{$level}] {$message}".PHP_EOL;
}
/**
- * Writes a $line to the log with a severity level of EMERG.
- *
- * @param string $line Information to log
- * @return void
+ * Takes the given context and coverts it to a string.
+ *
+ * @param array $context The Context
+ * @return string
*/
- public function logEmerg($line, $args = self::NO_ARGUMENTS)
+ private function contextToString($context)
{
- $this->log($line, self::EMERG, $args);
- }
+ $export = var_export($context, true);
- /**
- * Writes a $line to the log with the given severity
- *
- * @param string $line Text to add to the log
- * @param integer $severity Severity level of log message (use constants)
- */
- public function log($line, $severity, $args = self::NO_ARGUMENTS)
- {
- if ($this->_severityThreshold >= $severity) {
- $status = $this->_getTimeLine($severity);
-
- $line = "$status $line";
-
- if($args !== self::NO_ARGUMENTS) {
- /* Print the passed object value */
- $line = $line . '; ' . var_export($args, true);
- }
-
- $this->writeFreeFormLine($line . PHP_EOL);
- }
+ // var_export is ugly, let's pretty it up a bit.
+ return preg_replace(array(
+ '/=>\s+([a-zA-Z])/im',
+ '/array\(\s+\)/im',
+ '/^ |\G /m',
+ ), array(
+ '=> $1',
+ 'array()',
+ ' ',
+ ), str_replace('array (', 'array(', $export));
}
/**
- * Writes a line to the log without prepending a status or timestamp
- *
- * @param string $line Line to write to the log
- * @return void
+ * Indents the given string with the given indent.
+ *
+ * @param string $string The string to indent
+ * @param string $indent What to use as the indent.
+ * @return string
*/
- public function writeFreeFormLine($line)
- {
- if ($this->_logStatus == self::STATUS_LOG_OPEN
- && $this->_severityThreshold != self::OFF) {
- if (fwrite($this->_fileHandle, $line) === false) {
- $this->_messageQueue[] = $this->_messages['writefail'];
- }
- }
- }
-
- private function _getTimeLine($level)
+ private function indent($string, $indent = ' ')
{
- $time = date(self::$_dateFormat);
-
- switch ($level) {
- case self::EMERG:
- return "$time - EMERG -->";
- case self::ALERT:
- return "$time - ALERT -->";
- case self::CRIT:
- return "$time - CRIT -->";
- case self::FATAL: # FATAL is an alias of CRIT
- return "$time - FATAL -->";
- case self::NOTICE:
- return "$time - NOTICE -->";
- case self::INFO:
- return "$time - INFO -->";
- case self::WARN:
- return "$time - WARN -->";
- case self::DEBUG:
- return "$time - DEBUG -->";
- case self::ERR:
- return "$time - ERROR -->";
- default:
- return "$time - LOG -->";
- }
+ return $indent.str_replace("\n", "\n".$indent, $string);
}
}
|