From a21f4d0b1e776d59c87c1157e9c295a73e489a91 Mon Sep 17 00:00:00 2001 From: zijunchiang Date: Wed, 14 Oct 2026 20:14:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A5=E5=BF=97:=20=E8=BF=9C=E7=A8=8B?= =?UTF-8?q?=E5=8F=AA=E6=94=B6=E3=80=8C=E5=90=AF=E5=8A=A8=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=20+=20=E6=8A=A5=E9=94=99=E3=80=8D=EF=BC=8Cinfo/notice/warn=20?= =?UTF-8?q?=E4=B8=80=E5=BE=8B=E5=8F=AA=E5=86=99=E6=9C=AC=E5=9C=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MiliLog 新增 remote()(启动检测专用,仍上远程);info/notice/warn 改为只写本地 - 启动检测 4 处改用 remote(): APP-INIT / BOOT / STORAGE / JS-BRIDGE ready - error 语义不变(报错仍上远程);local* 不变(只写本地) - 调用点名称不变,其余 40+ 处只是不再上传 - AGENTS 第 5 条日志约定重写;版本号 1.6.3(46) → 1.6.4(47) - 验证: assembleRelease + 单测 127 例全过 --- AGENTS.md | 31 ++++++++++--------- app/build.gradle | 4 +-- .../main/java/com/local/ktv/KtvApplication.kt | 2 +- .../main/java/com/local/ktv/KtvJsBridge.kt | 2 +- .../main/java/com/local/ktv/MainActivity.kt | 4 +-- app/src/main/java/com/local/ktv/MiliLog.kt | 20 ++++++++++-- 6 files changed, 39 insertions(+), 24 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 210ddc5..fa9caa6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -195,12 +195,13 @@ $BT/apksigner verify 目标名.apk ### 版本号 -- `app/build.gradle`:`versionName "1.6.3"` / `versionCode 46` +- `app/build.gradle`:`versionName "1.6.4"` / `versionCode 47` (`1.5.5`/`37` 已发布;`1.5.6` = 更新源加 Gitee、`1.5.7` = 删除「歌曲源临时受限」弹窗、`1.5.8` = 精简远程日志、`1.5.9` = 按 HAR 对齐原版协议、`1.5.10` = 源列表只留 zk.ktv1.top:6677、`1.5.11`(命名越界,已改) / `1.6.0` = whoami 心跳/设备身份/点歌推送/带 query 的地址闸门 + 并入 selfhost-source 支线、 `1.6.1`/`44` = App 接入自建源(自建源优先 / App 令牌 / 媒体允许清单 / 推送默认目标)、 `1.6.2`/`45` = **取址反转成"官方源优先、自建源兜底" + 只有官方源成功才上报**(含 6 条隐患修复与死代码清理)、 `1.6.3`/`46` = **点歌延迟优化**(终态失败不退避 / 上游 i.php token 缓存 / 后台预热 / 分阶段耗时日志), - 以上 1.5.6~1.6.3 均尚未发布。18~21 曾被本机临时诊断包占用) + `1.6.4`/`47` = **远程日志只收「启动检测 + 报错」**(info/notice/warn 一律只写本地), + 以上 1.5.6~1.6.4 均尚未发布。18~21 曾被本机临时诊断包占用) - App 内显示统一用纯版本号(不加 `(versionCode)` 括号) - ⚠️ **本机 `/tmp` 是 tmpfs,单测必须绕开它**:`/tmp`(5.6G tmpfs)长期被"已删除但仍被打开"的 文件占满,单测写临时文件会抛 `IOException: 超出磁盘配额`(EDQUOT),**看起来像测试失败**。 @@ -516,8 +517,10 @@ $BT/apksigner verify 目标名.apk 由 `MiliLog.PUBLIC_IP_URL` 查询,结果缓存 5 分钟、失败 1 分钟后重试,查询在独立后台线程, 绝不在主线程发起),`clientip` = **客户端 IP**(设备当前网卡获取到的局域网 IP,由 `MiliLog.updateDeviceContext(ip = ...)` 注入,网络变化时自动刷新并顺带复核公网 IP)。 - 客户端为 `MiliLog`(有界队列 + 后台线程 + 失败重试),调用点 `MiliLog.info/notice/warn/error` - 保持不变。启动上报(`reportDeviceBootInfo()`)只采集这 10 项:包名、版本号、安装时间、品牌、型号、 + 客户端为 `MiliLog`(有界队列 + 后台线程 + 失败重试)。⚠️ **级别语义见下面第 5 条**: + 现在只有 `MiliLog.remote(...)`(启动检测)与 `MiliLog.error(...)`(报错)会上传, + `info/notice/warn` 已改为**只写本地**(调用点名可以不变,但不要再指望它们出现在远程服务上)。 + 启动上报(`reportDeviceBootInfo()`)只采集这 10 项:包名、版本号、安装时间、品牌、型号、 设备名、Android 版本、CPU 架构、内核版本、屏幕分辨率 - **写日志的五条约定**(2026-09-26 依据现场日志复盘补充): 1. **持久状态只记一次**,不要每次事件都记。反例:桥不可用曾按「每次点歌一条 WARN」输出, @@ -531,17 +534,15 @@ $BT/apksigner verify 目标名.apk 4. **日志要能自我定位**:失败行写清"哪一步/哪个源/耗时/原因",例如 `NATIVE-SONG 全部源失败 编号=... 详情=token-fail|no-url|demo-or-mismatch 用时=...ms`; 桥侧由 `JS-BRIDGE ...` 说明 WebView 到底卡在哪一步(初始化失败/KtvApi 未导出/20s 超时)。 - 5. **⚠️ 远程日志只留"每次事件一条"的汇总,细节走本地(2026-10 精简)**: - `MiliLog.local(msg)` / `localWarn` / `localError` **只写本地文件、不上报远程**。 - 判定标准——**逐源 / 逐次重试 / 单次 HTTP 错误 / JS 控制台输出**一律用 `local*`; - 远程只保留"这件事的结论": - - 取址:成功一条 `NATIVE-SONG 取址成功 编号=… 源=… urlHost=… 用时=…ms`, - 失败一条 `NATIVE-SONG 全部源失败 编号=… 详情=… 用时=…ms`, - 全部只发广告一条 `SOURCE-BLOCKED 全部 N 个源只返回广告/测试资源…` - → **每次取址远程恰好一条**(改前是每个源一条,9 个源就是 9+ 条); - - `JS …`(ktv_api.js 的 console 转发)**只进本地**,不再进远程; - JS 路径失败仍由远程的 `点歌失败 编号=… 请求源=… 详情=…` 一行说明原因。 - ⚠️ 新加日志时先问自己:"这条是'结论'还是'过程'?" —— 过程写本地。 + 5. **⚠️⚠️ 远程日志只收「启动检测 + 报错」两类(2026-10-15 二次收紧,用户要求)**: + `MiliLog` 的级别语义已定死为 —— + - **上远程**:`MiliLog.remote(...)`(**仅启动检测**:`APP-INIT` / `BOOT` / `STORAGE` / + `JS-BRIDGE ready`)+ `MiliLog.error(...)`(**报错**); + - **只写本地**:`info` / `notice` / `warn` / `local` / `localWarn` / `localError` + → `<存储根>/logs/ktv.log`(纯文本,什么都不缺)。 + ⚠️ **不要**把 `info`/`notice`/`warn` 改回上传;想让某条"警告类失败"也进远程, + 就把它**显式改成 `MiliLog.error(...)`**(一次改动、意图可见)。 + 现场排查一律先取本地日志文件;远程只回答"机器起来了没"与"有没有报错"。 6. **状态样本 + 事件**缺一不可:事件(点歌/失败)说明"发生了什么",但排查"随时间变化"的 问题(空间变少、曲库丢失、长期离线)需要状态样本 —— 现由 6 小时一条 `HEALTH ...` (版本/在线/可用空间/曲库大小/根目录)提供。 diff --git a/app/build.gradle b/app/build.gradle index 479f9b1..f1794bd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,8 +20,8 @@ android { applicationId "com.local.ktv" minSdk 21 targetSdk 25 - versionCode 46 - versionName "1.6.3" + versionCode 47 + versionName "1.6.4" ndk { // 双 ABI 打包:兼容 64 位(Exynos 1580 等 arm64-v8a)与 32 位设备(极米 Play 超越版 // 的 Amlogic 950X2/S905X2 采用 32 位 Android 用户态,必须包含 armeabi-v7a,否则 diff --git a/app/src/main/java/com/local/ktv/KtvApplication.kt b/app/src/main/java/com/local/ktv/KtvApplication.kt index bbdbc2d..41dcb69 100644 --- a/app/src/main/java/com/local/ktv/KtvApplication.kt +++ b/app/src/main/java/com/local/ktv/KtvApplication.kt @@ -31,7 +31,7 @@ class KtvApplication : Application() { // init 现在可重复调用且会自动重启发送线程,这里是"最靠前"的启动点。 runCatching { MiliLog.init(this) - MiliLog.info("APP-INIT 进程启动 ver=${BuildConfig.VERSION_NAME} logFile=${MiliLog.localLogPath()}") + MiliLog.remote("APP-INIT 进程启动 ver=${BuildConfig.VERSION_NAME} logFile=${MiliLog.localLogPath()}") }.onFailure { Log.e(TAG, "MiliLog.init failed", it) } OkDownload.setSingletonInstance(OkDownload.Builder(this).build()) Log.i(TAG, "KTV application initialized without native services") diff --git a/app/src/main/java/com/local/ktv/KtvJsBridge.kt b/app/src/main/java/com/local/ktv/KtvJsBridge.kt index dd75bba..1a5941d 100644 --- a/app/src/main/java/com/local/ktv/KtvJsBridge.kt +++ b/app/src/main/java/com/local/ktv/KtvJsBridge.kt @@ -287,7 +287,7 @@ class KtvJsBridge(context: Context) { unavailableReason = "" } Log.i(TAG, "JS runtime ready (${if (loadedFromCache) "cache" else "asset"})") - MiliLog.info("JS-BRIDGE ready (${if (loadedFromCache) "cache" else "asset"})") + MiliLog.remote("JS-BRIDGE ready (${if (loadedFromCache) "cache" else "asset"})") callback(true) } else if (loadedFromCache && !assetRetryAttempted) { Log.w(TAG, "Cached JS failed to load; falling back to packaged asset") diff --git a/app/src/main/java/com/local/ktv/MainActivity.kt b/app/src/main/java/com/local/ktv/MainActivity.kt index 548b95f..476eba6 100644 --- a/app/src/main/java/com/local/ktv/MainActivity.kt +++ b/app/src/main/java/com/local/ktv/MainActivity.kt @@ -3878,10 +3878,10 @@ class MainActivity : AppCompatActivity() { sb.append(" screen=").append(screenResolutionText()) // 等主机 IP(公网出口 IP)就绪,避免启动这条日志的 serverip 为空。 MiliLog.awaitServerIp() - MiliLog.notice(sb.toString()) + MiliLog.remote(sb.toString()) // BOOT 启动检测行 // 存储根目录探测结果(排查不同盒子存储差异用;单行便于按 STORAGE 检索)。 // 放在这里而不是启动主线程:既有完整上下文,又避免了主线程磁盘探测。 - runCatching { MiliLog.notice("STORAGE ${AppPaths.storageFacts(this@MainActivity)}") } + runCatching { MiliLog.remote("STORAGE ${AppPaths.storageFacts(this@MainActivity)}") } } catch (ignored: Exception) { } }, "ktv-boot-log").start() diff --git a/app/src/main/java/com/local/ktv/MiliLog.kt b/app/src/main/java/com/local/ktv/MiliLog.kt index b9bbe0e..6c79b9d 100644 --- a/app/src/main/java/com/local/ktv/MiliLog.kt +++ b/app/src/main/java/com/local/ktv/MiliLog.kt @@ -153,11 +153,25 @@ object MiliLog { } } - fun info(msg: String) = enqueue("INFO", msg) - fun notice(msg: String) = enqueue("INFO", msg) - fun warn(msg: String) = enqueue("WARN", msg) + /** + * ⚠️ **远程日志策略(2026-10-15 收紧,用户要求)**:远程服务**只收两类** —— + * 1. **启动检测**:显式用 [remote](`APP-INIT` / `BOOT` / `STORAGE` / `JS-BRIDGE ready` 等一次性行); + * 2. **报错**:[error]。 + * + * 其余一切(info / notice / warn、逐源逐次细节、JS 控制台输出、6 小时健康样本……) + * **只写本地** `<存储根>/logs/ktv.log`,不再上报远程。 + * + * ⚠️ 不要顺手把 [info]/[notice]/[warn] 改回上传:远程只做"这台机器是否起来 + 有没有报错", + * 需要细节时让现场把本地日志文件发出来(那里面什么都不缺)。 + */ + fun info(msg: String) = enqueueLocal("INFO", msg) + fun notice(msg: String) = enqueueLocal("INFO", msg) + fun warn(msg: String) = enqueueLocal("WARN", msg) fun error(msg: String) = enqueue("ERROR", msg) + /** **启动检测**专用:这类一次性行仍上报远程(其余细节只写本地)。 */ + fun remote(msg: String) = enqueue("INFO", msg) + /** * **只写本地**的详细日志(2026-10 新增)。 *