feat(access-logs): 明细详情支持 IP 分析与 URL Tab 记忆

- 新增单 IP 分析接口,趋势时间范围支持至 30 天
- 明细详情弹窗展示趋势、汇总与 Top 分布,可快捷管理 IP 组
- 访问日志页签改为 URL 参数记忆,筛选后保持当前 Tab
This commit is contained in:
ryan
2026-07-18 22:40:21 +08:00
parent bf71bc540b
commit 9aec984bee
13 changed files with 1443 additions and 86 deletions
+2
View File
@@ -26,6 +26,8 @@ sidebar: false
- 优化访问日志概览及其他图表全局排行榜 (RankChart) 的样式布局:将每一项改为单行横向排布(左侧标签、中间进度条、右侧数值),数值支持自动格式化为 Compact 形式(如 39.57k、1.2M),同时调整默认高度为 320px 并隐藏滚动条。
- 访问日志页面重构为「概览」与「日志明细」两个标签页:概览展示请求量、访问量、带宽趋势与 Top Paths/Hosts/IPs,明细列表保留检索能力;已移除时间折叠与 IP 汇总视图。
- 边缘访问日志现支持上报并存储 User-Agent;概览新增设备类型饼图,以及浏览器、操作系统、User-Agent 排行。
- 访问日志明细支持查看单条请求详情,可查看 User-Agent、IP 访问趋势与分析,并快捷将 IP 加入或移出 IP 组。
- 访问日志页签状态改为 URL 参数记忆,筛选后不会再跳回概览。
- 优化访问日志概览的设备类型与状态码饼图布局,使设备类型与状态码饼图在 1024px(lg)以上屏幕保持双列并排展示,提升页面紧凑度。
- 修复访问日志概览在 ClickHouse 查询发生错误时静默吞掉报错的缺陷,引入错误日志输出,方便定位问题。
+163
View File
@@ -5315,6 +5315,93 @@ const docTemplate = `{
}
}
},
"/api/v1/d/access-logs/ip-summary/analysis": {
"get": {
"security": [
{
"SessionCookie": []
}
],
"description": "返回指定 IP 的汇总指标与 Top 分布,需要管理员权限",
"produces": [
"application/json"
],
"tags": [
"openflare-observability"
],
"summary": "获取访问日志 IP 分析",
"parameters": [
{
"type": "string",
"description": "节点 ID",
"name": "node_id",
"in": "query"
},
{
"type": "string",
"description": "客户端 IP",
"name": "remote_addr",
"in": "query"
},
{
"type": "string",
"description": "请求 Host",
"name": "host",
"in": "query"
},
{
"type": "integer",
"description": "统计时间范围(小时)",
"name": "hours",
"in": "query"
}
],
"responses": {
"200": {
"description": "IP 访问分析",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.Any"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/observability.AccessLogIPAnalysisView"
}
}
}
]
}
},
"400": {
"description": "参数错误",
"schema": {
"$ref": "#/definitions/response.Any"
}
},
"401": {
"description": "未登录",
"schema": {
"$ref": "#/definitions/response.Any"
}
},
"404": {
"description": "无权限或不存在",
"schema": {
"$ref": "#/definitions/response.Any"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/response.Any"
}
}
}
}
},
"/api/v1/d/access-logs/ip-summary/trend": {
"get": {
"security": [
@@ -16129,6 +16216,82 @@ const docTemplate = `{
}
}
},
"observability.AccessLogIPAnalysisSummary": {
"type": "object",
"properties": {
"bandwidth_served": {
"type": "integer"
},
"bytes_received": {
"type": "integer"
},
"error_count": {
"type": "integer"
},
"total_requests": {
"type": "integer"
},
"unique_hosts": {
"type": "integer"
},
"unique_paths": {
"type": "integer"
}
}
},
"observability.AccessLogIPAnalysisView": {
"type": "object",
"properties": {
"device_types": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"generated_at": {
"type": "string"
},
"hours": {
"type": "integer"
},
"remote_addr": {
"type": "string"
},
"status_codes": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"summary": {
"$ref": "#/definitions/observability.AccessLogIPAnalysisSummary"
},
"top_browsers": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"top_hosts": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"top_paths": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"top_user_agents": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
}
}
},
"observability.AccessLogIPSummaryList": {
"type": "object",
"properties": {
+163
View File
@@ -5308,6 +5308,93 @@
}
}
},
"/api/v1/d/access-logs/ip-summary/analysis": {
"get": {
"security": [
{
"SessionCookie": []
}
],
"description": "返回指定 IP 的汇总指标与 Top 分布,需要管理员权限",
"produces": [
"application/json"
],
"tags": [
"openflare-observability"
],
"summary": "获取访问日志 IP 分析",
"parameters": [
{
"type": "string",
"description": "节点 ID",
"name": "node_id",
"in": "query"
},
{
"type": "string",
"description": "客户端 IP",
"name": "remote_addr",
"in": "query"
},
{
"type": "string",
"description": "请求 Host",
"name": "host",
"in": "query"
},
{
"type": "integer",
"description": "统计时间范围(小时)",
"name": "hours",
"in": "query"
}
],
"responses": {
"200": {
"description": "IP 访问分析",
"schema": {
"allOf": [
{
"$ref": "#/definitions/response.Any"
},
{
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/observability.AccessLogIPAnalysisView"
}
}
}
]
}
},
"400": {
"description": "参数错误",
"schema": {
"$ref": "#/definitions/response.Any"
}
},
"401": {
"description": "未登录",
"schema": {
"$ref": "#/definitions/response.Any"
}
},
"404": {
"description": "无权限或不存在",
"schema": {
"$ref": "#/definitions/response.Any"
}
},
"500": {
"description": "内部错误",
"schema": {
"$ref": "#/definitions/response.Any"
}
}
}
}
},
"/api/v1/d/access-logs/ip-summary/trend": {
"get": {
"security": [
@@ -16122,6 +16209,82 @@
}
}
},
"observability.AccessLogIPAnalysisSummary": {
"type": "object",
"properties": {
"bandwidth_served": {
"type": "integer"
},
"bytes_received": {
"type": "integer"
},
"error_count": {
"type": "integer"
},
"total_requests": {
"type": "integer"
},
"unique_hosts": {
"type": "integer"
},
"unique_paths": {
"type": "integer"
}
}
},
"observability.AccessLogIPAnalysisView": {
"type": "object",
"properties": {
"device_types": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"generated_at": {
"type": "string"
},
"hours": {
"type": "integer"
},
"remote_addr": {
"type": "string"
},
"status_codes": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"summary": {
"$ref": "#/definitions/observability.AccessLogIPAnalysisSummary"
},
"top_browsers": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"top_hosts": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"top_paths": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
},
"top_user_agents": {
"type": "array",
"items": {
"$ref": "#/definitions/observability.DistributionItem"
}
}
}
},
"observability.AccessLogIPSummaryList": {
"type": "object",
"properties": {
+103
View File
@@ -1872,6 +1872,56 @@ definitions:
retention_days:
type: integer
type: object
observability.AccessLogIPAnalysisSummary:
properties:
bandwidth_served:
type: integer
bytes_received:
type: integer
error_count:
type: integer
total_requests:
type: integer
unique_hosts:
type: integer
unique_paths:
type: integer
type: object
observability.AccessLogIPAnalysisView:
properties:
device_types:
items:
$ref: '#/definitions/observability.DistributionItem'
type: array
generated_at:
type: string
hours:
type: integer
remote_addr:
type: string
status_codes:
items:
$ref: '#/definitions/observability.DistributionItem'
type: array
summary:
$ref: '#/definitions/observability.AccessLogIPAnalysisSummary'
top_browsers:
items:
$ref: '#/definitions/observability.DistributionItem'
type: array
top_hosts:
items:
$ref: '#/definitions/observability.DistributionItem'
type: array
top_paths:
items:
$ref: '#/definitions/observability.DistributionItem'
type: array
top_user_agents:
items:
$ref: '#/definitions/observability.DistributionItem'
type: array
type: object
observability.AccessLogIPSummaryList:
properties:
has_more:
@@ -7181,6 +7231,59 @@ paths:
summary: 列出访问日志 IP 汇总
tags:
- openflare-observability
/api/v1/d/access-logs/ip-summary/analysis:
get:
description: 返回指定 IP 的汇总指标与 Top 分布,需要管理员权限
parameters:
- description: 节点 ID
in: query
name: node_id
type: string
- description: 客户端 IP
in: query
name: remote_addr
type: string
- description: 请求 Host
in: query
name: host
type: string
- description: 统计时间范围(小时)
in: query
name: hours
type: integer
produces:
- application/json
responses:
"200":
description: IP 访问分析
schema:
allOf:
- $ref: '#/definitions/response.Any'
- properties:
data:
$ref: '#/definitions/observability.AccessLogIPAnalysisView'
type: object
"400":
description: 参数错误
schema:
$ref: '#/definitions/response.Any'
"401":
description: 未登录
schema:
$ref: '#/definitions/response.Any'
"404":
description: 无权限或不存在
schema:
$ref: '#/definitions/response.Any'
"500":
description: 内部错误
schema:
$ref: '#/definitions/response.Any'
security:
- SessionCookie: []
summary: 获取访问日志 IP 分析
tags:
- openflare-observability
/api/v1/d/access-logs/ip-summary/trend:
get:
description: 返回指定 IP 在时间范围内的访问趋势数据,需要管理员权限