OpenObserve vs 观测云:自建和托管的日志成本

从原始量与留存预算,到事件时间、字段类型、SQL/DQL、冷缓存和双写对账,比较 OpenObserve 自建与观测云 SaaS。附 OpenObserve v1.0.4 小样本查询及观测云 Pipeline 验证结果。

最佳实践
自建与托管日志平台主题插画

如果只是为了降低日志费用,我不建议把自建当作必经之路。按价值分流、缩短普通日志保留期、减少不必要的加工和索引,这些事在托管平台上同样可以做。做完以后还剩多少费用,再决定是否值得自己运行后端。

OpenObserve 适合希望自己掌握存储、查询资源,也有人持续维护的团队。观测云则适合希望尽快交付日志、告警和关联排障,把后端部署与运行交给服务方的团队。两边都需要整理业务字段和规则,费用差别主要出现在这部分共同工作之后。

迁移里的细节也会增加投入。比如这次小样本验证,OpenObserve 回灌接口返回 HTTP 200,响应体却是 successful: 0, failed: 1,原因是事件时间超过允许写入的历史范围。只改一个写入地址,远没有把日志平台交给业务使用。下面会把这样的实际结果和费用一起展开。

没有长期专职维护日志平台的人,又需要尽快可用,我更倾向先用观测云完成分流与留存优化。 已有的加工、查询和告警能力可以直接配置,不必先投入一个后端建设项目。只有同样需求下的总费用仍然不合适,再决定哪些部分值得自建。

观测云编辑部 · 2026 年 10 月 9 日。比较范围为 OpenObserve 开源版自建与观测云 SaaS。本文执行了 OpenObserve v1.0.4 本地写入与查询、观测云 Pipeline 样本调试和 DQL 语法校验;未执行观测云入库查询、双方生产压测或完整迁移。样本、配置和结果见文末附件。

日志量与保留期

容量先从应用产生的原始日志算起。采集器压缩后的请求与对象存储合并后的文件,是另外两个口径;直接拿它们的字节数给写入节点或存储配资源,会低估或高估需求。

每日字节数之外,还要记录日志条数和峰值。同样是 1 TiB/天,平均每条 1 KiB,对应约 12,400 条/秒;平均每条 4 KiB,则约 3,100 条/秒。平均字节率相近,逐条解析与处理的次数相差四倍。日均值也覆盖不了业务高峰,写入能力和缓冲预算应使用实际峰值评估。

下面用 1 TiB/天原始日志做一个容量推导。所有数字都是便于复算的假设:80% 的日志只需保留 3 天,20% 需要保留 30 天;暂按数据文件压缩后为原始量的四分之一计算,不含索引、副本、缓存和备份。

全部保留 30 天:1 × 30 ÷ 4 = 7.5 TiB
分开保留:    (1 × 80% × 3 + 1 × 20% × 30) ÷ 4 = 2.1 TiB

这个模型里,保留策略调整后,稳态数据文件减少 5.4 TiB。四倍压缩只是算式假设,但保留时间的影响很清楚。采用哪种后端都可以先做这项整理,自建是否更省,应当在双方采用相同策略以后比较。

同一个交付要求 OpenObserve 开源版自建 观测云 SaaS
不同日志保留不同时间 按 Stream 配置留存,并承担后端资源规划 按日志索引配置分流、留存,使用托管后端
自定义 JSON 解析与字段整理 在采集器或平台 Pipeline 中配置转换 DataKit / Pipeline 配置转换,有样本调试入口
查询高峰仍可用于排障 规划 Querier、缓存和调度资源 验证服务规格;企业版可购买工作空间独占算力
扩容、升级、恢复 团队负责部署的各个后端组件 SaaS 后端由服务方运行,客户仍负责自己的采集端

观测云普通日志索引按顺序匹配,写入首个命中的索引。“所有生产日志”放在“生产审计日志”前面,就可能先接走后者,所以具体规则要排在宽规则前。当前普通索引总数上限为 6 个,包含 default,新建多索引需要申请开通。大量 OpenObserve Stream 迁入时,索引组织通常要重新安排。日志索引规则

