<?php /** * 执行日志记录 */ namespace Meibuyu\Micro\Handler\LogTrace; use Meibuyu\Micro\Model\LogTrace; use Hyperf\Utils\Coroutine; use Swoole\Server; use Throwable; /** * Class LogTraceHandler * @package App\Service */ class LogTraceHandler { /** * 1.对执行操作进行的方法入口注解 LogTrace 2.对程序主动进行输出 try { //流程1 LogTraceHandler::recordProcess('执行到流程1'); //流程2 LogTraceHandler::recordProcess('执行到流程2'); //记录输出数组 LogTraceHandler::recordProcess(['test'=>1]); //流程3 抛出一个异常 throw new Exception('test111'); //流程执行完成标记结束 LogTraceHandler::markComplete(); }catch (\Throwable $exception){ //记录异常日志 LogTraceHandler::recordProcess($exception); } * @param $params * @param $source * @return mixed * @throws \Exception */ public static function createLogTrace($source, $params) { if(!Coroutine::inCoroutine()) return; LogTrace::insertOrIgnore([ 'request_id' => self::getRequestId(), 'origin_params' => json_encode($params), 'source' => $source, 'created_at' => now(), 'process_info' => '' ]); } /** * @param bool $isInAsyncCoroutine * @return string * @throws \Exception */ private static function getRequestId($isInAsyncCoroutine=false) { $workId = posix_getpid(); $cid = $isInAsyncCoroutine?Coroutine::parentId(Coroutine::id()):Coroutine::id(); if(!$cid) throw new \Exception('无法使用协程标记录日志'); return container(Server::class)->stats()['start_time'] .$workId. $cid; } /** * 程序执行完成标记结束 * @throws \Exception */ public static function markComplete() { if(!Coroutine::inCoroutine()) return; container(LogTraceQueue::class)->addToQueue([ 'request_id'=>self::getRequestId(), 'is_completed'=>YES ]); //LogTrace::where('request_id', self::getRequestId())->update(['is_completed' => YES]); } /* * 事务回滚导致部分流程日志无法记录 暂写到文件里 * 待写到Es后可以避免 * 记录当前日志(包括异常捕获) */ public static function recordProcess($track,$isInAsyncCoroutine=false) { if (empty($track)) return; if(!Coroutine::inCoroutine()) return; $logInfo = ''; if ($track instanceof Throwable) { $logInfo = $track->getMessage() . "\n" . $track->getFile() . " line:" . $track->getLine() . "\n" . $track->getTraceAsString(); } if (is_array($track)) { $logInfo = var_export($track, true); } if (is_string($track)||is_numeric($track)) { $logInfo = $track; } $logInfo .= "\n\n"; container(LogTraceQueue::class)->addToQueue([ 'request_id'=>self::getRequestId($isInAsyncCoroutine), 'process_info'=>$logInfo ]); // $log = LogTrace::where('request_id', self::getRequestId())->first(); // if(empty($log)) return ; // // $log->update([ // 'process_info' => Db::raw("CONCAT(process_info,\"{$logInfo}\")") // ]); // //写入文件 // put_log( // self::getRequestId()."\n". // $logInfo, // str_replace('\\','_',$log->source).'/'.today() // ); } // /** // * 记录流程日志 // * @param $funName // * @param $arguments // * @throws \Exception // */ // public static function __callStatic($funName, $arguments) // { // if(self::$instance){ // throw new \Exception('请用LogTraceService::createLogTrace 先实例化对象'); // } // self::$instance->$funName($arguments); // } }