幸福

如人饮水,冷暖自知

Laravel统计所有API响应时长等信息

项目的持久运行过程中,随着数据的积累或陡增,时长伴随着一些性能问题、接口响应慢等用户体验问题,当然也不排除一些写法不合理的慢查询SQL所导致。我们在排查问题时,通常都会开启慢日志查询,来通过慢查询的SQL语句来推导出业务功能,但是这里面可能存在一个问题,即在大型项目上纷繁的功能模块,产生的各种形形色色的SQL语句,而且有些业务模块功能强关联的,很难一下通过一条SQL直接定位功能所在。

在思考这个问题的时候一直在想能否有一些辅助方法,来方便快速、便捷的排查慢查询语句,查询愈慢则与之最直接的就是API响应时间愈长,于是思路顿开,通过记录每个API调用的接口访问情况,譬如客户端client_ip、rui、route、path及相应时间等等,其次还可以通过汇总统计API的调用频率,用以评估功能受众如何,岂不妙哉?而后通过laravel的前置/后置中间件的使用场景实现了整个过程,详述如下:

新建访问日志表 access_log

CREATE TABLE `access_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`enterprise_id` int(11) DEFAULT NULL,
`method` char(6) DEFAULT NULL,
`route` varchar(255) DEFAULT NULL,
`client_ip` varchar(45) DEFAULT NULL,
`params` varchar(300) DEFAULT NULL,
`user_agent` varchar(100) DEFAULT NULL,
`time` char(30) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=177 DEFAULT CHARSET=utf8mb4;

 

新建Model  /laravel/app/Models/AccessLog.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class AccessLog extends Model
{
    protected $table = 'access_log';

    protected $guarded = ['id'];
}

 

新增前置中间件 /laravel/app/Http/Middleware/BeforeMiddleware.php

<?php

namespace App\Http\Middleware;

use Closure;

define('START', microtime(true));

class BeforeMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        return $next($request);
    }
}

 

新建后置中间件 /laravel/app/Http/Middleware/AfterMiddleware.php

<?php

namespace App\Http\Middleware;

use App\Models\AccessLog;
use Closure;
use Illuminate\Support\Facades\DB;

class AfterMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        $params = $request->all();
        $data = [
            'method' => $request->method(),
            'route' => $request->getPathInfo(),
            'client_ip' => $request->ip(),
            'params' => $params ? json_encode($params) : '',
            'user_agent' => $request->userAgent(),
            'time' => round(microtime(true) - START, 3)
        ];

        $authToken = $request->bearerToken();
        if ($authToken) {
            $object = \Tymon\JWTAuth\Facades\JWTAuth::setToken($authToken)->getPayload()->get('sub');
            $authInfo = object_to_array($object);
            if (isset($authInfo['enterprise_id'])) {
                $data['enterprise_id'] = $authInfo['enterprise_id'];
            }
        }

        DB::beginTransaction();
        try {
            AccessLog::query()->create($data);
            DB::commit();
        } catch (\Exception $e){
            DB::rollback();
        }

        return $response;
    }
}

编辑 Kernel 文件 /laravel/app/Http/Kernel.php

$middleware里面添加中间件:
protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    \App\Http\Middleware\TrustProxies::class,
    \App\Http\Middleware\EnableCrossRequestMiddleware::class,
    \App\Http\Middleware\AfterMiddleware::class,
    \App\Http\Middleware\BeforeMiddleware::class,
];

访问项目任意接口即可看到效果如下



去打赏

您的支持将鼓励我们继续创作!

[微信] 扫描二维码打赏

[支付宝] 扫描二维码打赏

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注