更合适的组织方式,是让索引承载保留期与访问需求,用 source、service、env 区分来源。这样,新增服务通常只需沿用已有规则,而不用同步增加一套存储配置。

长期数据的访问也有取舍。观测云日志长期存储单次查询最多覆盖 24 小时,偶尔回查某一天的记录比较合适;经常跨整月聚合,则应按满足该需求的标准存储报价。保留期缩短以后,旧数据仍按原策略计费直到滚动删除,费用会逐步接近新稳态。存储策略与变更规则

时间和字段处理

下面这条合成日志很普通:应用时间、级别、耗时和 trace ID 都在,直接转发也容易被认为已经足够。

延伸阅读日志平台迁移:双写、对账和回滚怎么安排

{
  "event_id": "e-001",
  "timestamp": "2026-10-09T10:00:00.123456+08:00",
  "service": "checkout",
  "env": "prod",
  "level": "ERROR",
  "duration_ms": "1200",
  "trace_id": "00000000000000000000000000000001",
  "message": "upstream timeout"
}

这里至少有三处需要明确处理:timestamp 是事件时间,level 是应用自定义的级别字段,duration_ms 则是字符串。

通过 OpenObserve JSON 接口直接写入、不附加转换时,业务字段 timestamp 不会自动成为平台的时间字段。该接口识别 _timestamp 或 @timestamp;都没提供时,会补入当前时间。JSON 写入与时间字段

我们把六条事件时间位于 10:00—10:05 的日志原样写入,成功数是 6。按事件时间查,返回 0 条;按实际写入时间查,返回 6 条。再把原来的 timestamp 映射到 _timestamp,相同事件时间窗口就能查到全部六条。日志没有丢,只是落在了另一段时间里。日常实时写入时,这个差别不容易暴露;一旦消费积压或回灌历史数据,趋势图和告警窗口就会偏离业务发生的时间。

观测云侧也需要把应用字段接到平台约定上。这次执行的 Pipeline 如下:

json(_, timestamp, "time")
json(_, event_id)
json(_, service)
json(_, env)
json(_, level, "status")
lowercase(status)
json(_, trace_id)
json(_, duration_ms)
cast(duration_ms, "float")
json(_, message, "message")
default_time(time)

调试输出中,第一条日志的时间是 1791511200 秒加 123456000 纳秒,换算成 OpenObserve 使用的微秒,正好是 1791511200123456;duration_ms 变为数值 1200,status 为 error。六条样本均执行成功,其中缺少耗时字段的一条仍保持缺失,没有被补成 0。Pipeline 调试与时间处理

另一个容易忽略的差异来自 WARN。在本次观测云 Pipeline 调试结果中,它被规范成 warning;OpenObserve 则保留了我们预处理后写入的 warn。如果原告警里写着 status='warn',迁到观测云以后只改查询语法就会漏匹配。将两边统一为 warning 后,OpenObserve 查询出的六条记录,与 Pipeline 输出的字段、事件时间逐条一致。这里验证的是查询结果与解析结果的一致性,尚不包含观测云入库后的查询。

这组样本以后还可以继续用。应用格式变化、采集规则升级时,正常值、缺失值、异常时间和不同级别的写法一起回归,就能较早发现查询与告警受到了什么影响。这是两种方案都需要维护的业务规则。

观测云在这里提供的是已经可用的采集、解析和调试流程。常见格式可以从官方脚本开始,例如 Nginx 的 nginx.p;自定义格式补上自己的规则。OpenObserve 也有转换能力,不必从零开发解析器。选择 SaaS 能减少的,是完成这些业务配置之后,还要另行部署和维护接收、查询、存储后端的工作。观测云日志 Pipeline 使用方式

SQL 与 DQL 查询

继续用这六条日志。三条是错误日志,其中两条有耗时,分别为 1200 和 1600 毫秒,另一条没有耗时字段。

先查慢请求。保留原始字符串类型,在 OpenObserve 中执行:

