mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-21 15:45:36 +08:00
use zhamao/logger table printer instead
This commit is contained in:
@@ -18,14 +18,14 @@ use ZM\Annotation\Swoole\SwooleHandler;
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\ConnectionManager\ManagerGM;
|
||||
use ZM\Console\Console;
|
||||
use ZM\Console\TermColor;
|
||||
use ZM\Exception\ConfigException;
|
||||
use ZM\Exception\ZMKnownException;
|
||||
use ZM\Logger\TablePrinter;
|
||||
use ZM\Store\LightCache;
|
||||
use ZM\Store\LightCacheInside;
|
||||
use ZM\Store\Lock\SpinLock;
|
||||
use ZM\Store\ZMAtomic;
|
||||
use ZM\Utils\DataProvider;
|
||||
use ZM\Utils\Manager\ProcessManager;
|
||||
use ZM\Utils\Terminal;
|
||||
use ZM\Utils\ZMUtil;
|
||||
|
||||
@@ -84,9 +84,9 @@ class Framework
|
||||
*/
|
||||
public function __construct(array $args = [], bool $instant_mode = false)
|
||||
{
|
||||
$tty_width = $this->getTtyWidth();
|
||||
self::$instant_mode = $instant_mode;
|
||||
self::$argv = $args;
|
||||
Runtime::enableCoroutine(false);
|
||||
|
||||
// 初始化配置
|
||||
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
|
||||
@@ -152,7 +152,7 @@ class Framework
|
||||
}
|
||||
|
||||
// 解析命令行参数
|
||||
$this->parseCliArgs(self::$argv, $add_port);
|
||||
$coroutine_mode = $this->parseCliArgs(self::$argv, $add_port);
|
||||
|
||||
// 设置默认最长等待时间
|
||||
if (!isset($this->swoole_server_config['max_wait_time'])) {
|
||||
@@ -180,7 +180,7 @@ class Framework
|
||||
}
|
||||
$out['environment'] = ($args['env'] ?? null) === null ? 'default' : $args['env'];
|
||||
$out['log_level'] = Console::getLevel();
|
||||
$out['version'] = ZM_VERSION . (LOAD_MODE === 0 ? (' (build ' . ZM_VERSION_ID . ')') : '');
|
||||
$out['version'] = Framework::VERSION . (LOAD_MODE === 0 ? (' (build ' . ZM_VERSION_ID . ')') : '');
|
||||
$out['master_pid'] = posix_getpid();
|
||||
if (APP_VERSION !== 'unknown') {
|
||||
$out['app_version'] = APP_VERSION;
|
||||
@@ -212,7 +212,12 @@ class Framework
|
||||
$conf = ZMConfig::get('global', 'remote_terminal');
|
||||
$out['terminal'] = $conf['host'] . ':' . $conf['port'];
|
||||
}
|
||||
self::printProps($out, $tty_width, $args['log-theme'] === null);
|
||||
if (LOAD_MODE === 0) {
|
||||
echo Console::setColor("* Framework started with source mode.\n", $args['log-theme'] === null ? 'yellow' : '');
|
||||
}
|
||||
// $this->mapOutput($out); // 汉化操作
|
||||
$printer = new TablePrinter($out);
|
||||
$printer->setValueColor('random')->printAll();
|
||||
}
|
||||
|
||||
// 预览模式则直接提出
|
||||
@@ -312,7 +317,14 @@ class Framework
|
||||
|
||||
// 非静默模式下,打印欢迎信息
|
||||
if (!self::$argv['private-mode']) {
|
||||
self::printMotd($tty_width);
|
||||
self::printMotd(isset($printer) ? $printer->fetchTerminalSize() : 79);
|
||||
}
|
||||
|
||||
$global_hook = ZMConfig::get('global', 'runtime')['swoole_coroutine_hook_flags'] ?? (SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL));
|
||||
if ($coroutine_mode) {
|
||||
Runtime::enableCoroutine(true, $global_hook);
|
||||
} else {
|
||||
Runtime::enableCoroutine(false, SWOOLE_HOOK_ALL);
|
||||
}
|
||||
|
||||
global $asd;
|
||||
@@ -374,157 +386,21 @@ class Framework
|
||||
} catch (Exception $e) {
|
||||
Console::error('框架初始化出现异常,请检查!');
|
||||
Console::error(zm_internal_errcode('E00010') . $e->getMessage());
|
||||
if (strpos($e->getMessage(), 'Address already in use') !== false) {
|
||||
if (!ProcessManager::isStateEmpty()) {
|
||||
Console::error('检测到可能残留框架的工作进程,请先通过命令杀死:server:stop --force');
|
||||
}
|
||||
}
|
||||
Console::debug($e);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将各进程的pid写入文件,以备后续崩溃及僵尸进程处理使用
|
||||
*
|
||||
* @param int|string $pid
|
||||
* @internal
|
||||
*/
|
||||
public static function saveProcessState(int $type, $pid, array $data = [])
|
||||
{
|
||||
switch ($type) {
|
||||
case ZM_PROCESS_MASTER:
|
||||
$file = _zm_pid_dir() . '/master.json';
|
||||
$json = [
|
||||
'pid' => intval($pid),
|
||||
'stdout' => $data['stdout'],
|
||||
'daemon' => $data['daemon'],
|
||||
];
|
||||
file_put_contents($file, json_encode($json, JSON_UNESCAPED_UNICODE));
|
||||
return;
|
||||
case ZM_PROCESS_MANAGER:
|
||||
$file = _zm_pid_dir() . '/manager.pid';
|
||||
file_put_contents($file, strval($pid));
|
||||
return;
|
||||
case ZM_PROCESS_WORKER:
|
||||
$file = _zm_pid_dir() . '/worker.' . $data['worker_id'] . '.pid';
|
||||
file_put_contents($file, strval($pid));
|
||||
return;
|
||||
case ZM_PROCESS_USER:
|
||||
$file = _zm_pid_dir() . '/user.' . $data['process_name'] . '.pid';
|
||||
file_put_contents($file, strval($pid));
|
||||
return;
|
||||
case ZM_PROCESS_TASKWORKER:
|
||||
$file = _zm_pid_dir() . '/taskworker.' . $data['worker_id'] . '.pid';
|
||||
file_put_contents($file, strval($pid));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于框架内部获取多进程运行状态的函数
|
||||
*
|
||||
* @param mixed $id_or_name
|
||||
* @throws ZMKnownException
|
||||
* @return false|int|mixed
|
||||
* @internal
|
||||
*/
|
||||
public static function getProcessState(int $type, $id_or_name = null)
|
||||
{
|
||||
$file = _zm_pid_dir();
|
||||
switch ($type) {
|
||||
case ZM_PROCESS_MASTER:
|
||||
if (!file_exists($file . '/master.json')) {
|
||||
return false;
|
||||
}
|
||||
$json = json_decode(file_get_contents($file . '/master.json'), true);
|
||||
if ($json !== null) {
|
||||
return $json;
|
||||
}
|
||||
return false;
|
||||
case ZM_PROCESS_MANAGER:
|
||||
if (!file_exists($file . '/manager.pid')) {
|
||||
return false;
|
||||
}
|
||||
return intval(file_get_contents($file . '/manager.pid'));
|
||||
case ZM_PROCESS_WORKER:
|
||||
if (!is_int($id_or_name)) {
|
||||
throw new ZMKnownException('E99999', 'worker_id必须为整数');
|
||||
}
|
||||
if (!file_exists($file . '/worker.' . $id_or_name . '.pid')) {
|
||||
return false;
|
||||
}
|
||||
return intval(file_get_contents($file . '/worker.' . $id_or_name . '.pid'));
|
||||
case ZM_PROCESS_USER:
|
||||
if (!is_string($id_or_name)) {
|
||||
throw new ZMKnownException('E99999', 'process_name必须为字符串');
|
||||
}
|
||||
if (!file_exists($file . '/user.' . $id_or_name . '.pid')) {
|
||||
return false;
|
||||
}
|
||||
return intval(file_get_contents($file . '/user.' . $id_or_name . '.pid'));
|
||||
case ZM_PROCESS_TASKWORKER:
|
||||
if (!is_int($id_or_name)) {
|
||||
throw new ZMKnownException('E99999', 'worker_id必须为整数');
|
||||
}
|
||||
if (!file_exists($file . '/taskworker.' . $id_or_name . '.pid')) {
|
||||
return false;
|
||||
}
|
||||
return intval(file_get_contents($file . '/taskworker.' . $id_or_name . '.pid'));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|int|string $id_or_name
|
||||
* @throws ZMKnownException
|
||||
* @internal
|
||||
*/
|
||||
public static function removeProcessState(int $type, $id_or_name = null)
|
||||
{
|
||||
switch ($type) {
|
||||
case ZM_PROCESS_MASTER:
|
||||
$file = _zm_pid_dir() . '/master.json';
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
return;
|
||||
case ZM_PROCESS_MANAGER:
|
||||
$file = _zm_pid_dir() . '/manager.pid';
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
return;
|
||||
case ZM_PROCESS_WORKER:
|
||||
if (!is_int($id_or_name)) {
|
||||
throw new ZMKnownException('E99999', 'worker_id必须为整数');
|
||||
}
|
||||
$file = _zm_pid_dir() . '/worker.' . $id_or_name . '.pid';
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
return;
|
||||
case ZM_PROCESS_USER:
|
||||
if (!is_string($id_or_name)) {
|
||||
throw new ZMKnownException('E99999', 'process_name必须为字符串');
|
||||
}
|
||||
$file = _zm_pid_dir() . '/user.' . $id_or_name . '.pid';
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
return;
|
||||
case ZM_PROCESS_TASKWORKER:
|
||||
if (!is_int($id_or_name)) {
|
||||
throw new ZMKnownException('E99999', 'worker_id必须为整数');
|
||||
}
|
||||
$file = _zm_pid_dir() . '/taskworker.' . $id_or_name . '.pid';
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
try {
|
||||
self::$loaded_files = get_included_files();
|
||||
LightCacheInside::set('tmp_kv', 'start_time', microtime(true));
|
||||
self::$server->start();
|
||||
zm_atomic('server_is_stopped')->set(1);
|
||||
if (!self::$argv['private-mode']) {
|
||||
@@ -535,63 +411,6 @@ class Framework
|
||||
}
|
||||
}
|
||||
|
||||
public static function printProps($out, $tty_width, $colorful = true)
|
||||
{
|
||||
$max_border = min($tty_width, 65);
|
||||
if (LOAD_MODE === 0) {
|
||||
echo Console::setColor("* Framework started with source mode.\n", $colorful ? 'yellow' : '');
|
||||
}
|
||||
echo str_pad('', $max_border, '=') . PHP_EOL;
|
||||
|
||||
$current_line = 0;
|
||||
$line_width = [];
|
||||
$line_data = [];
|
||||
foreach ($out as $k => $v) {
|
||||
start:
|
||||
if (!isset($line_width[$current_line])) {
|
||||
$line_width[$current_line] = $max_border - 2;
|
||||
}
|
||||
// Console::info("行宽[$current_line]:".$line_width[$current_line]);
|
||||
if ($max_border >= 57) { // 很宽的时候,一行能放两个短行
|
||||
if ($line_width[$current_line] === ($max_border - 2)) { // 空行
|
||||
self::writeNoDouble($k, $v, $line_data, $line_width, $current_line, $colorful, $max_border);
|
||||
} else { // 不是空行,已经有东西了
|
||||
$tmp_line = $k . ': ' . $v;
|
||||
// Console::info("[$current_line]即将插入后面的东西[".$tmp_line."]");
|
||||
if (strlen($tmp_line) > $line_width[$current_line]) { // 地方不够,另起一行
|
||||
$line_data[$current_line] = str_replace('| ', '', $line_data[$current_line]);
|
||||
++$current_line;
|
||||
goto start;
|
||||
} // 地方够,直接写到后面并另起一行
|
||||
$line_data[$current_line] .= $k . ': ';
|
||||
if ($colorful) {
|
||||
$line_data[$current_line] .= TermColor::color8(32);
|
||||
}
|
||||
$line_data[$current_line] .= $v;
|
||||
if ($colorful) {
|
||||
$line_data[$current_line] .= TermColor::RESET;
|
||||
}
|
||||
++$current_line;
|
||||
}
|
||||
} else { // 不够宽,直接写单行
|
||||
self::writeNoDouble($k, $v, $line_data, $line_width, $current_line, $colorful, $max_border);
|
||||
}
|
||||
}
|
||||
foreach ($line_data as $v) {
|
||||
echo $v . PHP_EOL;
|
||||
}
|
||||
echo str_pad('', $max_border, '=') . PHP_EOL;
|
||||
}
|
||||
|
||||
public function getTtyWidth(): int
|
||||
{
|
||||
$size = exec('stty size');
|
||||
if (empty($size)) {
|
||||
return 65;
|
||||
}
|
||||
return (int) explode(' ', trim($size))[1];
|
||||
}
|
||||
|
||||
public static function loadFrameworkState()
|
||||
{
|
||||
if (!file_exists(DataProvider::getDataFolder() . '.state.json')) {
|
||||
@@ -609,6 +428,24 @@ class Framework
|
||||
return file_put_contents(DataProvider::getDataFolder() . '.state.json', json_encode($data, 64 | 128 | 256));
|
||||
}
|
||||
|
||||
public function mapOutput(array &$out)
|
||||
{
|
||||
$translate = [
|
||||
'working_dir' => '工作目录',
|
||||
'listen' => '监听地址',
|
||||
'worker' => '工作进程数',
|
||||
'environment' => '环境类型',
|
||||
'log_level' => '日志级别',
|
||||
'version' => '框架版本',
|
||||
'master_pid' => '主进程PID',
|
||||
];
|
||||
foreach ($out as $k => $v) {
|
||||
if (isset($translate[$k])) {
|
||||
$this->arrayChangeKey($out, $k, $translate[$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function printMotd($tty_width)
|
||||
{
|
||||
if (file_exists(DataProvider::getSourceRootDir() . '/config/motd.txt')) {
|
||||
@@ -776,68 +613,14 @@ class Framework
|
||||
}
|
||||
}
|
||||
}
|
||||
$global_hook = ZMConfig::get('global', 'runtime')['swoole_coroutine_hook_flags'] ?? (SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL));
|
||||
if ($coroutine_mode) {
|
||||
Runtime::enableCoroutine(true, $global_hook);
|
||||
} else {
|
||||
Runtime::enableCoroutine(false, SWOOLE_HOOK_ALL);
|
||||
}
|
||||
return $coroutine_mode;
|
||||
}
|
||||
|
||||
private static function writeNoDouble($k, $v, &$line_data, &$line_width, &$current_line, $colorful, $max_border)
|
||||
private function arrayChangeKey(array &$arr, $old_key, $new_key)
|
||||
{
|
||||
$tmp_line = $k . ': ' . $v;
|
||||
// Console::info("写入[".$tmp_line."]");
|
||||
if (strlen($tmp_line) > $line_width[$current_line]) { // 输出的内容太多了,以至于一行都放不下一个,要折行
|
||||
$title_strlen = strlen($k . ': ');
|
||||
$content_len = $line_width[$current_line] - $title_strlen;
|
||||
|
||||
$line_data[$current_line] = ' ' . $k . ': ';
|
||||
if ($colorful) {
|
||||
$line_data[$current_line] .= TermColor::color8(32);
|
||||
}
|
||||
$line_data[$current_line] .= substr($v, 0, $content_len);
|
||||
if ($colorful) {
|
||||
$line_data[$current_line] .= TermColor::RESET;
|
||||
}
|
||||
$rest = substr($v, $content_len);
|
||||
++$current_line; // 带标题的第一行满了,折到第二行
|
||||
do {
|
||||
if ($colorful) {
|
||||
$line_data[$current_line] = TermColor::color8(32);
|
||||
}
|
||||
$line_data[$current_line] .= ' ' . substr($rest, 0, $max_border - 2);
|
||||
if ($colorful) {
|
||||
$line_data[$current_line] .= TermColor::RESET;
|
||||
}
|
||||
$rest = substr($rest, $max_border - 2);
|
||||
++$current_line;
|
||||
} while ($rest > $max_border - 2); // 循环,直到放完
|
||||
} else { // 不需要折行
|
||||
// Console::info("不需要折行");
|
||||
$line_data[$current_line] = ' ' . $k . ': ';
|
||||
if ($colorful) {
|
||||
$line_data[$current_line] .= TermColor::color8(32);
|
||||
}
|
||||
$line_data[$current_line] .= $v;
|
||||
if ($colorful) {
|
||||
$line_data[$current_line] .= TermColor::RESET;
|
||||
}
|
||||
|
||||
if ($max_border >= 57) {
|
||||
if (strlen($tmp_line) >= intval(($max_border - 2) / 2)) { // 不需要折行,直接输出一个转下一行
|
||||
// Console::info("不需要折行,直接输出一个转下一行");
|
||||
++$current_line;
|
||||
} else { // 输出很小,写到前面并分片
|
||||
// Console::info("输出很小,写到前面并分片");
|
||||
$space = intval($max_border / 2) - 2 - strlen($tmp_line);
|
||||
$line_data[$current_line] .= str_pad('', $space);
|
||||
$line_data[$current_line] .= '| '; // 添加分片
|
||||
$line_width[$current_line] -= (strlen($tmp_line) + 3 + $space);
|
||||
}
|
||||
} else {
|
||||
++$current_line;
|
||||
}
|
||||
}
|
||||
$keys = array_keys($arr);
|
||||
$values = array_values($arr);
|
||||
$keys[array_search($old_key, $keys)] = $new_key;
|
||||
$arr = array_combine($keys, $values);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user