|
@@ -0,0 +1,96 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+declare(strict_types=1);
|
|
|
|
|
+namespace SixShop\System\Log\Driver;
|
|
|
|
|
+
|
|
|
|
|
+use think\contract\LogHandlerInterface;
|
|
|
|
|
+
|
|
|
|
|
+class FeiShu implements LogHandlerInterface
|
|
|
|
|
+{
|
|
|
|
|
+ private $curlHandle = null;
|
|
|
|
|
+
|
|
|
|
|
+ public function __construct(private array $config = [])
|
|
|
|
|
+ {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function __destruct()
|
|
|
|
|
+ {
|
|
|
|
|
+ if ($this->curlHandle) {
|
|
|
|
|
+ curl_close($this->curlHandle);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[\Override]
|
|
|
|
|
+ public function save(array $log): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ foreach ($log as $record) {
|
|
|
|
|
+ $type = $record->type;
|
|
|
|
|
+ $msg = $record->message;
|
|
|
|
|
+ $time = $record->time->format($this->config['time_format']);
|
|
|
|
|
+ if (!is_string($msg)) {
|
|
|
|
|
+ $msg = var_export($msg, true);
|
|
|
|
|
+ }
|
|
|
|
|
+ $message = sprintf($this->config['format'], $time, $type, $msg);
|
|
|
|
|
+ $this->write($message);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function write(string $message): void
|
|
|
|
|
+ {
|
|
|
|
|
+ if (empty($this->config['webhook_url'])) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $data = [
|
|
|
|
|
+ 'msg_type' => 'text',
|
|
|
|
|
+ 'content' => [
|
|
|
|
|
+ 'app_name' => $this->config['app_name'] ?? 'sixshop',
|
|
|
|
|
+ 'msg' => $message
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ $this->sendWebhook($this->config['webhook_url'], $data);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function sendWebhook(string $url, array $data): void
|
|
|
|
|
+ {
|
|
|
|
|
+ // 复用 curl 句柄
|
|
|
|
|
+ if (!$this->curlHandle) {
|
|
|
|
|
+ $this->curlHandle = curl_init();
|
|
|
|
|
+ curl_setopt_array($this->curlHandle, [
|
|
|
|
|
+ CURLOPT_POST => true,
|
|
|
|
|
+ CURLOPT_HTTPHEADER => [
|
|
|
|
|
+ 'Content-Type: application/json',
|
|
|
|
|
+ 'Accept: application/json'
|
|
|
|
|
+ ],
|
|
|
|
|
+ CURLOPT_RETURNTRANSFER => true,
|
|
|
|
|
+ CURLOPT_TIMEOUT => 10,
|
|
|
|
|
+ CURLOPT_CONNECTTIMEOUT => 5,
|
|
|
|
|
+ CURLOPT_SSL_VERIFYPEER => false,
|
|
|
|
|
+ CURLOPT_SSL_VERIFYHOST => false
|
|
|
|
|
+ ]);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 每次请求设置特定的 URL 和数据
|
|
|
|
|
+ curl_setopt_array($this->curlHandle, [
|
|
|
|
|
+ CURLOPT_URL => $url,
|
|
|
|
|
+ CURLOPT_POSTFIELDS => json_encode($data, JSON_UNESCAPED_UNICODE)
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ $response = curl_exec($this->curlHandle);
|
|
|
|
|
+ $httpCode = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE);
|
|
|
|
|
+ $error = curl_error($this->curlHandle);
|
|
|
|
|
+
|
|
|
|
|
+ // 可以在这里记录发送结果到系统日志
|
|
|
|
|
+ if ($error || $httpCode !== 200) {
|
|
|
|
|
+ // 发送失败,可以选择记录到文件或其他方式
|
|
|
|
|
+ error_log(sprintf(
|
|
|
|
|
+ 'FeiShu webhook send failed: %s, HTTP Code: %d, Response: %s',
|
|
|
|
|
+ $error ?: 'Unknown error',
|
|
|
|
|
+ $httpCode,
|
|
|
|
|
+ $response
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|