4 * This file is part of the Monolog package.
6 * (c) Jordi Boggiano <j.boggiano@seld.be>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Monolog\Handler;
14 use Monolog\Formatter\WildfireFormatter;
17 * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
19 * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
21 class FirePHPHandler extends AbstractProcessingHandler
24 * WildFire JSON header message format
26 const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2';
29 * FirePHP structure for parsing messages & their presentation
31 const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1';
34 * Must reference a "known" plugin, otherwise headers won't display in FirePHP
36 const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3';
39 * Header prefix for Wildfire to recognize & parse headers
41 const HEADER_PREFIX = 'X-Wf';
44 * Whether or not Wildfire vendor-specific headers have been generated & sent yet
46 protected static $initialized = false;
49 * Shared static message index between potentially multiple handlers
52 protected static $messageIndex = 1;
54 protected static $sendHeaders = true;
57 * Base header creation function used by init headers & record headers
59 * @param array $meta Wildfire Plugin, Protocol & Structure Indexes
60 * @param string $message Log message
61 * @return array Complete header string ready for the client as key and message as value
63 protected function createHeader(array $meta, $message)
65 $header = sprintf('%s-%s', self::HEADER_PREFIX, join('-', $meta));
67 return array($header => $message);
71 * Creates message header from record
74 * @param array $record
77 protected function createRecordHeader(array $record)
79 // Wildfire is extensible to support multiple protocols & plugins in a single request,
80 // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
81 return $this->createHeader(
82 array(1, 1, 1, self::$messageIndex++),
90 protected function getDefaultFormatter()
92 return new WildfireFormatter();
96 * Wildfire initialization headers to enable message parsing
102 protected function getInitHeaders()
104 // Initial payload consists of required headers for Wildfire
106 $this->createHeader(array('Protocol', 1), self::PROTOCOL_URI),
107 $this->createHeader(array(1, 'Structure', 1), self::STRUCTURE_URI),
108 $this->createHeader(array(1, 'Plugin', 1), self::PLUGIN_URI)
113 * Send header string to the client
115 * @param string $header
116 * @param string $content
118 protected function sendHeader($header, $content)
120 if (!headers_sent() && self::$sendHeaders) {
121 header(sprintf('%s: %s', $header, $content));
126 * Creates & sends header for a record, ensuring init headers have been sent prior
129 * @see sendInitHeaders()
130 * @param array $record
132 protected function write(array $record)
134 if (!self::$sendHeaders) {
138 // WildFire-specific headers must be sent prior to any messages
139 if (!self::$initialized) {
140 self::$initialized = true;
142 self::$sendHeaders = $this->headersAccepted();
143 if (!self::$sendHeaders) {
147 foreach ($this->getInitHeaders() as $header => $content) {
148 $this->sendHeader($header, $content);
152 $header = $this->createRecordHeader($record);
153 if (trim(current($header)) !== '') {
154 $this->sendHeader(key($header), current($header));
159 * Verifies if the headers are accepted by the current user agent
163 protected function headersAccepted()
165 if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) {
169 return isset($_SERVER['HTTP_X_FIREPHP_VERSION']);
173 * BC getter for the sendHeaders property that has been made static
175 public function __get($property)
177 if ('sendHeaders' !== $property) {
178 throw new \InvalidArgumentException('Undefined property '.$property);
181 return static::$sendHeaders;
185 * BC setter for the sendHeaders property that has been made static
187 public function __set($property, $value)
189 if ('sendHeaders' !== $property) {
190 throw new \InvalidArgumentException('Undefined property '.$property);
193 static::$sendHeaders = $value;