From ee9d651c8a22ff44301f459119c5e08c75fbdcd0 Mon Sep 17 00:00:00 2001 From: ryan Date: Sat, 18 Jul 2026 22:46:46 +0800 Subject: [PATCH] =?UTF-8?q?docs(obs):=20=E7=BA=A6=E5=AE=9A=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E6=97=A5=E5=BF=97=20cache=5Fstatus=20=E4=B8=8E?= =?UTF-8?q?=E6=98=8E=E7=BB=86=E4=B8=89=E6=80=81=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 仅上报 $upstream_cache_status,不上报回源地址;UI 由原始值推导 命中缓存 / 回源 / 未使用缓存。 --- docs/design/observability-data-model.md | 70 +++++++++++++++++--- docs/design/observability-transport-model.md | 11 ++- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/docs/design/observability-data-model.md b/docs/design/observability-data-model.md index 70eb2986..f9d650b4 100644 --- a/docs/design/observability-data-model.md +++ b/docs/design/observability-data-model.md @@ -202,7 +202,9 @@ Agent:tail access.log → 解析 JSON 行 → 原样字段上报(可截断 p "status_code": 200, "bytes_sent": 1024, "request_length": 128, - "request_time_ms": 15 + "request_time_ms": 15, + "user_agent": "Mozilla/5.0 ...", + "cache_status": "HIT" } ``` @@ -216,6 +218,8 @@ Agent:tail access.log → 解析 JSON 行 → 原样字段上报(可截断 p | `bytes_sent` | int64 | ✅ | **`$body_bytes_sent`** | **已提供数据**(响应体) | | `request_length` | int64 | 建议 | `$request_length` | **接收数据** | | `request_time_ms` | int64 | 可选 | `$request_time * 1000` | 耗时;缺省 0 | +| `user_agent` | string | 建议 | `$http_user_agent` | UA;可截断入库 | +| `cache_status` | string | 建议 | **`$upstream_cache_status`** | 边缘缓存结果(见 §3.5.1) | **明确不由 Agent 上报(由 Server 写入):** @@ -223,6 +227,45 @@ Agent:tail access.log → 解析 JSON 行 → 原样字段上报(可截断 p * `id` / `created_at`:Server 生成 * `node_id`:取自 payload / 鉴权上下文 +**明确不上报:** + +* `upstream_addr` / 回源地址 / `origin_fetched`:不做回源端点追踪;「是否回源」仅由 `cache_status` 在控制面推导(§3.5.1) + +### 3.5.1 `cache_status` — 缓存命中与回源(明细优先) + +**目标(第一期):** 访问日志明细/详情能展示「是否命中缓存 / 是否回源 / 未使用缓存」。 +**口径:** 只存 OpenResty `$upstream_cache_status` 原始值;**不上报** upstream 地址。 + +#### 原始值(入库) + +| 值 | 含义(OpenResty) | +| --- | --- | +| `HIT` | 命中缓存 | +| `MISS` | 未命中,向 upstream 取内容 | +| `BYPASS` | 跳过缓存(如 method/cookie/策略导致 `$openflare_skip_cache`) | +| `EXPIRED` | 缓存过期后回源 | +| `STALE` | 提供陈旧缓存(stale) | +| `UPDATING` | 后台更新中,可能返回旧缓存 | +| `REVALIDATED` | 协商验证后仍用缓存 | +| `-` 或空 | 未经过 `proxy_cache`(如 Pages 本地静态、非代理 location) | + +#### UI 三态推导(不落库) + +控制面展示用派生枚举 `cache_outcome`,**不写 CH**: + +| 三态 | 条件(`cache_status`) | 列表标签建议 | +| --- | --- | --- | +| **命中缓存** | `HIT` / `STALE` / `REVALIDATED` / `UPDATING` | 命中 | +| **回源** | `MISS` / `EXPIRED` | 回源 | +| **未使用缓存** | `BYPASS` / `-` / `""` | 未缓存 | + +详情可同时显示三态 + 原始 `cache_status`。 + +#### 边界 + +* Pages 静态 / 无 `proxy_cache` 的 location:多为空或 `-` → **未使用缓存**,不得标成「命中」。 +* 第一期只做明细可见;命中率看板、hourly 维度可后续用同一列聚合。 + **单次心跳条数建议:** * 软上限例如 2000 条/拍;超出进入 `buffered` 下一批,**禁止** 在 Agent 压成 TrafficReport。 @@ -309,6 +352,8 @@ type NodeAccessLog struct { RemoteAddr string `json:"remote_addr"` Host string `json:"host"` Path string `json:"path"` + UserAgent string `json:"user_agent,omitempty"` + CacheStatus string `json:"cache_status,omitempty"` // $upstream_cache_status StatusCode int `json:"status_code"` BytesSent int64 `json:"bytes_sent"` // body_bytes_sent,已提供数据 RequestLength int64 `json:"request_length"` // 接收数据 @@ -419,10 +464,12 @@ CREATE TABLE IF NOT EXISTS of_node_access_logs region String, -- Server GeoIP 写入,Agent 不传 host String, path String, + user_agent String DEFAULT '', -- $http_user_agent + cache_status String DEFAULT '', -- $upstream_cache_status status_code Int32, bytes_sent UInt64, -- 已提供数据(body) - request_length UInt64 DEFAULT 0, -- 接收数据;新增 - request_time_ms UInt32 DEFAULT 0, -- 可选;新增 + request_length UInt64 DEFAULT 0, -- 接收数据 + request_time_ms UInt32 DEFAULT 0, -- 可选 created_at DateTime64(3, 'UTC') ) ENGINE = MergeTree() @@ -441,18 +488,19 @@ SETTINGS index_granularity = 8192; | `region` | String | Server GeoIP | | `host` | String | 上报 | | `path` | String | 上报 | +| `user_agent` | String | 上报(可空) | +| `cache_status` | String | 上报(可空)→ **缓存状态** | | `status_code` | Int32 | 上报 | | `bytes_sent` | UInt64 | 上报 → **已提供数据** | | `request_length` | UInt64 | 上报 → **接收数据** | | `request_time_ms` | UInt32 | 上报可选 | | `created_at` | DateTime64(3) | Server now | -**迁移:** 现表已有 `bytes_sent`;新增: +**迁移:** 现表已有 `bytes_sent` / `request_length` / `request_time_ms` / `user_agent`;缓存状态新增: ```sql ALTER TABLE of_node_access_logs - ADD COLUMN IF NOT EXISTS request_length UInt64 DEFAULT 0, - ADD COLUMN IF NOT EXISTS request_time_ms UInt32 DEFAULT 0; + ADD COLUMN IF NOT EXISTS cache_status String DEFAULT ''; ``` ### 5.2 L1 小时汇总(Server 侧 MV) @@ -625,14 +673,16 @@ Relay 专用 `of_node_obs_frps` / `of_node_obs_frpc` **保留**(非本 Agent ## 7. OpenResty 日志格式(与明细对齐) -目标 `log_format`(与现网一致,保证 `bytes_sent` 键 = body): +目标 `log_format`(保证 `bytes_sent` 键 = body;含 UA 与缓存状态): ```nginx log_format openflare_json escape=json '{"ts":"$time_iso8601","host":"$host","path":"$request_uri",' '"remote_addr":"$remote_addr","status":$status,' '"request_time":$request_time,' - '"bytes_sent":$body_bytes_sent,"request_length":$request_length}'; + '"bytes_sent":$body_bytes_sent,"request_length":$request_length,' + '"user_agent":"$http_user_agent",' + '"cache_status":"$upstream_cache_status"}'; ``` Agent 解析: @@ -640,7 +690,9 @@ Agent 解析: * `ts` → `logged_at_unix` * `bytes_sent` → 协议 `bytes_sent`(已提供) * `request_length` → 协议 `request_length` -* `request_time` → 可选 `request_time_ms = round(sec * 1000)` +* `request_time` → 可选 `request_time_ms = round(sec * 1000)` +* `user_agent` → 协议 `user_agent` +* `cache_status` → 协议 `cache_status`(原样透传,不做三态压缩) --- diff --git a/docs/design/observability-transport-model.md b/docs/design/observability-transport-model.md index 03ea1bb1..5de97051 100644 --- a/docs/design/observability-transport-model.md +++ b/docs/design/observability-transport-model.md @@ -154,6 +154,8 @@ status ← $status request_time ← $request_time bytes_sent ← $body_bytes_sent 【已提供数据 = 响应体字节】 request_length← $request_length 【接收数据】 +user_agent ← $http_user_agent +cache_status ← $upstream_cache_status 【缓存状态;UI 可推导命中/回源/未缓存】 ``` 观测端口请求 **不写** 业务 access.log(独立 server `access_log off`)。 @@ -170,7 +172,9 @@ request_length← $request_length 【接收数据】 "status_code": 200, "bytes_sent": 1024, "request_length": 128, - "request_time_ms": 15 + "request_time_ms": 15, + "user_agent": "curl/8.0", + "cache_status": "MISS" }, { "logged_at_unix": 1721289602, @@ -180,7 +184,9 @@ request_length← $request_length 【接收数据】 "status_code": 200, "bytes_sent": 8192, "request_length": 300, - "request_time_ms": 8 + "request_time_ms": 8, + "user_agent": "Mozilla/5.0", + "cache_status": "HIT" } ] ``` @@ -191,6 +197,7 @@ request_length← $request_length 【接收数据】 | `request_length` | **接收数据**(单请求) | | `logged_at_unix` | 请求完成时间(业务时间轴) | | `host` | 用于 Zone 域名过滤 | +| `cache_status` | `$upstream_cache_status` 原样;详情/列表可推导三态(命中/回源/未缓存);**不上报** upstream 地址 | | 无 `region` | **Server 入库时** GeoIP 写入 | ### 4.3 Server 如何用(产品指标)