ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
HipChatHandler.php
Go to the documentation of this file.
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 
30 {
34  const API_V1 = 'v1';
35 
39  const API_V2 = 'v2';
40 
44  const MAXIMUM_NAME_LENGTH = 15;
45 
49  const MAXIMUM_MESSAGE_LENGTH = 9500;
50 
54  private $token;
55 
59  private $room;
60 
64  private $name;
65 
69  private $notify;
70 
74  private $format;
75 
79  private $host;
80 
84  private $version;
85 
98  public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com', $version = self::API_V1)
99  {
100  if ($version == self::API_V1 && !$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) {
101  throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.');
102  }
103 
104  $connectionString = $useSSL ? 'ssl://'.$host.':443' : $host.':80';
105  parent::__construct($connectionString, $level, $bubble);
106 
107  $this->token = $token;
108  $this->name = $name;
109  $this->notify = $notify;
110  $this->room = $room;
111  $this->format = $format;
112  $this->host = $host;
113  $this->version = $version;
114  }
115 
122  protected function generateDataStream($record)
123  {
124  $content = $this->buildContent($record);
125 
126  return $this->buildHeader($content) . $content;
127  }
128 
135  private function buildContent($record)
136  {
137  $dataArray = array(
138  'notify' => $this->version == self::API_V1 ?
139  ($this->notify ? 1 : 0) :
140  ($this->notify ? 'true' : 'false'),
141  'message' => $record['formatted'],
142  'message_format' => $this->format,
143  'color' => $this->getAlertColor($record['level']),
144  );
145 
146  if (!$this->validateStringLength($dataArray['message'], static::MAXIMUM_MESSAGE_LENGTH)) {
147  if (function_exists('mb_substr')) {
148  $dataArray['message'] = mb_substr($dataArray['message'], 0, static::MAXIMUM_MESSAGE_LENGTH).' [truncated]';
149  } else {
150  $dataArray['message'] = substr($dataArray['message'], 0, static::MAXIMUM_MESSAGE_LENGTH).' [truncated]';
151  }
152  }
153 
154  // if we are using the legacy API then we need to send some additional information
155  if ($this->version == self::API_V1) {
156  $dataArray['room_id'] = $this->room;
157  }
158 
159  // append the sender name if it is set
160  // always append it if we use the v1 api (it is required in v1)
161  if ($this->version == self::API_V1 || $this->name !== null) {
162  $dataArray['from'] = (string) $this->name;
163  }
164 
165  return http_build_query($dataArray);
166  }
167 
174  private function buildHeader($content)
175  {
176  if ($this->version == self::API_V1) {
177  $header = "POST /v1/rooms/message?format=json&auth_token={$this->token} HTTP/1.1\r\n";
178  } else {
179  // needed for rooms with special (spaces, etc) characters in the name
180  $room = rawurlencode($this->room);
181  $header = "POST /v2/room/{$room}/notification?auth_token={$this->token} HTTP/1.1\r\n";
182  }
183 
184  $header .= "Host: {$this->host}\r\n";
185  $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
186  $header .= "Content-Length: " . strlen($content) . "\r\n";
187  $header .= "\r\n";
188 
189  return $header;
190  }
191 
198  protected function getAlertColor($level)
199  {
200  switch (true) {
201  case $level >= Logger::ERROR:
202  return 'red';
203  case $level >= Logger::WARNING:
204  return 'yellow';
205  case $level >= Logger::INFO:
206  return 'green';
207  case $level == Logger::DEBUG:
208  return 'gray';
209  default:
210  return 'yellow';
211  }
212  }
213 
219  protected function write(array $record)
220  {
221  parent::write($record);
222  $this->finalizeWrite();
223  }
224 
231  protected function finalizeWrite()
232  {
233  $res = $this->getResource();
234  if (is_resource($res)) {
235  @fread($res, 2048);
236  }
237  $this->closeSocket();
238  }
239 
243  public function handleBatch(array $records)
244  {
245  if (count($records) == 0) {
246  return true;
247  }
248 
249  $batchRecords = $this->combineRecords($records);
250 
251  $handled = false;
252  foreach ($batchRecords as $batchRecord) {
253  if ($this->isHandling($batchRecord)) {
254  $this->write($batchRecord);
255  $handled = true;
256  }
257  }
258 
259  if (!$handled) {
260  return false;
261  }
262 
263  return false === $this->bubble;
264  }
265 
274  private function combineRecords($records)
275  {
276  $batchRecord = null;
277  $batchRecords = array();
278  $messages = array();
279  $formattedMessages = array();
280  $level = 0;
281  $levelName = null;
282  $datetime = null;
283 
284  foreach ($records as $record) {
285  $record = $this->processRecord($record);
286 
287  if ($record['level'] > $level) {
288  $level = $record['level'];
289  $levelName = $record['level_name'];
290  }
291 
292  if (null === $datetime) {
293  $datetime = $record['datetime'];
294  }
295 
296  $messages[] = $record['message'];
297  $messageStr = implode(PHP_EOL, $messages);
298  $formattedMessages[] = $this->getFormatter()->format($record);
299  $formattedMessageStr = implode('', $formattedMessages);
300 
301  $batchRecord = array(
302  'message' => $messageStr,
303  'formatted' => $formattedMessageStr,
304  'context' => array(),
305  'extra' => array(),
306  );
307 
308  if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) {
309  // Pop the last message and implode the remaining messages
310  $lastMessage = array_pop($messages);
311  $lastFormattedMessage = array_pop($formattedMessages);
312  $batchRecord['message'] = implode(PHP_EOL, $messages);
313  $batchRecord['formatted'] = implode('', $formattedMessages);
314 
315  $batchRecords[] = $batchRecord;
316  $messages = array($lastMessage);
317  $formattedMessages = array($lastFormattedMessage);
318 
319  $batchRecord = null;
320  }
321  }
322 
323  if (null !== $batchRecord) {
324  $batchRecords[] = $batchRecord;
325  }
326 
327  // Set the max level and datetime for all records
328  foreach ($batchRecords as &$batchRecord) {
329  $batchRecord = array_merge(
330  $batchRecord,
331  array(
332  'level' => $level,
333  'level_name' => $levelName,
334  'datetime' => $datetime,
335  )
336  );
337  }
338 
339  return $batchRecords;
340  }
341 
357  private function validateStringLength($str, $length)
358  {
359  if (function_exists('mb_strlen')) {
360  return (mb_strlen($str) <= $length);
361  }
362 
363  return (strlen($str) <= $length);
364  }
365 }
const DEBUG
Detailed debug information.
Definition: Logger.php:33
const ERROR
Runtime errors.
Definition: Logger.php:58
Stores to any socket - uses fsockopen() or pfsockopen().
PHP_EOL
Definition: complexTest.php:5
$records
Definition: simple_test.php:22
finalizeWrite()
Finalizes the request by reading some bytes and then closing the socket.
Sends notifications through the hipchat api to a hipchat room.
$messages
Definition: en.php:5
handleBatch(array $records)
{Handles a set of records at once.The records to handle (an array of record arrays)} ...
foreach($_POST as $key=> $value) $res
const API_V2
Use API version v2.
const MAXIMUM_NAME_LENGTH
The maximum allowed length for the name used in the "from" field.
const MAXIMUM_MESSAGE_LENGTH
The maximum allowed length for the message.
getFormatter()
{Gets the formatter.FormatterInterface}
const WARNING
Exceptional occurrences that are not errors.
Definition: Logger.php:53
__construct($token, $room, $name='Monolog', $notify=false, $level=Logger::CRITICAL, $bubble=true, $useSSL=true, $format='text', $host='api.hipchat.com', $version=self::API_V1)
const CRITICAL
Critical conditions.
Definition: Logger.php:65
const API_V1
Use API version 1.
isHandling(array $record)
{Checks whether the given record will be handled by this handler.This is mostly done for performance ...
processRecord(array $record)
Processes a record.
buildHeader($content)
Builds the header of the API Call.
combineRecords($records)
Combines multiple records into one.
getAlertColor($level)
Assigns a color to each level of log records.
closeSocket()
Close socket, if open.
validateStringLength($str, $length)
Validates the length of a string.
buildContent($record)
Builds the body of API call.
const INFO
Interesting events.
Definition: Logger.php:40