关键是两个,1是修改配置文件,指定自定义的驱动。2是自定义驱动的save方法
直接上代码

config/log.php

<?php// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
return [// 默认日志记录通道'default'      => env('log.channel', 'file'),// 日志记录级别'level'        => [],// 日志类型记录的通道 ['error'=>'email',...]'type_channel' => [],// 关闭全局日志写入'close'        => false,// 全局日志处理 支持闭包'processor'    => null,//ThinkPHP对系统的日志按照级别来分类记录,按照PSR-3日志规范,日志的级别从低到高依次为: debug, info, notice, warning, error, critical, alert, emergency,ThinkPHP额外增加了一个sql日志级别仅用于记录SQL日志(并且仅当开启数据库调试模式有效)。// 日志通道列表'channels'     => ['file' => [// 日志记录方式//'type'           => 'File','type'           => '\app\driver\log\Tp6Log',// 日志保存目录'path'           => '',// 单文件日志写入'single'         => false,// 独立日志级别'apart_level'    => ['error', 'sql','user','fun','pay','refund','order','cancelBadOrder','ar','job'],// 最大日志文件数量'max_files'      => 0,// 使用JSON格式记录'json'           => false,// 文件大小'file_size'    =>  1024*1024*2,// 日志处理'processor'      => null,// 关闭通道日志写入'close'          => false,// 日志输出格式化'format'         => '[%s][%s] %s',// 是否实时写入'realtime_write' => true,],// 其它日志通道配置],];

app\drive\log\Tp6Log.php

<?php
declare (strict_types=1);namespace app\driver\log;use DateTime;
use DateTimeZone;
use Exception;
use think\App;
use think\contract\LogHandlerInterface;
use think\facade\Request;/*** 本地化调试输出到文件*/
class Tp6Log implements LogHandlerInterface
{/*** 配置参数* @var array*/protected $config = ['time_format' => 'c','single' => false,'file_size' => 2097152,'path' => '','apart_level' => [],'max_files' => 0,'json' => false,'json_options' => JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,'format' => '[%s][%s] %s',];protected $app;// 实例化并传入参数public function __construct(App $app, $config = []){$this->app = $app;if (is_array($config)) {$this->config = array_merge($this->config, $config);}if (empty($this->config['format'])) {$this->config['format'] = '[%s][%s] %s';}if (empty($this->config['path'])) {$this->config['path'] = $app->getRuntimePath() . 'log';}if (substr($this->config['path'], -1) != DIRECTORY_SEPARATOR) {$this->config['path'] .= DIRECTORY_SEPARATOR;}}/*** 日志写入接口* @access public* @param array $log 日志信息* @return bool*/public function save(array $log): bool{$destination = $this->getMasterLogFile();$path = dirname($destination);!is_dir($path) && mkdir($path, 0755, true);$info = [];// 日志信息封装$time = DateTime::createFromFormat('0.u00 U', microtime())->setTimezone(new DateTimeZone(date_default_timezone_get()))->format($this->config['time_format']);$request = Request::instance();//新增$requestInfo = ['ip' => $request->ip(),'method' => $request->method(),'host' => $request->host(),'uri' => $request->url()];if(isset($log['sql'][0]) && strpos('CONNECT',$log['sql'][0])){}if (!$this->config['json']) {$debugInfo = ['param' => '[ PARAM ] ' . var_export($request->param(), true),'header' => '[ HEADER ] ' . var_export($request->header(), true)];foreach ($debugInfo as $row) {array_unshift($info, $row);}// 增加额外的调试信息$runtime = round(microtime(true) - $this->app->getBeginTime(), 10);$reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞';$memory_use = number_format((memory_get_usage() - $this->app->getBeginMem()) / 1024, 2);$time_str = '[运行时间:' . number_format($runtime, 6) . 's] [吞吐率:' . $reqs . 'req/s]';$memory_str = ' [内存消耗:' . $memory_use . 'kb]';$file_load = ' [文件加载:' . count(get_included_files()) . ']';array_unshift($info, $time_str . $memory_str . $file_load);array_unshift($info, "---------------------------------------------------------------\r\n[{$time}] {$requestInfo['ip']} {$requestInfo['method']} {$requestInfo['host']}{$requestInfo['uri']}");}foreach ($log as $type => $val) {$message = [];foreach ($val as $msg) {if (!is_string($msg)) {$msg = var_export($msg, true);}$message[] = $this->config['json'] ?json_encode(['time' => $time, 'type' => $type, 'msg' => $msg], $this->config['json_options']) :sprintf($this->config['format'], $time, $type, $msg);}if (true === $this->config['apart_level'] || in_array($type, $this->config['apart_level'])) {//这一句很关键,可以给mysql或者其他独立的日志,也加上请求和时间等信息array_unshift($message, "---------------------------------------------------------------\r\n[{$time}] {$requestInfo['ip']} {$requestInfo['method']} {$requestInfo['host']}{$requestInfo['uri']}");// 独立记录的日志级别$filename = $this->getApartLevelFile($path, $type);$this->write($message, $filename);continue;}$info[$type] = $message;}if ($info) {return $this->write($info, $destination);}return true;}/*** 获取主日志文件名* @access public* @return string*/protected function getMasterLogFile(): string{if ($this->config['max_files']) {$files = glob($this->config['path'] . '*.log');try {if (count($files) > $this->config['max_files']) {unlink($files[0]);}} catch (Exception $e) {//}}if ($this->config['single']) {$name = is_string($this->config['single']) ? $this->config['single'] : 'single';$destination = $this->config['path'] . $name . '.log';} else {if ($this->config['max_files']) {$filename = date('Ymd') . '.log';} else {$filename = date('Ym') . DIRECTORY_SEPARATOR . date('d') . '.log';}$destination = $this->config['path'] . $filename;}return $destination;}/*** 获取独立日志文件名* @access public* @param string $path 日志目录* @param string $type 日志类型* @return string*/protected function getApartLevelFile(string $path, string $type): string{if ($this->config['single']) {$name = is_string($this->config['single']) ? $this->config['single'] : 'single';$name .= '_' . $type;} elseif ($this->config['max_files']) {$name = date('Ymd') . '_' . $type;} else {$name = date('d') . '_' . $type;}return $path . DIRECTORY_SEPARATOR . $name . '.log';}/*** 日志写入* @access protected* @param array $message 日志信息* @param string $destination 日志文件* @return bool*/protected function write(array $message, string $destination): bool{// 检测日志文件大小,超过配置大小则备份日志文件重新生成$this->checkLogSize($destination);$info = [];foreach ($message as $type => $msg) {$info[$type] = is_array($msg) ? implode(PHP_EOL, $msg) : $msg;}$message = implode(PHP_EOL, $info) . PHP_EOL;return error_log($message, 3, $destination);}/*** 检查日志文件大小并自动生成备份文件* @access protected* @param string $destination 日志文件* @return void*/protected function checkLogSize(string $destination): void{if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) {try {rename($destination, dirname($destination) . DIRECTORY_SEPARATOR . time() . '-' . basename($destination));} catch (Exception $e) {//}}}
}

效果如下

mysql

---------------------------------------------------------------
[2021-11-11T09:05:00+08:00] 127.0.0.1 POST localhost:4100/api/Dictionary/getDictData
[2021-11-11T09:05:00+08:00][sql] CONNECT:[ UseTime:0.083536s ] mysql:host=47.99.78.253;port=3306;dbname=ad_qingclouds_c;charset=utf8
---------------------------------------------------------------
[2021-11-11T09:05:01+08:00] 127.0.0.1 POST localhost:4100/api/Dictionary/getDictData
[2021-11-11T09:05:01+08:00][sql] SHOW FULL COLUMNS FROM `user` [ RunTime:0.056446s ]
---------------------------------------------------------------
[2021-11-11T09:05:01+08:00] 127.0.0.1 POST localhost:4100/api/Dictionary/getDictData
[2021-11-11T09:05:01+08:00][sql] SELECT * FROM `user` WHERE  `access_token` = '5bdb8c308b77089bb68754ea37717dd2' LIMIT 1 [ RunTime:0.055739s ]
---------------------------------------------------------------
[2021-11-11T09:05:01+08:00] 127.0.0.1 POST localhost:4100/api/Dictionary/getDictData
[2021-11-11T09:05:01+08:00][sql] SHOW FULL COLUMNS FROM `system_config` [ RunTime:0.060319s ]

log

---------------------------------------------------------------
[2021-11-11T09:05:01+08:00] 127.0.0.1 POST localhost:4100/api/Dictionary/getDictData
[运行时间:0.305206s] [吞吐率:3.28req/s] [内存消耗:3,629.77kb] [文件加载:145]
[ HEADER ] array ('connection' => 'close','user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1','content-type' => 'application/x-www-form-urlencoded','accept' => '*/*','origin' => 'http://localhost:4100','sec-fetch-site' => 'same-origin','sec-fetch-mode' => 'cors','sec-fetch-dest' => 'empty','referer' => 'http://localhost:4100/','accept-language' => 'zh-CN,zh-TW;q=0.9,zh;q=0.8,en-US;q=0.7,en;q=0.6','cookie' => 'Phpstorm-262f24aa=fae27331-cd1a-4ce2-982f-52f41bd8c1f0; Webstorm-1bff894e=03b215c5-737b-4ab8-83b2-d225427ad987; EGG_SESS=tDY1kbt9o6NheiNmX1fErLhQvJBtAIKxPlxB98-6sQwe0-RkHzejSB8i3uXkzdbfH79HB6RNchgIKNBTBkfJWkwfCT4Ozy0N97Rk028vPE0MZE8p0sN9v16L7eQZ4sF4newIVv2REd9RXzCH8U9CKD1DgTAM23BfTfTaN3X3dTcZg0vZNVPWB-5P_Wh_C1LsAGHDyjkAVVE-uUcg0EZT2rNsCC_uJJW3fLLldEfx59MK7vO9gG1IwW8rgiFF1OP_Gm-0XrclP2_sx4A6lw4ZI4TAj_T-xjukYMzuri1Rp2mXtf5uyLkxIdb6oxi865426J_EUbGBKmgU5Hfxv3V8i8MfvOf6NvBp-aiYRASpQVhOZ348P4vv3TiODVdramlRvsjt86adzZUVi5E4ZD_uz6RkOm6fhSzQNySOqq4y_VXgAGhott7Jlhba2ewQB6qGA1_t1LLLtJUMVL9yXLypo8lOccbbSfjDZvOe9LWQz28W1B85AbvESp0Pqadk1LYDl6GTxuT4r-ed6j4IjzWfQzEPjqqxMP7gSF6djqlvK1VjhSz6LwVE0hxOxVQ_QmzMgGbTHMT1lPnnAMOkBg7jKqNrW1mYv5htfNTLkvoDTp-VI55cgN66vlx7Wu6tP4KUrSrg5AkNDfEYEFIyb89ZL4Dc5U6wpJxfLufC8ZPOkRliieUOsLYrdxp66Jw1jxp0x5NfNVHMDq0qpRsqrXdwOjUWmvGhY1nC7EIbC91Fz295qvlBpv_SowOLKa_p10WwK1ppaBNWh2RsQyAUYN3wN8hIFGHsgavjndhddbCB4IssEfhgN-15XnKM2M2Eg28KmCtyR-Zg1m76lJRLcexhi32UyHBHuo9RvM08DqmF68MlIl4LLZb9Nhwm_n9ayy3caMvBWkW7oRll33n8FOz48T7GQXqKr3GANQxXaq8VJ9k=; UM_distinctid=17cee0244cd10e-0cefb9b964c974-c343365-1fa400-17cee0244cef85; CNZZDATA1258685886=2051018770-1636073879-%7C1636073879','postman-token' => 'ca1d434f-51c6-49b5-a4eb-7f82531d9ae3','host' => 'api.qingyun.com','accept-encoding' => 'gzip, deflate, br','content-length' => '163','x-forwarded-for' => '127.0.0.1','x-forwarded-port' => '4100','x-forwarded-proto' => 'http','x-forwarded-host' => 'localhost:4100',
)
[ PARAM ] array ('is_dev' => '1','build' => '310','access_token' => '5bdb8c308b77089bb68754ea37717dd2','env' => 'wap','act' => '/Dictionary/getDictData','timestamp' => '1636524784','sign' => '6b898e0b0f453b94e820ba5acadf7b40',
)
---------------------------------------------------------------
[2021-11-11T09:05:01+08:00] 127.0.0.1 POST localhost:4100/api/Dictionary/getDictData
[运行时间:0.309771s] [吞吐率:3.23req/s] [内存消耗:3,725.85kb] [文件加载:151]
[ HEADER ] array ('connection' => 'close','user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1','content-type' => 'application/x-www-form-urlencoded','accept' => '*/*','origin' => 'http://localhost:4100','sec-fetch-site' => 'same-origin','sec-fetch-mode' => 'cors','sec-fetch-dest' => 'empty','referer' => 'http://localhost:4100/','accept-language' => 'zh-CN,zh-TW;q=0.9,zh;q=0.8,en-US;q=0.7,en;q=0.6','cookie' => 'Phpstorm-262f24aa=fae27331-cd1a-4ce2-982f-52f41bd8c1f0; Webstorm-1bff894e=03b215c5-737b-4ab8-83b2-d225427ad987; EGG_SESS=tDY1kbt9o6NheiNmX1fErLhQvJBtAIKxPlxB98-6sQwe0-RkHzejSB8i3uXkzdbfH79HB6RNchgIKNBTBkfJWkwfCT4Ozy0N97Rk028vPE0MZE8p0sN9v16L7eQZ4sF4newIVv2REd9RXzCH8U9CKD1DgTAM23BfTfTaN3X3dTcZg0vZNVPWB-5P_Wh_C1LsAGHDyjkAVVE-uUcg0EZT2rNsCC_uJJW3fLLldEfx59MK7vO9gG1IwW8rgiFF1OP_Gm-0XrclP2_sx4A6lw4ZI4TAj_T-xjukYMzuri1Rp2mXtf5uyLkxIdb6oxi865426J_EUbGBKmgU5Hfxv3V8i8MfvOf6NvBp-aiYRASpQVhOZ348P4vv3TiODVdramlRvsjt86adzZUVi5E4ZD_uz6RkOm6fhSzQNySOqq4y_VXgAGhott7Jlhba2ewQB6qGA1_t1LLLtJUMVL9yXLypo8lOccbbSfjDZvOe9LWQz28W1B85AbvESp0Pqadk1LYDl6GTxuT4r-ed6j4IjzWfQzEPjqqxMP7gSF6djqlvK1VjhSz6LwVE0hxOxVQ_QmzMgGbTHMT1lPnnAMOkBg7jKqNrW1mYv5htfNTLkvoDTp-VI55cgN66vlx7Wu6tP4KUrSrg5AkNDfEYEFIyb89ZL4Dc5U6wpJxfLufC8ZPOkRliieUOsLYrdxp66Jw1jxp0x5NfNVHMDq0qpRsqrXdwOjUWmvGhY1nC7EIbC91Fz295qvlBpv_SowOLKa_p10WwK1ppaBNWh2RsQyAUYN3wN8hIFGHsgavjndhddbCB4IssEfhgN-15XnKM2M2Eg28KmCtyR-Zg1m76lJRLcexhi32UyHBHuo9RvM08DqmF68MlIl4LLZb9Nhwm_n9ayy3caMvBWkW7oRll33n8FOz48T7GQXqKr3GANQxXaq8VJ9k=; UM_distinctid=17cee0244cd10e-0cefb9b964c974-c343365-1fa400-17cee0244cef85; CNZZDATA1258685886=2051018770-1636073879-%7C1636073879','postman-token' => 'ca1d434f-51c6-49b5-a4eb-7f82531d9ae3','host' => 'api.qingyun.com','accept-encoding' => 'gzip, deflate, br','content-length' => '163','x-forwarded-for' => '127.0.0.1','x-forwarded-port' => '4100','x-forwarded-proto' => 'http','x-forwarded-host' => 'localhost:4100',
)
[ PARAM ] array ('is_dev' => '1','build' => '310','access_token' => '5bdb8c308b77089bb68754ea37717dd2','env' => 'wap','act' => '/Dictionary/getDictData','timestamp' => '1636524784','sign' => '6b898e0b0f453b94e820ba5acadf7b40',
)

thinkphp6自定义日志驱动,增加显示全部请求信息相关推荐

  1. cli能记日志web不能php,ThinkPHP6.0日志变化

    ### 2019 年 7 月 28 日 发布 `6.0`的日志类比之前版本完善了很多,主要新特性包括: * 日志信息格式化 * 多通道写入支持 * 延时/实时写入 * 日志信息处理事件 * 日志级别指 ...

  2. Serilog 自定义 Enricher 来增加记录的信息

    Serilog 自定义 Enricher 来增加记录的信息 Intro Serilog 是 .net 里面非常不错的记录日志的库,结构化日志记录,而且配置起来很方便,自定义扩展也很方便 Serilog ...

  3. nginx如何自定义日志记录格式?

    Nginx日志主要分为两种:access_log(访问日志)和error_log(错误日志).通过访问日志我们可以得到用户的IP地址.浏览器的信息,请求的处理时间等.错误日志记录了访问出错的信息,可以 ...

  4. HAproxy增加日志记录功能和自定义日志输出内容、格式

    http://blog.51cto.com/eric1/1854574 一.增加haproxy日志记录功能   1.1 由于数据分析的需要,我们必须打开haproxy日志,记录相关信息. 在配置前,我 ...

  5. ml不是内部或外部命令_美国飞机制造商波音公司采用VR技术训练宇航员 ; Snap Lens Studio推出支持自定义ML驱动的Snapchat镜头...

    看日报是个好习惯!  Valve宣布为Steam开发者推出OpenXR预览版本,支持跨平台VR/AR内容开发  Valve在为Steam游戏开发人员迎接OpenXR面世的准备方面迈出了重要的一步,开发 ...

  6. log4cplus使用(二)-自定义日志等级

    log4cplus支持用户自定义日志等级,操作也比较简单,使用之前贴如下宏定义 #define LOG4CPLUS_MACRO_CREASH_LOG_LEVEL(pred) LOG4CPLUS_UNL ...

  7. ELK 经典用法—企业自定义日志收集切割和mysql模块

    ELK 经典用法-企业自定义日志收集切割和mysql模块 一.收集切割公司自定义的日志 很多公司的日志并不是和服务默认的日志格式一致,因此,就需要我们来进行切割了. 1.需切割的日志示例 2018-0 ...

  8. slf4j注解log报错_SpringBoot自定义日志注解,用于数据库记录操作日志,你用过吗?...

    大家好,我是程序员7歌! 今天我将为大家讲解如何通过自定义注解记录接口访问日志.一般的开发中,有两种方式可以记录日志信息,第一种:把接口日志信息保存到日志文件中,第二种:把接口操作日志保存到数据库中, ...

  9. logback自定义日志格式

    logback自定义日志格式 1.ClassicConverter 继承ClassicConverter package com.demo.conf;import ch.qos.logback.cla ...

  10. Spring自定义注解驱动开发使用及源码分析

    目录 前言 注解驱动开发使用 需求 代码实现 测试效果 源码分析 BeanDefinitionRegistryPostProcessor接口 解析BeanDefinition 处理Bean上配置的注解 ...

最新文章

  1. oracle数据库enq: TX - allocate ITL entry性能诊断
  2. 给老婆写的带返回的2048(数据库存储)
  3. CodeSmith连接mysql
  4. 柔性机械臂_CSR论文精选 | 基于视觉的双连杆柔性机械臂末端位置跟踪控制
  5. 数加:从数据工程师到CDO的七次升职路
  6. getHibernateTemplate()(Spring中常用的hql查询方法)
  7. 在安装mysql出现的错误以及解决方法
  8. 2006年上半年开发心得
  9. cocos2dx box2d使用(一)
  10. 跟老男孩学linux运维核心基础 linux运维实战教程
  11. java中打开eclipse_关于Java:如何在Eclipse中打开jar文件
  12. 又是被打败的一天 (记招商银行笔试)
  13. 霏霏暮雨 eclipse+HBASE开发环境搭建(已实践
  14. 控制算法和编程算法_算法中的编程公平性
  15. Linux强制修改root用户密码
  16. 秃顶和程序员有直接关系?
  17. GOSSIP PROTOCOL(又被称为反熵Anti-Entropy, 一种弱一致性, 同步信息交换通信的协议)...
  18. python_discover方法遍历所有执行的用例
  19. 双11真无线蓝牙耳机盘点分享,高音质游戏低延迟无惧卡顿
  20. 信息流广告投放小白怎么入门?给刚毕业和想转行的人

热门文章

  1. winform中ComboBox下拉框控件的动态数据填充
  2. 计算机教师所需技能,信息技术教师应具备哪些教学技能
  3. 【小程序】自定义组件设置样式失效使用外部样式类解决
  4. Fiverr 攻略:跨境自由职业通过 Fiverr 盈利
  5. python django的查询语句
  6. 广义矩方法(GMM)与动态面板数据简述
  7. Canto加速市场的发展,连接全球的金融衍生品市场
  8. 同一计算机打印机无法连接,共享打印机无法连接怎么办 共享打印机无法连接解决方法【图文教程】...
  9. java drm_DRM系统工作原理
  10. php中合并图片并添加水印,php通过imagecopymerge 函数给图片制作水印