Logs 的原理
2026/8/25 14:06:19 网站建设 项目流程

目录

第一部分 Logs

第二部分 操作

第三部分 AI 要点(只建框架)


第一部分 Logs

1. 一条日志本质上是什么

一条日志 = 带时间戳的事件记录。最小形态:时间 + 谁说的 + 严重程度 + 说了什么

可观测性里还希望有:服务名、实例、请求 ID、错误码、耗时,这样才能检索、聚合、和 Trace 关联。

日志回答的是「发生了什么」,包括:

  • 业务事件:订单创建、库存不足
  • 错误与堆栈
  • 审计:谁在何时改了什么(你们有独立流cht_log_aws_audit
  • 调试:开发期的细节(生产要慎打)

必看文档

  1. ​编辑OTel Logs
  2. OpenObserve:​编辑Logs 概述
  3. ​编辑第一次搜日志
  4. ​编辑SQL 示例
  5. ​编辑SQL Reference(先看match_allstr_match

2. 三种形态(最重要的原理之一)

非结构化(纯文本):

2026-08-20 17:01:02 ERROR order failed timeout

人能读,机器很难稳定解析。全文搜索可以,但按「服务 + 错误码」聚合很痛。

半结构化:

time=2026-08-20T17:01:02Z level=error service=order msg="timeout" trace=abc

有键值,但格式各写各的,字段名容易漂。

结构化(推荐,JSON 等):

{ "_timestamp": "2026-08-20T17:01:02Z", "level": "error", "service": "order", "trace": "4bf9e929d0e0e4736", "error": "upstream timeout", "http_code": "504" }

每个键都是列。好处:过滤准、聚合快、告警稳、和 Trace 对齐容易。

JSON 同时满足几件事:

  1. 字段就是键。levelservicetracepurchase_ordersn不用靠正则从句子里抠。
  2. 跨语言。 Java、Go、PHP、前端都能直接json.Marshal/json_encode
  3. 能嵌套。 采购单、SKU 列表、错误对象可以放在一个对象里,不像纯文本只能摊成一长串。
  4. 采集端好拆。 OpenObserve 看到 JSON,就能把键变成cht_log_aws里的列,于是能写:
SELECT * FROM cht_log_aws WHERE trace = '4bf9e929d0e0e4736'

反面教材:cht_log_aws目前大约 192 个字段。同一类意思出现了多套名字,例如error/err/errcode/error_msg/errormsg/errmessage/http_code/code。这就是长期半结构化、各服务各打各的结果:schema 爆炸,查询要写一堆OR,索引也变贵。


3. 级别(level)

常见级别从低到高:

级别何时用生产建议

TRACE / DEBUG

开发细节

默认关,按需打开

INFO

关键业务里程碑

克制,不要每个循环打

WARN

可恢复异常、降级

要能说明风险

ERROR

这次操作失败

必须能定位

FATAL

进程要死

极少

原则:级别表达「对运维的紧急程度」,不要把 INFO 当 DEBUG 用。
告警一般盯 ERROR+,但「ERROR 刷屏」也可能是下游抖动,要结合数量和service,不能一条 ERROR 就叫人。


4. 日志数据模型(OTEL 视角)

日志数据模型就是约定「一条日志长什么样」:必须有哪些字段、每个字段什么含义。不是指磁盘怎么存,而是双方怎么理解这一条记录。

有了模型,采集端、OpenObserve、查询 SQL 才说的是同一种东西。没有模型,就只是一堆字。

OTEL 里一条 Log Record 大致包括:

  • Timestamp:事件时间(注意:采集时间 ≠ 事件时间)
  • ObservedTimestamp:被采集到的时间
  • Severity:级别
  • Body:正文(字符串或结构化体)
  • Attributes:字段(http.status_code等)
  • Resource:谁在打(service.name、主机)
  • TraceContext:trace_idspan_id(有则能关联链路)

即使现在很多日志不是 OTLP 进来的,模型仍应往这套靠:时间、级别、资源、属性、trace 上下文。

OpenObserve 里常见还会有_timestamp(平台时间列)。查询时间范围用的就是它。


5. 采集路径

应用 logger.info(...) / 写文件 / stdout


Agent / 采集器(Fluent Bit、Vector、OTEL Collector、云 sidecar)
│ 解析、加字段、脱敏、丢弃 DEBUG

管道 / 消息队列(可选,削峰)


存储(OpenObserve / Elasticsearch / Loki)


查询 UI、告警、看板

每一跳都可能丢数据或改字段。排障时要问:

  • 日志是应用直接打 OTLP,还是先写文件再采集?
  • 解析规则会不会把 JSON 拆错(你们流里有_badkey,往往就是解析失败的痕迹)?
  • 时钟是否准?(容器时区、多机会导致同一请求时间对不齐)

6. 采样、脱敏、保留(成本与合规)

量:日志是三类里通常最贵的。1 亿 QPS 级别的 DEBUG 能把集群打满。手段:

  • 生产默认 INFO+
  • 成功请求抽样(例如只留 1%),错误全量
  • 丢弃健康检查、静态资源
  • 字段裁剪:不要把整段请求体、Token、身份证打进日志

脱敏:密码、Cookie、证件号、手机号进日志是事故。应在采集器或应用侧打码,而不是指望查询的人「注意别看」。

保留:越久越贵。你们cht_log_aws当前设置为 保留约 20 天,单次查询窗口最大约 72 小时。所以:

  • 查日志先收窄时间,不要一上来查 30 天SELECT *
  • 审计日志(cht_log_aws_audit)往往要更长留存、更少字段,和业务调试日志分开

这就是「日志原理」里和存储绑定的部分:不是记越多越好,而是记对的、能查的、能留得起的。


7. 索引与查询原理(操作前要懂)

日志存储一般会:

  • 按时间分片
  • 对少量列建索引(你们:serviceappcodetracetraceid
  • 全文检索(match_all)扫的是文本,通常比「等值过滤索引列」更重

所以查询要:

  1. 先定时间范围
  2. 优先过滤索引字段(servicetrace
  3. 再用match_all('timeout')str_match(error, 'timeout')收窄

不要:无时间范围 + 全文搜一个很宽的词。

第二部分 操作

1. 结构化日志最低字段集

新日志至少带:

字段说明

时间

ISO8601 或平台_timestamp

level

info / warn / error

service

服务名,稳定、短

tracetrace_id

与 Trace 同一值

errorerror_msg

失败时必填,一种名字用到底

可选

span_idhttp_codedurationappcodeenv

不要再发明errmessage第五个同义词。已有流字段乱,新服务按这一套即可。


2. 在 OpenObserve 里检索

组织默认default,业务日志流cht_log_aws。时间用微秒时间戳;查询窗口尽量 ≤ 72h。

按服务看最近错误:

SELECT _timestamp, service, appcode, trace, error, error_msg, http_code, content FROM cht_log_aws WHERE service = '某个服务名' AND (level = 'error' OR error IS NOT NULL OR error_msg IS NOT NULL) ORDER BY _timestamp DESC

全文:

SELECT _timestamp, service, trace, content FROM cht_log_aws WHERE match_all('timeout')

聚合:哪个服务错误最多:

SELECT service, COUNT(*) AS cnt FROM cht_log_aws WHERE error IS NOT NULL OR errcode IS NOT NULL GROUP BY service ORDER BY cnt DESC

字段不统一时,聚合会不准——这正是结构化没做好的代价。


3. 用同一 ID 验证日志 ↔ 链路

test_otel(traces)里取一条trace_id

在日志里查:

SELECT _timestamp, service, appcode, level, error, content, trace, traceid FROM cht_log_aws WHERE trace = '<这条 trace_id>' OR trace_id = '<这条 trace_id>' OR traceid = '<这条 trace_id>'

审计流也可查:

SELECT * FROM cht_log_aws_audit WHERE trace = '<trace_id>'

三种结果都要记进实验:

  • 两边都有:关联成功,记下服务名、时间是否接近。
  • 只有 Trace 没有日志:日志没打关联字段,或时间范围/流不对,或日志采样丢掉了。
  • 只有日志没有 Trace:没插桩、Trace 采样丢了,或 ID 不是同一套。

4. 错误日志告警(最小可用)

最小规则例如:

  • 条件:某service在 5 分钟内level=error条数 > N
  • 通知:值班人
  • 消噪:排除健康检查;N 按基线调,避免一条 ERROR 就叫

第三部分 AI 要点(只建框架)

计划里有两条线,目前只要分得清,不要混:

主线含义例子

AI for Observability

用 AI 分析已有日志/链路/指标

自然语言转 SQL、错误摘要、日志聚类

Observability for AI

观测 LLM/Agent 自己

token、工具调用 span

日志上的 AI 能力:

  • 聚类 / Pattern:把上万条相似 ERROR 收成几种模板
  • NL → 查询:你说「查订单超时」,模型写出 SQL
  • 摘要:把堆栈收成几句人话

风险:幻觉(编造不存在的字段或结论)。规范是:先检索,再生成;结论必须能指回具体查询和原文。


延伸

组件定位

ELK(Elasticsearch / Logstash / Kibana)

经典日志栈,倒排检索强,成本高

Grafana Loki

标签索引 + 日志内容,成本往往更低,标签基数要控制

Fluent Bit / Vector

采集与加工(解析、脱敏、路由),不是存储

OpenObserve

你们的统一平台:日志 + 链路(+ 指标)一起查


术语表

术语含义

Observability

由外部遥测推断系统内部状态的能力

Logs / Traces / Metrics

三大支柱:事件、请求链、数字趋势

Signal

OTEL 对三类遥测的统称

OpenTelemetry (OTEL)

厂商无关的采集与传输标准

OTLP

OTEL 的导出协议

Collector

接收、处理、转发遥测的独立进程

Instrumentation

插桩,在运行路径上采集遥测

SLI / SLO / SLA

测量指标 / 内部目标 / 对外合同

RED

Rate、Errors、Duration

Structured log

字段稳定的日志(如 JSON)

Severity / level

日志级别

Resource

谁在发数据(服务名、环境)

Attribute

单条记录上的键值

trace_id/trace

跨日志与链路的请求 ID

Cardinality

字段取值组合数;过高会爆成本和 schema

Retention

数据保留时长

Sampling

只保留一部分数据以控制成本

Agent

采集侧进程(读文件、stdout 或自动插桩)

AI for Observability

用 AI 分析遥测

Observability for AI

对 AI 应用做遥测


日志实验记录怎么写

  1. 采集说明:数据从哪来、流名(cht_log_aws)、组织default、关联字段trace、保留约 20 天、查询窗口约 72h。
  2. 典型查询 2~3 条:例如按service过滤、match_all、按服务COUNT聚合;贴 SQL 和结果摘要(条数、时间范围)。
  3. 一次trace_id关联:ID、Trace 是否存在、日志是否命中、时间/服务是否一致、若不命中则分析缺字段还是时间/采样问题。
  4. 观察:例如字段名不统一(errorvserror_msg)、192 列 schema、索引字段有哪些。

总结:

  1. 日志看「发生了什么」,链路看「请求怎么走」,指标看「整体健不健康」。
  2. 可观测性靠统一字段把三类数据连起来,关键是trace_id(你们日志里是trace)。
  3. 结构化日志的价值是可过滤、可聚合、可告警;字段名混乱会变成上百列。
  4. 采集是「应用 → Agent/Collector → 存储 → 查询」;查询先锁时间,再用索引字段。
  5. 日志最贵,要靠级别、采样、脱敏、保留控制;AI 只能辅助,结论必须能回溯到查询。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询