版本 1.0html
The OpenTracing Semantic Specificationgit
这是一份”正式”的OpenTracing语义规范文档。因为OpenTracing是跨语言的,本文档会尽可能避免提到特定语言相关的概念。也就是说,咱们认为全部语言都具备相似”接口”这样的概念,并提供相关的功能。github
OpenTracing采用了 主版本号.次版本号
形式的版本号,可是没有 .修订号
。当对规范进行向后不兼容的更改时,主版本增长。次版本的增长则用于用于不间断更改,如引入新的标准标记,日志字段或SpanContext引用类型。(你能够在这个Issue specification#2 中读到更多有关此版本控制方案的信息)编程
OpenTracing中的Traces由其Span隐式定义。Trace可被认为是由一组Span定义的有向无环图(DAG),在Span之间的被称为References。网络
如下是一个由8个Span构成的Trace的例子:并发
一个Trace中Span间的因果关系 [Span A] ←←←(the root span) | +------+------+ | | [Span B] [Span C] ←←←(Span C之于Span A的关系是 `ChildOf` ) | | [Span D] +---+-------+ | | [Span E] [Span F] >>> [Span G] >>> [Span H] ↑ ↑ ↑ (Span G `FollowsFrom` Span F)
有时用时间轴来显示Traces更容易,以下图所示:编程语言
一个Trace中Span间的时间关系 ––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time [Span A···················································] [Span B··············································] [Span D··········································] [Span C········································] [Span E·······] [Span F··] [Span G··] [Span H··]
每一个Span封装了以下状态:分布式
操做名称函数
开始时间戳工具
结束时间戳
一组零或多个键:值结构的Span标签(Tags)。键必须是字符串。值能够是字符串,布尔或数值类型.
一组零或多个Span日志(Logs),其中每一个都是一个键:值映射并与一个时间戳配对。键必须是字符串,值能够是任何类型。 并不是全部的OpenTracing实现都必须支持每种值类型。
一个SpanContext(见下文)
零或多个因果相关的Span间的References (经过那些相关的Span的SpanContext)
每一个SpanContext封装了以下状态:
任何须要跟跨进程Span关联的,依赖于OpenTracing实现的状态(例如Trace和Span的id)
键:值结构的跨进程的Baggage Items
一个Span可引用零或多个因果相关的SpanContext。OpenTracing目前定义了两种类型的Reference: ChildOf
和 FollowsFrom
。这两种Reference类型都对父子Span间的因果关系进行了建模。将来,OpenTracing可能会为不具因果关系的Span提供不一样类型的Reference (例如批量的Span,卡在队列中的Span等)。
ChildOf
reference: 一个Span能够是另外一个Span的子Span。在 ChildOf
引用中,父Span在某种程度上取决于子Span。下列状况会构成 ChildOf
关系:
在一个RPC中,表明服务端的Span可做为 ChildOf
表明客户端的Span
在一个持久化进程中,表明SQL插入的Span可做为 ChildOf
表明ORM save方法的Span
多个并发(多是分布式)执行任务的Span可能分别各自为 Childof
一个合并了多个子Span结果的父Span
下列这些都是有效的具备 ChildOf
关系的时序图
[-Parent Span---------] [-Child Span----] [-Parent Span--------------] [-Child Span A----] [-Child Span B----] [-Child Span C----] [-Child Span D---------------] [-Child Span E----]
FollowsFrom
reference: 有些父Span不依赖于任何子Span的结果。这种状况下,咱们仅认为子Span在因果上 FollowsFrom
父Span。有许多不一样的 FollowsFrom
引用子类别,在OpenTracing的将来版本中,它们可能会被更正式地区分。
下列这些都是有效的具备 FollowsFrom
关系的时序图
[-Parent Span-] [-Child Span-] [-Parent Span--] [-Child Span-] [-Parent Span-] [-Child Span-]
OpenTracing规范中有三种相互关联的关键类型 Tracer
,Span
,and SpanContext
。接下来,咱们来看一下各类类型的行为; 简单来讲,每种行为分别在编程语言中对应为一个”方法”,尽管实际上多是一组重载方法。
当咱们讨论“可选”参数时,应当清楚,不一样的语言有不一样的方式来解释这个概念。好比说,在Go语言中咱们会使用”functional Options”这个术语,而在Java中咱们会使用builder模式。
Tracer
Tracer
接口创造 Span
而且可以跨进程地 Inject
(序列化)和 Extract
(反序列化)。严格来讲,它应具备如下能力:
Span
必须参数
操做名称,一我的工可读的字符串,它简洁地表示由Span完成的工做 (例如,RPC方法名称、函数名称或一个较大的计算任务中的阶段的名称)。操做名称应该用泛化的字符串形式标识出一个Span实例. 也就是说,get_user
比 get_user/314159
好。
好比说这里有几个操做名称,用于获得一个虚构的帐户信息:
操做名称 | 建议 |
---|---|
get |
太宽泛 |
get_account/792 |
太具体 |
get_account |
刚恰好,account_id=792 可做为一个合适的 Span 标签 |
可选参数
零或多个与 SpanContext
相关的references,尽量包括 ChildOf
和 FollowFrom
引用类型的信息
开始时间戳,若是没有的话,默认使用现实时间(walltime)
零或多个标签
返回值是一个刚刚启动的 Span
实例
SpanContext
到载体中必须参数
SpanContext
实例
格式描述符(format descriptor)(一般但不必定是字符串常量),告诉Tracer的实现如何在载体对象中对SpanContext进行编码
载体(carrier),其类型由格式描述符指定。Tracer的实现将根据格式描述对此载体对象中的SpanContext进行编码
SpanContext
必须参数
格式描述符(format descriptor),告诉Tracer的实现如何在载体对象中对SpanContext进行解码
载体,其类型由格式描述符指定。 Tracer的实现将根据格式描述对此载体对象中的SpanContext进行解码
返回值是一个SpanContext实例,适合做为经过Tracer启动Span时的reference
Injection和Extraction都依赖于一个可扩展的格式描述符参数,其指定了相关联的”载体”类型以及 SpanContext
是如何被编码的。Tracer实现必须支持下列全部格式。
文本映射(Text Map): 任意的无字符编码限制的string-string型键值结构
HTTP Headers: string-string型的键值结构在HTTP headers( RFC 7230 )中也适用。在实操中,因为HTTP header很容易被各类不一样的方式处理, 强烈建议在Tracer的实现中使用有限的键空间和保守的转意值
二进制: 表明了 SpanContext
的任意二进制数据
Span
除了获取 Span
的 SpanContext
的方法以外,下面任何方法都不能在 Span
完成后被调用。
Span
的 SpanContext
无需参数。
返回值是 Span
的 SpanContext
。返回值甚至可能在 Span
结束后被使用。
必须参数
新的操做名,当 Span
启动时取代旧内容
Span
可选参数
显式地添加Span的结束时间戳,若是没有这个参数则会隐式的添加现实时间(walltime)
除了获取Span的SpanContext的方法以外,任何Span对象的方法都不能在其完成后被调用。
Span
标签必须参数
标签的键,必须是字符串
标签的值,必须是字符串,布尔值,数值类型其中之一
注意OpenTracing项目文档中已经为一些”标准标签”规定了语义。
记录(Log)
结构化的数据必须参数
一到多个键值对,键必须是字符串,值能够是任意类型。有些OpenTracing的实现能够处理更多的日志的值。
可选参数
显式时间戳。该参数必须落在当前Span的开始与结束时间戳之间。
注意OpenTracing项目文档中已经为一些“日志的标准键“ 规定了语义。
Baggage item是对应于某个 Span
及其 SpanContext
,以及全部直接或间接引用自本地(local) Span
的 Span
的键值对。也就是说,baggage items是与其trace一块儿传播的。
Baggage item为全栈式的OpenTracing集成提供了强大的功能(好比在移动App上使用时,它能够一路追踪数据直至储存系统的深度),不过使用这些功能时要小心。
每一个键值都会被拷贝到每个本地(local)及远程的子Span,这可能致使巨大的网络和CPU开销。
必须参数
baggage键,字符串
baggage值,字符串
必须参数
baggage键,字符串
返回值是对应的baggage值,或是一个表示没有baggage值的一个量。
SpanContext
在通常所指的OpenTracing层面上,SpanContext
更像是一个概念而不是一种实用功能。也就是说,这对OpenTracing的实现来讲提供一层薄的接口是相当重要的。当启动一个 Span
或者注入/提取(injecting/extracting) trace时,多数OpenTracing用户仅经过reference与 SpanContext
进行交互。
在OpenTracing中,SpanContext
被强制设定为不可变的(immutable),以应对在 Span
结束时和引用(reference)时产生的复杂的生命周期问题。
不一样语言对此有不一样的建模方式,不过给出一个 SpanContext
实例,语义上仍是应该能让调用者在短期内遍历baggage items。
NoopTracer
全部语言的OpenTracing API必须提供某种 NoopTracer
实现,可用做标记控制(flag-control)或者进行一些用于测试的无害注入等。某些状况下(好比Java),NoopTracer
可能在它本身的制品包(packaging artifact)中。
有些语言提供了在单进程中用来传递活动的 Span
和 SpanContext
的工具。好比,opentracing-go
提供了在Go的 context.Context
机制中,用来set和get活动 Span
的帮助函数(helpers)。