feat(nginx-log): NginxLogStatAggregate 定时任务 + timer config 注册

This commit is contained in:
augushong
2026-07-28 06:02:07 +08:00
parent 8eaa672ed6
commit 2b677c6f89
2 changed files with 101 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
<?php
declare(strict_types=1);
namespace base\tools\controller\timer;
use app\common\controller\TimerController;
use think\facade\Log;
/**
* nginx 访问日志按小时聚合定时任务Base 层).
*
* 流程:
* 1. env 总开关校验(严格布尔判断,详见 notepad Task 2 #14
* 2. 计算目标统计窗口:默认 now - 1 hour上一完整小时
* 支持 ?date=YYYYMMDD&hour=HH 手动指定(用于补跑历史数据)
* 3. 依赖倒置:实例化 app 层 NginxLogAggregator调 aggregateHour($date, $hour)
* 4. return JSON含 stat_hour_rows / stat_url_rows / stat_referer_rows / stat_ua_rows
*
* 业务侧如需定制聚合触发逻辑(如改默认窗口策略、加业务过滤),重写
* app/tools/controller/timer/NginxLogStatAggregate.php 对应方法即可拦截。
*/
class NginxLogStatAggregateBase extends TimerController
{
/**
* 防刷间隔(秒).
* 仅做控制器侧防刷,不影响定时器侧 frequency 节流。
* timer config frequency=3600这里设 300 是为了允许补跑历史窗口时
* 连续手动触发不同 (date,hour) 不被卡。
*/
protected $frequency = 300;
/**
* 并发上限 cap单分片id=0
*/
protected $concurrency = 1;
public function do()
{
// 1. 严格布尔判断env convert 'true'→true / 'false'→false
// 见 notepad Task 2 #14必须 !== true不能用 !== 'true' 字符串比较
if (env('nginx_log.enable') !== true) {
Log::debug('nginx_log disabled, skip aggregate');
return 'disabled';
}
// 2. 解析目标统计窗口
// 默认now - 1 hour上一完整小时避免正在写入的小时数据不完整
// 手动:?date=YYYYMMDD&hour=HH 用于补跑历史窗口
$manualDate = $this->request->param('date', '');
$manualHour = $this->request->param('hour', '');
if ($manualDate !== '' && $manualHour !== '') {
// 手动模式:强校验
$dateInt = (int) $manualDate;
$hourInt = (int) $manualHour;
// YYYYMMDD 范围10000101 ~ 99991231hour: 0-23
if ($dateInt < 10000101 || $dateInt > 99991231) {
return json_encode(['error' => 'invalid date format, expect YYYYMMDD'], JSON_UNESCAPED_UNICODE);
}
if ($hourInt < 0 || $hourInt > 23) {
return json_encode(['error' => 'invalid hour, expect 0-23'], JSON_UNESCAPED_UNICODE);
}
} else {
// 默认模式:取当前时间 - 1 小时(按服务器时区,框架 default_timezone=Asia/Shanghai
$ts = time() - 3600;
$dateInt = (int) date('Ymd', $ts);
$hourInt = (int) date('G', $ts);
}
// 3. 依赖倒置:调用 app 层入口类(业务侧可重写拦截)
$aggregator = new \app\common\service\NginxLogAggregator();
$result = $aggregator->aggregateHour($dateInt, $hourInt);
// 4. return JSON补充窗口信息便于日志检索
return json_encode(array_merge([
'stat_date' => $dateInt,
'stat_hour' => $hourInt,
], $result), JSON_UNESCAPED_UNICODE);
}
}