具体来说,这意味着即使没有 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,因此我们需要做一些工作来进行转换。
(以及 )介绍了基本思想。
简而言之,这是将 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-