BP_Log

Provides easy and abstracted logging facilities.

Defined (1)

The class is defined in the following location(s).

/bp-forums/bbpress/bb-includes/backpress/class.bp-log.php  
  1. class BP_Log 
  2. /** 
  3. * The logging level 
  4. * @var integer 
  5. */ 
  6. var $level = BP_LOG_NONE; 
  7.  
  8. /** 
  9. * The type of logging 
  10. * @var string 
  11. */ 
  12. var $type = 'php'; 
  13.  
  14. /** 
  15. * The types of logging available 
  16. * @var array 
  17. */ 
  18. var $types = array('php', 'file', 'display', 'console'); 
  19.  
  20. /** 
  21. * The filename of the file to log messages to when type is "file" 
  22. * @var string 
  23. */ 
  24. var $filename = ''; 
  25.  
  26. /** 
  27. * Whether or not the javascript functions are available 
  28. * @var boolean 
  29. **/ 
  30. var $console_javascript_loaded = false; 
  31.  
  32. /** 
  33. * Console log messages which are queued up to be displayed on page load 
  34. * @var array 
  35. **/ 
  36. var $console_javascript_onloads = array(); 
  37.  
  38. /** 
  39. * Initialises the logging 
  40. * @return void 
  41. */ 
  42. function BP_log($level = false, $type = false, $filename = false) 
  43. $this->set_level($level); 
  44. $this->set_type($type); 
  45. $this->set_filename($filename); 
  46.  
  47. /** 
  48. * Sets the logging level 
  49. * @return integer|boolean The old level on success or false 
  50. * @uses BP_LOG_LEVEL 
  51. */ 
  52. function set_level($level) 
  53. $old_level = $this->level; 
  54.  
  55. if (is_integer($level)) { 
  56. $this->level = $level; 
  57. } elseif (defined('BP_LOG_LEVEL') && is_integer(BP_LOG_LEVEL)) { 
  58. $this->level = BP_LOG_LEVEL; 
  59. } else { 
  60. return false; 
  61.  
  62. return $old_level; 
  63.  
  64. /** 
  65. * Sets the logging type 
  66. * @return string|false The old type on success or false 
  67. * @uses BP_LOG_TYPE 
  68. */ 
  69. function set_type($type) 
  70. $old_type = $this->type; 
  71. $type = strtolower($type); 
  72.  
  73. if (in_array($type, $this->types)) { 
  74. $this->type = $type; 
  75. } elseif (defined('BP_LOG_TYPE') && in_array(BP_LOG_TYPE, $this->types)) { 
  76. $this->type = BP_LOG_TYPE; 
  77. } else { 
  78. return false; 
  79.  
  80. return $old_type; 
  81.  
  82. /** 
  83. * Sets the logging filename 
  84. * @return string|boolean The old filename on success or false 
  85. * @uses BP_LOG_FILENAME 
  86. */ 
  87. function set_filename($filename) 
  88. $old_filename = $this->filename; 
  89.  
  90. if (is_string($filename)) { 
  91. $_filename = $filename; 
  92. } elseif (defined('BP_LOG_FILENAME') && is_string(BP_LOG_FILENAME)) { 
  93. $_filename = BP_LOG_FILENAME; 
  94. } else { 
  95. return false; 
  96.  
  97. if (isset($_filename) && file_exists($_filename) && is_file($_filename) && is_writable($_filename)) { 
  98. $this->filename = $_filename; 
  99. } else { 
  100. return false; 
  101.  
  102. return $old_filename; 
  103.  
  104. /** 
  105. * Sends a message to the log 
  106. * @return boolean True on success, false on failure 
  107. */ 
  108. function send($message = '', $level = BP_LOG_DEBUG, $type = false, $prefix = false) 
  109. // Make sure the level of this message is set to be logged 
  110. if (($level & $this->level) === 0) { 
  111. return; 
  112.  
  113. // Format the message into an array of lines to be logged 
  114. $lines = $this->format_message($message, $level, $prefix); 
  115.  
  116. // Do some validation on the type 
  117. if ($type && in_array($type, $this->types)) { 
  118. $_type = $type; 
  119. } else { 
  120. $_type = $this->type; 
  121.  
  122. // Get a name for the level 
  123. if ($level) { 
  124. $_level = $this->get_level_from_integer($level); 
  125.  
  126. // Setup strings to prepend to some of the types 
  127. $prepend = $_level . ': '; 
  128. if ($prefix) { 
  129. $prepend .= $prefix . ': '; 
  130. $pad = str_repeat(' ', strlen($prepend) - 2) . '| '; 
  131.  
  132. // Switch over the four types 
  133. switch ($_type) { 
  134. case 'php': 
  135. $php_fail = false; 
  136.  
  137. // Check that the error_log() function is available 
  138. if (function_exists('error_log') && is_callable('error_log')) { 
  139. foreach ($lines as $key => $line) { 
  140. if ($key === 0) { 
  141. $_prepend = $prepend; 
  142. } else { 
  143. $_prepend = $pad; 
  144. if (!error_log($_prepend . $line, 0)) { 
  145. $php_fail = true; 
  146. break; 
  147. } else { 
  148. $php_fail = true; 
  149.  
  150. if ($php_fail) { 
  151. // The PHP error log process failed, path of least resistance is to write to display 
  152. $this->send($message, $level, 'display', $prefix); 
  153. return; 
  154. break; 
  155.  
  156. case 'file': 
  157. $file_fail = false; 
  158.  
  159. // We've already done the prerequisite checks on the file by now so just write to it 
  160. if (!$file_handle = fopen($this->filename, 'a')) { 
  161. $file_fail = true; 
  162. } else { 
  163. // Prepare a string to write 
  164. $_lines = array( 
  165. '[' . date('c') . ']',  
  166. '[client ' . $_SERVER['REMOTE_ADDR'] . ']',  
  167. $prepend,  
  168. join("\n", $lines) 
  169. ); 
  170. if (fwrite($file_handle, join(' ', $_lines) . "\n") === false) { 
  171. $file_fail = true; 
  172. if ($file_handle) { 
  173. fclose($file_handle); 
  174. if ($file_fail) { 
  175. // Writing to file failed, output to display 
  176. $this->send($message, $level, 'display', $prefix); 
  177. return; 
  178. break; 
  179.  
  180. case 'display': 
  181. $_lines = array(); 
  182. foreach ($lines as $key => $line) { 
  183. if ($key === 0) { 
  184. $_lines[] = $prepend . $line; 
  185. } else { 
  186. $_lines[] = $pad . $line; 
  187. echo '<div class="bplog_message bplog_level_' . strtolower($_level) . '"><pre>' . join("\n", $_lines) . '</pre></div>' . "\n"; 
  188. break; 
  189.  
  190. case 'console': 
  191. $_lines = array(); 
  192. foreach ($lines as $key => $line) { 
  193. if ($key === 0 && $prefix) { 
  194. $_lines[] = $prefix . ': ' . $line; 
  195. } else { 
  196. $_lines[] = $line; 
  197.  
  198. $_lines = $ident . $_level . ' ~\n' . str_replace('\'', '\\\'', join('\n', $_lines)); 
  199.  
  200. if (!$this->console_javascript_loaded) { 
  201. // Queue it for logging onload 
  202. $this->console_javascript_onloads[] = array('message' => $_lines, 'level' => $level, 'time' => date('c')); 
  203. } else { 
  204. // Log it now 
  205. echo '<script type="text/javascript" charset="utf-8">bp_log_add(\'' . $this->_esc_js_log( $_lines ) . '\', ' . $this->_esc_js_log( $level ) . ', \'' . $this->_esc_js_log( date('c') ) . '\');</script>' . "\n"; 
  206. break; 
  207.  
  208. return true; 
  209.  
  210. /** 
  211. * Gets the name of the log level from an integer 
  212. * @return string The logging level 
  213. */ 
  214. function get_level_from_integer($integer) 
  215. switch ($integer) { 
  216. case BP_LOG_NONE: 
  217. return 'BP_LOG_NONE'; 
  218. break; 
  219. case BP_LOG_FAIL: 
  220. return 'BP_LOG_FAIL'; 
  221. break; 
  222. case BP_LOG_ERROR: 
  223. return 'BP_LOG_ERROR'; 
  224. break; 
  225. case BP_LOG_WARNING: 
  226. return 'BP_LOG_WARNING'; 
  227. break; 
  228. case BP_LOG_NOTICE: 
  229. return 'BP_LOG_NOTICE'; 
  230. break; 
  231. case BP_LOG_DEBUG: 
  232. return 'BP_LOG_DEBUG'; 
  233. break; 
  234. default: 
  235. return 'BP_LOG_UNDEFINED'; 
  236. break; 
  237.  
  238. /** 
  239. * Formats a message for output to a log file 
  240. * @return boolean True on success, false on failure 
  241. */ 
  242. function format_message($message, $level = BP_LOG_DEBUG, $prefix = false, $tabs = 0) 
  243. $lines = array(); 
  244.  
  245. if (is_null($message)) { 
  246. $lines[] = 'null (' . var_export($message, true) . ')'; 
  247. return $lines; 
  248.  
  249. if (is_bool($message)) { 
  250. $lines[] = 'bool (' . var_export($message, true) . ')'; 
  251. return $lines; 
  252.  
  253. if (is_string($message)) { 
  254. if ($level === BP_LOG_DEBUG || $message === '') { 
  255. $lines[] = 'string(' . strlen($message) . ') ("' . $message . '")'; 
  256. } else { 
  257. $lines[] = $message; 
  258. return $lines; 
  259.  
  260. if (is_array($message) || is_object($message)) { 
  261. if (is_array($message)) { 
  262. $lines[] = 'array(' . count($message) . ') ('; 
  263. } else { 
  264. $lines[] = 'object(' . get_class($message) . ') ('; 
  265. $tabs++; 
  266. foreach ($message as $key => $value) { 
  267. $array = $this->format_message($value, $level, false, $tabs); 
  268. if (is_array($array)) { 
  269. $array[0] = str_repeat(' ', $tabs) . $key . ' => ' . $array[0]; 
  270. $lines = array_merge($lines, $array); 
  271. } else { 
  272. $lines[] = str_repeat(' ', $tabs) . $key . ' => ' . $array; 
  273. $tabs--; 
  274. $lines[] = str_repeat(' ', $tabs) . ')'; 
  275. return $lines; 
  276.  
  277. if (is_int($message)) { 
  278. $lines[] = 'int (' . $message . ')'; 
  279. return $lines; 
  280.  
  281. if (is_float($message)) { 
  282. $lines[] = 'float (' . $message . ')'; 
  283. return $lines; 
  284.  
  285. if (is_resource($message)) { 
  286. $lines[] = 'resource (' . get_resource_type($message) . ')'; 
  287. return $lines; 
  288.  
  289. $lines[] = 'unknown (' . $message . ')'; 
  290. return $lines; 
  291.  
  292. /** 
  293. * Send a debug message 
  294. * @return boolean True on success, false on failure 
  295. */ 
  296. function debug($message, $prefix = false) 
  297. $this->send($message, BP_LOG_DEBUG, false, $prefix); 
  298.  
  299. /** 
  300. * Send a notice message 
  301. * If the message is an array, then it sends each index as a separate message 
  302. * @return boolean True on success, false on failure 
  303. */ 
  304. function notice($message) 
  305. if (is_array($message)) { 
  306. foreach ($message as $value) { 
  307. $this->send($value, BP_LOG_NOTICE); 
  308. } else { 
  309. $this->send($message, BP_LOG_NOTICE); 
  310.  
  311. /** 
  312. * Send a warning message 
  313. * If the message is an array, then it sends each index as a separate message 
  314. * @return boolean True on success, false on failure 
  315. */ 
  316. function warning($message) 
  317. if (is_array($message)) { 
  318. foreach ($message as $value) { 
  319. $this->send($value, BP_LOG_WARNING); 
  320. } else { 
  321. $this->send($message, BP_LOG_WARNING); 
  322.  
  323. /** 
  324. * Send an error message 
  325. * If the message is an array, then it sends each index as a separate message 
  326. * @return boolean True on success, false on failure 
  327. */ 
  328. function error($message) 
  329. if (is_array($message)) { 
  330. foreach ($message as $value) { 
  331. $this->send($value, BP_LOG_ERROR); 
  332. } else { 
  333. $this->send($message, BP_LOG_ERROR); 
  334.  
  335. /** 
  336. * Send an error message and die 
  337. * If the message is an array, then it sends each index as a separate message 
  338. * @return boolean True on success, false on failure 
  339. */ 
  340. function fail($message) 
  341. if (is_array($message)) { 
  342. foreach ($message as $value) { 
  343. $this->send($value, BP_LOG_FAIL); 
  344. } else { 
  345. $this->send($message, BP_LOG_FAIL); 
  346.  
  347. die(); 
  348.  
  349. /** 
  350. * Outputs javascript functions for the head of the html document 
  351. * Must be included in the head of the debug document somehow when using 'console' type. 
  352. * @return void 
  353. **/ 
  354. function console_javascript() 
  355. if ($this->type !== 'console') { 
  356. return; 
  357.  
  358. $this->console_javascript_loaded = true; 
  359. ?> 
  360.  
  361. <script type="text/javascript" charset="utf-8"> 
  362. var BP_LOG_NONE = 0; 
  363. var BP_LOG_FAIL = 1; 
  364. var BP_LOG_ERROR = 2; 
  365. var BP_LOG_WARNING = 4; 
  366. var BP_LOG_NOTICE = 8; 
  367. var BP_LOG_DEBUG = 16; 
  368.  
  369. function bp_log_send(message, level, time) { 
  370. if (window.console) { 
  371. // Works in later Safari and Firefox with Firebug 
  372. switch (level) { 
  373. case BP_LOG_NONE: 
  374. // This shouldn't happen really 
  375. break; 
  376. case BP_LOG_FAIL: 
  377. case BP_LOG_ERROR: 
  378. window.console.error("[" + time + "] " + message); 
  379. break; 
  380. case BP_LOG_WARNING: 
  381. window.console.warn("[" + time + "] " + message); 
  382. break; 
  383. case BP_LOG_NOTICE: 
  384. window.console.info("[" + time + "] " + message); 
  385. break; 
  386. case BP_LOG_DEBUG: 
  387. window.console.log("[" + time + "] " + message); 
  388. break; 
  389. default: 
  390. break; 
  391.  
  392. var bp_log_queue = new Array(); 
  393.  
  394. function bp_log_add(message, level, time) { 
  395. bp_log_queue.push(new Array(message, level, time)); 
  396.  
  397. function bp_log_process() { 
  398. while (item = bp_log_queue.shift()) { 
  399. bp_log_send(item[0], item[1], item[2]); 
  400.  
  401. function bp_log_onload() { 
  402. <?php 
  403. foreach ($this->console_javascript_onloads as $onload) { 
  404. echo "\t\t\t" . 'bp_log_send(\'' . $this->_esc_js_log( $onload['message'] ) . '\', ' . $this->_esc_js_log( $onload['level'] ) . ', \'' . $this->_esc_js_log( $onload['time'] ) . '\');' . "\n"; 
  405. ?> 
  406. bp_log_process(); 
  407.  
  408. window.onload = bp_log_onload; 
  409. </script> 
  410.  
  411. <?php 
  412.  
  413. function _esc_js_log( $message ) 
  414. return str_replace( 
  415. array( '\'', "\n" ),  
  416. array( '\\\'', '\n' ),  
  417. $message 
  418. ); 
  419.  
  420. } // END class BP_Log