Laravel8记录请求和返回日志

599次阅读
没有评论

相关环境:PHP7.4 + Laravel8.83.8

日志记录是项目必不可少的,他可以帮助我们排查一些问题,那这节我们就以接口请求与接口返回的记录作为重点。
项目里面的接口很多,我们不可能在每个方法里面人工的加 Log::info () 这种,这样太累也不好维护。所以我是使用中间件来做的:
第一步新建一个中间件

php artisan make:middleware AccessLog
便会在 app\Http\Middleware 下面生成 AccessLog.php,代码如下:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class AccessLog
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$traceId = md5(time() . mt_rand(1, 1000000));
// 记录请求信息
$requestMessage = ‘traceId’ => $traceId, ‘url’ => $request->url(), ‘method’ => $request->method(), ‘ip’ => $request->ips(), ‘headers’ => $request->header(‘Authorization’), ‘params’ => $request->all() ;
Log::info(“请求信息:”, $requestMessage);

    $respone = $next($request);
    $responeData = [
        'traceId' => $traceId,
        'respone' => json_decode($respone->getContent(), true) ?? ""
    ];

    Log::info("返回信息:", $responeData);

    return $respone;
}

}
以 $respone = $next ($request); 为界限,上面是请求下面是返回。
第二步配置全局路由
在 app\Http\Kernel.php 里的 $middleware 数组加入 AccessLog:

<?php

namespace App\Http;

use App\Http\Middleware\AccessLog;
use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
/**
* The application’s global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
AccessLog::class, //全局请求返回日志记录
];
这样所有请求都会进入这个 AccessLog 里面。

测试一下:
控制器代码:

<?php

namespace App\Http\Admin\User;

use App\Http\Admin\Controller;

class UserController extends Controller
{
public function detail()
{
$id = request()->input(“id”);
$data = UserAdmin::find($id, [‘id’, ‘mobile’]);
return response()->json([
‘code’ => 0,
‘message’ => “success”,
‘data’ => $data
]);
}
}
日志打印如下:

补充:
如果代码出现异常,我们发现日志会把这异常也记录下来,模拟一下,查个不存在的字段:

<?php

namespace App\Http\Admin\User;

use App\Http\Admin\Controller;

class UserController extends Controller
{
public function detail()
{
$id = request()->input(“id”);
$data = UserAdmin::find($id, [‘id’, ‘test’]); //不存在的test字段
return response()->json([
‘code’ => 0,
‘message’ => “success”,
‘data’ => $data
]);
}
}
这个时候去看日志,除了请求返回日志外,还有一个很长很长的异常日志【图片只截取一小部分,返回日志在下面没有截取出来】:

那如果你不想打印这个异常日志,也可以实现,在 app\Exceptions\Handler.php 里面有个 $dontReport 数组,他就是配置不会被记录到日志文件的异常类型数组。我们看异常日志,他是通过 Illuminate\Database\QueryException 类抛出的,那我们在 $dontReport 加上他:

<?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;

class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
* 不会被记录到日志文件的异常类型数组
*
* @var array>
*/
protected $dontReport = [
\Illuminate\Database\QueryException::class,
];

/**
 * A list of the inputs that are never flashed for validation exceptions.
 *
 * @var array<int, string>
 */
protected $dontFlash = [
    'current_password',
    'password',
    'password_confirmation',
];

/**
 * Register the exception handling callbacks for the application.
 *
 * @return void
 */
public function register()
{
    $this->reportable(function (Throwable $e) {
        //
    });
}

public function render($request, Throwable $e)
{
    return response()->json([
        'code' => $e->getCode() ?? 1,
        'file' => $e->getFile(),
        'line' => $e->getLine(),
        'message' => $e->getMessage() ?? "error!",
        'data' => []
    ]);
}

}
再次运行接口,发现异常日志就不会记录了

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 
评论(没有评论)