写在前面
本文主要讲解在利用opentelemetry 排查问题时沉淀的一些方法论。主要聚焦以下几个问题:
- 什么时候创建新的span?什么时候打tag,什么时候使用event?
- 跨服务传播时,如何更好的捕捉到异常/我想关注的 trace
什么时候创建新的span?什么时候打tag,什么时候使用event?
tag 与event
Tags(在OpenTelemetry中也被称为Attributes)被用来描述一个Span的上下文信息。他是静态的并且会被附加到Span上,用于搜索和过滤。
Events被用来代表一个Span中发生的特定的时间点。它们可以用来记录Span生命周期中的重要事件,比如错误或者其它异常。与Tags不同的是,Events是有时间顺序的,可以用来表示一个序列的事件。
基于此,我们可以约定一个使用tag和event的规范:
什么时候记录Tag
-
影响任务执行的关键参数
-
发生错误时记录 错误等级 错误码 错误信息
-
任何可能对排查问题有帮助的信息。
- 比如一个子任务可能还包括多个计算操作,此时可以通过tag分别记录几个计算操作的耗时
什么时候记录 Event
- 很多时候服务可能面对不同的分支,我们可以用event记录我们服务走过的分支
- 很多服务可能涉及一些状态的流转,我们可以用event记录状态的变更信息
在event中,我们要尽可能的详细记录信息,方便研发通过event可以清晰的看出发生了什么事件,发生在代码的哪个位置,以及任何相关的上下文信息。
划分span
划分span让我们可以更细粒度的关注服务的运行状态,这个看起来和event其实相差不多,只不过event相较于span更加的细粒度。那么在什么时候创建新的span呢?
- 当服务收到请求时,或者某个定时任务启动时,我们要创建一个span,这个也是我们服务的“根”span
- 当发生关键业务操作时,比如数据预处理、数据库访问、外部API调用、后置处理等操作,也要创建一个新的子span
- 如果整体任务是一个有向无环图,图中的每一个节点也需要建立一个span。
跨服务传播时,如何更好的捕捉到异常/我想关注的 trace
很多时候我们搜索trace时,我们需要选择service,operation,tag以及时间范围, 当我们想选择某个耗时超过100,或者tag为XXX时,可以很轻松的进行检索和过滤
但是这有一个美中不足:
我们没有办法同时搜索子服务的tag和父服务的tag,这样的话就会在搜索时无法很方便的捕捉到异常。
那么如何解决这个问题呢?
两个思路!
思路1: 通过利用api进行拓展
在搜索子服务的tag的同时时,对所有结果的traceid进行过滤,过滤掉父服务中包含tag为指定值的trace
思路2: 在调用下游时,传递相关字段至下游服务
因为跨服务传播本质上是传递了上下文信息,不妨就多传递一些字段,并在下游服务中写入span,这样就可以直接使用jaeger-query对tag进行过滤。