java-api详解
中文官方的中文手册
API简介
一、opentracing的概念与术语
opentracing 本质是一套tracing字段的规范,并不是监控产品。
这么做是希望各种监控产品能对接进去。
opentracing的概念与术语
二、opentracing 的规范
规范
为了被各厂家支持,opentracing 模糊定义了必要的字段,由使用者具体决定。
其他字段基本上是清晰定义了。
2.1 模糊定义的部分
各个APM产品的调用链关键字段描述都有差异。但是共识是
要有调用链标识
、operationName(名称)
,span的标识
、上游span的标识
、时间戳
、span耗时
。
示例
如下是一个例子,在一级字段例定义了如下格式。但是其他监控产品有可能把traceId
换成trace_Id
。所以这部分opentracing
是模糊定义的
名称 | 描述 | |
---|---|---|
traceId | 调用链唯一标识 | uint64 |
spanId | 本次调用的唯一标识 | uint64 |
parentSpanId | 上游调用块的标识 | uint64 |
start | 请求开始的时间 | string |
duration | 请求耗时,单位为毫秒 | uint64 |
operation | String span的名称 | string |
baggages
一级字段可以为空一个Map类型,这个字段要求所有要在trace所有的span中流动。这个字段不管是进程间,还是跨应用调用,都应该在span间传递。
2.2 清晰定义的部分
tags和logs是也是一级字段,但是可以为空。
不在span间传递,最终被和生成的span存储进数据库中。
tags是span的标签,标识关键信息。
logs偏重于日志的输出。
2.2.1 tags & logs 表 (耳机标签)
tags
tags是应该被应用到整个Span的属性。比如某个时间范围内的,而不是一个特殊的时刻。比如component=spring
并不会针对特定的span,而是对span
而言这个模块产生的消息就是spring
框架产生的。像事件event
等一些特殊的应该放在logs
字段中。
Span tag name | Type | Notes and examples |
---|---|---|
component |
string | 软件包,框架,库,或者模块 eg., "grpc" , "django" , "JDBI" . |
db.instance |
string | 数据库实例的名称. eg., 如果jdbc.url="jdbc:mysql://127.0.0.1:3306/customers" , ,那么实例名称应该是"customers" . |
db.statement |
string | 数据库的查询语句。eg., 对于db.type="sql" , "SELECT * FROM wuser_table" ; 对于 db.type="redis" ,"SET mykey 'WuValue'" . |
db.type |
string | 数据库的类型., "sql"代表SQL 类型的database。其他数据库, eg. "cassandra" , "hbase" 或"redis" |
db.user |
string | 访问数据的用户名eg., "readonly_user" 或者 "reporting_user" |
error |
bool | true 意味应用的程序出现了问题 |
http.method |
string | HTTP method 的请求类型 Span. eg., "GET", "POST" |
http.status_code |
integer | HTTP 相应的状态码. eg., 200, 503, 404 |
http.url |
string | 请求的 URL。eg., "https://domain.net/path/|to?resource=here" |
message_bus.destination |
string | 用来交换信息的地址。eg. 一条Kafka 的记录 和 "topic name" 可以被 采集器的 producer 或者 consumer 解析、存储在这个tag |
peer.address |
string | 远程的“address” ,适合网络通信。他的值可能是ip:port 、一个hostname , FQDN, 沈甚至一个JDBC子字符串类似 "mysql://prod-db:3306" |
peer.hostname |
string | 远程的hostname eg., "opentracing.io", "internal.dns.name" |
peer.ipv4 |
string | 远程的 IPv4 eg., “127.0.0.1” |
peer.ipv6 |
string | 远程的 IPv6 eg.,"2001:0db8:85a3:0000:0000:8a2e:0370:7334" |
peer.port |
integer | 远程的 port. eg.,80 |
peer.service |
string | 远程的 service name ,eg., "elasticsearch", "a_custom_microservice", "memcache" |
sampling.priority |
integer | 如果 > 0, 选中,\<0 , 丢弃掉 。 |
span.kind |
string | 类型"client" 或"server" 对于 RPC, 或者合适的语义比如"producer" ,"consumer" 在消息服务 |
logs
每个span的LOG字段都有时间戳。想日志一箱,
Span log field name | Type | Notes and examples |
---|---|---|
error.kind |
string | 这个类型仅仅是("error" ). eg.,"Exception", "OSError" |
error.object |
object | 针对与特定语言的支持 (比如., Java, Python),真实的lThrowable/Exception/Error . eg., java的java.lang.UnsupportedOperationException , python的a pythonexceptions.NameError instance |
event |
string | 对span生命周期内,一些特定的事件的标识。例如,在浏览器页面加载过程中,获得或释放一个互斥锁就是一个特定的事件域, 标准. E.g., 比如 Zipkin的"cs", "sr", "ss", or "cr" . 或者"initialized" 、 "timed out"、"error" |
message |
string | 一个简洁的人类可读的,只有一行的消息"Could not connect to backend", "Cache invalidation succeeded" |
stack |
string | 栈信息最终,具体语言相关,先错代码出错的行数,但是不一定是一个error。E.g., "File \"example.py\", line 7, in \<module\>\ncaller()\nFile \"example.py\", line 5, in caller\ncallee()\nFile \"example.py\", line 2, in callee\nraise Exception(\"Yikes\")\n" |
2.2.2 解释
1 描述特殊模型的变量,比如rpc
span.kind
。 如"client" or “server”,标识rpc的访问端Peer Tags
。记录地址信息peer.address, peer.hostname, peer.ipv4, peer.ipv6, peer.port, peer.service
2 HTTP Server Tags
http.url
- string- URL 分布式追踪中,这一阶段的调用的URL地址, 参考 standard URI format.
- Protocol 协议,可选
- Examples:
1. https://domain.net/path/to?resource=here
2. domain.net/path/to/resource
3. http://user:pass@domain.org:8888
+http.method
- string
+ HTTP 请求被处理的方法.
+ Case-insensitive 大小写敏感
+ Examples:
GET, POST, HEAD
http.status_code
- integer- HTTP 返回值
- Examples:
200, 503
+span.kind
- string
server 定义这是服务端类型的span (see “Component Identification, 框架定义”)
3 Captured errors
捕获错误
示例
比如捕获错误的对象
event="error"
error.object=<error object instance>
示例
vent="error"
message="..."
stack="..." (optional)
error.kind="..." (optional)
4 描述database
+db.type, db.instance, db.user, and db.statement
: as described in the table above
peer.address, peer.hostname, peer.ipv4, peer.ipv6, peer.port, peer.service
: optional- tags that describe the database peer
span.kind: "client"
5 Message Bus 信息交换
一般可以按照如下的方式组合
message_bus.destination:
如表中描述
+span.kind
: either"producer"
or"consumer".
+peer.address, peer.hostname, peer.ipv4, peer.ipv6, peer.port, peer.service
: 可选的标签 描述消息broker
三、opentracing 代码结构
3.1 代码结构
代码结构
在maven 仓库里
名称 | 描述 | 依赖 |
---|---|---|
opentracing-api |
是一个纯粹的API没有任何依赖 | - |
opentracing-noop |
实现了API,但是是空实现什么也不干 | opentracing-api |
opentracing-util |
包含了一个GlobalTracer 和基于Thread_local 的简单实现ScopeManager |
opentracing-api ; opentracing.noop |
opentracing-mock |
mock测试,包含一个简单的MockTracer ,将数据存褚进内存 |
opentracing-api ; opentracing.noop ;opentracing-util |
一个存在在测试是的包,用于测试和尝试新特性opentracing-testbed
3.2 核心组件概念介绍
大致将各个模块的作用
代码模型
java-api
opentracing里主要包含以下几个组件:
Tracer
Tracer
是一个调用链生成器,他应该是全局的。最佳实践是应用在启动时,创建一个Tracer
的实例。可以被其他线程访问到,去生成消息。
ScopeManager
这个类是0.30版本之后新加入的组件,这个组件的作用是能够通过它获取当前线程中启用的Span信息,并且可以启用一些处于未启用状态的span。在一些场景中,我们在一个线程中可能同时建立多个span,但是同一时间统一线程只会有一个span在启用,其他的span可能处在下列的状态中:
- 等待子span完成
- 等待某种阻塞方法
- 创建并未开始
对于一个线程Thread来说,一个时刻只有一个
span
是激活状态的(active)。其他spans
,可能是这个span
的上游,或者等待资源(I/O或者childspan的完成)等,这些spans
的特点是,开始了(start)但是没有结束(end)。
这个时候获取当前的span
是很不方便的,所以就有scopeManager()
来管理每个span的scope
。获取当前的span可以使用
io.opentracing.Tracer tracer = ...;
...
Span span = tracer.scopeManager().activeSpan();
if (span != null)