SELECT event_id, duration_ms
FROM time_checkout
WHERE duration_ms > '900'
ORDER BY event_id

结果是 0 条。把字段显式转换成数值,或者在写入前完成数值转换,再比较 duration_ms > 900,结果才是 e-001 和 e-002。前一条做的是字符串比较,'1200' 并不会因为代表一个更大的数字,就排在 '900' 后面。

接着查错误数:

SELECT count(*) AS error_events,
       count(duration_ms) AS with_duration
FROM checkout
WHERE env = 'prod' AND status = 'error'

在固定的 10:00—10:05 窗口内,实际返回 error_events=3、with_duration=2。这个差别会直接进入错误率的分子、分母。用 count(duration_ms) 代替事件总数,恰好会漏掉没有成功记录耗时的那条错误。

观测云对应的错误事件计数可以写成:

L::checkout:(count(*))
{ `env` = "prod" AND `status` = "error" }
[1791511200000:1791511500000]

这条 DQL 已通过语法校验。它以 source=checkout、default 索引为前提;调试 Pipeline 本身不会替你建立这个采集源。OpenObserve 的查询请求使用微秒时间戳,以上 DQL 使用毫秒时间戳,两者都指向北京时间 2026 年 10 月 9 日 10:00—10:05。迁移核对时要固定这样的绝对时间窗口,别在两边先后执行“最近五分钟”。count(*) 与字段计数的含义也应分别保留。DQL 语法 · 聚合函数

全文检索也要做相同的语义核对。寻找词项 timeout、寻找子串 time、匹配整个字段,得到的记录可能不同。旧查询里的 LIKE '%time%',不能仅仅因为某个全文函数更快,就直接替换掉。拿一批预先知道应命中哪些事件的样本,逐条核对返回的 event_id,比只看两边都返回了一张表更可靠。

告警迁移还要继续核对检测频率、回看窗口、迟到数据、分组维度和空结果处理。查询结果一致,只完成了其中一部分。特别是按 service, env 分组的规则,标签名称变了,会同时改变告警数量和通知对象。

查询性能与资源

字段和查询结果对齐之后,再讨论性能才有意义。

延伸阅读日志可靠交付:缓冲、消费位点和失败重试

OpenObserve 的查询路径与数据所在位置有关。新到的日志可能仍由 Ingester 的内存表等路径提供查询;落入对象存储的历史数据,则涉及查询节点读取、缓存和执行。把刚写进去的一小批日志反复查几次,即使很快,也不能用来估计七天历史日志的首次回查。OpenObserve 架构

日常查询大致可以分成下面几类,它们会消耗不同资源:

实际工作 时间与并发条件 需要记录的结果
按 trace ID 定位请求 近期窗口,少量结果 结果是否完整、端到端延迟
查陌生报错文本 首次查询历史窗口 扫描量、索引使用、远端读取与延迟
按接口做错误聚合 较长窗口,多人同时使用 P95 延迟、超时、CPU 与内存压力
定时告警同时运行 与人工大查询重叠 检测是否延迟,人工查询是否被拖慢

历史查询可以等几十秒,资源配置就有余地;所有查询都要求两秒内结束,则可能需要更多索引、缓存和计算。首次冷查询与重复热查询分开记录,才能解释为响应时间多花的钱。

OpenObserve 的 Tantivy 能为全文词项和结构化字段提供索引加速,但表达式会改变执行路径。官方文档明确说明:AND 中可索引的一侧仍能得到加速;OR 中只要有一个分支不可索引,整个 OR 就不能走这条索引加速路径。因此,match_all('timeout') OR message LIKE '%timed out%' 这样的查询,不能按一条精确 trace ID 查询的结果来估算性能。Tantivy 查询行为

遇到慢查询,先核对扫描范围、过滤语义和实际索引路径,再决定加什么资源。直接加缓存盘,可能只让反复访问的文件更快;扩大并发,也可能让多个重查询一起争抢内存。容量表里的对象存储,只覆盖了存放数据的一部分成本,查询节点的内存、本地缓存盘和故障余量仍要另算。

