背景
为了方便工作,我业余时间开发了一个线上接收日志的系统,提供日志推送接口。于是基于TP6 自定义日志驱动,每次打日志时,推送到线上查看。
接口文档
https://www.yuque.com/docs/share/20a266c3-61bd-472c-a971-b9cc2f957f96?# 《沙屿沫服务接口规范》
密码:去《关于我》私聊我吧
步骤
1、修改日志配置文件 config/log.php
2、创建日志驱动类(放置的位置没有要求,能加载到即可。)
3、对接线上日志系统。
1、修改日志配置文件
在 channels 增加一个通道
<?php
return [ ...
'channels' => [ ... 'shayvmo' => [ 'type' => \app\OnlineLog::class, 'realtime_write' => false, 'url' => '', 'appid' => '', 'secret_key' => '', ], ],
];
|
2、创建日志驱动类
<?php
declare (strict_types=1);
namespace app;
use app\util\Signature; use think\App; use think\contract\LogHandlerInterface;
class OnlineLog implements LogHandlerInterface { protected $config = [ 'url' => '', 'appid' => '', 'secret_key' => '', ];
protected $app;
public function __construct(App $app, $config = []) { if (is_array($config)) { $this->config = array_merge($this->config, $config); } }
public function save(array $log): bool { $function = function (string $url, array $data = []) { $header = [ 'Content-Type: application/x-www-form-urlencoded' ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $result = curl_exec($ch); curl_close($ch); return $result; };
$signature = new Signature($this->config['appid'], $this->config['secret_key']); foreach ($log as $key => $item) { foreach ($item as $i) { $i = json_decode($i, true); $i['log_type'] = $key; $signData = $signature->getSignData($i); $function($this->config['url'], $signData); } } return true; } }
|
3、对接线上日志系统
1)日志辅助类
<?php
declare (strict_types=1);
namespace app\service;
class LogService { public static function info(string $title, array $content) { self::push($title, $content); }
public static function debug(string $title, array $content) { self::push($title, $content, 'debug'); }
public static function error(string $title, array $content) { self::push($title, $content, 'error'); }
public static function warning(string $title, array $content) { self::push($title, $content, 'warning'); }
public static function push(string $title, array $content, string $log_type = 'info') { \think\facade\Log::channel('shayvmo')->$log_type(json_encode([ 'request_ip' => request()->ip(), 'title' => $title, 'content' => json_encode($content, JSON_UNESCAPED_UNICODE), ])); } }
|
2)签名类
<?php
declare (strict_types=1);
namespace app\util;
class Signature { private $appId;
private $secretKey;
public function __construct(string $appId, string $secretKey) { $this->appId = $appId; $this->secretKey = $secretKey; }
public function getSignData(array $data): array { $data['appid'] = $this->appId; $data['nonce_str'] = strtoupper(bin2hex(random_bytes(16))); $content = $this->getContent($data); $data['sign'] = $this->getSign($content); return $data; }
public function checkSign(array $data, string $sign): bool { return $this->getSign($this->getContent($data)) === $sign; }
private function getContent(array $data): string { ksort($data);
$temp = [];
foreach ($data as $key => $item) { if ($key === 'sign' || $item === '' || is_null($item)) { continue; } $temp[] = $key .'='.$item; }
return implode('&', $temp); }
private function getSign(string $content): string { return strtoupper(md5(md5($content . $this->secretKey) . $this->secretKey)); } }
|