LogTraceHandler.php 4.17 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
<?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(),
            'process_info'=>'',
            '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,
            'is_completed'=>NO
        ]);
//        $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);
//    }

}