告警负载也不能省略。OpenObserve 可通过 ZO_NODE_ROLE_GROUP 将查询节点划为 interactive 与 background,分别承接交互查询和告警、报表等后台任务。团队可以据此做隔离,但需要为相应节点配置资源并持续观察调度效果。节点角色配置

观测云 SaaS 由服务方运行后端。企业版可购买工作空间级独占算力,相应空间使用这些查询节点。查询并发高、隔离要求明确时,把这部分算力加入报价,再与自建 Querier 和缓存资源比较。企业版独占算力

这里省下的工作很具体:团队继续决定什么查询算可用,由服务方承担查询后端的部署和运行。对于没有专职日志平台维护者的团队,这通常比拿到一组漂亮的单次查询耗时更有意义。

双写和历史回填

历史回填里,写入时间限制很容易拖延进度。

本次 OpenObserve 验证显式设置了 ZO_INGEST_ALLOWED_UPTO=24,再提交一条事件时间位于两天前的日志。实际响应节选如下:

{
  "code": 200,
  "status": [{
    "name": "old_checkout",
    "successful": 0,
    "failed": 1
  }]
}

完整响应说明数据超出了允许写入的历史范围。当前官方环境变量文档列出的默认值为 5 小时;本次运行使用的是 24 小时。写入准入窗口与保存时间是两项配置:能够保存 30 天的数据,不意味着当前接口就允许导入 30 天前的记录。历史回灌要先明确准入范围,再检查响应体里的成功数、失败数及原因。写入时间范围配置

实时双写也不能只看总数。我们故意让目标端少一条 e-003,多写一次 e-001,再对实际查询结果做对账:

对账项 来源样本 故意制造差异的目标样本
日志总数 6 6
唯一 event_id 数 6 5
e-003 的出现次数 1 0
e-001 的出现次数 1 2

总数没有变化,事件已经不一样。这是人为注入的验收反例,不是 OpenObserve 自动丢失或重复了数据。

生产里可以按事件时间分桶,再按服务、环境、来源细分,比较事件 ID 及各自出现次数。若应用没有稳定的事件 ID,可以在分流前生成并随两条链路一起保留;从文件采集时,也可以考虑文件身份和偏移,但必须处理轮转、截断与路径复用。trace_id 不能代替事件 ID,一条请求本来就会产生多条日志。只对正文做哈希也不够,相同正文可能是两次独立事件。

对账窗口还需要等迟到数据。十点发生、十点十分才送达的日志,应当回到十点的事件窗口。可以保留接收时间,观察事件时间到接收时间的延迟分布,再确定何时将一个时间桶视为稳定。对正在增长的时间桶立即宣布“漏数”,往往只是在测两条链路的速度差。

如果通过 Kafka 或兼容队列扇出,旧平台和新平台应各用独立的消费组;两路消费者放进同一个消费组会分摊消息,不能得到完整双写。Kafka 消费组与分区分配。采集器内部扇出则要确认慢分支的缓冲和反压是否会影响另一侧。Vector 的确认语义还取决于链路和缓冲配置,启用持久缓冲时,确认可能发生在最终后端接收之前。位点已提交,只能结合确认发生的位置来解释。Vector 交付保证

缓冲大小也能算清楚。假设队列入口持续为 20 MiB/s,要求后端中断两小时仍可接收,单份有效积压需要约 140.6 GiB;采用三副本时,仅这部分数据就约 421.9 GiB,尚未计磁盘余量。恢复后若消费只有 30 MiB/s,扣掉不断新增的 20 MiB/s,清掉这两小时积压还要四小时。这些是恒定速率下的算术结果,实际配置要使用测得的峰值和故障恢复能力。

双写期间要留出一次高峰和一次中断后的追赶,才能知道正常写入、查询与告警是否还可用。回滚期限则受队列留存和旧端采集状态限制,停掉旧写入以后,可退回的空间会逐渐变小。

