首页 > 文章列表 > thinkphp6如何使用中间件记录行为日志

thinkphp6如何使用中间件记录行为日志

php
360 2023-05-14

前言

发现本站没有一个靠谱的tp6记录行为日志的教程,于是就整理了一下自己在项目中已经投入使用的行为日志中间件的详细配置步骤供大家参考

提示:先阅读官方中间件教程 https://www.kancloud.cn/manual/thinkphp6_0/1037493

中间件

一、定义中间件

可以通过命令行指令快速生成中间件

php think make:middleware Behavior

这个指令会 app/middleware目录下面生成一个Behavior中间件。

内容如下:

<?php

declare (strict_types = 1);

namespace app\middleware;

use think\facade\Log;



class Behavior

{

    /**

     * 处理请求

     *

     * @param \think\Request $request

     * @param \Closure       $next

     * @return Response

     */

    public function handle($request, \Closure $next)

    {

         //start 加入以下内容

         $admin  =  get_admin_info();   				//当前登录用户的信息,自己实现

         $method = strtolower($request->method());

         $is_ajax = $request->isAjax();

         $route = $request->pathinfo();

         $req = $_REQUEST;

         unset($req['s'],$req['_session']);  

         $req_data = $req ?  json_encode($req) : '';

         $data = [

               'admin_id' => $admin['id'],				//操作人id

               'admin_user' => $admin['user'],			//操作人用户名

               'route' => $route,						//操作的路由地址

               'method' => $method,						//get/post

               'req_tp' => $is_ajax ? 'ajax' : 'normal',

               'req_data' => $req_data,   				 //get/post的数据

               'ip' => getIp(),

               'create_time' => time()

         ];

         //end

         return $next($request);

    }

}

二、使用日志通道暂存行为日志

不建议将行为日志实时写入数据库给数据库造成不必要的压力. 我们先写入log文件缓存,定时存入数据库

提示:先阅读官方日志处理教程 https://www.kancloud.cn/manual/thinkphp6_0/1037616

日志处理

1.修改log配置文件

打开config/log.php ,在’channels’ => [] 最后加入一个记录行为日志的单独通道:

 // 其它日志通道配置

 //行为日志

 'behavior'    =>    [

     'path'           => runtime_path().'behavior',  //日志存放目录

     'type'    =>    'File',

     'single' =>     'b',        		//单一文件日志:文件名

     'file_size'   	=> 	1024*1024*10, 	//日志文件大小限制(超出会生成多个文件

     'max_files' => 30,                  //文件最大数量

     'realtime_write'    =>    false,    // 关闭实时写入

 ],

2.注册全局中间件

打开app/middleware.php ,注册个行为日志全局中间件

<?php

// 全局中间件定义文件

return [

    // 全局请求缓存

    // \think\middleware\CheckRequestCache::class,

    // 多语言加载

    // \think\middleware\LoadLangPack::class,

    // Session初始化

    // \think\middleware\SessionInit::class

    // 行为日志

    \app\middleware\Behavior::class,   

];

3.测试能否成功生成日志

随便访问一个本项目页面,例如:http://www.tp6.com/index/index/test?a=1&b=2,看能否生成以下文件.

打开文件,数据已写入

{“time”:“2022-04-16T21:38:48+08:00”,“type”:“info”,“msg”:"{“admin_id”:888,“admin_user”:“fanchen”,“route”:“index\/index\/test”,“method”:“get”,“req_tp”:“normal”,“req_data”:"{\“a\”:\“1\”,\“b\”:\“2\”}",“ip”:“127.0.0.1”,“create_time”:1650116328}"}

三、使用定时任务将日志内容定时写入数据库

1.新建一个api方法

要求定时任务可以访问到

 /**

     * 定时任务服务器定时将用户行为日志插入到数据库

     * @return void

     */

    public function sync_behavior_log()

    {

        $path = runtime_path() . 'behavior/b.log';

        $b_file = file_get_contents($path);

        $b_arr = explode(PHP_EOL, $b_file);

        $d = [];

        foreach ($b_arr as $b) {

            $data = json_decode($b, true);

            if (!empty($data['msg'])) {

                $d[] = json_decode($data['msg'], true);

            }

        }

        if ($d) {

            try {

                Db::name('log_behavior')->insertAll($d);     //批量插入数据库

                file_put_contents($path, '');       //清空文件日志

                echo '采集用户行为日志成功' . count($d);

            } catch (DbException $e) {

                echo ($e->getMessage());

            }

        }

    }

2.新建行为日志数据表log_behavior

SET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;



-- ----------------------------

-- Table structure for log_behavior

-- ----------------------------

DROP TABLE IF EXISTS `log_behavior`;

CREATE TABLE `log_behavior`  (

  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',

  `admin_id` int(11) NOT NULL DEFAULT 0 COMMENT '用户id',

  `admin_user` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '用户名',

  `route` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模块名称',

  `method` enum('delete','put','post','get') CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'get' COMMENT '请求方式 1get 2post 3put 4delete',

  `req_data` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '请求数据',

  `ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '用户ip',

  `create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',

  PRIMARY KEY (`id`) USING BTREE,

  INDEX `uid`(`admin_id`) USING BTREE,

  INDEX `admin_user`(`admin_user`) USING BTREE,

  INDEX `route`(`route`) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 3902195 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '行为日志' ROW_FORMAT = Compact;



SET FOREIGN_KEY_CHECKS = 1;

3.新建定时任务

新建定时任务,定时访问步骤1的sync_behavior_log地址就行了, 建议5分钟1次

至此, 有用户访问时,数据表就会每隔一段时间就批量插入行为日志数据了

总结

写得比较简单粗暴, 有些地方需要自己实现, 比如获取登录用户信息…