龙空技术网

系统日志输出规范

TerryQi 1988

前言:

当前看官们对“php输出日志”都比较珍视,兄弟们都需要了解一些“php输出日志”的相关知识。那么小编在网上网罗了一些关于“php输出日志””的相关文章,希望你们能喜欢,姐妹们一起来了解一下吧!

「to后端」在业务运营过程中,我们希望能够主动的了解应用系统存在的bug和错误,以便进行迭代优化,提升系统的健壮性。在系统运维过程中,日志的管理非常重要,需要进行规范化的日志管理,以便进行故障分析、错误排查和问题回溯。本文针对laravel框架,介绍日志管理规范。

一、设计思路

以接口调用为例进行说明,每次用户请求,分配请求流水,存入session,在本次请求过程中输出的日志都加入请求流水标识,在工具类中封装日志打印方法,从请求进入到报文返回,均带流水号,以便进行日志查询。

日志记录过程

二、实例展示

以下为测试环境中的实例展示:

日志实例

红色框:LOG类型(Request:请求接口;Process:过程接口;Error:代码错误;Back:返回接口);

黄色框:流水号;

蓝色框:过程接口中的过程描述;

绿色框:动作控制器;

红线:数据;

白框:错误返回信息

三、实现方法

以laravel为例,实现方案如下:

Utils文件添加以下方法:

/** * 请求接口LOG * @param string $logPath 请求接口 * @param string $logIp IP地址 * @param array $logData 请求参数 */ public static function requestLog($logPath="",$logIp="",$logData=[]){ $LOGO_NO = 'LOG'.date('Ymdhis',time()).rand(1000000,10000000); Session::put('LOGO_NO', $LOGO_NO); Log::info('[Request] '.$LOGO_NO.' '. $logPath . "(" . $logIp . ") " .json_encode($logData)); } /** * 过程中接口LOG * @param string $logModular 模块 * @param string/array $logData 数据 * @param string $logContent 备注 */ public static function processLog($logModular="", $logContent="", $logData=""){ $LOGO_NO = Session::get("LOGO_NO"); if(is_array($logData)){ $logData = json_encode($logData,true); } if($logContent){ Log::info('[Process] '.$LOGO_NO.' '.$logContent.' '.$logModular .' ' . $logData ); } else{ Log::info('[Process] '.$LOGO_NO.' '.$logModular .' ' . $logData ); } } /** * 过程报错接口LOG * @param string/array $logData 数据 */ public static function errorLog($logData=""){ $LOGO_NO = Session::get("LOGO_NO"); if(!$LOGO_NO){ $LOGO_NO = 'LOG'.date('Ymdhis',time()).rand(1000000,10000000); Session::put('LOGO_NO', $LOGO_NO); } if(is_array($logData)){ $logData = json_encode($logData,true); } Log::info('[Error] '.$LOGO_NO.' '. $logData ); Session::remove("LOGO_NO"); } /** * 返回接口LOG * @param string $logModular 模块 * @param string/array $logData 数据 */ public static function backLog($logModular="", $logData=[]){ $LOGO_NO = Session::get("LOGO_NO"); $log = array( 'code' => $logData['code'], 'result' => $logData['result'], 'message' => $logData['message'], ); if(array_key_exists('ret',$logData)){ $log['ret'] = $logData['ret']; } Log::info('[Back] '.$LOGO_NO.' '. $logModular .' ' .json_encode($log,true)); Session::remove("LOGO_NO"); } /** * 自定义LOG * @param string $label log标签 * @param string $logContent 备注 * @param string/array $logData 数据 */ public static function customLog($label="DEBUG", $logContent="", $logData=""){ $LOGO_NO = Session::get("LOGO_NO"); if(!$LOGO_NO){ $LOGO_NO = 'LOG'.date('Ymdhis',time()).rand(1000000,10000000); Session::put('LOGO_NO', $LOGO_NO); } if(is_array($logData)){ // 将数组转为字符串 $logDataArray = $logData; $logData = ''; foreach ($logDataArray as $key=>$logDataRow){ if(is_array($logDataRow)){ $logDataRow = json_encode($logDataRow,true); } $str=$key.":".$logDataRow; $logData.=$str.' '; } } if($logContent){ Log::info('['.$label.'] '.$LOGO_NO.' '.$logContent.' '. $logData ); } else{ Log::info('['.$label.'] '.$LOGO_NO.' '. $logData ); } Session::remove("LOGO_NO"); }
调用:入参时调用(中间件BeforeRequest)
public function handle($request, Closure $next) { Utils::requestLog($request->getPathInfo(), $request->getClientIp(), $request->all()); return $next($request); }
过程中调用,例如:
public function recommendUsers(Request $request) { Utils::processLog(__METHOD__, '测试'); // 1 $data = Utils::requestParameter($request); $user_id = $data['user_id']; $language = $data['language']; Utils::processLog(__METHOD__, '',$language); // 2 Utils::processLog(__METHOD__, '',[$language,$user_id]); // 3 Utils::processLog(__METHOD__,'我是测试', [$language,$user_id]); // 4 //推荐骑士 $users = self::getUsersWithOutNotice($user_id, $language); return ApiResponse::makeResponse(true, $users, ApiResponse::SUCCESS_CODE, $data['language']); }
代码错误时(/app/Exceptions/Handler.php)
public function report(Exception $exception) { Utils::errorLog($exception); //添加此行代码 parent::report($exception); }
返回时调用(ApiResponse):
//以上为省略代码Utils::backLog(__METHOD__, $rsp);return response()->json($rsp);
5.自定义LOG,以检测到错误路由为例:(/vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php)
public function match(Request $request) { $routes = $this->get($request->getMethod()); // First, we will see if we can find a matching route for this current request // method. If we can, great, we can just return it so that it can be called // by the consumer. Otherwise we will check for routes with another verb. $route = $this->matchAgainstRoutes($routes, $request); if (! is_null($route)) { return $route->bind($request); } /////////////LOG-START//////////////////// $logData=array( 'route'=>$request->getPathInfo(), 'method'=>$request->getMethod(), 'Info'=>$request ); Utils::customLog("ErrorNotFoundHttpException","路由错误",$logData); /////////////LOG-END//////////////////// // If no route was found we will now check if a matching route is specified by // another HTTP verb. If it is we will need to throw a MethodNotAllowed and // inform the user agent of which HTTP verb it should use for this route. $others = $this->checkForAlternateVerbs($request); if (count($others) > 0) { return $this->getRouteForMethods($request, $others); } throw new NotFoundHttpException; }

四、后记

应用日志是排查故障、发展隐患、回溯问题的重要工具,本次主要讲解应用系统的日志输出方案,每天应该进行日志巡检(tail -f -n 100000 laravel.log | grep Error),检索错误信息,及时优化业务系统,提升稳定性和健壮性。

标签: #php输出日志