scratch – Blame information for rev 115

Subversion Repositories:
Rev:
Rev Author Line No. Line
115 office 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\Formatter\ElasticaFormatter;
15 use Monolog\Formatter\NormalizerFormatter;
16 use Monolog\TestCase;
17 use Monolog\Logger;
18 use Elastica\Client;
19 use Elastica\Request;
20 use Elastica\Response;
21  
22 class ElasticSearchHandlerTest extends TestCase
23 {
24 /**
25 * @var Client mock
26 */
27 protected $client;
28  
29 /**
30 * @var array Default handler options
31 */
32 protected $options = array(
33 'index' => 'my_index',
34 'type' => 'doc_type',
35 );
36  
37 public function setUp()
38 {
39 // Elastica lib required
40 if (!class_exists("Elastica\Client")) {
41 $this->markTestSkipped("ruflin/elastica not installed");
42 }
43  
44 // base mock Elastica Client object
45 $this->client = $this->getMockBuilder('Elastica\Client')
46 ->setMethods(array('addDocuments'))
47 ->disableOriginalConstructor()
48 ->getMock();
49 }
50  
51 /**
52 * @covers Monolog\Handler\ElasticSearchHandler::write
53 * @covers Monolog\Handler\ElasticSearchHandler::handleBatch
54 * @covers Monolog\Handler\ElasticSearchHandler::bulkSend
55 * @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter
56 */
57 public function testHandle()
58 {
59 // log message
60 $msg = array(
61 'level' => Logger::ERROR,
62 'level_name' => 'ERROR',
63 'channel' => 'meh',
64 'context' => array('foo' => 7, 'bar', 'class' => new \stdClass),
65 'datetime' => new \DateTime("@0"),
66 'extra' => array(),
67 'message' => 'log',
68 );
69  
70 // format expected result
71 $formatter = new ElasticaFormatter($this->options['index'], $this->options['type']);
72 $expected = array($formatter->format($msg));
73  
74 // setup ES client mock
75 $this->client->expects($this->any())
76 ->method('addDocuments')
77 ->with($expected);
78  
79 // perform tests
80 $handler = new ElasticSearchHandler($this->client, $this->options);
81 $handler->handle($msg);
82 $handler->handleBatch(array($msg));
83 }
84  
85 /**
86 * @covers Monolog\Handler\ElasticSearchHandler::setFormatter
87 */
88 public function testSetFormatter()
89 {
90 $handler = new ElasticSearchHandler($this->client);
91 $formatter = new ElasticaFormatter('index_new', 'type_new');
92 $handler->setFormatter($formatter);
93 $this->assertInstanceOf('Monolog\Formatter\ElasticaFormatter', $handler->getFormatter());
94 $this->assertEquals('index_new', $handler->getFormatter()->getIndex());
95 $this->assertEquals('type_new', $handler->getFormatter()->getType());
96 }
97  
98 /**
99 * @covers Monolog\Handler\ElasticSearchHandler::setFormatter
100 * @expectedException InvalidArgumentException
101 * @expectedExceptionMessage ElasticSearchHandler is only compatible with ElasticaFormatter
102 */
103 public function testSetFormatterInvalid()
104 {
105 $handler = new ElasticSearchHandler($this->client);
106 $formatter = new NormalizerFormatter();
107 $handler->setFormatter($formatter);
108 }
109  
110 /**
111 * @covers Monolog\Handler\ElasticSearchHandler::__construct
112 * @covers Monolog\Handler\ElasticSearchHandler::getOptions
113 */
114 public function testOptions()
115 {
116 $expected = array(
117 'index' => $this->options['index'],
118 'type' => $this->options['type'],
119 'ignore_error' => false,
120 );
121 $handler = new ElasticSearchHandler($this->client, $this->options);
122 $this->assertEquals($expected, $handler->getOptions());
123 }
124  
125 /**
126 * @covers Monolog\Handler\ElasticSearchHandler::bulkSend
127 * @dataProvider providerTestConnectionErrors
128 */
129 public function testConnectionErrors($ignore, $expectedError)
130 {
131 $clientOpts = array('host' => '127.0.0.1', 'port' => 1);
132 $client = new Client($clientOpts);
133 $handlerOpts = array('ignore_error' => $ignore);
134 $handler = new ElasticSearchHandler($client, $handlerOpts);
135  
136 if ($expectedError) {
137 $this->setExpectedException($expectedError[0], $expectedError[1]);
138 $handler->handle($this->getRecord());
139 } else {
140 $this->assertFalse($handler->handle($this->getRecord()));
141 }
142 }
143  
144 /**
145 * @return array
146 */
147 public function providerTestConnectionErrors()
148 {
149 return array(
150 array(false, array('RuntimeException', 'Error sending messages to Elasticsearch')),
151 array(true, false),
152 );
153 }
154  
155 /**
156 * Integration test using localhost Elastic Search server
157 *
158 * @covers Monolog\Handler\ElasticSearchHandler::__construct
159 * @covers Monolog\Handler\ElasticSearchHandler::handleBatch
160 * @covers Monolog\Handler\ElasticSearchHandler::bulkSend
161 * @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter
162 */
163 public function testHandleIntegration()
164 {
165 $msg = array(
166 'level' => Logger::ERROR,
167 'level_name' => 'ERROR',
168 'channel' => 'meh',
169 'context' => array('foo' => 7, 'bar', 'class' => new \stdClass),
170 'datetime' => new \DateTime("@0"),
171 'extra' => array(),
172 'message' => 'log',
173 );
174  
175 $expected = $msg;
176 $expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601);
177 $expected['context'] = array(
178 'class' => '[object] (stdClass: {})',
179 'foo' => 7,
180  
181 );
182  
183 $client = new Client();
184 $handler = new ElasticSearchHandler($client, $this->options);
185 try {
186 $handler->handleBatch(array($msg));
187 } catch (\RuntimeException $e) {
188 $this->markTestSkipped("Cannot connect to Elastic Search server on localhost");
189 }
190  
191 // check document id from ES server response
192 $documentId = $this->getCreatedDocId($client->getLastResponse());
193 $this->assertNotEmpty($documentId, 'No elastic document id received');
194  
195 // retrieve document source from ES and validate
196 $document = $this->getDocSourceFromElastic(
197 $client,
198 $this->options['index'],
199 $this->options['type'],
200 $documentId
201 );
202 $this->assertEquals($expected, $document);
203  
204 // remove test index from ES
205 $client->request("/{$this->options['index']}", Request::DELETE);
206 }
207  
208 /**
209 * Return last created document id from ES response
210 * @param Response $response Elastica Response object
211 * @return string|null
212 */
213 protected function getCreatedDocId(Response $response)
214 {
215 $data = $response->getData();
216 if (!empty($data['items'][0]['create']['_id'])) {
217 return $data['items'][0]['create']['_id'];
218 }
219 }
220  
221 /**
222 * Retrieve document by id from Elasticsearch
223 * @param Client $client Elastica client
224 * @param string $index
225 * @param string $type
226 * @param string $documentId
227 * @return array
228 */
229 protected function getDocSourceFromElastic(Client $client, $index, $type, $documentId)
230 {
231 $resp = $client->request("/{$index}/{$type}/{$documentId}", Request::GET);
232 $data = $resp->getData();
233 if (!empty($data['_source'])) {
234 return $data['_source'];
235 }
236  
237 return array();
238 }
239 }