152 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
| <?php
 | |
| 
 | |
| /*
 | |
|  * This file is part of the Monolog package.
 | |
|  *
 | |
|  * (c) Jordi Boggiano <j.boggiano@seld.be>
 | |
|  *
 | |
|  * For the full copyright and license information, please view the LICENSE
 | |
|  * file that was distributed with this source code.
 | |
|  */
 | |
| 
 | |
| namespace Monolog\Handler;
 | |
| 
 | |
| use Monolog\Logger;
 | |
| 
 | |
| /**
 | |
|  * Logs to Cube.
 | |
|  *
 | |
|  * @link http://square.github.com/cube/
 | |
|  * @author Wan Chen <kami@kamisama.me>
 | |
|  */
 | |
| class CubeHandler extends AbstractProcessingHandler
 | |
| {
 | |
|     private $udpConnection;
 | |
|     private $httpConnection;
 | |
|     private $scheme;
 | |
|     private $host;
 | |
|     private $port;
 | |
|     private $acceptedSchemes = array('http', 'udp');
 | |
| 
 | |
|     /**
 | |
|      * Create a Cube handler
 | |
|      *
 | |
|      * @throws \UnexpectedValueException when given url is not a valid url.
 | |
|      *                                   A valid url must consist of three parts : protocol://host:port
 | |
|      *                                   Only valid protocols used by Cube are http and udp
 | |
|      */
 | |
|     public function __construct($url, $level = Logger::DEBUG, $bubble = true)
 | |
|     {
 | |
|         $urlInfo = parse_url($url);
 | |
| 
 | |
|         if (!isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
 | |
|             throw new \UnexpectedValueException('URL "'.$url.'" is not valid');
 | |
|         }
 | |
| 
 | |
|         if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) {
 | |
|             throw new \UnexpectedValueException(
 | |
|                 'Invalid protocol (' . $urlInfo['scheme']  . ').'
 | |
|                 . ' Valid options are ' . implode(', ', $this->acceptedSchemes));
 | |
|         }
 | |
| 
 | |
|         $this->scheme = $urlInfo['scheme'];
 | |
|         $this->host = $urlInfo['host'];
 | |
|         $this->port = $urlInfo['port'];
 | |
| 
 | |
|         parent::__construct($level, $bubble);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Establish a connection to an UDP socket
 | |
|      *
 | |
|      * @throws \LogicException           when unable to connect to the socket
 | |
|      * @throws MissingExtensionException when there is no socket extension
 | |
|      */
 | |
|     protected function connectUdp()
 | |
|     {
 | |
|         if (!extension_loaded('sockets')) {
 | |
|             throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler');
 | |
|         }
 | |
| 
 | |
|         $this->udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0);
 | |
|         if (!$this->udpConnection) {
 | |
|             throw new \LogicException('Unable to create a socket');
 | |
|         }
 | |
| 
 | |
|         if (!socket_connect($this->udpConnection, $this->host, $this->port)) {
 | |
|             throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Establish a connection to a http server
 | |
|      * @throws \LogicException when no curl extension
 | |
|      */
 | |
|     protected function connectHttp()
 | |
|     {
 | |
|         if (!extension_loaded('curl')) {
 | |
|             throw new \LogicException('The curl extension is needed to use http URLs with the CubeHandler');
 | |
|         }
 | |
| 
 | |
|         $this->httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put');
 | |
| 
 | |
|         if (!$this->httpConnection) {
 | |
|             throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port);
 | |
|         }
 | |
| 
 | |
|         curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST");
 | |
|         curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * {@inheritdoc}
 | |
|      */
 | |
|     protected function write(array $record)
 | |
|     {
 | |
|         $date = $record['datetime'];
 | |
| 
 | |
|         $data = array('time' => $date->format('Y-m-d\TH:i:s.uO'));
 | |
|         unset($record['datetime']);
 | |
| 
 | |
|         if (isset($record['context']['type'])) {
 | |
|             $data['type'] = $record['context']['type'];
 | |
|             unset($record['context']['type']);
 | |
|         } else {
 | |
|             $data['type'] = $record['channel'];
 | |
|         }
 | |
| 
 | |
|         $data['data'] = $record['context'];
 | |
|         $data['data']['level'] = $record['level'];
 | |
| 
 | |
|         if ($this->scheme === 'http') {
 | |
|             $this->writeHttp(json_encode($data));
 | |
|         } else {
 | |
|             $this->writeUdp(json_encode($data));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private function writeUdp($data)
 | |
|     {
 | |
|         if (!$this->udpConnection) {
 | |
|             $this->connectUdp();
 | |
|         }
 | |
| 
 | |
|         socket_send($this->udpConnection, $data, strlen($data), 0);
 | |
|     }
 | |
| 
 | |
|     private function writeHttp($data)
 | |
|     {
 | |
|         if (!$this->httpConnection) {
 | |
|             $this->connectHttp();
 | |
|         }
 | |
| 
 | |
|         curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']');
 | |
|         curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, array(
 | |
|             'Content-Type: application/json',
 | |
|             'Content-Length: ' . strlen('['.$data.']'),
 | |
|         ));
 | |
| 
 | |
|         Curl\Util::execute($this->httpConnection, 5, false);
 | |
|     }
 | |
| }
 |