mirror of
https://github.com/Seldaek/monolog.git
synced 2025-08-05 12:47:39 +02:00
HipChat Handler
Adds a handler that is capable of sending notices into HipChat, the team communication system provided by Atlassian. This is based on the PushoverHandler and built on top of the socketHandler. The needed configuration is described in the docblock of the HipChatHandler file.
This commit is contained in:
@@ -115,6 +115,7 @@ Handlers
|
|||||||
[`mail()`](http://php.net/manual/en/function.mail.php) function.
|
[`mail()`](http://php.net/manual/en/function.mail.php) function.
|
||||||
- _SwiftMailerHandler_: Sends emails using a [`Swift_Mailer`](http://swiftmailer.org/) instance.
|
- _SwiftMailerHandler_: Sends emails using a [`Swift_Mailer`](http://swiftmailer.org/) instance.
|
||||||
- _PushoverHandler_: Sends mobile notifications via the [Pushover](https://www.pushover.net/) API.
|
- _PushoverHandler_: Sends mobile notifications via the [Pushover](https://www.pushover.net/) API.
|
||||||
|
- _HipChatHandler_: Logs records to a [HipChat](http://hipchat.com) chat room using its API.
|
||||||
|
|
||||||
### Log specific servers and networked logging
|
### Log specific servers and networked logging
|
||||||
|
|
||||||
|
154
src/Monolog/Handler/HipChatHandler.php
Normal file
154
src/Monolog/Handler/HipChatHandler.php
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<?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
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $room;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
private $notify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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. Required when pushing messages to users that are not
|
||||||
|
* the pushover.net app owner. OpenSSL is required for this option.
|
||||||
|
*/
|
||||||
|
public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true)
|
||||||
|
{
|
||||||
|
$connectionString = $useSSL ? 'ssl://api.hipchat.com:443' : 'api.hipchat.com:80';
|
||||||
|
parent::__construct($connectionString, $level, $bubble);
|
||||||
|
|
||||||
|
$this->token = $token;
|
||||||
|
$this->name = $name;
|
||||||
|
$this->notify = $notify;
|
||||||
|
$this->room = $room;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@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' => 'text',
|
||||||
|
'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
|
||||||
|
*/
|
||||||
|
public function write(array $record)
|
||||||
|
{
|
||||||
|
parent::write($record);
|
||||||
|
$this->closeSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
110
tests/Monolog/Handler/HipChatHandlerTest.php
Normal file
110
tests/Monolog/Handler/HipChatHandlerTest.php
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
<?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\TestCase;
|
||||||
|
use Monolog\Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Rafael Dohms <rafael@doh.ms>
|
||||||
|
* @see https://www.hipchat.com/docs/api
|
||||||
|
*/
|
||||||
|
class HipChatHandlerTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
private $res;
|
||||||
|
private $handler;
|
||||||
|
|
||||||
|
public function testWriteHeader()
|
||||||
|
{
|
||||||
|
$this->createHandler();
|
||||||
|
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
|
||||||
|
fseek($this->res, 0);
|
||||||
|
$content = fread($this->res, 1024);
|
||||||
|
|
||||||
|
$this->assertRegexp('/POST \/v1\/rooms\/message\?format=json&auth_token=.* HTTP\/1.1\\r\\nHost: api.hipchat.com\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @depends testWriteHeader
|
||||||
|
*/
|
||||||
|
public function testWriteContent($content)
|
||||||
|
{
|
||||||
|
$this->assertRegexp('/from=Monolog&room_id=room1¬ify=0&message=test1&message_format=text&color=red$/', $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testWriteWithComplexMessage()
|
||||||
|
{
|
||||||
|
$this->createHandler();
|
||||||
|
$this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.'));
|
||||||
|
fseek($this->res, 0);
|
||||||
|
$content = fread($this->res, 1024);
|
||||||
|
|
||||||
|
$this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideLevelColors
|
||||||
|
*/
|
||||||
|
public function testWriteWithErrorLevelsAndColors($level, $expectedColor)
|
||||||
|
{
|
||||||
|
$this->createHandler();
|
||||||
|
$this->handler->handle($this->getRecord($level, 'Backup of database "example" finished in 16 minutes.'));
|
||||||
|
fseek($this->res, 0);
|
||||||
|
$content = fread($this->res, 1024);
|
||||||
|
|
||||||
|
$this->assertRegexp('/color='.$expectedColor.'/', $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideLevelColors()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
array(Logger::DEBUG, 'gray'),
|
||||||
|
array(Logger::INFO, 'green'),
|
||||||
|
array(Logger::WARNING, 'yellow'),
|
||||||
|
array(Logger::ERROR, 'red'),
|
||||||
|
array(Logger::CRITICAL, 'red'),
|
||||||
|
array(Logger::ALERT, 'red'),
|
||||||
|
array(Logger::EMERGENCY,'red'),
|
||||||
|
array(Logger::NOTICE, 'green'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createHandler($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false)
|
||||||
|
{
|
||||||
|
$constructorArgs = array($token, $room, $name, $notify, Logger::DEBUG);
|
||||||
|
$this->res = fopen('php://memory', 'a');
|
||||||
|
$this->handler = $this->getMock(
|
||||||
|
'\Monolog\Handler\HipChatHandler',
|
||||||
|
array('fsockopen', 'streamSetTimeout', 'closeSocket'),
|
||||||
|
$constructorArgs
|
||||||
|
);
|
||||||
|
|
||||||
|
$reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
|
||||||
|
$reflectionProperty->setAccessible(true);
|
||||||
|
$reflectionProperty->setValue($this->handler, 'localhost:1234');
|
||||||
|
|
||||||
|
$this->handler->expects($this->any())
|
||||||
|
->method('fsockopen')
|
||||||
|
->will($this->returnValue($this->res));
|
||||||
|
$this->handler->expects($this->any())
|
||||||
|
->method('streamSetTimeout')
|
||||||
|
->will($this->returnValue(true));
|
||||||
|
$this->handler->expects($this->any())
|
||||||
|
->method('closeSocket')
|
||||||
|
->will($this->returnValue(true));
|
||||||
|
|
||||||
|
$this->handler->setFormatter($this->getIdentityFormatter());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user