Log、Trace、Metric是系统自身发出的三种可观测信号。Log显示发生了什么事件,Trace显示请求经过了哪些路径,Metric显示相同现象发生的频率和规模。
在安全运营中,这三者的作用也各不相同。仅凭登录失败急剧增加的Metric无法得知攻击路径,仅凭Trace可能不足以了解用户获得了哪些权限决策。如果只存储所有详细Log,则会增加成本和个人信息泄露的风险,并且容易错过整体趋势。
因此,与单独收集这三种信号相比,将同一事件通过共同上下文连接起来的设计更为重要。本文将基于OpenTelemetry的官方数据模型,总结各信号的区别、安全事件调查顺序以及安全的收集方法。

三种信号不可相互替代
OpenTelemetry将描述系统和应用程序活动的输出数据称为信号(Signal)。目前,官方文档将Trace、Metric、Log和Baggage描述为支持信号,并将Profiles等作为独立的开发领域。本文中的“三种”是指专注于可观测系统中最广泛共同处理的Log、Trace、Metric,并非指不存在其他信号。
| 信号 | 最能回答的问题 | 基本单位 | 安全示例 | 典型弱点 |
| — | — | — | — | — |
| Log | 发生了什么事件? | 带有时间和属性的事件 | 登录失败、权限拒绝、配置更改 | 数量庞大,易混入敏感信息 |
| Trace | 一个请求经过了哪些路径? | Trace和Span | API → 认证 → 订单 → DB调用路径 | 采样可能导致部分请求丢失 |
| Metric | 发生频率和规模如何? | 时间序列数值 | 失败率、401/403比例、延迟时间 | 单个事件的详细上下文较少 |
三种信号的关系可以比作侦探工作。Metric是远处的警报,Trace是移动路径,Log是现场记录。然而,比喻更重要的是,每种信号的数据结构和保存成本都不同。
Log:描述事件的记录
Log记录了在特定时间点发生的事件。OpenTelemetry Log Data Model定义了Timestamp、ObservedTimestamp、严重性、正文、Resource、Attributes以及可选的TraceId·SpanId等字段。
安全Log中包含需要后续确认责任和影响的事件,例如认证成功/失败、授权拒绝、管理员操作、秘密查询、策略更改等。OWASP Logging Cheat Sheet也强调了应用程序的安全事件日志记录。因为仅凭Web服务器访问日志无法了解应用程序内部的权限判断。
以下结构化Log比自由格式字符串更容易进行搜索和关联分析:
{
"event.name": "authorization.denied",
"service.name": "order-api",
"trace_id": "4fd0...9a2c",
"span_id": "91ab...20ef",
"subject.type": "user",
"resource.type": "order",
"action": "read",
"reason": "tenant_mismatch",
"outcome": "failure"
}
实际的用户ID、订单号、IP地址不应无条件地以原文形式保留。需要同时考虑调查所需的识别能力和个人信息最小化,并且不记录令牌、密码、会话Cookie、API密钥。Log存储的访问权限、保留期限和完整性保护与应用程序权限同样重要。
Trace:显示请求因果关系的地图
Trace是一个请求通过多个服务和操作的完整路径。每个操作段称为Span,Span包含操作名称、开始/结束时间、Attributes、Events、状态以及父Span关系。同一Trace中的Span通过共同的TraceId进行关联,每个Span都有一个SpanId。
例如,如果一个外部请求经过了API Gateway、认证服务、订单服务和数据库,Trace很适合回答以下问题:
- 认证检查是否实际被调用?
- 延迟或错误是从哪个服务开始的?
- 本应被拒绝的请求是否到达了后续的DB调用?
- 内部服务是否调用了意料之外的外部API?
然而,Trace不能替代审计Log。Span的status=ERROR可能表示技术故障,但可能不足以表达谁被拒绝了何种业务权限。此外,使用采样(Sampling)可能导致部分请求未被保存。出于安全考虑,对于必须保留的审计事件,不应仅依赖Trace的保留情况。
Metric:最先发现异常的数字
Metric是随时间重复测量的数值。代表性的有处理增量的Sum(如请求数)、表示当前值的Gauge以及显示延迟时间分布的Histogram等。由于它不存储每个单独的请求,而是进行聚合,因此适用于大规模系统的趋势和警报。
从安全角度来看,有用的示例包括:
- auth_failures_total: 认证失败次数
- authorization_denied_total: 授权拒绝次数
- token_validation_errors_total: 令牌验证错误
- http.server.request.duration: 请求延迟时间分布
- outbound_requests_total: 按外部目的地划分的调用次数
如果在Metric Label或Attribute中包含原始用户ID、完整URL、会话ID等值类型不断增加的项,时间序列的数量将急剧增加。这被称为高基数(High Cardinality)。这不仅会导致成本和内存问题,还可能引发标识符在监控系统中复制的安全问题。按用户进行的详细调查应在Trace或受访问控制的Log中进行,而Metric通常应使用服务、状态码、允许的结果分类等受限维度,以确保安全。
连接三种信号的关键
三种信号并非放入同一个后端就能自动连接。至少需要一致地设计以下上下文:
| 连接轴 | 目的 | 设计示例 |
| — | — | — |
| 时间 | 比较同一时间点的现象 | NTP同步,区分事件时间与观测时间 |
| Resource | 识别事件发生自哪个执行主体 | service.name, service.version, 部署环境 |
| Trace Context | 直接连接Log和请求路径 | Log的trace_id, span_id, trace_flags |
| 部署上下文 | 比较变更前后 | 发布版本,Git SHA或镜像Digest |
| 业务事件分类 | 一致地聚合安全事件 | event.name, action, outcome, reason |
OpenTelemetry允许LogRecord包含TraceId和SpanId,从而将同一执行上下文中的Log和Trace连接起来。即使使用非OTLP JSON Log,官方兼容性文档也建议使用顶层的trace_id、span_id和trace_flags字段。
Metric和Trace可以通过Exemplar连接。Exemplar是附加了trace_id和span_id等上下文的聚合Metric的特定观测值示例数据。例如,在仪表盘的延迟时间直方图中选择一个异常缓慢的点,然后跳转到相应的Trace。
用三种信号调查一个安全事故
让我们假设一个场景:凌晨时分,某个特定API的授权拒绝突然增加,并且部分请求耗时比平时更长。
1. 使用Metric确定范围
首先,检查authorization_denied_total的增加时间点、目标服务、状态码和部署版本。将其与整体流量增长进行比例比较。如果只看原始计数,可能会将正常的流量增长误认为是攻击。
2. 通过Exemplar或时间范围查找Trace
如果延迟时间直方图中有Exemplar,则跳转到代表性的Trace。如果没有,则使用异常时间段、服务和路径条件搜索Trace。在Trace中,检查认证服务调用情况、授权决策后的DB访问、异常的外部调用以及重复重试。
3. 检查相同TraceId的Log
使用可疑Span的trace_id和span_id查询结构化Log。确认业务上下文,例如event.name=authorization.denied, reason=tenant_mismatch, outcome=failure。这应该通过检查预定义的安全字段来判断,而不是通过搜索请求正文或原始令牌。
4. 确认变更点和影响
比较三种信号的service.version或镜像Digest,查看事件是否在特定部署后开始。如果是实际入侵,则阻止相关账户和会话;如果是策略变更或代码缺陷,则回滚或修复。调查中使用的查询和时间线应作为单独的事故记录保存。
这个顺序并非绝对规则。也可以从具体的警报Log开始,然后扩展到Trace和Metric。重要的是不要在一个信号中得出结论,而是要用其他信号来验证假设。
OpenTelemetry Collector 的作用是什么?
OpenTelemetry Collector是一个厂商中立的组件,用于接收(Receiver)、处理(Processor)和导出(Exporter)遥测数据。Trace、Metric、Log可以配置不同的Pipeline,每个Pipeline连接支持的Receiver、Processor和Exporter。
service:
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlp]
logs:
receivers: [otlp]
processors: [memory_limiter, redaction, batch]
exporters: [otlp]
此配置是用于说明结构的简化示例。redaction等Processor的包含情况和稳定性应在使用中的Collector发行版中确认,并且Receiver和Exporter的实际Endpoint、TLS、认证设置也需要单独配置。OpenTelemetry官方文档也说明,Collector必须安全配置,以处理敏感数据、篡改和DoS风险。
仅仅部署Collector并不能自动使所有信号都安全。接收Endpoint认证、传输加密、网络访问限制、Processor顺序、传输失败队列、后端权限以及Collector自身的Log·Metric都需要一并设计。
必须避免的收集方式
“稍后擦除”原始敏感信息
应用程序先将令牌和个人信息记录到Log中,然后由Collector擦除的方式,虽然可以作为防御层使用,但并非最佳起点。在传输过程中可能出现错误,或者通过绕过Exporter,原始信息可能残留在本地文件中。最安全的默认做法是应用程序从一开始就不记录这些信息。
在Baggage中放入敏感信息
Baggage是跨服务边界传递的Key-Value上下文。在自动检测过程中,它可能通过HTTP Header传递到外部服务,并且缺乏内置的完整性保证,因此不应放入密码、令牌、API密钥和个人信息。来自外部的Trace Context也不应被用作可信的权限信息。
仅将安全事件委托给Trace采样
采样(Sampling)可以降低Trace成本,但可能会丢弃需要调查的请求。尽管优先保留错误或高延迟Trace的尾部采样(Tail Sampling)可能有所帮助,但它不应作为法规要求保留的认证和授权审计记录的唯一存储手段。
将用户ID放入Metric Label
这可能导致时间序列的数量与用户数量一样多。Metric应限于可聚合的维度,而个人单位的查询应在应用了访问权限和保留策略的其他信号中执行。
实际应用清单
- 针对每个安全问题,确定了Log、Trace、Metric中哪个信号是主要证据。
- 确保所有服务记录一致的service.name、环境和版本。
- 验证了trace_id和span_id是否自动注入到请求处理Log中。
- 标准化了认证、授权和管理员操作的Event Name、Action、Outcome、Reason。
- 测试了密码、令牌、Cookie、API密钥和不必要的个人信息是否未出现在这三种信号中。
- 管理了Metric Attribute的允许列表和基数限制。
- 将Trace采样策略与必须保留的审计Log分离开来。
- 对Collector接收Endpoint应用了认证、TLS和网络限制。
- 管理了Collector和后端(Backend)的访问权限、保留期限、加密和审计历史。
- 实际执行了从警报(Metric)→ Trace → Log的导航训练。
结论:设计一个统一的调查流程,而非三种独立的信号
Log提供事件的详细信息,Trace显示请求的因果关系,Metric揭示规模和趋势。目标不是选择三种信号中的一种,而是构建一个以不同分辨率查看同一事件的结构。
最实用的起点很简单:选择一个安全Metric,配置Exemplar或通用Resource,以便从异常区域跳转到Trace。然后,确认是否可以使用该TraceId找到权限判断Log。当这种连接在实际事故演练中发挥作用时,Log、Trace和Metric就不再是三种数据,而是一个统一的安全调查体系。
官方参考资料
- OpenTelemetry Signals
- OpenTelemetry Logs Data Model
- OpenTelemetry Logging与Log Correlation
- 非OTLP Log格式中的Trace Context
- OpenTelemetry Metrics Data Model与Exemplars
- OpenTelemetry Collector 架构
- OpenTelemetry 安全
- OpenTelemetry Baggage 安全考量
- OWASP Logging Cheat Sheet
分类: 云/opentelemetry
标签: OpenTelemetry, Log, Trace, Metric, 可观测性, 安全监控, DevSecOps
发表回复