K8S + Helm 一键微服务部署
Sentry 开发者贡献指南 - 前端(ReactJS生态)
Sentry 开发者贡献指南 - 后端服务(Python/Go/Rust/NodeJS)
Sentry 开发者贡献指南 - 前端 React Hooks 与虫洞状态管理模式
性能监控指南
本文档介绍了
SDK
应如何通过
分布式跟踪
添加对性能监控的支持。
https://docs.sentry.io/product/performance/distributed-tracing/
这应该提供
SDK
需要实现的
API
的概述,而不强制要求内部实现细节。
参考实现:
@sentry/tracing
(JavaScript)
https://github.com/getsentry/sentry-javascript/tree/master/packages/tracing
Python SDK
https://github.com/getsentry/sentry-python/blob/master/sentry_sdk/tracing.py
SDK 配置
通过设置两个新的
SDK
配置选项之一来启用跟踪,
tracesSampleRate
和
tracesSampler
。如果未设置,则两者都默认为
undefined
,从而选择如何加入跟踪。
tracesSampleRate
这应该是介于
0.0
和
1.0
(含)之间的
float/double
,表示任何给定
transaction
将被发送到
Sentry
的百分比机会。
因此,
0.0
是
0%
的机会(不会发送),而
1.0
是
100%
的机会(都将发送)。
此
rate
同样适用于所有
transaction
;
换句话说,每个
transaction
都应该有相同的随机机会以
sampled = true
结束,等于
tracesSampleRate
。
tracesSampler
这应该是一个
callback
,在
transaction
开始时调用,它将被赋予一个
samplingContext
对象,并且应该返回一个介于
0.0
和
1.0
之间的采样率_对于所讨论的 transaction_。
此采样率的行为方式应与上面的
tracesSampleRate
相同,不同之处在于它仅适用于新创建的
transaction
,因此可以以不同的
rate
对不同的
transaction
进行采样。
返回
0.0
应该强制删除
transaction
(设置为
sampled = false
),返回
1.0
应该强制发送
transaction
(设置
sampled = true
)。
可选地,
tracesSampler
callback
也可以返回一个布尔值来强制进行采样决策(
false
等同于
0.0
,
true
等同于
1.0
)。
如果返回两种不同的数据类型在实现语言中不是一个选项,则可以安全地省略这种可能性。
maxSpans
由于
transaction
payload
在摄取端强制执行最大大小,因此
SDK
应限制附加到事务的
span
数。
这类似于如何限制
面包屑
和其他任意大小的列表以防止意外误用。
如果在达到最大值后添加新的
span
,
SDK
应删除
span
并理想地使用内部日志记录来帮助调试。
maxSpans
应该作为一个内部的、不可配置的、默认为
1000
的常量来实现。如果在给定的平台中有理由,它可能会变得可配置。
maxSpans
限制还可以帮助避免永远不会完成的
transaction
(在
span
打开时保持
transaction
打开的平台中),防止
OOM
错误,并通常避免降低应用程序性能。
Event
变更
在撰写本文时,
transaction
是作为
Event
模型的扩展实现的。
Transaction
的显着特征是
type: "transaction"
。
除此之外,
Event
获得了新的字段:
spans
、
contexts.TraceContext
。
新的
Span
和
Transaction
类
在内存中,
span
构建了一个定时操作的
概念树(conceptual tree)
。
我们称整个
span tree
为
transaction
。
有时我们使用术语
"transaction"
来指代作为整棵树的
span tree
,有时特指树的
root span
。
通过网络,
transaction
被序列化为
JSON
作为增强的
Event
,并作为
envelope
发送。
不同的
envelope
类型用于优化摄取(因此我们可以以不同于其他事件的方式路由
“transaction events”
,主要是
“error events”
)。
在
Sentry UI
中,您可以使用
Discover
查看所有类型的事件,并使用
Issues
和
Performance
部分分别深入研究
errors
和
transactions
。
面向用户的跟踪文档
解释了更多产品级别的概念。
https://docs.sentry.io/product/performance/distributed-tracing/#traces-transactions-and-spans
Span
类将每个单独的
span
存储在
trace
中。
Transaction
类就像一个
span
,有几个主要区别:
Transaction
有
name
,
span
没有。
在
span
上调用
finish
方法会记录
span
的结束时间戳。对于
transaction
,
finish
方法另外向
Sentry
发送一个事件。
Transaction
类可能继承自
Span
,但这是一个实现细节。
从语义上讲,
transaction
既表示
span tree
的
top-level span
,也表示向
Sentry
报告的单位。
Span
接口
创建
Span
时,将
startTimestamp
设置为当前时间
SpanContext
是
Span
的属性集合(可以是一个实现细节)。如果可能,
SpanContext
应该是不可变的。
Span
应该有一个方法
startChild
,它使用当前
span
的
id
作为新
span
的
parentSpanId
创建一个新的
span
,并将当前
span
的
sampled
值复制到新
span
的
sampled
属性
startChild
方法应遵守
maxSpans
限制,一旦达到限制,
SDK
不应为给定的
transaction
创建新的子
span
。
Span
应该有一个名为
toSentryTrace
的方法,它返回一个字符串,该字符串可以作为名为
sentry-trace
的
header
发送。
Span
应该有一个名为
iterHeaders
(适应平台的命名约定)的方法,它返回一个可迭代的或
header
名称和值的映射。这是一个包含
return {"sentry-trace": toSentryTrace()}
的薄
wrapper
。 请参阅
continueFromHeaders
以了解为什么存在这种情况,并且在编写
集成(integration)
时应该首选。
Transaction
接口
一个
Transaction
内部包含一个子
Span
的平面列表(不是树结构)
Transaction
还有一个
setName
方法来设置
transaction
的名称
Transaction
在创建时收到一个
TransactionContext
(新属性与
SpanContext
是
name
)
由于
Transaction
继承了
Span
,因此它具有所有
Span
可用的函数并且可以像
Span
一样进行交互
一个
transaction
要么被采样(
sampled = true
),要么被取消采样(
sampled = false
),一个在
transaction
的生命周期中被继承或设置一次的决定,并且在任何一种情况下都会传播给所有的
children
。不应将未抽样的
transaction
发送给
Sentry
。
TransactionContext
应该有一个叫做
fromSentryTrace
的
static/ctor
方法,它用从
sentry-trace
header
值接收的数据预填充一个
TransactionContext
TransactionContext
应该有一个名为
continueFromHeaders(headerMap)
的
static/ctor
方法,它现在实际上只是一个围绕
fromSentryTrace(headerMap.get("sentry-trace"))
的薄
wrapper
。
integration/framework-sdk
的作者应该更喜欢
fromSentryTrace
,因为它隐藏了核心
sdk
中更深层次使用的确切
header
名称,并为将来使用其他
header
(来自
W3C
)留下了机会,而无需更改所有集成。
Span.finish()
只需将
endTimestamp
设置为当前时间(在
payload
timestamp
中)
Transaction.finish()
super.finish()
(在 Span 上调用 finish)
仅当
sampled == true
时才将其发送给
Sentry
一个
Transaction
需要被包裹在一个
Envelope
中并发送到
Envelope Endpoint
Transport
应该为
Transactions
/
Events
使用相同的内部队列
Transport
应该实现基于类别的速率限制 →
Transport
应该处理在内部将
Transaction
包装在
Envelope
中
每个
transaction
都有一个
“抽样决策”
,即一个布尔值,指示是否应该将其发送给
Sentry
。
这应该在
transaction
的生命周期内只设置一次,并且应该存储在内部的
sampled
布尔值中。
transaction
可以通过多种方式结束
抽样决策(sampling decision)
:
根据
tracesSampleRate
中设置的
静态采样率
随机采样
根据
tracesSampler
返回的
动态采样率
进行随机采样
tracesSampler
返回的绝对决策(
100%
概率或
0%
概率)
如果
transaction
有父级,继承其父级的
抽样决策
传递给
startTransaction
的绝对决策
当其中一个以上发挥作用的可能性时,应适用以下优先规则:
如果将
抽样决策
传递给
startTransaction
(
startTransaction({name: "my transaction", sampled: true})
),则将使用该决策,而不管其他任何事情。
如果定义了
tracesSampler
,则将使用其
决策
。它可以选择保留或忽略任何父
采样决策
,或使用
采样上下文数据
做出自己的决策或为
transaction
选择
采样率
。
如果未定义
tracesSampler
,但存在父采样决策,则将使用父采样决策。
如果没有定义
tracesSampler
并且没有父采样决策,则将使用
tracesSampleRate
。
Transaction
应仅通过
tracesSampleRate
或
tracesSampler
进行采样。
sampleRate
配置用于
error
事件,不应应用于
transaction
。
采样上下文
如果定义,
tracesSampler
回调应该传递一个
samplingContext
对象,该对象至少应该包括:
创建
transaction
的
transactionContext
一个布尔值
parentSampled
,包含从父级传递过来的
采样决策
,如果有的话
来自可选的
customSamplingContext
对象的数据在手动调用时传递给
startTransaction
根据平台,可能包含其他默认数据。(例如,对于服务器框架,包含与
transaction
正在测量的请求相对应的
request
对象是有意义的。)
transaction
的
抽样决策
应传递给其所有子项,包括跨服务边界。这可以在相同服务子项的
startChild
方法中完成,并为不同服务中的子项使用
senry-trace
header
。
Header
用于跟踪传播。
SDK
使用
header
继续跟踪来自上游服务(传入
HTTP
请求),并将跟踪信息传播到下游服务(传出
HTTP
请求)。
sentry-trace = traceid-spanid-sampled
sampled
是可选的。所以至少,它是预期的:
sentry-trace = traceid-spanid
为了与
W3C
traceparent
header
(没有版本前缀)
和
Zipkin's
b3
headers
(考虑
64
位和
128
位的
traceId
有效)提供最小的兼容性,
sentry-trace
header 应具有以
32
个十六进制字符编码的
128
位的
traceId
以及以
16
个十六进制字符编码的
64
位
spanId
。
为了避免与 W3C
traceparent
header(我们的
header
相似但不相同)混淆,
我们将其简称为
sentry-trace
。
header
中没有定义版本。
https://www.w3.org/TR/trace-context/#traceparent-header
https://zipkin.io/pages/instrumenting#communicating-trace-information
sampled
值
为简化处理,该值由单个(可选)字符组成。可能的值为:
- No value means defer
0 - Don't sample
1 - Sampled
与 b3 header 不同,sentry-trace header 不应该只包含一个采样决策,没有 traceid 或 spanid 值。有很好的理由 无论采样决策如何,始终包含 traceid 和 spanid,这样做也简化了实现。
https://github.com/apache/incubator-zipkin-b3-propagation/blob/bc937b6854ea30e46b3e85fbf147d8f4de685dd5/README.md#why-send-trace-ids-with-a-reject-sampling-decision
除了在 Sentry 的情况下使用 *defer 的通常原因外,
还有一个原因是下游系统使用 Sentry 捕获 error 事件。可以在那时做出决定,对跟踪进行采样,以便为报告的崩溃提供跟踪数据。
https://github.com/apache/incubator-zipkin-b3-propagation/blob/bc937b6854ea30e46b3e85fbf147d8f4de685dd5/README.md#why-defer-a-sampling-decision
sentry-trace = sampled
这实际上对于代理将其设置为 0 并选择退出跟踪很有用。
Static API 变更
Sentry.startTransaction 函数应该接受两个参数 - 传递给 Transaction 构造函数的 transactionContext 和一个包含要传递给 tracesSampler(如果已定义)的数据的可选的 customSamplingContext 对象。
它创建一个绑定到当前 hub 的 Transaction 并返回实例。
用户与实例交互以创建子 span,因此,必须自己跟踪它。
Hub 变更
引入一个名为 traceHeaders 的方法
此函数返回 header(string)sentry-trace
该值应该是当前在 Scope 上的 Span 的 trace header 字符串
引入一个名为 startTransaction 的方法
采用与 Sentry.startTransaction 相同的两个参数
创建一个新的 Transaction 实例
应按照本文档 'Sampling' 部分中更详细的描述实施抽样
修改名为 captureEvent 或 captureTransaction 的方法
不要为 transaction 设置 lastEventId
Scope 变更
Scope 持有对当前 Span 或 Transaction 的引用。
Scope 引入 setSpan
这可以在内部使用,来传递 Span / Transaction,以便集成可以将子项附加到它
在 Scope(旧版)上设置 transaction 属性应该覆盖存储在 Scope 中的 Transaction 的名称,如果有的话。
这样,即使用户无法直接访问 Transaction 的实例,我们也可以让用户选择更改 transaction 名称。
与 beforeSend 和事件处理器的交互
beforeSend 回调是我们认为最重要的特殊 Event Processor。适当的事件处理器通常被认为是内部的。
Transaction 应该不通过 beforeSend。但是,它们仍然由事件处理器处理。
这是在将 transaction 作为 event 的当前实现处理的一些灵活性与为 transaction 和 span 的不同生命周期 hook 留出空间之间的折衷。
面向未来:如果用户依赖 beforeSend 进行 transaction,
这将使最终在不破坏用户代码的情况下实现单个 span 摄取变得复杂。
在撰写本文时,transaction 作为 event 发送,但这被视为实现细节。
API 兼容性:用户拥有他们现有的 beforeSend 实现,只需要处理错误事件。
我们将 transaction 作为一种新型 event 引入。
当用户升级到新的 SDK 版本并开始使用跟踪时,他们的 beforeSend 将开始看到他们的代码不打算处理的新类型。
在 transaction 之前,他们根本不必关心不同的事件类型。
有几种可能的后果:破坏用户应用程序;默默地和无意地放弃 transaction;
transaction 事件以令人惊讶的方式修改。
就可用性而言,beforeSend 不适合删除 transaction,就像删除 error 一样。
Error 是一个时间点事件。当 error 发生时,用户在 beforeSend 中有完整的上下文,
并且可以在它进入 Sentry 之前修改/丢弃事件。对于交易,transaction 是不同的。
创建 transaction,然后将它们打开一段时间,同时创建 child span 并将其附加到它。
同时传出的 HTTP 请求包括当前 transaction 与其他服务的采样决策。
在 span 和 transaction 完成后,将 transaction 放入类似 beforeSend 的钩子中会在跟踪中留下来自其他服务的孤立 transaction。
同样,在此后期将采样决策修改为 "yes" 也会产生不一致的痕迹。
跟踪上下文(实验性)
为了对跟踪进行采样,我们需要沿着调用链传递 trace id 以及做出采样决策所需的信息,即所谓的 跟踪上下文(trace context)。
Trace 信息作为编码的 tracestate header 在 SDK 之间传递,SDK 预计会拦截和传播这些 header。
对于向 sentry 提交的事件,trace context 作为嵌入在 Envelope header 中的 JSON 对象发送,key 为 trace。
跟踪上下文
无论采用何种传输机制,trace context 都是具有以下字段的 JSON 对象:
trace_id (string, required) - UUID V4 编码为不带破折号的十六进制序列(例如771a43a4192642f0b136d5159a501700),它是一个由 32 个十六进制数字组成的序列。这必须与提交的 transaction item 的 trace id 匹配。
public_key (string, required) - 来自 SDK 使用的 DSN 的 Public key。它允许 Sentry 通过基于起始项目解析相同的规则集来对跨多个项目的跟踪进行采样。
release (string, optional) - 客户端选项中指定的版本名称,通常是:package@x.y.z+build。 这应该与 transaction event payload 的 release 属性匹配*
environment - 客户端选项中指定的 environment 名称,例如 staging。 这应该与 transaction event payload 的 environment 属性匹配*
user (object, optional) - 包含以下字段的 scope 的 user context 的子集:
id (string, optional) - 用户上下文的 id 属性。
segment (string, optional) - 用户数据包中的 segment 属性值(如果存在)。将来,该字段可能会被提升为用户上下文的适当属性。
transaction (string, optional) - 在 scope 上设置的 transaction 名称。这应该与 transaction event payload 的 transaction 属性匹配*
"trace_id": "771a43a4192642f0b136d5159a501700",
"public_key": "49d0f7386ad645858ae85020e393bef3",
"release": "myapp@1.1.2",
"environment": "production",
"user": {
"id": "7efa4978da177713df088f846f8c484d",
"segment": "vip"
"transaction": "/api/0/project_details"
当通过 Envelope 向 Sentry 发送 transaction 事件时,必须在 trace 字段下的 envelope header 中设置 trace 信息。
这是一个包含 trace context 的最小 envelope header 的示例(尽管 header 不包含换行符,但在下面的示例中添加了换行符以提高可读性):
"event_id": "12c2d058d58442709aa2eca08bf20986",
"trace": {
"trace_id": "771a43a4192642f0b136d5159a501700",
"public_key": "49d0f7386ad645858ae85020e393bef3"
// other trace attributes
将跟踪上下文传播到其他 SDK 时,Sentry 使用 W3C tracestate header。有关如何将这些 header 传播到其他 SDK 的更多信息,请参阅 "Trace Propagation"。
https://www.w3.org/TR/trace-context/#trace-context-http-headers-format
Tracestate header 包含几个特定于供应商的不透明数据。根据 HTTP 规范,这些多个 header 值可以通过两种方式给出,通常由 HTTP 库和开箱即用的框架支持:
用逗号连接:tracestate: sentry=<data>,other=<data>
重复:tracestate: sentry=<data>
tracestate: other=<data>
要创建 tracestate header 的内容:
将完整的 trace context 序列化为 JSON,包括 trace_id。
如果字符串在平台上的表示方式不同,则将生成的 JSON 字符串编码为 UTF-8。
使用 base64 对 UTF-8 字符串进行编码。
去除尾随填充字符 (=),因为这是一个保留字符。
在前面加上 "sentry=",导致 "sentry=<base64>"。
如上所述加入 header。
通过去除尾随填充,默认的 base64 解析器可能会检测到不完整的 payload。选择允许丢失 = 或允许截断 payload 的解析模式。
"trace_id": "771a43a4192642f0b136d5159a501700",
"public_key": "49d0f7386ad645858ae85020e393bef3",
"release": "1.1.22",
"environment": "dev",
"user": {
"segment": "vip",
"id": "7efa4978da177713df088f846f8c484d"
ewogICJ0cmFjZV9pZCI6ICI3NzFhNDNhNDE5MjY0MmYwYjEzNmQ1MTU5YTUwMTcwMCIsCiAgInB1YmxpY19rZXkiOiAiNDlkMGY3Mzg2YWQ2NDU4NThhZTg1MDIwZTM5M2JlZjMiLAogICJyZWxlYXNlIjogIjEuMS4yMiIsCiAgImVudmlyb25tZW50IjogImRldiIsCiAgInVzZXIiOiB7CiAgICAic2VnbWVudCI6ICJ2aXAiLAogICAgImlkIjogIjdlZmE0OTc4ZGExNzc3MTNkZjA4OGY4NDZmOGM0ODRkIgogIH0KfQ
并导致 header
tracestate: sentry=ewogIC...IH0KfQ,other=[omitted]
(注意 header 末尾的第三方条目;新的或修改的条目总是添加到左侧,因此我们将 sentry= 值放在那里。另请注意,尽管此处为了清晰起见省略了编码值, 在真正的 header 中,将使用完整的值。)
支持此 header 的 SDK 必须:
创建新的 trace context 时使用 scope 信息
为包含 transaction 的 envelope 添加带有 trace context 的 envelope header
将 tracestate HTTP header 添加到传出的 HTTP 请求以进行传播
在适用的情况下拦截对 tracestate HTTP header 的传入 HTTP 请求,并将它们应用到 local trace context
这是性能指南涵盖的 trace ID 传播的扩展。
根据统一 API 跟踪规范,Sentry SDK 通过集成向传出请求添加 HTTP header sentry-trace。
最重要的是,此 header 包含 trace ID,它必须与 transaction event 的 trace id 以及下面的 trace context 的 trace id 匹配。
trace context 应在 W3C traceparent header 中定义的附加 tracestate header 中传播。
请注意,我们必须保持与 W3C 规范的兼容性,而不是专有的 sentry-trace header。
除了 Sentry SDK 放置的内容之外,tracestate header 还包含供应商特定的不透明数据。
https://www.w3.org/TR/trace-context/#trace-context-http-headers-format
Client 选项
虽然 trace context 正在开发中,但它们应该在内部 trace_sampling 布尔值 client 选项后面进行门控。该选项默认为 false,不应在 Sentry 文档中记录。
根据平台命名指南,该选项应该适当地区分大小写:
trace_sampling (snake case)
traceSampling (camel case)
TraceSampling (pascal case)
setTraceSampling (Java-style setters)
在以下任何一种情况下,SDK 应将 envelope header 添加到传出 envelope 中:
envelope 包含 transaction event。
scope 有一个 transaction 绑定。
具体来说,这意味着即使没有 transaction 的 envelope 也可以包含 trace envelope header,
从而允许 Sentry 最终对属于 transaction 的 attachment 进行采样。
当 envelope 包含 transaction 且 scope 有绑定 transaction 时,
SDK 应使用 envelope 的 transaction 来创建 trace envelope header。
冻结上下文
为了确保 trace 中所有 transaction 的 trace context 完全一致,一旦通过网络发送 trace context,就不能更改 trace context,即使 scope 或 options 之后发生更改。
也就是说,一旦计算出 trace context 就不再更新。即使应用程序调用 setRelease,旧版本仍保留在 context 中。
为了弥补对 setTransaction 和 setUser 等函数的延迟调用,
可以认为 trace context 处于两种状态:NEW 和 SENT。
最初,context 处于 NEW 状态并且可以修改。第一次发送后,它将变为 SENT 并且不能再更改。
我们建议 trace context 应该在第一次需要时即时计算:
创建 Envelope
传播到传出的 HTTP 请求
Trace context 必须保留,直到用户开始新的 trace,此时 SDK 必须计算新的 trace context。
建议 SDK 记录在 trace context 冻结时会导致 trace context 更改的属性修改,例如 user.id,以简化常见动态采样陷阱的调试。
传入上下文
与拦截来自入站 HTTP 请求的 trace ID 相同,SDK 应读取 tracestate header 并假设 Sentry 跟踪上下文(如果指定)。这样的上下文立即冻结在 SENT 状态,不应再允许修改。
在 JavaScript 中编码
如前所述,我们需要使用 UTF-8 字符串对 JSON trace context 进行编码。JavaScript 内部使用 UTF16,因此我们需要做一些工作来进行转换。
Base64 encoding and decoding in JavaScript(以及 Using Javascript's atob to decode base64 doesn't properly decode utf-8 strings)介绍了基本思想。
https://attacomsian.com/blog/javascript-base64-encode-decode
https://stackoverflow.com/questions/30106476/using-javascripts-atob-to-decode-base64-doesnt-properly-decode-utf-8-strings
简而言之,这是将 context 转换为可以保存在 tracestate 中的 base64 字符串的函数。最后我们采用了一个更简单的实现,但想法是一样的:
// Compact form
function objToB64(obj) {
const utf16Json = JSON.stringify(obj);
const b64 = btoa(
encodeURIComponent(utf16Json).replace(
/%([0-9A-F]{2})/g,
function toSolidBytes(match, p1) {
return String.fromCharCode("0x" + p1);
const len = b64.length;
if (b64[len - 2] === "=") {
return b64.substr(0, len - 2);
} else if (b64[len - 1] === "=") {
return b64.substr(0, len - 1);
return b64;
// Commented
function objToB64(obj) {
// object to JSON string
const utf16Json = JSON.stringify(obj);
// still utf16 string but with non ASCI escaped as UTF-8 numbers)
const encodedUtf8 = encodeURIComponent(utf16Json);
// replace the escaped code points with utf16
// in the first 256 code points (the most wierd part)
const b64 = btoa(
endcodedUtf8.replace(/%([0-9A-F]{2})/g, function toSolidBytes(match, p1) {
return String.fromCharCode("0x" + p1);
// drop the '=' or '==' padding from base64
const len = b64.length;
if (b64[len - 2] === "=") {
return b64.substr(0, len - 2);
} else if (b64[len - 1] === "=") {
return b64.substr(0, len - 1);
return b64;
// const test = {"x":"a-🙂-读写汉字 - 学中文"}
// objToB64(test)
// "eyJ4IjoiYS3wn5mCLeivu+WGmeaxieWtlyAtIOWtpuS4reaWhyJ9"
这是接受 base64 字符串(带或不带 '=' 填充)并返回一个对象的函数
function b64ToObj(b64) {
utf16 = decodeURIComponent(
atob(b64)
.split("")
.map(function(c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
.join("")
return JSON.parse(utf16);
// b64ToObj("eyJ4IjoiYS3wn5mCLeivu+WGmeaxieWtlyAtIOWtpuS4reaWhyJ9")
// {"x":"a-🙂-读写汉字 - 学中文"}
带有命令行实用程序的 Base64
GNU base64 命令行实用程序带有一个开关来包装编码的字符串。
这与 tracestate header 不兼容,应该避免。
如果 base64 实现创建多行,则必须将它们连接在一起。
Span Operations(跨度操作)
Span 操作是识别 span 正在测量的操作类型的短代码。
Span 操作是低基数属性 - 它们应该尽可能通用,同时仍然是人类可读和有用的。他们应该避免包含高基数数据,如 ID 和 URL。
操作应尽可能遵循 OpenTelemetry 的语义约定。
https://github.com/open-telemetry/opentelemetry-specification/blob/24de67b3827a4e3ab2515cd8ab62d5bcf837c586/specification/trace/semantic_conventions/README.md
保持 SDK 和 integration 之间的类别一致很重要,因为 Sentry 在操作细分功能中使用它们。
例如,db.init 和db.query 都将被归类为数据库操作(db)。可以在projectoptions/defaults.py 查看默认操作细分配置。
https://docs.sentry.io/product/sentry-basics/tracing/event-detail/#operations-breakdown
https://github.com/getsentry/sentry/blob/809b7fe54c6f06cc1e4c503cf83ded896472a011/src/sentry/projectoptions/defaults.py#L74
下表包含 SDK 和 Sentry 产品使用的操作示例。
表中的 Usage 列包含使用该操作类别的示例,但不是操作用法的硬性建议。
只要类别保持一致,SDK 开发人员就可以自由选择最适合他们正在检测的用例的操作和标识符。
如果未提供 span 操作,则使用 default 的值。
Browser
Category
Usage
Description
https://w3c.github.io/resource-timing/#sec-performanceresourcetiming
https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark
https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure
JS Frameworks
JS 框架应该在 UI 组件相关的操作前加上 ui 类别。
Category
Usage
Description