PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/core/libraries/Log.php

https://github.com/pmwalsh/dwa
PHP | 430 lines | 198 code | 45 blank | 187 comment | 27 complexity | 650dd69f21ee998ec893d75bfecf9983 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * Adapated from Klogger
  4. * Usage:
  5. * $log = new Log('/var/log/', Log::INFO );
  6. * $log->logInfo('Returned a million search results'); //Prints to the log file
  7. * $log->logFatal('Oh dear.'); //Prints to the log file
  8. * $log->logDebug('x = 5'); //Prints nothing due to current severity threshhold
  9. *
  10. * @author Kenny Katzgrau <katzgrau@gmail.com>
  11. * @since July 26, 2008
  12. * @link http://codefury.net
  13. * @version 0.1
  14. */
  15. /**
  16. * Class documentation
  17. */
  18. class Log
  19. {
  20. /**
  21. * Error severity, from low to high. From BSD syslog RFC, secion 4.1.1
  22. * @link http://www.faqs.org/rfcs/rfc3164.html
  23. */
  24. const EMERG = 0; // Emergency: system is unusable
  25. const ALERT = 1; // Alert: action must be taken immediately
  26. const CRIT = 2; // Critical: critical conditions
  27. const ERR = 3; // Error: error conditions
  28. const WARN = 4; // Warning: warning conditions
  29. const NOTICE = 5; // Notice: normal but significant condition
  30. const INFO = 6; // Informational: informational messages
  31. const DEBUG = 7; // Debug: debug messages
  32. //custom logging level
  33. /**
  34. * Log nothing at all
  35. */
  36. const OFF = 8;
  37. /**
  38. * Alias for CRIT
  39. * @deprecated
  40. */
  41. const FATAL = 2;
  42. /**
  43. * Internal status codes
  44. */
  45. const STATUS_LOG_OPEN = 1;
  46. const STATUS_OPEN_FAILED = 2;
  47. const STATUS_LOG_CLOSED = 3;
  48. /**
  49. * Current status of the log file
  50. * @var integer
  51. */
  52. private $_logStatus = self::STATUS_LOG_CLOSED;
  53. /**
  54. * Holds messages generated by the class
  55. * @var array
  56. */
  57. private $_messageQueue = array();
  58. /**
  59. * Path to the log file
  60. * @var string
  61. */
  62. private $_logFilePath = null;
  63. /**
  64. * Current minimum logging threshold
  65. * @var integer
  66. */
  67. private $_severityThreshold = self::INFO;
  68. /**
  69. * This holds the file handle for this instance's log file
  70. * @var resource
  71. */
  72. private $_fileHandle = null;
  73. /**
  74. * Standard messages produced by the class. Can be modified for il8n
  75. * @var array
  76. */
  77. private $_messages = array(
  78. //'writefail' => 'The file exists, but could not be opened for writing. Check that appropriate permissions have been set.',
  79. 'writefail' => 'The file could not be written to. Check that appropriate permissions have been set.',
  80. 'opensuccess' => 'The log file was opened successfully.',
  81. 'openfail' => 'The file could not be opened. Check permissions.',
  82. );
  83. /**
  84. * Default severity of log messages, if not specified
  85. * @var integer
  86. */
  87. private static $_defaultSeverity = self::DEBUG;
  88. /**
  89. * Valid PHP date() format string for log timestamps
  90. * @var string
  91. */
  92. private static $_dateFormat = 'Y-m-d G:i:s';
  93. /**
  94. * Octal notation for default permissions of the log file
  95. * @var integer
  96. */
  97. private static $_defaultPermissions = 0777;
  98. /**
  99. * Array of Log instances, part of Singleton pattern
  100. * @var array
  101. */
  102. private static $instances = array();
  103. /**
  104. * Partially implements the Singleton pattern. Each $logDirectory gets one
  105. * instance.
  106. *
  107. * @param string $logDirectory File path to the logging directory
  108. * @param integer $severity One of the pre-defined severity constants
  109. * @return Log
  110. */
  111. public static function instance($logDirectory = false, $severity = false)
  112. {
  113. if ($severity === false) {
  114. $severity = self::$_defaultSeverity;
  115. }
  116. if ($logDirectory === false) {
  117. if (count(self::$instances) > 0) {
  118. return current(self::$instances);
  119. } else {
  120. $logDirectory = dirname(__FILE__);
  121. }
  122. }
  123. if (in_array($logDirectory, self::$instances)) {
  124. return self::$instances[$logDirectory];
  125. }
  126. self::$instances[$logDirectory] = new self($logDirectory, $severity);
  127. return self::$instances[$logDirectory];
  128. }
  129. /**
  130. * Class constructor
  131. *
  132. * @param string $logDirectory File path to the logging directory
  133. * @param integer $severity One of the pre-defined severity constants
  134. * @return void
  135. */
  136. public function __construct($logDirectory, $severity)
  137. {
  138. $logDirectory = rtrim($logDirectory, '\\/');
  139. if ($severity === self::OFF) {
  140. return;
  141. }
  142. $this->_logFilePath = $logDirectory
  143. . DIRECTORY_SEPARATOR
  144. . 'log_'
  145. . date('Y-m-d')
  146. . '.txt';
  147. $this->_severityThreshold = $severity;
  148. if (!file_exists($logDirectory)) {
  149. $results = mkdir($logDirectory, self::$_defaultPermissions, true);
  150. # Show problem when in development
  151. if(!$results && !IN_PRODUCTION) {
  152. die("Failed to make a directory for logs; please create a writable directory at: ".LOG_PATH);
  153. }
  154. # Email problem when in production
  155. elseif(!$results && IN_PRODUCTION) {
  156. # Email app owner
  157. $subject = "Log Directory Error:".LOG_PATH;
  158. $body = "Failed to make a directory for logs; please create a writable directory at: ".LOG_PATH;
  159. Utils::alert_admin($subject, $body);
  160. die();
  161. }
  162. }
  163. if (file_exists($this->_logFilePath) && !is_writable($this->_logFilePath)) {
  164. $this->_logStatus = self::STATUS_OPEN_FAILED;
  165. $this->_messageQueue[] = $this->_messages['writefail'];
  166. return;
  167. }
  168. if (($this->_fileHandle = fopen($this->_logFilePath, 'a'))) {
  169. $this->_logStatus = self::STATUS_LOG_OPEN;
  170. $this->_messageQueue[] = $this->_messages['opensuccess'];
  171. } else {
  172. # Show problem when in development
  173. if(!IN_PRODUCTION) {
  174. die("Logging failed; please make the following directory writable: ".LOG_PATH);
  175. }
  176. # Email problem when in production
  177. else {
  178. # Email app owner
  179. $subject = "Log Permissions Error:".LOG_PATH;
  180. $body = "Logging failed; please make the following directory writable: ".LOG_PATH;
  181. Utils::alert_admin($subject, $body);
  182. die();
  183. }
  184. $this->_logStatus = self::STATUS_OPEN_FAILED;
  185. $this->_messageQueue[] = $this->_messages['openfail'];
  186. }
  187. }
  188. /**
  189. * Class destructor
  190. */
  191. public function __destruct()
  192. {
  193. if ($this->_fileHandle) {
  194. fclose($this->_fileHandle);
  195. }
  196. }
  197. /**
  198. * Writes a $line to the log with a severity level of DEBUG
  199. *
  200. * @param string $line Information to log
  201. * @return void
  202. */
  203. public function logDebug($line)
  204. {
  205. return $this->log($line, self::DEBUG);
  206. }
  207. /**
  208. * Returns (and removes) the last message from the queue.
  209. * @return string
  210. */
  211. public function getMessage()
  212. {
  213. return array_pop($this->_messageQueue);
  214. }
  215. /**
  216. * Returns the entire message queue (leaving it intact)
  217. * @return array
  218. */
  219. public function getMessages()
  220. {
  221. return $this->_messageQueue;
  222. }
  223. /**
  224. * Empties the message queue
  225. * @return void
  226. */
  227. public function clearMessages()
  228. {
  229. $this->_messageQueue = array();
  230. }
  231. /**
  232. * Sets the date format used by all instances of Log
  233. *
  234. * @param string $dateFormat Valid format string for date()
  235. */
  236. public static function setDateFormat($dateFormat)
  237. {
  238. self::$_dateFormat = $dateFormat;
  239. }
  240. /**
  241. * Writes a $line to the log with a severity level of INFO. Any information
  242. * can be used here, or it could be used with E_STRICT errors
  243. *
  244. * @param string $line Information to log
  245. * @return void
  246. */
  247. public function logInfo($line)
  248. {
  249. return $this->log($line, self::INFO);
  250. }
  251. /**
  252. * Writes a $line to the log with a severity level of NOTICE. Generally
  253. * corresponds to E_STRICT, E_NOTICE, or E_USER_NOTICE errors
  254. *
  255. * @param string $line Information to log
  256. * @return void
  257. */
  258. public function logNotice($line)
  259. {
  260. return $this->log($line, self::NOTICE);
  261. }
  262. /**
  263. * Writes a $line to the log with a severity level of WARN. Generally
  264. * corresponds to E_WARNING, E_USER_WARNING, E_CORE_WARNING, or
  265. * E_COMPILE_WARNING
  266. *
  267. * @param string $line Information to log
  268. * @return void
  269. */
  270. public function logWarn($line)
  271. {
  272. return $this->log($line, self::WARN);
  273. }
  274. /**
  275. * Writes a $line to the log with a severity level of ERR. Most likely used
  276. * with E_RECOVERABLE_ERROR
  277. *
  278. * @param string $line Information to log
  279. * @return void
  280. */
  281. public function logError($line)
  282. {
  283. return $this->log($line, self::ERR);
  284. }
  285. /**
  286. * Writes a $line to the log with a severity level of FATAL. Generally
  287. * corresponds to E_ERROR, E_USER_ERROR, E_CORE_ERROR, or E_COMPILE_ERROR
  288. *
  289. * @param string $line Information to log
  290. * @return void
  291. * @deprecated Use logCrit
  292. */
  293. public function logFatal($line)
  294. {
  295. return $this->log($line, self::FATAL);
  296. }
  297. /**
  298. * Writes a $line to the log with a severity level of ALERT.
  299. *
  300. * @param string $line Information to log
  301. * @return void
  302. */
  303. public function logAlert($line)
  304. {
  305. return $this->log($line, self::ALERT);
  306. }
  307. /**
  308. * Writes a $line to the log with a severity level of CRIT.
  309. *
  310. * @param string $line Information to log
  311. * @return void
  312. */
  313. public function logCrit($line)
  314. {
  315. return $this->log($line, self::CRIT);
  316. }
  317. /**
  318. * Writes a $line to the log with a severity level of EMERG.
  319. *
  320. * @param string $line Information to log
  321. * @return void
  322. */
  323. public function logEmerg($line)
  324. {
  325. return $this->log($line, self::EMERG);
  326. }
  327. /**
  328. * Writes a $line to the log with the given severity
  329. *
  330. * @param string $line Text to add to the log
  331. * @param integer $severity Severity level of log message (use constants)
  332. */
  333. public function log($line, $severity)
  334. {
  335. if(is_array($line)) {
  336. $line = var_export($line, true);
  337. }
  338. if ($this->_severityThreshold >= $severity) {
  339. $status = $this->_getTimeLine($severity);
  340. $this->writeFreeFormLine("$status $line \n");
  341. }
  342. # For when we want to echo the results
  343. return "$status $line <br>";
  344. }
  345. /**
  346. * Writes a line to the log without prepending a status or timestamp
  347. *
  348. * @param string $line Line to write to the log
  349. * @return void
  350. */
  351. public function writeFreeFormLine($line)
  352. {
  353. if ($this->_logStatus == self::STATUS_LOG_OPEN && $this->_severityThreshold != self::OFF) {
  354. if (fwrite($this->_fileHandle, $line) === false) {
  355. $this->_messageQueue[] = $this->_messages['writefail'];
  356. }
  357. }
  358. }
  359. private function _getTimeLine($level)
  360. {
  361. $time = date(self::$_dateFormat);
  362. switch ($level) {
  363. case self::EMERG:
  364. return "$time - EMERG -->";
  365. case self::ALERT:
  366. return "$time - ALERT -->";
  367. case self::CRIT:
  368. return "$time - CRIT -->";
  369. case self::FATAL: # FATAL is an alias of CRIT
  370. return "$time - FATAL -->";
  371. case self::NOTICE:
  372. return "$time - NOTICE -->";
  373. case self::INFO:
  374. return "$time - INFO -->";
  375. case self::WARN:
  376. return "$time - WARN -->";
  377. case self::DEBUG:
  378. return "$time - DEBUG -->";
  379. case self::ERR:
  380. return "$time - ERROR -->";
  381. default:
  382. return "$time - LOG -->";
  383. }
  384. }
  385. }