summaryrefslogtreecommitdiff
path: root/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php')
-rw-r--r--vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php300
1 files changed, 300 insertions, 0 deletions
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php
new file mode 100644
index 00000000..29614d31
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php
@@ -0,0 +1,300 @@
+<?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;
+
+/**
+ * Sends notifications through the hipchat api to a hipchat room
+ *
+ * Notes:
+ * API token - HipChat API token
+ * Room - HipChat Room Id or name, where messages are sent
+ * Name - Name used to send the message (from)
+ * notify - Should the message trigger a notification in the clients
+ *
+ * @author Rafael Dohms <rafael@doh.ms>
+ * @see https://www.hipchat.com/docs/api
+ */
+class HipChatHandler extends SocketHandler
+{
+ /**
+ * The maximum allowed length for the name used in the "from" field.
+ */
+ const MAXIMUM_NAME_LENGTH = 15;
+
+ /**
+ * The maximum allowed length for the message.
+ */
+ const MAXIMUM_MESSAGE_LENGTH = 9500;
+
+ /**
+ * @var string
+ */
+ private $token;
+
+ /**
+ * @var array
+ */
+ private $room;
+
+ /**
+ * @var string
+ */
+ private $name;
+
+ /**
+ * @var boolean
+ */
+ private $notify;
+
+ /**
+ * @var string
+ */
+ private $format;
+
+ /**
+ * @param string $token HipChat API Token
+ * @param string $room The room that should be alerted of the message (Id or Name)
+ * @param string $name Name used in the "from" field
+ * @param bool $notify Trigger a notification in clients or not
+ * @param int $level The minimum logging level at which this handler will be triggered
+ * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param Boolean $useSSL Whether to connect via SSL.
+ * @param string $format The format of the messages (default to text, can be set to html if you have html in the messages)
+ * @param string $host The HipChat server hostname.
+ */
+ public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $format = 'text', $host = 'api.hipchat.com')
+ {
+ if (!$this->validateStringLength($name, static::MAXIMUM_NAME_LENGTH)) {
+ throw new \InvalidArgumentException('The supplied name is too long. HipChat\'s v1 API supports names up to 15 UTF-8 characters.');
+ }
+
+ $connectionString = $useSSL ? 'ssl://'.$host.':443' : $host.':80';
+ parent::__construct($connectionString, $level, $bubble);
+
+ $this->token = $token;
+ $this->name = $name;
+ $this->notify = $notify;
+ $this->room = $room;
+ $this->format = $format;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param array $record
+ * @return string
+ */
+ protected function generateDataStream($record)
+ {
+ $content = $this->buildContent($record);
+
+ return $this->buildHeader($content) . $content;
+ }
+
+ /**
+ * Builds the body of API call
+ *
+ * @param array $record
+ * @return string
+ */
+ private function buildContent($record)
+ {
+ $dataArray = array(
+ 'from' => $this->name,
+ 'room_id' => $this->room,
+ 'notify' => $this->notify,
+ 'message' => $record['formatted'],
+ 'message_format' => $this->format,
+ 'color' => $this->getAlertColor($record['level']),
+ );
+
+ return http_build_query($dataArray);
+ }
+
+ /**
+ * Builds the header of the API Call
+ *
+ * @param string $content
+ * @return string
+ */
+ private function buildHeader($content)
+ {
+ $header = "POST /v1/rooms/message?format=json&auth_token=".$this->token." HTTP/1.1\r\n";
+ $header .= "Host: api.hipchat.com\r\n";
+ $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
+ $header .= "Content-Length: " . strlen($content) . "\r\n";
+ $header .= "\r\n";
+
+ return $header;
+ }
+
+ /**
+ * Assigns a color to each level of log records.
+ *
+ * @param integer $level
+ * @return string
+ */
+ protected function getAlertColor($level)
+ {
+ switch (true) {
+ case $level >= Logger::ERROR:
+ return 'red';
+ case $level >= Logger::WARNING:
+ return 'yellow';
+ case $level >= Logger::INFO:
+ return 'green';
+ case $level == Logger::DEBUG:
+ return 'gray';
+ default:
+ return 'yellow';
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param array $record
+ */
+ protected function write(array $record)
+ {
+ parent::write($record);
+ $this->closeSocket();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function handleBatch(array $records)
+ {
+ if (count($records) == 0) {
+ return true;
+ }
+
+ $batchRecords = $this->combineRecords($records);
+
+ $handled = false;
+ foreach ($batchRecords as $batchRecord) {
+ if ($this->isHandling($batchRecord)) {
+ $this->write($batchRecord);
+ $handled = true;
+ }
+ }
+
+ if (!$handled) {
+ return false;
+ }
+
+ return false === $this->bubble;
+ }
+
+ /**
+ * Combines multiple records into one. Error level of the combined record
+ * will be the highest level from the given records. Datetime will be taken
+ * from the first record.
+ *
+ * @param $records
+ * @return array
+ */
+ private function combineRecords($records)
+ {
+ $batchRecord = null;
+ $batchRecords = array();
+ $messages = array();
+ $formattedMessages = array();
+ $level = 0;
+ $levelName = null;
+ $datetime = null;
+
+ foreach ($records as $record) {
+ $record = $this->processRecord($record);
+
+ if ($record['level'] > $level) {
+ $level = $record['level'];
+ $levelName = $record['level_name'];
+ }
+
+ if (null === $datetime) {
+ $datetime = $record['datetime'];
+ }
+
+ $messages[] = $record['message'];
+ $messgeStr = implode(PHP_EOL, $messages);
+ $formattedMessages[] = $this->getFormatter()->format($record);
+ $formattedMessageStr = implode('', $formattedMessages);
+
+ $batchRecord = array(
+ 'message' => $messgeStr,
+ 'formatted' => $formattedMessageStr,
+ 'context' => array(),
+ 'extra' => array(),
+ );
+
+ if (!$this->validateStringLength($batchRecord['formatted'], static::MAXIMUM_MESSAGE_LENGTH)) {
+ // Pop the last message and implode the remainging messages
+ $lastMessage = array_pop($messages);
+ $lastFormattedMessage = array_pop($formattedMessages);
+ $batchRecord['message'] = implode(PHP_EOL, $messages);
+ $batchRecord['formatted'] = implode('', $formattedMessages);
+
+ $batchRecords[] = $batchRecord;
+ $messages = array($lastMessage);
+ $formattedMessages = array($lastFormattedMessage);
+
+ $batchRecord = null;
+ }
+ }
+
+ if (null !== $batchRecord) {
+ $batchRecords[] = $batchRecord;
+ }
+
+ // Set the max level and datetime for all records
+ foreach ($batchRecords as &$batchRecord) {
+ $batchRecord = array_merge(
+ $batchRecord,
+ array(
+ 'level' => $level,
+ 'level_name' => $levelName,
+ 'datetime' => $datetime
+ )
+ );
+ }
+
+ return $batchRecords;
+ }
+
+ /**
+ * Validates the length of a string.
+ *
+ * If the `mb_strlen()` function is available, it will use that, as HipChat
+ * allows UTF-8 characters. Otherwise, it will fall back to `strlen()`.
+ *
+ * Note that this might cause false failures in the specific case of using
+ * a valid name with less than 16 characters, but 16 or more bytes, on a
+ * system where `mb_strlen()` is unavailable.
+ *
+ * @param string $str
+ * @param int $length
+ *
+ * @return bool
+ */
+ private function validateStringLength($str, $length)
+ {
+ if (function_exists('mb_strlen')) {
+ return (mb_strlen($str) <= $length);
+ }
+
+ return (strlen($str) <= $length);
+ }
+}