6 Commits
Author SHA1 Message Date
opsx 5e59347c40 feat(settings,analysis): 日志保留时间可配(发送历史保留 7 天)+ 分析页手动刷新;修复我引入的 RWMutex 死锁
=== 0. 【严重】修复上一版引入的死锁(平台写路径全卡死)===
上一版把保留期读取写成 `GetRetentionSettings()`(内部 db.RLock()),
却在 `db.Lock()` 已持有的情况下调用(recordDelivery / RecordAudit 的裁剪路径)。
Go 的 sync.RWMutex **不可重入** → 第一次写投递历史/审计日志就永久死锁。
现象:登录 28 秒返回空(登录也要写审计)、所有写接口挂住。
go build / go vet / 之前的单测(不触发写路径)全都查不出来。
修法:
  - 拆出 retentionFromDBLocked(db) / alertDeliveryRetentionLocked(db) /
    auditLogRetentionLocked(db),调用方已持锁时用无锁版本
  - upsertSettingLocked 里**不能**用 db.NextID()(内部 d.mu.Lock(),同样死锁),
    改为锁内自算 max(id)+1
  - 新增 retention_test.go:持写锁调用裁剪函数,2 秒超时未返回即判死锁
实测修复后:登录 103ms(原 28000ms)、panic/deadlock 命中 0。

=== 1. 平台数据保留期可配(系统设置 → 通用配置 → 日志保留时间)===
新增 GET/PUT /api/v1/settings/retention:
  alertDeliveryDays  告警发送历史保留天数,默认 7(原写死"最近 50 条")
  auditLogDays       审计日志保留天数,默认 90(原写死常量)
保存后立即按新策略裁剪一次,不必等下次触发。
校验:发送历史 1~365 天、审计 1~3650 天,超出返回明确中文原因(不是 500)。
注意与「Loki 日志保留期」区分:那个是部署级配置(组件部署 → 保留策略)。

=== 2. 发送历史:50 条硬上限 → 保留 7 天 ===
后端 Deliveries 接口原来写死 `len(out) < 50`,现在按保留期取(响应上限 500 可调),
标题改为「发送历史(保留 N 天)」,N 从设置里读。

=== 3. 菜单「日志服务」→「组件部署」===

=== 4. 分析页:去掉「全部命名空间」+ 改手动刷新 ===
- 移除「全部命名空间」选项:{namespace=~".+"} 要扫全集群(约 370GB/天),
  一次分析几十秒,得不偿失;历史值 __all__ 也会被忽略并回退到策略/第一个 ns
- 筛选改为「选择值 / 已生效值」分离:切换命名空间或时间范围**不再自动查询**,
  只把刷新按钮点亮并提示「筛选条件已改,点刷新生效」;
  点一次才应用并取数。
  原因:一次分析要跑多条 count_over_time,切一下下拉就重查一轮,
  快速连点会把 Loki 打满(并发护栏 429),还拖慢别人。

=== 实测(9739c7c092e7)===
  登录 103ms / token 273 字符
  GET retention → {alertDeliveryDays:7, auditLogDays:90}
  PUT 0 天 → 400「告警发送历史保留天数需在 1~365 之间」
  平台日志 panic/deadlock 命中 0
  go test ./... 全绿(含 2 个新死锁回归用例)
2026-10-29 04:16:52 +00:00
opsx 46e73d3d17 fix(loki): COS 存储全链路修复 —— Secret 生成/env 注入/凭据解密/endpoint 规范化
API 端到端跑通中暴露 4 个串联问题(腾讯云 COS + K8s 场景):

1. loki_manifest.go: switch 缺少 cos / obs
   → 不生成 loki-storage-credentials Secret、不注入 LOKI_STORAGE_* 环境变量、
     也不给 Loki 加 -config.expand-env=true
   → 配置里 ${LOKI_STORAGE_ACCESS_KEY} 无法展开 → AK 为空
   → COS 返回 403 InvalidAccessKeyId(ruler 每分钟报错)
   修复:case 补上 cos / obs

