Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
103 - 1
<?php
2
 
3
/*
4
 * This file is part of the Monolog package.
5
 *
6
 * (c) Jordi Boggiano <j.boggiano@seld.be>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Monolog\Handler;
13
 
14
use Monolog\Logger;
15
 
16
/**
17
 * Logs to Cube.
18
 *
19
 * @link http://square.github.com/cube/
20
 * @author Wan Chen <kami@kamisama.me>
21
 */
22
class CubeHandler extends AbstractProcessingHandler
23
{
24
    private $udpConnection;
25
    private $httpConnection;
26
    private $scheme;
27
    private $host;
28
    private $port;
29
    private $acceptedSchemes = array('http', 'udp');
30
 
31
    /**
32
     * Create a Cube handler
33
     *
34
     * @throws \UnexpectedValueException when given url is not a valid url.
35
     *                                   A valid url must consist of three parts : protocol://host:port
36
     *                                   Only valid protocols used by Cube are http and udp
37
     */
38
    public function __construct($url, $level = Logger::DEBUG, $bubble = true)
39
    {
40
        $urlInfo = parse_url($url);
41
 
42
        if (!isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
43
            throw new \UnexpectedValueException('URL "'.$url.'" is not valid');
44
        }
45
 
46
        if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) {
47
            throw new \UnexpectedValueException(
48
                'Invalid protocol (' . $urlInfo['scheme']  . ').'
49
                . ' Valid options are ' . implode(', ', $this->acceptedSchemes));
50
        }
51
 
52
        $this->scheme = $urlInfo['scheme'];
53
        $this->host = $urlInfo['host'];
54
        $this->port = $urlInfo['port'];
55
 
56
        parent::__construct($level, $bubble);
57
    }
58
 
59
    /**
60
     * Establish a connection to an UDP socket
61
     *
62
     * @throws \LogicException           when unable to connect to the socket
63
     * @throws MissingExtensionException when there is no socket extension
64
     */
65
    protected function connectUdp()
66
    {
67
        if (!extension_loaded('sockets')) {
68
            throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler');
69
        }
70
 
71
        $this->udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0);
72
        if (!$this->udpConnection) {
73
            throw new \LogicException('Unable to create a socket');
74
        }
75
 
76
        if (!socket_connect($this->udpConnection, $this->host, $this->port)) {
77
            throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port);
78
        }
79
    }
80
 
81
    /**
82
     * Establish a connection to a http server
83
     * @throws \LogicException when no curl extension
84
     */
85
    protected function connectHttp()
86
    {
87
        if (!extension_loaded('curl')) {
88
            throw new \LogicException('The curl extension is needed to use http URLs with the CubeHandler');
89
        }
90
 
91
        $this->httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put');
92
 
93
        if (!$this->httpConnection) {
94
            throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port);
95
        }
96
 
97
        curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST");
98
        curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true);
99
    }
100
 
101
    /**
102
     * {@inheritdoc}
103
     */
104
    protected function write(array $record)
105
    {
106
        $date = $record['datetime'];
107
 
108
        $data = array('time' => $date->format('Y-m-d\TH:i:s.uO'));
109
        unset($record['datetime']);
110
 
111
        if (isset($record['context']['type'])) {
112
            $data['type'] = $record['context']['type'];
113
            unset($record['context']['type']);
114
        } else {
115
            $data['type'] = $record['channel'];
116
        }
117
 
118
        $data['data'] = $record['context'];
119
        $data['data']['level'] = $record['level'];
120
 
121
        if ($this->scheme === 'http') {
122
            $this->writeHttp(json_encode($data));
123
        } else {
124
            $this->writeUdp(json_encode($data));
125
        }
126
    }
127
 
128
    private function writeUdp($data)
129
    {
130
        if (!$this->udpConnection) {
131
            $this->connectUdp();
132
        }
133
 
134
        socket_send($this->udpConnection, $data, strlen($data), 0);
135
    }
136
 
137
    private function writeHttp($data)
138
    {
139
        if (!$this->httpConnection) {
140
            $this->connectHttp();
141
        }
142
 
143
        curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']');
144
        curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, array(
145
            'Content-Type: application/json',
146
            'Content-Length: ' . strlen('['.$data.']'),
147
        ));
148
 
149
        Curl\Util::execute($this->httpConnection, 5, false);
150
    }
151
}