From 054a0bcba733ca3944a83b053240e4adb59a8868 Mon Sep 17 00:00:00 2001 From: joyboo Date: Tue, 26 Sep 2023 02:03:10 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Logs=E6=97=A5=E5=BF=97=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=99=A8=20&&=20=E6=B6=88=E8=B4=B9=E8=BF=9B=E7=A8=8B=E4=BC=A0?= =?UTF-8?q?=E9=80=92=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/Common/Classes/LamLog.php | 136 ----------------------------- src/Common/Logs/Handler.php | 140 ++++++++++++++++++++++++++++++ src/Common/Logs/Item.php | 55 ++++++++++++ src/Consumer/BaseTrait.php | 19 ++-- src/Consumer/HttpTrackerTrait.php | 4 +- src/Consumer/ProcessInfoTrait.php | 3 +- 7 files changed, 209 insertions(+), 150 deletions(-) delete mode 100644 src/Common/Classes/LamLog.php create mode 100644 src/Common/Logs/Handler.php create mode 100644 src/Common/Logs/Item.php diff --git a/README.md b/README.md index 6fc0c61..7892ac8 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ │ │ ├── ExceptionTrigger 自定义异常处理器,将异常上报至redis或http │ │ ├── FdManager WebSocket连接符管理,共享内存(Swoole\Table)实现 │ │ ├── LamJwt jwt - │ │ ├── LamLog 自定义日志处理器 │ │ ├── LamOpenssl RSA数据加密和解密 │ │ ├── LamUnit 辅助工具类 │ │ ├── Mysqli 对MysqlClient的二次封装 @@ -37,6 +36,7 @@ │ │ ├── Dictionary 国际化字典,项目请`继承`它 │ │ └── Languages I18n助手类,主要用来注册、设置 │ │ + │ ├── Logs 自定义日志处理器 │ └── OrmCache 模型缓存组件,已实现 String、Hash、Set、SplArray │ ├── HttpController diff --git a/src/Common/Classes/LamLog.php b/src/Common/Classes/LamLog.php deleted file mode 100644 index 98732de..0000000 --- a/src/Common/Classes/LamLog.php +++ /dev/null @@ -1,136 +0,0 @@ -logDir = $logDir ?: ''; - } - - public function log($msg, int $logLevel = self::LOG_LEVEL_INFO, string $category = 'debug'): string - { - $str = $this->_preAct($msg, $logLevel, $category, 'log'); - - // 立即写入 - if ($category === self::CATE_IMMEDIATE || Coroutine::getCid() < 0) { - $this->save(); - } // 协程defer时写入 - else { - Coroutine::defer(function () { - $this->save(); - }); - } - - return $str; - } - - public function console($msg, int $logLevel = self::LOG_LEVEL_INFO, string $category = 'debug') - { - $str = $this->_preAct($msg, $logLevel, $category, 'console'); - $cid = Coroutine::getCid(); - fwrite(STDOUT, "[CID=$cid]$str\n"); - } - - // 保存日志 - public function save() - { - empty($this->logDir) && $this->logDir = config('LOG.dir'); - $dir = $this->logDir . '/' . date('ym'); - is_dir($dir) or @ mkdir($dir, 0777, true); - - // conArr[$cid][$key][] = $value - foreach ((array)$this->conArr[Coroutine::getUid()] as $key => $value) { - if (empty($value) || ! is_array($value)) { - continue; - } - - $fname = $key == $this->dfKey ? '' : "-$key"; - - file_put_contents("$dir/" . date('d') . $fname . ".log", "\n" . implode("\n", $value) . "\n", FILE_APPEND | LOCK_EX); - } - - unset($this->conArr[Coroutine::getUid()]); - - return true; - } - - private function _preAct($msg, int &$logLevel = self::LOG_LEVEL_INFO, string $category = 'console', string $func = 'log') - { - if ( ! is_scalar($msg)) { - $msg = json_encode($msg, JSON_UNESCAPED_UNICODE); - } - $msg = str_replace(["\n", "\r"], '', $msg); - - // 不在东8区则拼接上东8区的时间 - $tznInt = intval(substr((int)date('O'), 0, -2)); - $time = time(); - if ($tznInt !== 8) { - $date = "{$tznInt}区: " . date(DateUtils::FULL, $time); - $date .= ', +8区: ' . date(DateUtils::FULL, DateUtils::getTimeZoneStamp($time, 'PRC')); - } else { - $date = date(DateUtils::FULL, $time); - } - - $logLevel = $this->levelMap($logLevel); - - $str = "[$date][$category][$logLevel]$msg"; - - if ($func == 'log') { - if (in_array($logLevel, config('LOG.apart_level'))) { - $this->merge($logLevel, $str); - } elseif (in_array($category, config('LOG.apart_category'))) { - $this->merge($category, $str); - } else { - $this->merge($this->dfKey, $str); - } - } - - return $str; - } - - private function levelMap(int $level) - { - switch ($level) { - case self::LOG_LEVEL_INFO: - return 'info'; - case self::LOG_LEVEL_NOTICE: - return 'notice'; - case self::LOG_LEVEL_WARNING: - return 'warning'; - case self::LOG_LEVEL_ERROR: - return 'error'; - default: - return 'unknown'; - } - } - - /** - * 完整实例: conArr[$cid][$key][] = $value - * @param string $key - * @param string $value - */ - protected function merge($key = '', $value = '') - { - $this->conArr[Coroutine::getUid()][$key][] = $value; - } -} diff --git a/src/Common/Logs/Handler.php b/src/Common/Logs/Handler.php new file mode 100644 index 0000000..fb88e99 --- /dev/null +++ b/src/Common/Logs/Handler.php @@ -0,0 +1,140 @@ +logDir = $logDir ?: ''; + $times && $this->times = $times; + } + + public function __destruct() + { + $this->run(); + } + + public function log($msg, int $logLevel = self::LOG_LEVEL_INFO, string $category = 'debug'): string + { + $logLevel = $this->levelMap($logLevel); + $Item = new Item([ + 'message' => $msg, + 'level' => $logLevel, + 'category' => $category + ]); + $this->list[] = $Item; + + if (Coroutine::getCid() < 0) { + $this->run(); + } else { + Coroutine::defer(function () { + $this->run(); + }); + if (count($this->list) >= $this->times) { + $this->run(); + } + } + return $Item->getWriteStr(); + } + + public function console($msg, int $logLevel = self::LOG_LEVEL_INFO, string $category = 'debug') + { + $logLevel = $this->levelMap($logLevel); + $Item = new Item([ + 'message' => $msg, + 'level' => $logLevel, + 'category' => $category + ]); + $str = $Item->getWriteStr(); + fwrite(STDOUT, "$str\n"); + } + + public function run() + { + if ($this->writeing) { + return; + } + $this->writeing = true; + + empty($this->logDir) && $this->logDir = config('LOG.dir'); + $dir = $this->logDir . '/' . date('ym'); + is_dir($dir) or @ mkdir($dir, 0777, true); + + if (empty($this->list)) { + return; + } + + $apartLevel = config('LOG.apart_level'); + $apartCategory = config('LOG.apart_category'); + + // $apart-独立记录, $arr-通用记录 + $apart = $arr = []; + /** @var Item $Item */ + foreach ($this->list as $key => $Item) { + + $str = $Item->getWriteStr(); + + if (in_array($Item->level, $apartLevel)) { + $apart[$Item->level][] = $str; + } elseif (in_array($Item->category, $apartCategory)) { + $apart[$Item->category][] = $str; + } else { + $arr[] = $str; + } + + unset($this->list[$key]); + } + $this->list = []; + $this->writeing = false; + + foreach ($apart as $name => $values) { + $this->save($dir, $values, $name); + } + $arr && $this->save($dir, $arr); + } + + protected function save($dir, $values, $name = '') + { + if (empty($values)) { + return; + } + $name = $name ? "-$name" : ''; + + $d = date('d'); + file_put_contents("$dir/{$d}{$name}.log", "\n" . implode("\n", $values) . "\n", FILE_APPEND | LOCK_EX); + } + + private function levelMap(int $level) + { + switch ($level) { + case self::LOG_LEVEL_INFO: + return 'info'; + case self::LOG_LEVEL_NOTICE: + return 'notice'; + case self::LOG_LEVEL_WARNING: + return 'warning'; + case self::LOG_LEVEL_ERROR: + return 'error'; + default: + return 'unknown'; + } + } +} diff --git a/src/Common/Logs/Item.php b/src/Common/Logs/Item.php new file mode 100644 index 0000000..e33e1c0 --- /dev/null +++ b/src/Common/Logs/Item.php @@ -0,0 +1,55 @@ +cid = Coroutine::getCid(); + + if ( ! is_scalar($this->message)) { + $this->message = json_encode($this->message, JSON_UNESCAPED_UNICODE); + } + $this->message = str_replace(["\n", "\r"], '', $this->message); + + // 产生日志的时间 + $this->time = time(); + $this->date = date(DateUtils::FULL, $this->time); + // 不在东8区,则记录东8区时间 + $tznInt = intval(substr((int)date('O'), 0, -2)); + if ($tznInt !== 8) { + $this->date .= ', +8区: ' . date(DateUtils::FULL, DateUtils::getTimeZoneStamp($this->time, 'PRC')); + } + } + + public function getWriteStr() + { + return "[cid={$this->cid}][{$this->date}][{$this->category}][{$this->level}]{$this->message}"; + } + + public function __get($name) + { + if (property_exists($this, $name)) { + return $this->{$name}; + } + throw new \Exception(__CLASS__ . ' Not fount property : ' . $name); + } +} diff --git a/src/Consumer/BaseTrait.php b/src/Consumer/BaseTrait.php index da1cb52..aebda3e 100644 --- a/src/Consumer/BaseTrait.php +++ b/src/Consumer/BaseTrait.php @@ -21,8 +21,8 @@ trait BaseTrait * 'queue' => 'queue_login', // 监听的redis队列名 * 'tick' => 1000, // 多久运行一次,单位毫秒, 默认1000毫秒 * 'limit' => 200, // 单次出队列的阈值, 默认200 - * 'coroutine' => false // 是否为每条数据开启协程 - * 'pool' => 'default' // redis连接池名称 + * 'pool' => 'default' // redis连接池名称 + * 'json' => false // 是否需要json_decode * ], * */ @@ -36,10 +36,11 @@ protected function onException(\Throwable $throwable, ...$args) /** * 消费单条数据,由子类继承实现 - * @param string $data 每一条队列数据 + * @param string|array $data 每一条队列数据 + * @param Redis|null $redis redis连接 * @return mixed */ - abstract protected function consume($data = ''); + abstract protected function consume($data = [], Redis $redis = null); /** * EasySwoole自定义进程入口 @@ -63,14 +64,10 @@ public function run() break; } try { - $openCoroutine = $this->args['coroutine'] ?? false; - if ($openCoroutine) { - go(function () use ($data) { - $this->consume($data); - }); - } else { - $this->consume($data); + if ( ! empty($this->args['json'])) { + $data = json_decode($data); } + $this->consume($data, $Redis); } catch (\Throwable $throwable) { \EasySwoole\EasySwoole\Trigger::getInstance()->throwable($throwable); } diff --git a/src/Consumer/HttpTrackerTrait.php b/src/Consumer/HttpTrackerTrait.php index 9595c93..b031027 100644 --- a/src/Consumer/HttpTrackerTrait.php +++ b/src/Consumer/HttpTrackerTrait.php @@ -2,9 +2,11 @@ namespace WonderGame\EsUtility\Consumer; +use EasySwoole\Redis\Redis; + trait HttpTrackerTrait { - protected function consume($data = '') + protected function consume($data = [], Redis $redis = null) { try { diff --git a/src/Consumer/ProcessInfoTrait.php b/src/Consumer/ProcessInfoTrait.php index 6488444..7930cab 100644 --- a/src/Consumer/ProcessInfoTrait.php +++ b/src/Consumer/ProcessInfoTrait.php @@ -3,10 +3,11 @@ namespace WonderGame\EsUtility\Consumer; use EasySwoole\ORM\AbstractModel; +use EasySwoole\Redis\Redis; trait ProcessInfoTrait { - protected function consume($data = '') + protected function consume($data = [], Redis $redis = null) { $data = json_decode($data, true); if ( ! $data) { From eaee6fa0d3fdfcb208d7bec879fe6ddf4c63de4d Mon Sep 17 00:00:00 2001 From: Joyboo Date: Tue, 26 Sep 2023 15:25:58 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E5=86=99=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/Logs/Handler.php | 91 ++++++------------------------------- src/Consumer/BaseTrait.php | 2 +- 2 files changed, 16 insertions(+), 77 deletions(-) diff --git a/src/Common/Logs/Handler.php b/src/Common/Logs/Handler.php index fb88e99..2d8cbea 100644 --- a/src/Common/Logs/Handler.php +++ b/src/Common/Logs/Handler.php @@ -2,35 +2,18 @@ namespace WonderGame\EsUtility\Common\Logs; -use EasySwoole\Component\Timer; use EasySwoole\Log\LoggerInterface; -use Swoole\Coroutine; +/** + * 日志处理器 + */ class Handler implements LoggerInterface { /** - * @var array Item[] + * 本地降级使用的保存目录 + * @var string */ - protected $list = []; - - protected $times = 10; - - protected $writeing = false; - - /** - * @param string|null $logDir 日志主目录 - * @params int $times - */ - public function __construct(string $logDir = null, $times = 10) - { - $this->logDir = $logDir ?: ''; - $times && $this->times = $times; - } - - public function __destruct() - { - $this->run(); - } + protected $logDir = ''; public function log($msg, int $logLevel = self::LOG_LEVEL_INFO, string $category = 'debug'): string { @@ -40,18 +23,8 @@ public function log($msg, int $logLevel = self::LOG_LEVEL_INFO, string $category 'level' => $logLevel, 'category' => $category ]); - $this->list[] = $Item; - if (Coroutine::getCid() < 0) { - $this->run(); - } else { - Coroutine::defer(function () { - $this->run(); - }); - if (count($this->list) >= $this->times) { - $this->run(); - } - } + $this->save($Item); return $Item->getWriteStr(); } @@ -67,59 +40,25 @@ public function console($msg, int $logLevel = self::LOG_LEVEL_INFO, string $cate fwrite(STDOUT, "$str\n"); } - public function run() + public function save(Item $Item) { - if ($this->writeing) { - return; - } - $this->writeing = true; - empty($this->logDir) && $this->logDir = config('LOG.dir'); $dir = $this->logDir . '/' . date('ym'); is_dir($dir) or @ mkdir($dir, 0777, true); - if (empty($this->list)) { - return; - } - $apartLevel = config('LOG.apart_level'); $apartCategory = config('LOG.apart_category'); - // $apart-独立记录, $arr-通用记录 - $apart = $arr = []; - /** @var Item $Item */ - foreach ($this->list as $key => $Item) { - - $str = $Item->getWriteStr(); - - if (in_array($Item->level, $apartLevel)) { - $apart[$Item->level][] = $str; - } elseif (in_array($Item->category, $apartCategory)) { - $apart[$Item->category][] = $str; - } else { - $arr[] = $str; - } - - unset($this->list[$key]); - } - $this->list = []; - $this->writeing = false; - - foreach ($apart as $name => $values) { - $this->save($dir, $values, $name); - } - $arr && $this->save($dir, $arr); - } - - protected function save($dir, $values, $name = '') - { - if (empty($values)) { - return; + $name = ''; + if (in_array($Item->level, $apartLevel)) { + $name = '-' . $Item->level; + } elseif (in_array($Item->category, $apartCategory)) { + $name = '-' . $Item->category; } - $name = $name ? "-$name" : ''; $d = date('d'); - file_put_contents("$dir/{$d}{$name}.log", "\n" . implode("\n", $values) . "\n", FILE_APPEND | LOCK_EX); + $str = $Item->getWriteStr(); + file_put_contents("$dir/{$d}{$name}.log", "$str\n", FILE_APPEND | LOCK_EX); } private function levelMap(int $level) diff --git a/src/Consumer/BaseTrait.php b/src/Consumer/BaseTrait.php index aebda3e..da2df40 100644 --- a/src/Consumer/BaseTrait.php +++ b/src/Consumer/BaseTrait.php @@ -65,7 +65,7 @@ public function run() } try { if ( ! empty($this->args['json'])) { - $data = json_decode($data); + $data = json_decode($data, true); } $this->consume($data, $Redis); } catch (\Throwable $throwable) {