ChatOpsによるアプリケーションのエラー監視 (Slack / Hubot / SQS)


#概要 / 目的

運用サービスのエラーをHubotを使ってSlackに通知させる。
これによって、
・エラーの早期検知/対応
・エラーのチーム内での共有
が可能となる。

#構成 / 手順

構成の概要図は以下の通りです。

![Untitled (2).png](https://qiita-image-store.s3.amazonaws.com/0/47881/fa122584-a710-4bfc-f14e-e2c1335fe06b.png)

処理の主な流れは以下の通りです。
1. 運用サービスのアプリ（今回はCakePHP）で、エラーをハンドリングし、SQSにプッシュ
2. Hubotで定期的にSQSを監視し、エラーがキューに溜まっていれば、それらを取り出してSlackに通知

\* アプリからSlackのIncommingWebhook等を使って、直接Slackにエラーを投げた方が構成としてはシンプルですが、
パフォーマンスの面や、アプリ(CakePHP)とエラー監視システム（HubotやSlack）の依存度を下げるために、このような構成にしてます。

#実装

## アプリからエラーをSQSにプッシュ

PHP用のAWS-SDKが必要です（今回のサンプルで使ったVersionは2.7.0）。
CakePHPのbootstrap.phpなどでエラーをハンドリングして、SQSにメッセージを送信します。
この際、通知用のSlackのchannel名も指定しています。

```bootstrap.php
	// Custom Error Handler
	function myapp_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
		if ((error_reporting() & $errno) === $errno) {
			$title = "[大変です]: エラーが起きたよ !!";
			$uri = isset($_SERVER['REQUEST_URI'])? $_SERVER['REQUEST_URI'] : '';
			$ref = isset($_SERVER['HTTP_REFERER'])? $_SERVER['HTTP_REFERER'] : '';

			$message =	"[{$errno}] {$errstr}\n" .
						"File :  {$errfile} on line {$errline}\n" .
						"URI :  {$uri}\n" .
						'Access IP :  ' . Kh_Device::getIpAddress() ."\n" .
						"Referer :  {$ref}";// Format error messages*/

			Myapp_AwsSQS_MessageSender4ChatOps::getInstance()->send($title, $message, '#your-slack-channel');
		}
		return  true;
	}	
	
	// Setting Error Handler
	set_error_handler('myapp_error_handler');
```

```Libs/Myapp/AwsSQS/MessageSender4ChatOps.php

<?php 

use Aws\Sqs\SqsClient as SqsClient;

class Myapp_AwsSQS_MessageSender4ChatOps
{
	private static $__instance;
	
	private function __construct() {
		$config = array (
				'key' => '**************',
				'secret' => '****************',
				'region' => '*******************'
		);		
		$this->__sqs = SqsClient::factory($config);
	}
	
	public static function getInstance()
	{
		if (!self::$__instance) {
			self::$__instance = new self;
		}
		return self::$__instance;
	}
	
	public function send($title, $message, $channel = false)
	{
 		//エラーが発生した場合は、アプリは落とさず、メール通知。
		try {
			$queueUrl = $this->__sqs->getQueueUrl(array('QueueName' => 'queue4slack'));//キュー名は適当に
			$this->__sqs->sendMessage(array(
					'QueueUrl'    => $queueUrl['QueueUrl'],
					'MessageBody' => json_encode(array('title'=>$title, 'message'=>$message, 'channel'=>$channel)),
			));			
		} catch (Exception $e) {
			mb_send_mail("your@email.com", "{$_SERVER['HTTP_HOST']}: Error occured on sending message for chatops", $e->getMessage());
			return;
		}
	}
		
}

```


## Hubotで定期的にSQS監視 & Slackに通知

Hubot側のコードは以下のレポジトリに上げています。

https://github.com/s-kiriki/slack-hubot-scripts/blob/master/src/scripts/sqs2slack-cron.coffee

npmのcron (https://www.npmjs.org/package/cron ) ライブラリを用いて、定期的にSQSに問い合わせを行っています。
 

#実行例

実際にアプリ側でエラーが起きると、以下のようにSlackに通知してくれます。

![zzz_スクリーンショット_2014-11-11_11_29_56.png](https://qiita-image-store.s3.amazonaws.com/0/47881/19f9afa7-3fe3-d77e-3c98-947404f980b0.png)


また、エラー監視だけではなく、サイト上での新着口コミのSlackへの通知なども今回用いたSQS/Hubot/Slackと全く同じ構成でメッセージと通知先のchannel名を変えるだけで簡単に行えます。

![zzz_スクリーンショット_2014-11-11_11_36_20.png](https://qiita-image-store.s3.amazonaws.com/0/47881/eabbf574-fbcd-c47e-7ee1-6163a3b980ce.png)