feat(nginx-log): 新增 6 张表 phinx migration + Scheme + model

This commit is contained in:
augushong
2026-07-28 00:03:49 +08:00
parent f48e0947cb
commit 0d19881a22
18 changed files with 590 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
<?php
use think\migration\Migrator;
/**
* nginx 日志分析 - 文件读取位置表
*
* 记录每个被解析日志文件的 inode/offset/最近读取时间/失败计数等增量读取状态。
*/
class NginxLogPosition extends Migrator
{
public function change()
{
$table = $this->table('nginx_log_position')
->setComment('nginx 日志文件读取位置(增量读取状态)')
->addColumn('file_path', 'string', ['limit' => 500, 'null' => false, 'comment' => '日志文件绝对路径'])
->addColumn('inode', 'biginteger', ['default' => 0, 'comment' => '文件 inode用于检测日志轮转', 'signed' => false])
->addColumn('offset', 'biginteger', ['default' => 0, 'comment' => '上次读取到的字节偏移', 'signed' => false])
->addColumn('last_read_time', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '上次读取时间戳', 'signed' => false])
->addColumn('last_line_hash', 'string', ['limit' => 32, 'default' => '', 'comment' => '上次最后一行的 md5 哈希(容错校验)'])
->addColumn('parse_fail_count', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '解析失败累计次数', 'signed' => false])
->addColumn('parse_fail_samples', 'text', ['null' => true, 'comment' => '解析失败样本行(最多保留若干条)'])
->addColumn('create_time', 'integer', ['limit' => 11, 'comment' => '创建时间戳', 'signed' => false])
->addColumn('update_time', 'integer', ['limit' => 11, 'comment' => '更新时间戳', 'signed' => false])
->addIndex(['file_path'], ['unique' => true, 'name' => 'uniq_file_path'])
->create();
}
}

View File

@@ -0,0 +1,44 @@
<?php
use think\migration\Migrator;
/**
* nginx 日志分析 - 原始访问日志表
*
* 解析 nginx access.log 后入库的明细数据,按行一条记录。
* country/province/city 留作 GeoIP 扩展字段,默认 NULL。
*/
class NginxAccessLog extends Migrator
{
public function change()
{
$table = $this->table('nginx_access_log', ['id' => false, 'primary_key' => ['id']])
->setComment('nginx 访问日志明细(解析入库)')
->addColumn('id', 'biginteger', ['null' => false, 'signed' => false, 'identity' => true, 'comment' => '主键ID'])
->addColumn('file_path', 'string', ['limit' => 500, 'null' => false, 'comment' => '来源日志文件路径'])
->addColumn('remote_addr', 'string', ['limit' => 45, 'null' => false, 'comment' => '客户端 IP含 IPv6'])
->addColumn('remote_user', 'string', ['limit' => 100, 'null' => true, 'comment' => 'HTTP 认证用户名'])
->addColumn('time_local', 'integer', ['limit' => 11, 'null' => false, 'comment' => '请求时间戳(业务时区)', 'signed' => false])
->addColumn('method', 'string', ['limit' => 10, 'null' => true, 'comment' => 'HTTP 方法'])
->addColumn('uri', 'string', ['limit' => 255, 'null' => false, 'comment' => '请求 URI超 255 截断)'])
->addColumn('query_string', 'string', ['limit' => 500, 'null' => false, 'default' => '', 'comment' => '查询字符串'])
->addColumn('http_version', 'string', ['limit' => 10, 'null' => true, 'comment' => 'HTTP 协议版本'])
->addColumn('status', 'integer', ['limit' => 11, 'default' => 0, 'comment' => 'HTTP 状态码'])
->addColumn('body_bytes_sent', 'biginteger', ['default' => 0, 'comment' => '响应体字节数'])
->addColumn('http_referer', 'string', ['limit' => 500, 'null' => false, 'default' => '', 'comment' => 'Referer'])
->addColumn('http_user_agent', 'string', ['limit' => 500, 'null' => false, 'default' => '', 'comment' => 'User-Agent超 500 截断)'])
->addColumn('request_time', 'decimal', ['precision' => 10, 'scale' => 3, 'default' => 0, 'comment' => 'nginx 请求总耗时(秒)'])
->addColumn('upstream_response_time', 'decimal', ['precision' => 10, 'scale' => 3, 'default' => 0, 'comment' => 'upstream 响应时间(秒)'])
->addColumn('bytes_sent', 'biginteger', ['default' => 0, 'comment' => '总发送字节数(含 header'])
->addColumn('country', 'string', ['limit' => 50, 'null' => true, 'comment' => '国家GeoIP 预留)'])
->addColumn('province', 'string', ['limit' => 50, 'null' => true, 'comment' => '省份GeoIP 预留)'])
->addColumn('city', 'string', ['limit' => 50, 'null' => true, 'comment' => '城市GeoIP 预留)'])
->addColumn('create_time', 'integer', ['limit' => 11, 'comment' => '入库时间戳', 'signed' => false])
->addIndex(['time_local'], ['name' => 'idx_time_local'])
->addIndex(['remote_addr'], ['name' => 'idx_remote_addr'])
->addIndex(['status'], ['name' => 'idx_status'])
->addIndex(['uri'], ['name' => 'idx_uri'])
->addIndex(['file_path'], ['name' => 'idx_file_path'])
->create();
}
}

View File