2. loki_manifest.go: 生成 Secret 时用了 ENC: 密文原始值
   → Secret data 里是 ENC:xxx 而非真实 AK/SK
   修复:crypto.DecryptField 解密后再 base64

3. loki_config.go: host-docker 模式同样把密文写进配置
   修复:解密后返回

4. loki_config.go: cos/oss/obs 的 endpoint 未剥离桶名前缀
   → 用户填虚拟主机式 endpoint(mybucket-1250000000.cos.<region>...)时,
     Loki 的 S3 客户端又拼一次 bucketnames,变成 <bucket>.<bucket>.cos...
   → TLS 证书校验失败(x509: certificate is valid for ... not <bucket>.<bucket>.cos...)
   修复:新增 stripBucketPrefix,s3/cos/oss/obs/minio 分支统一剥离桶名前缀

验证(log namespace,API 端到端):
  - Loki statefulset 1/1 Running,ruler 无 InvalidAccessKeyId/x509
  - 写入 + 查询日志成功(持久化到 COS)
  - Promtail DaemonSet 12/12 全节点就绪
  - collector status=active

运维侧附加动作(非代码,见部署文档):
  - 存储配置改用有效 AK/SK + 区域端点 cos.ap-hongkong.myqcloud.com
  - 平台 ServiceAccount log:lokistack 绑定 cluster-admin
    (否则无法创建 Promtail 所需的 ClusterRole/ClusterRoleBinding)
2026-10-26 19:32:38 +00:00
opsx cfe1ccd154 fix(storage): 按 endpoint 形态解析响应 + 凭据解密返回 + 无建桶权限友好提示
【真实根因】COS 桶明明存在却报"桶不存在/创建失败"

用户配置:endpoint=loki-log-1394668510.cos.ap-hongkong.myqcloud.com(虚拟主机式,已含桶名)
旧代码:始终 GET / 并按 ListBuckets 的 <Buckets><Bucket><Name> 解析。
但在虚拟主机式 endpoint 下,GET / 返回的是 ListObjects(<ListBucketResult>)——
桶内对象列表,不是桶列表。解析必然找不到桶名 → 误判"桶不存在"
→ 触发建桶 PUT → 用户的 AK 无 cos:PutBucket 权限 → 403
→ 最终报"创建后校验失败"。

【实测确认(用该 AK 直连 COS)】
  GET / (vhost)         → 200  <ListBucketResult>         桶存在,能列对象
  GET / (区域端点)       → 200  <ListAllMyBucketsResult>   AK 有 cos:GetService
  HEAD /                → 403  AK 无 cos:HeadBucket
  PUT /  (CreateBucket) → 403  AK 无 cos:PutBucket
即 QcloudCOSDataFullControl = 数据面全控(读写/列桶),不含管控面(建桶/HeadBucket)。

【修复】
1. 探测统一用 GET /,再按 endpoint 形态解释响应:
   - 虚拟主机式 → 按 ListObjects(<ListBucketResult>)判断,200 即桶存在
   - 区域端点   → 按 ListBuckets(<Buckets><Bucket><Name>)匹配桶名
   桶存在就直接返回"桶已存在",不再走建桶流程。
2. 建桶二次校验同样改用 GET /(不再用 HEAD,避免 HeadBucket 403 误判)。
3. 建桶返回 403 时给出明确友好提示:
   "当前 Access Key 无建桶权限。腾讯云 QcloudCOSDataFullControl 只授予数据读写/列出,
    不含 CreateBucket。请到 COS 控制台手动创建桶,或在 CAM 追加 cos:PutBucket"
4. models/storage.go Sanitized() 用 crypto.DecryptField 解密后再返回 AK/SK
   (原来直接返回 ENC:xxx 密文,前端编辑框显示密文)。
5. 前端访问地址输入框补充说明:推荐填区域端点(不带桶名)。