迁到观测云同样需要完成这部分核对。它替团队承担后端服务,不会自动修正错误的时间字段或消费位点。若旧日志仍在 SLS、Elasticsearch 等受支持的数据源中,可以先绑定观测云外部索引,让历史数据继续在原处保留,新数据再按批次接入。这样可以减少急着搬完全部历史数据的压力;原平台费用、授权和字段映射仍然要处理。这条路径不等于 OpenObserve 可以直接作为外部索引接入。外部索引

建设费用与长期维护

如果交付要求到“能查到错误日志”为止,比较可以主要围绕写入、查询、留存和可靠性展开。若开发团队下一步就要判断请求慢在哪个下游、当时哪个 Pod 有异常,还要把关联排障的接入和维护算进去。

观测云可以从 Trace 详情关联同一 trace_id 的日志,并查看相关主机、容器和 Pod 的指标。但要让入口有内容,日志与链路必须使用一致的标识,相关数据需要已经采集,service、env 等字段以及日志索引映射也要对应正确。若链路已被采样掉,或者日志保留 30 天而 Trace 只保留 7 天,历史日志里的 trace ID 也无法凭空找回那段链路。这些条件应在接入时一起安排。日志关联链路 · 链路详情

OpenObserve 也支持 Trace 和日志关联,相关软件能力已经存在。OpenObserve Traces。只需要日志检索,就按日志范围比较;业务还需要链路、指标与告警,就把双方完成这些接入和关联所需的资源一起计算。

观测云的价值在于这些能力已有相应的配置和操作入口。采集源、解析规则、留存、监控器、通知策略以及关联视图配置完成后,团队就可以围绕自己的业务使用;后端集群不再是一个需要自己交付的前置项目。OpenObserve 的软件能力也已存在,自建投入主要落在生产部署、容量调优、升级恢复和持续维护上,不能虚构成所有功能都要重新开发。

把自建和托管的差额拆开,可以得到一个直接的费用判断。设:

  • R:自建方案每月完整资源费,包含写入与查询计算、存储、索引、缓存,以及实际部署的队列、元数据等组件。
  • H:使用观测云后,每月能减少的维护投入,已经扣掉客户仍需维护采集端和业务规则的工作。
  • A:观测云相比自建能减少的一次性建设投入,已经扣掉双方都需要的数据整理、查询和告警迁移。
  • S:观测云完整月费加客户侧采集资源费用。

若按首年比较,并暂按双方迁移过渡成本相同计算:

S < R + H + A / 12

满足这个条件,观测云的首年总投入就低于自建。服务账单高于单独的云资源账单,也可能满足它。第二年不要再把已经发生的建设投入重复计入,再按运行期成本比较。如果两种方案的双写、历史保留期限不同,应把过渡成本差额另行加入。

H 和 A 应使用实际投入的工程时间估算,并与现金支出分列。现有平台团队有成熟部署与闲置容量,自建新增投入可能较低;需要业务运维临时抽人接手,这项成本就不能填零。

S 也要拿完整口径。观测云企业版写入按压缩后上报字节计量,中心 Pipeline 等数据处理按原始流量另计,此外还有存储、任务调用和按需购买的独占算力。具体费率需要按实际方案取得报价;OpenObserve 数据文件的压缩比不能套用成观测云上报流量的压缩比。企业版计费说明

对于没有专职日志平台维护者的团队,观测云的价值很具体:日志接入并配好规则后,就能开始使用查询、告警与关联,不需要先等集群建设完成。分流和留存优化也可以立即开展。服务费用低于机器、建设和长期维护的总投入时,托管就会比自建更省。

已有成熟平台团队、需要掌握底层资源,又能持续承担升级恢复,OpenObserve 则值得投入。选择它就把负责人和运行预算一起安排好;选择观测云就把采集与业务配置继续做好。降本最终来自适合团队的分工,而不是一定要把所有组件交给自己运行。

验证附件: 配置、样本与结果说明。实验仅覆盖文中明确标注的写入、解析、查询和对账行为,不包含性能排名、生产可靠性结论或客户节省金额。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台