@@ -0,0 +1,32 @@
<?php
use think\migration\Migrator;
/**
* nginx 日志分析 - 按小时聚合统计表
*
* 每个统计日 + 小时一行,记录 PV/UV/状态码分组/平均耗时。
* UNIQUE(stat_date, stat_hour) 保证幂等聚合。
*/
class NginxStatHour extends Migrator
{
public function change()
{
$table = $this->table('nginx_stat_hour')
->setComment('nginx 按小时聚合统计')
->addColumn('stat_date', 'integer', ['limit' => 11, 'null' => false, 'comment' => '统计日期(YYYYMMDD)', 'signed' => false])
->addColumn('stat_hour', 'tinyinteger', ['default' => 0, 'comment' => '小时(0-23)', 'signed' => false])
->addColumn('pv', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '页面浏览量'])
->addColumn('uv', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '独立访客数'])
->addColumn('total_bytes', 'biginteger', ['default' => 0, 'comment' => '总流量(字节)'])
->addColumn('status_2xx', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '2xx 响应数'])
->addColumn('status_3xx', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '3xx 响应数'])
->addColumn('status_4xx', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '4xx 响应数'])
->addColumn('status_5xx', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '5xx 响应数'])
->addColumn('status_other', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '其他状态码响应数'])
->addColumn('avg_request_time', 'decimal', ['precision' => 10, 'scale' => 3, 'default' => 0, 'comment' => '平均请求耗时(秒)'])
->addIndex(['stat_date', 'stat_hour'], ['unique' => true, 'name' => 'uniq_date_hour'])
->addIndex(['stat_date'], ['name' => 'idx_stat_date'])
->create();
}
}

View File

@@ -0,0 +1,26 @@
<?php
use think\migration\Migrator;
/**
* nginx 日志分析 - 按 URL 聚合统计表
*
* 每个统计日 + URI 一行,记录 PV/UV/流量/平均耗时,用于热门 URL 排行。
*/
class NginxStatUrl extends Migrator
{
public function change()
{
$table = $this->table('nginx_stat_url')
->setComment('nginx 按 URL 聚合统计')
->addColumn('stat_date', 'integer', ['limit' => 11, 'null' => false, 'comment' => '统计日期(YYYYMMDD)', 'signed' => false])
->addColumn('uri', 'string', ['limit' => 255, 'null' => false, 'comment' => '请求 URI'])
->addColumn('pv', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '页面浏览量'])
->addColumn('uv', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '独立访客数'])
->addColumn('total_bytes', 'biginteger', ['default' => 0, 'comment' => '总流量(字节)'])
->addColumn('avg_request_time', 'decimal', ['precision' => 10, 'scale' => 3, 'default' => 0, 'comment' => '平均请求耗时(秒)'])
->addIndex(['stat_date', 'uri'], ['unique' => true, 'name' => 'uniq_date_uri'])
->addIndex(['stat_date'], ['name' => 'idx_stat_date'])
->create();
}
}

View File

@@ -0,0 +1,24 @@
<?php
use think\migration\Migrator;
/**
* nginx 日志分析 - 按 Referer 来源域名聚合统计表
*
* 每个统计日 + 来源域名一行,记录 PV/UV用于外链来源排行。
*/
class NginxStatReferer extends Migrator
{
public function change()
{
$table = $this->table('nginx_stat_referer')
->setComment('nginx 按 Referer 来源域名聚合统计')
->addColumn('stat_date', 'integer', ['limit' => 11, 'null' => false, 'comment' => '统计日期(YYYYMMDD)', 'signed' => false])
->addColumn('referer_domain', 'string', ['limit' => 255, 'null' => false, 'comment' => 'Referer 来源域名(direct/unknown)'])
->addColumn('pv', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '页面浏览量'])
->addColumn('uv', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '独立访客数'])
->addIndex(['stat_date', 'referer_domain'], ['unique' => true, 'name' => 'uniq_date_referer'])
->addIndex(['stat_date'], ['name' => 'idx_stat_date'])
->create();
}
}

View File

@@ -0,0 +1,26 @@
<?php
use think\migration\Migrator;
/**
* nginx 日志分析 - 按 User-Agent 聚合统计表
*
* 每个统计日 + UA 类型 + UA 名称一行,记录 PV/UV。
* ua_type: browser/spider/unknown/手机浏览器等ua_name: 具体名称Chrome 120 等)。
*/
class NginxStatUa extends Migrator
{
public function change()
{
$table = $this->table('nginx_stat_ua')
->setComment('nginx 按 User-Agent 聚合统计')
->addColumn('stat_date', 'integer', ['limit' => 11, 'null' => false, 'comment' => '统计日期(YYYYMMDD)', 'signed' => false])
->addColumn('ua_type', 'string', ['limit' => 20, 'default' => 'unknown', 'comment' => 'UA 类型(browser/spider/unknown)'])
->addColumn('ua_name', 'string', ['limit' => 255, 'null' => false, 'comment' => 'UA 名称(具体型号)'])
->addColumn('pv', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '页面浏览量'])
->addColumn('uv', 'integer', ['limit' => 11, 'default' => 0, 'comment' => '独立访客数'])
->addIndex(['stat_date', 'ua_type', 'ua_name'], ['unique' => true, 'name' => 'uniq_date_type_name'])
->addIndex(['stat_date'], ['name' => 'idx_stat_date'])
->create();
}
}