2018-10-5

[PHP] MonologのDiscordWebhook対応

雑な技術メモ

Monolog には、Slack 用の Handler は公式で用意されているが、今回 Discord の WebHook を使いたかったためそれに関してメモ。

Monolog のコード例は以下な感じ。

<?php

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));

// add records to the log
$log->warning('Foo');
$log->error('Bar');

$log->warning等で送られたログをどう扱うかが Handler によって制御される(例の場合StreamHandler)。

Monolog では、以下のような形でオリジナルの Handler を作成できる。

class MyHandler extends AbstractProcessingHandler
{
    public function __construct($level = Logger::DEBUG, $bubble = true)
    {
        parent::__construct($level, $bubble);
    }

    protected function write(array $record)
    {
        echo $record["formatted"] . PHP_EOL;
    }
}

writeメソッドがログが送られてきた際の処理になるので、Discord の WebHook にログを送りたい場合は例えば

<?php

require_once __DIR__ . "/vendor/autoload.php";

use Monolog\Logger;
use Monolog\Handler\AbstractProcessingHandler;

class DiscordHandler extends AbstractProcessingHandler
{
    private $webhookUrl;
    private $client;

    public function __construct($webhookUrl, $level = Logger::DEBUG, $bubble = true)
    {
        $this->webhookUrl = $webhookUrl;
        $this->client = new GuzzleHttp\Client();

        parent::__construct($level, $bubble);
    }

    protected function write(array $record)
    {
        $this->client->request(
            "POST",
            $this->webhookUrl,
            [
                "json" => [
                    "content" => "```" . $record["formatted"] . "```",
                ],
            ]
        );
    }
}


$url = "Discord WebHook URL";

$log = new Logger("DiscordTest");
$log->pushHandler(new DiscordHandler($url, Logger::WARNING));

$log->warning("Warning Test");
$log->debug("Debug Test");

このようにすればいい。(今回は POST するために Guzzle を使用している)