mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-08-30 20:55:32 +08:00
feat(nginx-log): 多节点适配(node_id 全链路 + 全局/按节点聚合 + 节点筛选 + v2.4.0 升级脚本)
- 6 张表加 node_id 字段 + position/stat 改复合唯一键(migration) - 6 个 Scheme 同步 node_id 注解 + 唯一键 - Reader 带 node_id 参数 + 懒加载接管(getLastPosition 回退查 node_id='') - Aggregator 全局行(node_id='')+ 按节点循环 insertAggregatesForScope - Stat 所有查询方法加 where node_id 条件 - Dashboard 控制器/视图加节点筛选下拉框 + AJAX 带 node_id - AccessLog 列表加节点列 + 采集进度卡片显示节点信息 - import 定时任务 run_type 改 all(每节点采集自己的日志) - v2.4.0 升级脚本追加 ALTER TABLE(幂等 check-then-alter) - 菜单调整:去掉 Nginx 顶级菜单 + 读取位置管理,改为系统管理下挂两个子菜单 - ulthon-timer 文档补充 run_type=all 多节点部署注意事项
This commit is contained in:
@@ -45,11 +45,13 @@ class NginxLogStatBase extends AdminController
|
||||
$period = 'day';
|
||||
}
|
||||
|
||||
$nodeId = (string) $request->param('node_id', '');
|
||||
|
||||
// 解析时间范围(YYYYMMDD int 表示)
|
||||
[$startDate, $endDate] = $this->resolveDateRange($period);
|
||||
|
||||
if ($request->isAjax()) {
|
||||
$data = $this->buildStatData($period, $startDate, $endDate);
|
||||
$data = $this->buildStatData($period, $startDate, $endDate, $nodeId);
|
||||
|
||||
return json([
|
||||
'code' => 0,
|
||||
@@ -63,6 +65,11 @@ class NginxLogStatBase extends AdminController
|
||||
$this->assign('start', $startDate);
|
||||
$this->assign('end', $endDate);
|
||||
|
||||
// 在线节点列表(供视图渲染节点筛选下拉)
|
||||
$nodes = \app\admin\model\SystemHost::where('status', 1)->order('node_id', 'asc')->select();
|
||||
$this->assign('nodes', $nodes);
|
||||
$this->assign('node_id', $nodeId);
|
||||
|
||||
return $this->fetch();
|
||||
}
|
||||
|
||||
@@ -140,20 +147,20 @@ class NginxLogStatBase extends AdminController
|
||||
/**
|
||||
* 组装完整统计数据
|
||||
*/
|
||||
protected function buildStatData(string $period, int $startDate, int $endDate): array
|
||||
protected function buildStatData(string $period, int $startDate, int $endDate, string $nodeId = ''): array
|
||||
{
|
||||
// 时间范围不合法 → 空数据(不崩)
|
||||
if ($startDate <= 0 || $endDate <= 0 || $startDate > $endDate) {
|
||||
return $this->emptyData($period);
|
||||
}
|
||||
|
||||
$summary = $this->querySummary($startDate, $endDate);
|
||||
$trend = $this->queryTrend($period, $startDate, $endDate);
|
||||
$summary = $this->querySummary($startDate, $endDate, $nodeId);
|
||||
$trend = $this->queryTrend($period, $startDate, $endDate, $nodeId);
|
||||
|
||||
$topN = $this->getTopN();
|
||||
$topUrls = $this->queryTopByDateRange(NginxStatUrl::class, 'uri', $startDate, $endDate, $topN);
|
||||
$topReferers = $this->queryTopByDateRange(NginxStatReferer::class, 'referer_domain', $startDate, $endDate, $topN);
|
||||
$topUas = $this->queryTopByDateRange(NginxStatUa::class, 'ua_name', $startDate, $endDate, $topN);
|
||||
$topUrls = $this->queryTopByDateRange(NginxStatUrl::class, 'uri', $startDate, $endDate, $topN, $nodeId);
|
||||
$topReferers = $this->queryTopByDateRange(NginxStatReferer::class, 'referer_domain', $startDate, $endDate, $topN, $nodeId);
|
||||
$topUas = $this->queryTopByDateRange(NginxStatUa::class, 'ua_name', $startDate, $endDate, $topN, $nodeId);
|
||||
|
||||
// 跨周期 UV 估算标注:仅 day 为精确值,week/month/year/custom 均为按日累加的估算值
|
||||
$uvIsEstimate = $period !== 'day';
|
||||
@@ -208,7 +215,7 @@ class NginxLogStatBase extends AdminController
|
||||
* 整体指标:SUM stat_hour
|
||||
* avg_request_time 按 PV 加权平均(避免简单 AVG 被低 PV 时段拉偏)
|
||||
*/
|
||||
protected function querySummary(int $startDate, int $endDate): array
|
||||
protected function querySummary(int $startDate, int $endDate, string $nodeId = ''): array
|
||||
{
|
||||
$sumFields = [
|
||||
'IFNULL(SUM(pv),0) AS pv',
|
||||
@@ -223,6 +230,7 @@ class NginxLogStatBase extends AdminController
|
||||
];
|
||||
|
||||
$row = NginxStatHour::where('stat_date', 'between', [$startDate, $endDate])
|
||||
->where('node_id', $nodeId)
|
||||
->field(implode(',', $sumFields))
|
||||
->find();
|
||||
|
||||
@@ -252,10 +260,11 @@ class NginxLogStatBase extends AdminController
|
||||
* - year → 12 个月(按 stat_date DIV 100 分组,补全 1~12 月)
|
||||
* - custom→ 按 stat_date 分组,补全 start~end 日期序列
|
||||
*/
|
||||
protected function queryTrend(string $period, int $startDate, int $endDate): array
|
||||
protected function queryTrend(string $period, int $startDate, int $endDate, string $nodeId = ''): array
|
||||
{
|
||||
if ($period === 'day') {
|
||||
$rows = NginxStatHour::where('stat_date', 'between', [$startDate, $endDate])
|
||||
->where('node_id', $nodeId)
|
||||
->field('stat_hour, IFNULL(SUM(pv),0) AS pv, IFNULL(SUM(uv),0) AS uv')
|
||||
->group('stat_hour')
|
||||
->select()
|
||||
@@ -280,6 +289,7 @@ class NginxLogStatBase extends AdminController
|
||||
|
||||
if ($period === 'year') {
|
||||
$rows = NginxStatHour::where('stat_date', 'between', [$startDate, $endDate])
|
||||
->where('node_id', $nodeId)
|
||||
->field('(stat_date DIV 100) AS ym, IFNULL(SUM(pv),0) AS pv, IFNULL(SUM(uv),0) AS uv')
|
||||
->group('ym')
|
||||
->order('ym asc')
|
||||
@@ -307,6 +317,7 @@ class NginxLogStatBase extends AdminController
|
||||
|
||||
// week / month / custom → 按 stat_date 分组,补全日期序列
|
||||
$rows = NginxStatHour::where('stat_date', 'between', [$startDate, $endDate])
|
||||
->where('node_id', $nodeId)
|
||||
->field('stat_date, IFNULL(SUM(pv),0) AS pv, IFNULL(SUM(uv),0) AS uv')
|
||||
->group('stat_date')
|
||||
->order('stat_date asc')
|
||||
@@ -340,10 +351,12 @@ class NginxLogStatBase extends AdminController
|
||||
* @param string $modelClass 模型类(依赖倒置:调 app/admin/model 入口)
|
||||
* @param string $labelField 分组与展示的字段名
|
||||
* @param int $topN 取前 N 条;0 不限制
|
||||
* @param string $nodeId 节点 ID(空字符串=全局聚合行)
|
||||
*/
|
||||
protected function queryTopByDateRange(string $modelClass, string $labelField, int $startDate, int $endDate, int $topN): array
|
||||
protected function queryTopByDateRange(string $modelClass, string $labelField, int $startDate, int $endDate, int $topN, string $nodeId = ''): array
|
||||
{
|
||||
$query = $modelClass::where('stat_date', 'between', [$startDate, $endDate])
|
||||
->where('node_id', $nodeId)
|
||||
->field($labelField . ' AS label, IFNULL(SUM(pv),0) AS pv, IFNULL(SUM(uv),0) AS uv')
|
||||
->group($labelField)
|
||||
->order('pv desc');
|
||||
|
||||
Reference in New Issue
Block a user