镜像:lghost/lokistack:latest + v0.1 = sha256:350478003870
2026-10-26 18:38:00 +00:00
opsx ff69ea2ce8 fix(storage): 凭证明文返回便于编辑测试 + 建桶后二次校验防"假成功"
问题(log.astx.club/storage):
  1. 编辑存储时 Access Key / Secret Key 都是空的,点「测试连接」提示
     请先填写 Bucket 与 Access Key / Secret Key,无法测试也无法保存;
  2. 提示"桶不存在,已自动创建"但疑似没有真正创建;
  3. 测试失败提示用 toast 弹到右下角,不在弹框内。

修复:
  1. models/storage.go Sanitized() 返回 accessKey / secretKey 明文
     (内网运维工具,管理员需要在编辑弹框里看到并测试连接;脱敏会导致
      编辑时字段为空、校验失败)
  2. 前端 StorageConfig 类型补 accessKey / secretKey 字段;
     编辑弹框打开时回填这两个字段(原来只有 secretKey 且强制置空);
     Secret Key 标签去掉「留空保持不变」
  3. services/storage_check.go 建桶后二次 ListBuckets 校验:
     不同对象存储 CreateBucket 语义不同(腾讯云 COS 要求桶名放 Host、
     路径为 /),直接 PUT /<bucket> 可能返回 200 但未真正创建。
     现在创建后重新列举桶,找不到就报"创建后校验失败"并提示检查
     Endpoint / Region / 桶名(COS 需带 APPID)
  4. 前端「请先填写 Bucket 与 Access Key / Secret Key」改为在弹框内
     testResult 区域显示(原来 toast 弹右下角)

镜像:lghost/lokistack:latest + v0.1 = sha256:6b6cc9769e79
2026-10-26 18:30:47 +00:00
logan 2d73661dd1 feat: complete Loki query, insights, settings and deployment workflows
Add the Loki query UI, access policies, ingress insights, alert and registry settings, and their backend APIs. Include the related Kubernetes deployment and collector updates required by the integrated application.

Validated with go test ./..., npm run build, and npm run lint.
2026-10-25 21:28:32 +08:00
logan f9c6c1d826 feat: opsx-loki 全面升级 — 前端重构/用户与LDAP/部署向导/日志查询
基于 WEB-UI-Development-Guide 标准的整体升级,并更名 LokiDeploy → opsx-loki。

前端(Gin+React+shadcn/ui):
- 按 02/07 章重构:页面域化拆分(无超 400 行文件)、PageContainer/ListQuery、
  反馈分级(成功静默/失败 toast/危险确认)、401 单飞刷新+队列重放
- 暗色模式(next-themes)+ 语义 Token(--primary 品牌色/success/warning/info)
- 部署向导(状态推导四步:环境→存储→Loki→采集,内嵌表单闭环)
- 日志查询页:LogQL 标签构建器/拖拽直方图/日志上下文/Live Tail/查询历史
- 按用户+标签策略的查询授权(服务端强制合并策略)

后端(Go+Gin+JSON DB):
- 简单用户管理(仅 admin,无 RBAC)+ TokenVersion 会话吊销 + 登录 IP 限流
- LDAP 接入:配置(AES 加密存储/hasPassword 脱敏)/测试连接/批量导入/登录
- 存储配置测试连接(SigV4 零依赖)+ 桶不存在自动创建
- Loki 三模式部署修复:SSH 密钥认证、3.x 配置模板、ruler 对象存储嵌套块、
  凭证解密、孤儿 deploying 状态恢复、Grafana 部署(可选默认关)+面板导入
- DaemonSet 采集纯 YAML(去 helm 依赖)+ DNS 自愈回退 ClusterIP + 集群名标签
- 日志查询代理:cluster-svc 经 kube-apiserver proxy/url 直连 + cursor 翻页
- 统一 log 命名空间;部署就绪探活;Grafana 访问地址自动记录

修复:run.sh 增量编译检测、Sanitized 脱敏补全、LokiDeployment Update 白名单、
健康检查 CreatedAt 零值等 10+ 存量 bug。

数据兼容:DB 沿用旧 lokideploy.json(新名优先);localStorage 一次性迁移;
HKDF 加密前缀保留(已加密凭证不受影响)。
2026-10-24 13:20:12 +08:00