1<?php declare(strict_types=1); 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 12namespace Monolog\Handler; 13 14use Monolog\Formatter\FormatterInterface; 15use Monolog\Formatter\LineFormatter; 16use Monolog\Logger; 17 18/** 19 * Sends logs to Fleep.io using Webhook integrations 20 * 21 * You'll need a Fleep.io account to use this handler. 22 * 23 * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation 24 * @author Ando Roots <ando@sqroot.eu> 25 * 26 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler 27 */ 28class FleepHookHandler extends SocketHandler 29{ 30 protected const FLEEP_HOST = 'fleep.io'; 31 32 protected const FLEEP_HOOK_URI = '/hook/'; 33 34 /** 35 * @var string Webhook token (specifies the conversation where logs are sent) 36 */ 37 protected $token; 38 39 /** 40 * Construct a new Fleep.io Handler. 41 * 42 * For instructions on how to create a new web hook in your conversations 43 * see https://fleep.io/integrations/webhooks/ 44 * 45 * @param string $token Webhook token 46 * @throws MissingExtensionException 47 */ 48 public function __construct( 49 string $token, 50 $level = Logger::DEBUG, 51 bool $bubble = true, 52 bool $persistent = false, 53 float $timeout = 0.0, 54 float $writingTimeout = 10.0, 55 ?float $connectionTimeout = null, 56 ?int $chunkSize = null 57 ) { 58 if (!extension_loaded('openssl')) { 59 throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler'); 60 } 61 62 $this->token = $token; 63 64 $connectionString = 'ssl://' . static::FLEEP_HOST . ':443'; 65 parent::__construct( 66 $connectionString, 67 $level, 68 $bubble, 69 $persistent, 70 $timeout, 71 $writingTimeout, 72 $connectionTimeout, 73 $chunkSize 74 ); 75 } 76 77 /** 78 * Returns the default formatter to use with this handler 79 * 80 * Overloaded to remove empty context and extra arrays from the end of the log message. 81 * 82 * @return LineFormatter 83 */ 84 protected function getDefaultFormatter(): FormatterInterface 85 { 86 return new LineFormatter(null, null, true, true); 87 } 88 89 /** 90 * Handles a log record 91 */ 92 public function write(array $record): void 93 { 94 parent::write($record); 95 $this->closeSocket(); 96 } 97 98 /** 99 * {@inheritDoc} 100 */ 101 protected function generateDataStream(array $record): string 102 { 103 $content = $this->buildContent($record); 104 105 return $this->buildHeader($content) . $content; 106 } 107 108 /** 109 * Builds the header of the API Call 110 */ 111 private function buildHeader(string $content): string 112 { 113 $header = "POST " . static::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n"; 114 $header .= "Host: " . static::FLEEP_HOST . "\r\n"; 115 $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; 116 $header .= "Content-Length: " . strlen($content) . "\r\n"; 117 $header .= "\r\n"; 118 119 return $header; 120 } 121 122 /** 123 * Builds the body of API call 124 * 125 * @phpstan-param FormattedRecord $record 126 */ 127 private function buildContent(array $record): string 128 { 129 $dataArray = [ 130 'message' => $record['formatted'], 131 ]; 132 133 return http_build_query($dataArray); 134 } 135} 136