PageRenderTime 25ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php

https://gitlab.com/judielsm/Handora
PHP | 293 lines | 159 code | 33 blank | 101 comment | 15 complexity | cca497a0df73f19f88cb52c70e9db018 MD5 | raw file
  1. <?php
  2. /*
  3. * This file is part of the Monolog package.
  4. *
  5. * (c) Jordi Boggiano <j.boggiano@seld.be>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Monolog\Handler;
  11. use Monolog\Logger;
  12. use Monolog\Formatter\LineFormatter;
  13. /**
  14. * Sends notifications through Slack API
  15. *
  16. * @author Greg Kedzierski <greg@gregkedzierski.com>
  17. * @see https://api.slack.com/
  18. */
  19. class SlackHandler extends SocketHandler
  20. {
  21. /**
  22. * Slack API token
  23. * @var string
  24. */
  25. private $token;
  26. /**
  27. * Slack channel (encoded ID or name)
  28. * @var string
  29. */
  30. private $channel;
  31. /**
  32. * Name of a bot
  33. * @var string
  34. */
  35. private $username;
  36. /**
  37. * Emoji icon name
  38. * @var string
  39. */
  40. private $iconEmoji;
  41. /**
  42. * Whether the message should be added to Slack as attachment (plain text otherwise)
  43. * @var bool
  44. */
  45. private $useAttachment;
  46. /**
  47. * Whether the the context/extra messages added to Slack as attachments are in a short style
  48. * @var bool
  49. */
  50. private $useShortAttachment;
  51. /**
  52. * Whether the attachment should include context and extra data
  53. * @var bool
  54. */
  55. private $includeContextAndExtra;
  56. /**
  57. * @var LineFormatter
  58. */
  59. private $lineFormatter;
  60. /**
  61. * @param string $token Slack API token
  62. * @param string $channel Slack channel (encoded ID or name)
  63. * @param string $username Name of a bot
  64. * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
  65. * @param string|null $iconEmoji The emoji name to use (or null)
  66. * @param int $level The minimum logging level at which this handler will be triggered
  67. * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
  68. * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
  69. * @param bool $includeContextAndExtra Whether the attachment should include context and extra data
  70. */
  71. public function __construct($token, $channel, $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeContextAndExtra = false)
  72. {
  73. if (!extension_loaded('openssl')) {
  74. throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler');
  75. }
  76. parent::__construct('ssl://slack.com:443', $level, $bubble);
  77. $this->token = $token;
  78. $this->channel = $channel;
  79. $this->username = $username;
  80. $this->iconEmoji = trim($iconEmoji, ':');
  81. $this->useAttachment = $useAttachment;
  82. $this->useShortAttachment = $useShortAttachment;
  83. $this->includeContextAndExtra = $includeContextAndExtra;
  84. if ($this->includeContextAndExtra) {
  85. $this->lineFormatter = new LineFormatter;
  86. }
  87. }
  88. /**
  89. * {@inheritdoc}
  90. *
  91. * @param array $record
  92. * @return string
  93. */
  94. protected function generateDataStream($record)
  95. {
  96. $content = $this->buildContent($record);
  97. return $this->buildHeader($content) . $content;
  98. }
  99. /**
  100. * Builds the body of API call
  101. *
  102. * @param array $record
  103. * @return string
  104. */
  105. private function buildContent($record)
  106. {
  107. $dataArray = $this->prepareContentData($record);
  108. return http_build_query($dataArray);
  109. }
  110. /**
  111. * Prepares content data
  112. *
  113. * @param array $record
  114. * @return array
  115. */
  116. protected function prepareContentData($record)
  117. {
  118. $dataArray = array(
  119. 'token' => $this->token,
  120. 'channel' => $this->channel,
  121. 'username' => $this->username,
  122. 'text' => '',
  123. 'attachments' => array()
  124. );
  125. if ($this->useAttachment) {
  126. $attachment = array(
  127. 'fallback' => $record['message'],
  128. 'color' => $this->getAttachmentColor($record['level'])
  129. );
  130. if ($this->useShortAttachment) {
  131. $attachment['fields'] = array(
  132. array(
  133. 'title' => $record['level_name'],
  134. 'value' => $record['message'],
  135. 'short' => false
  136. )
  137. );
  138. } else {
  139. $attachment['fields'] = array(
  140. array(
  141. 'title' => 'Message',
  142. 'value' => $record['message'],
  143. 'short' => false
  144. ),
  145. array(
  146. 'title' => 'Level',
  147. 'value' => $record['level_name'],
  148. 'short' => true
  149. )
  150. );
  151. }
  152. if ($this->includeContextAndExtra) {
  153. if (!empty($record['extra'])) {
  154. if ($this->useShortAttachment) {
  155. $attachment['fields'][] = array(
  156. 'title' => "Extra",
  157. 'value' => $this->stringify($record['extra']),
  158. 'short' => $this->useShortAttachment
  159. );
  160. } else {
  161. // Add all extra fields as individual fields in attachment
  162. foreach ($record['extra'] as $var => $val) {
  163. $attachment['fields'][] = array(
  164. 'title' => $var,
  165. 'value' => $val,
  166. 'short' => $this->useShortAttachment
  167. );
  168. }
  169. }
  170. }
  171. if (!empty($record['context'])) {
  172. if ($this->useShortAttachment) {
  173. $attachment['fields'][] = array(
  174. 'title' => "Context",
  175. 'value' => $this->stringify($record['context']),
  176. 'short' => $this->useShortAttachment
  177. );
  178. } else {
  179. // Add all context fields as individual fields in attachment
  180. foreach ($record['context'] as $var => $val) {
  181. $attachment['fields'][] = array(
  182. 'title' => $var,
  183. 'value' => $val,
  184. 'short' => $this->useShortAttachment
  185. );
  186. }
  187. }
  188. }
  189. }
  190. $dataArray['attachments'] = json_encode(array($attachment));
  191. } else {
  192. $dataArray['text'] = $record['message'];
  193. }
  194. if ($this->iconEmoji) {
  195. $dataArray['icon_emoji'] = ":{$this->iconEmoji}:";
  196. }
  197. return $dataArray;
  198. }
  199. /**
  200. * Builds the header of the API Call
  201. *
  202. * @param string $content
  203. * @return string
  204. */
  205. private function buildHeader($content)
  206. {
  207. $header = "POST /api/chat.postMessage HTTP/1.1\r\n";
  208. $header .= "Host: slack.com\r\n";
  209. $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
  210. $header .= "Content-Length: " . strlen($content) . "\r\n";
  211. $header .= "\r\n";
  212. return $header;
  213. }
  214. /**
  215. * {@inheritdoc}
  216. *
  217. * @param array $record
  218. */
  219. protected function write(array $record)
  220. {
  221. parent::write($record);
  222. $this->closeSocket();
  223. }
  224. /**
  225. * Returned a Slack message attachment color associated with
  226. * provided level.
  227. *
  228. * @param int $level
  229. * @return string
  230. */
  231. protected function getAttachmentColor($level)
  232. {
  233. switch (true) {
  234. case $level >= Logger::ERROR:
  235. return 'danger';
  236. case $level >= Logger::WARNING:
  237. return 'warning';
  238. case $level >= Logger::INFO:
  239. return 'good';
  240. default:
  241. return '#e3e4e6';
  242. }
  243. }
  244. /**
  245. * Stringifies an array of key/value pairs to be used in attachment fields
  246. *
  247. * @param array $fields
  248. * @access protected
  249. * @return string
  250. */
  251. protected function stringify($fields)
  252. {
  253. $string = '';
  254. foreach ($fields as $var => $val) {
  255. $string .= $var.': '.$this->lineFormatter->stringify($val)." | ";
  256. }
  257. $string = rtrim($string, " |");
  258. return $string;
  259. }
  260. }