sfWebDebugLogger.class.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. /*
  3. * This file is part of the symfony package.
  4. * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * sfWebDebugLogger logs messages into the web debug toolbar.
  11. *
  12. * @package symfony
  13. * @subpackage log
  14. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  15. * @version SVN: $Id: sfWebDebugLogger.class.php 16942 2009-04-03 14:48:17Z fabien $
  16. */
  17. class sfWebDebugLogger extends sfLogger
  18. {
  19. protected
  20. $context = null,
  21. $dispatcher = null,
  22. $webDebug = null,
  23. $xdebugLogging = false;
  24. /**
  25. * Initializes this logger.
  26. *
  27. * Available options:
  28. *
  29. * - web_debug_class: The web debug class (sfWebDebug by default).
  30. * - xdebugLogging: Whether to add xdebug trace to the logs (false by default).
  31. *
  32. * @param sfEventDispatcher $dispatcher A sfEventDispatcher instance
  33. * @param array $options An array of options.
  34. *
  35. * @return Boolean true, if initialization completes successfully, otherwise false.
  36. */
  37. public function initialize(sfEventDispatcher $dispatcher, $options = array())
  38. {
  39. $this->context = sfContext::getInstance();
  40. $this->dispatcher = $dispatcher;
  41. $class = isset($options['web_debug_class']) ? $options['web_debug_class'] : 'sfWebDebug';
  42. $this->webDebug = new $class($dispatcher);
  43. $dispatcher->connect('response.filter_content', array($this, 'filterResponseContent'));
  44. if (isset($options['xdebug_logging']))
  45. {
  46. $this->xdebugLogging = $options['xdebug_logging'];
  47. }
  48. // disable xdebug when an HTTP debug session exists (crashes Apache, see #2438)
  49. if (isset($_GET['XDEBUG_SESSION_START']) || isset($_COOKIE['XDEBUG_SESSION']))
  50. {
  51. $this->xdebugLogging = false;
  52. }
  53. return parent::initialize($dispatcher, $options);
  54. }
  55. /**
  56. * Listens to the response.filter_content event.
  57. *
  58. * @param sfEvent $event The sfEvent instance
  59. * @param string $context The response content
  60. *
  61. * @return string The filtered response content
  62. */
  63. public function filterResponseContent(sfEvent $event, $content)
  64. {
  65. if (!sfConfig::get('sf_web_debug'))
  66. {
  67. return $content;
  68. }
  69. // log timers information
  70. $messages = array();
  71. foreach (sfTimerManager::getTimers() as $name => $timer)
  72. {
  73. $messages[] = sprintf('%s %.2f ms (%d)', $name, $timer->getElapsedTime() * 1000, $timer->getCalls());
  74. }
  75. $this->dispatcher->notify(new sfEvent($this, 'application.log', $messages));
  76. // don't add debug toolbar:
  77. // * for XHR requests
  78. // * if 304
  79. // * if not rendering to the client
  80. // * if HTTP headers only
  81. $response = $event->getSubject();
  82. if (!$this->context->has('request') || !$this->context->has('response') || !$this->context->has('controller') ||
  83. $this->context->getRequest()->isXmlHttpRequest() ||
  84. strpos($response->getContentType(), 'html') === false ||
  85. '3' == substr($response->getStatusCode(), 0, 1) ||
  86. $this->context->getController()->getRenderMode() != sfView::RENDER_CLIENT ||
  87. $response->isHeaderOnly()
  88. )
  89. {
  90. return $content;
  91. }
  92. // add needed assets for the web debug toolbar
  93. $root = $this->context->getRequest()->getRelativeUrlRoot();
  94. $assets = sprintf('
  95. <script type="text/javascript" src="%s"></script>
  96. <link rel="stylesheet" type="text/css" media="screen" href="%s" />',
  97. $root.sfConfig::get('sf_web_debug_web_dir').'/js/main.js',
  98. $root.sfConfig::get('sf_web_debug_web_dir').'/css/main.css'
  99. );
  100. $content = str_ireplace('</head>', $assets.'</head>', $content);
  101. // add web debug information to response content
  102. $webDebugContent = $this->webDebug->getResults();
  103. $count = 0;
  104. $content = str_ireplace('</body>', $webDebugContent.'</body>', $content, $count);
  105. if (!$count)
  106. {
  107. $content .= $webDebugContent;
  108. }
  109. return $content;
  110. }
  111. /**
  112. * Logs a message.
  113. *
  114. * @param string $message Message
  115. * @param string $priority Message priority
  116. */
  117. protected function doLog($message, $priority)
  118. {
  119. // if we have xdebug and dev has not disabled the feature, add some stack information
  120. $debugStack = array();
  121. if ($this->xdebugLogging && function_exists('xdebug_get_function_stack'))
  122. {
  123. foreach (xdebug_get_function_stack() as $i => $stack)
  124. {
  125. if (
  126. (isset($stack['function']) && !in_array($stack['function'], array('emerg', 'alert', 'crit', 'err', 'warning', 'notice', 'info', 'debug', 'log')))
  127. || !isset($stack['function'])
  128. )
  129. {
  130. $tmp = '';
  131. if (isset($stack['function']))
  132. {
  133. $tmp .= sprintf('in "%s" ', $stack['function']);
  134. }
  135. $tmp .= sprintf('from "%s" line %s', $stack['file'], $stack['line']);
  136. $debugStack[] = $tmp;
  137. }
  138. }
  139. }
  140. // get log type in {}
  141. $type = 'sfOther';
  142. if (preg_match('/^\s*{([^}]+)}\s*(.+?)$/s', $message, $matches))
  143. {
  144. $type = $matches[1];
  145. $message = $matches[2];
  146. }
  147. // send the log object containing the complete log information
  148. $this->webDebug->log(array(
  149. 'priority' => $priority,
  150. 'time' => time(),
  151. 'message' => $message,
  152. 'type' => $type,
  153. 'debugStack' => $debugStack,
  154. ));
  155. }
  156. }