精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Sentry 開發者貢獻指南 - SDK 開發(性能監控)

開發 前端
通過設置兩個新的 SDK 配置選項之一來啟用跟蹤,tracesSampleRate 和 tracesSampler。如果未設置,則兩者都默認為 undefined,從而選擇如何加入跟蹤。

[[441999]]

性能監控指南

本文檔介紹了 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 的絕對決策

當其中一個以上發揮作用的可能性時,應適用以下優先規則:

  1. 如果將抽樣決策傳遞給 startTransaction (startTransaction({name: "my transaction", sampled: true})),則將使用該決策,而不管其他任何事情。
  2. 如果定義了 tracesSampler,則將使用其決策。它可以選擇保留或忽略任何父采樣決策,或使用采樣上下文數據做出自己的決策或為 transaction 選擇采樣率。
  3. 如果未定義 tracesSampler,但存在父采樣決策,則將使用父采樣決策。
  4. 如果沒有定義 tracesSampler 并且沒有父采樣決策,則將使用 tracesSampleRate。

Transaction 應僅通過 tracesSampleRate 或 tracesSampler 進行采樣。sampleRate 配置用于 error 事件,不應應用于 transaction。

采樣上下文

如果定義,tracesSampler 回調應該傳遞一個 samplingContext 對象,該對象至少應該包括:

  • 創建 transaction 的 transactionContext
  • 一個布爾值 parentSampled,包含從父級傳遞過來的采樣決策,如果有的話
  • 來自可選的 customSamplingContext 對象的數據在手動調用時傳遞給 startTransaction

根據平臺,可能包含其他默認數據。(例如,對于服務器框架,包含與 transaction 正在測量的請求相對應的 request 對象是有意義的。)

傳播

transaction 的抽樣決策應傳遞給其所有子項,包括跨服務邊界。這可以在相同服務子項的 startChild 方法中完成,并為不同服務中的子項使用 senry-trace header。

Header sentry-trace

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 值

為簡化處理,該值由單個(可選)字符組成。可能的值為:

  1.   - No value means defer 
  2.  
  3. 0 - Don't sample 
  4.  
  5. 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 留出空間之間的折衷。

動機:

  1. 面向未來:如果用戶依賴 beforeSend 進行 transaction, 這將使最終在不破壞用戶代碼的情況下實現單個 span 攝取變得復雜。在撰寫本文時,transaction 作為 event 發送,但這被視為實現細節。
  2. API 兼容性:用戶擁有他們現有的 beforeSend 實現,只需要處理錯誤事件。我們將 transaction 作為一種新型 event 引入。當用戶升級到新的 SDK 版本并開始使用跟蹤時,他們的 beforeSend 將開始看到他們的代碼不打算處理的新類型。在 transaction 之前,他們根本不必關心不同的事件類型。有幾種可能的后果:破壞用戶應用程序;默默地和無意地放棄 transaction; transaction 事件以令人驚訝的方式修改。
  3. 就可用性而言,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 屬性匹配*

例子:

  1.   "trace_id""771a43a4192642f0b136d5159a501700"
  2.   "public_key""49d0f7386ad645858ae85020e393bef3"
  3.   "release""myapp@1.1.2"
  4.   "environment""production"
  5.   "user": { 
  6.     "id""7efa4978da177713df088f846f8c484d"
  7.     "segment""vip" 
  8.   }, 
  9.   "transaction""/api/0/project_details" 

Envelope Headers(信封頭)

當通過 Envelope 向 Sentry 發送 transaction 事件時,必須在 trace 字段下的 envelope header 中設置 trace 信息。

這是一個包含 trace context 的最小 envelope header 的示例(盡管 header 不包含換行符,但在下面的示例中添加了換行符以提高可讀性):

  1.   "event_id""12c2d058d58442709aa2eca08bf20986"
  2.   "trace": { 
  3.     "trace_id""771a43a4192642f0b136d5159a501700"
  4.     "public_key""49d0f7386ad645858ae85020e393bef3" 
  5.     // other trace attributes 
  6.   } 

Tracestate Headers(跟蹤狀態頭)

將跟蹤上下文傳播到其他 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 庫和開箱即用的框架支持:

用逗號連接:

  1. tracestate: sentry=<data>,other=<data> 

重復:

  1. tracestate: sentry=<data> 
  2. tracestate: other=<data> 

要創建 tracestate header 的內容:

  1. 將完整的 trace context 序列化為 JSON,包括 trace_id。
  2. 如果字符串在平臺上的表示方式不同,則將生成的 JSON 字符串編碼為 UTF-8。
  3. 使用 base64 對 UTF-8 字符串進行編碼。
  4. 去除尾隨填充字符 (=),因為這是一個保留字符。
  5. 在前面加上 "sentry=",導致 "sentry= "。
  6. 如上所述加入 header。

通過去除尾隨填充,默認的 base64 解析器可能會檢測到不完整的 payload。選擇允許丟失 = 或允許截斷 payload 的解析模式。

例如:

  1.   "trace_id""771a43a4192642f0b136d5159a501700"
  2.   "public_key""49d0f7386ad645858ae85020e393bef3"
  3.   "release""1.1.22"
  4.   "environment""dev"
  5.   "user": { 
  6.     "segment""vip"
  7.     "id""7efa4978da177713df088f846f8c484d" 
  8.   } 

將編碼為

  1. ewogICJ0cmFjZV9pZCI6ICI3NzFhNDNhNDE5MjY0MmYwYjEzNmQ1MTU5YTUwMTcwMCIsCiAgInB1YmxpY19rZXkiOiAiNDlkMGY3Mzg2YWQ2NDU4NThhZTg1MDIwZTM5M2JlZjMiLAogICJyZWxlYXNlIjogIjEuMS4yMiIsCiAgImVudmlyb25tZW50IjogImRldiIsCiAgInVzZXIiOiB7CiAgICAic2VnbWVudCI6ICJ2aXAiLAogICAgImlkIjogIjdlZmE0OTc4ZGExNzc3MTNkZjA4OGY4NDZmOGM0ODRkIgogIH0KfQ 

并導致 header

  1. 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)

添加 Envelope Header

在以下任何一種情況下,SDK 應將 envelope header 添加到傳出 envelope 中:

  1. envelope 包含 transaction event。
  2. 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 字符串的函數。最后我們采用了一個更簡單的實現,但想法是一樣的:

  1. // Compact form 
  2. function objToB64(obj) { 
  3.   const utf16Json = JSON.stringify(obj); 
  4.   const b64 = btoa( 
  5.     encodeURIComponent(utf16Json).replace
  6.       /%([0-9A-F]{2})/g, 
  7.       function toSolidBytes(match, p1) { 
  8.         return String.fromCharCode("0x" + p1); 
  9.       } 
  10.     ) 
  11.   ); 
  12.   const len = b64.length; 
  13.   if (b64[len - 2] === "=") { 
  14.     return b64.substr(0, len - 2); 
  15.   } else if (b64[len - 1] === "=") { 
  16.     return b64.substr(0, len - 1); 
  17.   } 
  18.   return b64; 
  19.  
  20. // Commented 
  21. function objToB64(obj) { 
  22.   // object to JSON string 
  23.   const utf16Json = JSON.stringify(obj); 
  24.   // still utf16 string but with non ASCI escaped as UTF-8 numbers) 
  25.   const encodedUtf8 = encodeURIComponent(utf16Json); 
  26.  
  27.   // replace the escaped code points with utf16 
  28.   // in the first 256 code points (the most wierd part) 
  29.   const b64 = btoa( 
  30.     endcodedUtf8.replace(/%([0-9A-F]{2})/g, function toSolidBytes(match, p1) { 
  31.       return String.fromCharCode("0x" + p1); 
  32.     }) 
  33.   ); 
  34.  
  35.   // drop the '=' or '==' padding from base64 
  36.   const len = b64.length; 
  37.   if (b64[len - 2] === "=") { 
  38.     return b64.substr(0, len - 2); 
  39.   } else if (b64[len - 1] === "=") { 
  40.     return b64.substr(0, len - 1); 
  41.   } 
  42.   return b64; 
  43. // const test = {"x":"a-🙂-讀寫漢字 - 學中文"
  44. // objToB64(test) 
  45. // "eyJ4IjoiYS3wn5mCLeivu+WGmeaxieWtlyAtIOWtpuS4reaWhyJ9" 

這是接受 base64 字符串(帶或不帶 '=' 填充)并返回一個對象的函數

  1. function b64ToObj(b64) { 
  2.   utf16 = decodeURIComponent( 
  3.     atob(b64) 
  4.       .split(""
  5.       .map(function(c) { 
  6.         return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2); 
  7.       }) 
  8.       .join(""
  9.   ); 
  10.   return JSON.parse(utf16); 
  11.  
  12. // b64ToObj("eyJ4IjoiYS3wn5mCLeivu+WGmeaxieWtlyAtIOWtpuS4reaWhyJ9"
  13. // {"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

  • 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 類別。

Web Server

Web server 相關的 span 應該盡可能遵循 OpenTelemetry 的 HTTP 和 RPC 語義約定。

https://grpc.io/

Web Frameworks

Database

在可能的情況下,與數據庫相關的 span 應遵循 OpenTelemetry 的 Database 語義約定。

https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/database.md

Serverless (FAAS)

Serverless 相關的 span 應盡可能遵循 OpenTelemetry 的 FaaS 語義約定。

https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/faas.md

Mobile

Messages/Queues

Messages/Queues 跨度應盡可能遵循 OpenTelemetry 的 Messaging 語義約定。

https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/messaging.md

 

責任編輯:姜華 來源: 黑客下午茶
相關推薦

2021-12-31 18:35:40

監控Sentry開發

2022-01-02 23:26:08

開發SDK Sentry

2022-01-21 21:33:03

開發JavaScript應用

2022-01-03 22:59:30

開發SDK數據

2022-01-02 06:59:43

SentrySDK 開發客戶端報告

2022-01-11 20:42:54

開發Sentry標志

2022-01-17 19:34:43

SentryWeb APISentry API

2022-01-15 23:33:47

SentryPyCharm配置

2022-01-18 23:26:45

開發

2022-01-19 19:49:53

Sentry瀏覽器SDK

2021-12-15 20:06:48

ReactJSSentry開發者

2022-01-16 22:16:59

數據庫Sentry開發者

2022-01-13 20:13:31

元宇宙搜索引擎

2021-12-16 20:12:37

后端開發Sentry

2022-01-20 19:49:10

Sentry開發Scope

2021-12-17 19:15:51

前端蟲洞狀態

2011-07-19 09:51:32

性能優化Designing FAndroid

2020-12-11 09:06:50

異常監控云服務

2015-07-22 16:08:46

OpenStack開源貢獻代碼

2018-03-27 23:25:40

Paddle
點贊
收藏

51CTO技術棧公眾號

岛国在线视频| 国产黄色一区二区三区| 色窝窝无码一区二区三区| 中文在线一区| 少妇高潮 亚洲精品| 香蕉网在线视频| 色戒汤唯在线| 亚洲人成网站精品片在线观看| 粉嫩精品一区二区三区在线观看| 久久久久久久黄色片| 色婷婷色综合| 亚洲国产精品va| 成人日韩在线视频| www.youjizz.com在线| 国产欧美一区二区三区在线老狼 | 91美女精品| 国产亚洲va综合人人澡精品 | a天堂在线视频| 蜜桃久久av| 欧美激情久久久久| 永久免费观看片现看| 精品国产乱子伦一区二区| 欧美三级欧美一级| 青青草视频在线免费播放 | 国产精品第五页| 国产综合第一页| 99国产精品久久久久99打野战| 另类av一区二区| 久久久久久久久久久免费| 精品女人久久久| 国产99久久精品一区二区300| 欧美v亚洲v综合ⅴ国产v| 免费看污黄网站| 中文日产幕无线码一区二区| 一区二区三区在线看| 亚洲精品视频一区二区三区| 亚洲日本中文字幕在线| 国产成人一级电影| 国产日韩精品在线播放| 亚洲天堂男人av| 国产精品日本| 午夜精品福利视频| 精品久久免费视频| 午夜欧美精品| 欧美成人精品一区二区三区| 青青操在线播放| 欧美色图国产精品| 一区二区三区四区在线观看视频 | 国产色综合久久| 国产在线精品一区二区中文 | 亚洲国产小视频| 一级全黄裸体片| 欧美视频二区欧美影视| 91麻豆精品国产91久久久使用方法 | 亚洲大胆视频| 欧美激情图片区| 久久久久亚洲av无码专区| 91精品一区国产高清在线gif| 中文字幕日韩在线视频| 国产人妻大战黑人20p| 色综合综合色| 一本色道久久88综合日韩精品| 亚洲AV无码片久久精品| 久久国产精品色av免费看| 亚洲国产精品国自产拍av秋霞| 动漫av在线免费观看| 超碰97成人| 精品国产乱码久久久久久浪潮 | 伊人久久国产精品| 久久se精品一区精品二区| 国产区精品视频| 国产视频在线观看免费| 国产经典欧美精品| 风间由美一区二区三区| 亚洲日本中文字幕在线| 国产欧美日韩中文久久| 国产高清免费在线| 国产羞羞视频在线播放| 色国产精品一区在线观看| 一区二区三区网址| 国产一区二区| 日韩精品福利在线| www.自拍偷拍| 欧美激情偷拍自拍| 欧美国产日韩xxxxx| 日本天堂网在线| 九色综合狠狠综合久久| 国产成人免费观看| 搞黄视频免费在线观看| 亚洲欧美日韩国产成人精品影院 | 丝袜亚洲精品中文字幕一区| 国产精品视频在线播放| www.综合色| 久久五月婷婷丁香社区| 中文字幕在线亚洲三区| av在线网页| 欧美日韩中文另类| 好男人香蕉影院| 久久精品国产www456c0m| 欧美极品美女视频网站在线观看免费| 久久国产黄色片| 国内不卡的二区三区中文字幕| 国产日韩一区二区| 一区二区高清不卡| 精品成人乱色一区二区| 四季av一区二区三区| 日本午夜精品久久久| 伦理中文字幕亚洲| 国产精品自拍第一页| 成人毛片老司机大片| 日韩精品一区二区三区外面 | 又色又爽又黄18网站| 精品av一区二区| 国产69精品99久久久久久宅男| 在线观看不卡的av| 91在线国产福利| 青青草综合在线| 久久久久久一区二区三区四区别墅| 欧美精品一区二区不卡| 国产极品美女在线| 日韩精彩视频在线观看| 精品国产一区二区三区四区vr| 麻豆tv免费在线观看| 日本韩国视频一区二区| 9.1在线观看免费| 中文字幕免费一区二区| 国产精品久久久久福利| 深夜福利视频在线观看| 亚洲一区二区中文在线| 亚洲天堂av一区二区三区| 精品一区av| 奇米4444一区二区三区| 天堂在线资源8| 亚洲国产欧美日韩另类综合| 日韩久久久久久久久久久| 99久久精品费精品国产风间由美| 国产成人+综合亚洲+天堂| 亚洲av片一区二区三区| 五月天欧美精品| 亚洲高清无码久久| 韩国在线一区| 国产精品久久精品视| 三级福利片在线观看| 欧美一区二区免费| 国产女片a归国片aa| 国产一区二区在线观看视频| 伊人久久青草| 精品国产一级| 欧美激情一级精品国产| 欧美一级特黄aaaaaa大片在线观看| 亚洲综合激情另类小说区| 天堂资源在线亚洲资源| 久久久精品视频网站 | 私库av在线播放| 91日韩在线| 国产99在线|中文| 欧美日韩在线中文字幕| 日韩欧美高清视频| 国产高清自拍视频| 欧美69视频| 亚洲一区二区三区四区视频| 欧美性videos| 欧美伊人精品成人久久综合97| 538精品视频| 日本一区中文字幕| 9999在线观看| 一区二区三区四区视频免费观看 | 欧美大片免费久久精品三p| 男的操女的网站| 国产成人精品1024| 妞干网在线视频观看| 精品一区三区| 国产在线日韩在线| 欧美黄色视屏| 亚洲精品天天看| 中文字幕一区二区三区四区免费看 | 91欧美视频网站| 波多一区二区| 亚洲香蕉在线观看| 国产熟女一区二区三区四区| 亚洲国产欧美日韩另类综合| 精品国产av无码| 国产一区二区三区蝌蚪| 成人免费aaa| 成人黄色av| 俄罗斯精品一区二区三区| 日韩在线影院| 欧美剧在线观看| 欧美美女色图| 欧美一卡在线观看| 中文字幕黄色片| 亚洲日本乱码在线观看| 国产乱了高清露脸对白| 精品一区二区av| 女人天堂av手机在线| 国产精品88久久久久久| 国产麻豆日韩| 青青草国产一区二区三区| 久久琪琪电影院| 欧美性videos| 亚洲欧美制服中文字幕| 午夜精品久久久久久久99老熟妇| 精品成人av| 欧美色综合影院| 国产一区二区播放| 久久综合色之久久综合| 亚洲国产古装精品网站| 亚洲精品一区二区二区| 亚洲高清不卡在线观看| 五月天免费网站| 91在线精品一区二区| 成年人性生活视频| 久久在线观看免费| 亚洲午夜精品一区二区三区| 伊色综合久久之综合久久| 国产成人精品免费视频| 秋霞在线视频| 色青青草原桃花久久综合| 天天操天天干天天爱| 91精品国产综合久久精品图片| 色一情一乱一伦| 人人草在线视频| 91视频在线观看免费| 岛国毛片在线播放| 久久九九免费| 18禁免费观看网站| 亚洲特色特黄| 男女爱爱视频网站| 99久久影视| 欧美精品激情在线观看| 日本在线视频网| 亚洲欧美日韩国产中文专区| 亚洲第一页在线观看| 欧美精品免费视频| 黄色网址中文字幕| 欧美视频13p| 中文字幕一区二区三区精品 | 日韩在线一区二区| 你懂的av在线| 亚洲精品专区| 怡红院av亚洲一区二区三区h| 久久国产中文字幕| 日本一区二区三区视频免费看| 日本成人a网站| 久久精品国产精品青草色艺 | 久九九久频精品短视频| 91精品国产精品| 97人澡人人添人人爽欧美| 国产做受高潮69| 97超碰国产一区二区三区| 亚洲欧美日韩网| 第九色区av在线| 亚洲欧美成人| 在线观看av的网址| 欧美一区二区三区久久精品茉莉花| 午夜啪啪免费视频| 亚洲破处大片| 欧美高清中文字幕| 99视频一区| 动漫av免费观看| 美美哒免费高清在线观看视频一区二区 | www.51av欧美视频| 日本精品久久电影| 日本欧美一区| 91精品视频在线播放| 日本免费精品| 久久国产精品久久精品国产| 久久99免费视频| 亚洲人久久久| 欧美日韩精品免费观看视频完整| 岛国大片在线播放| 免费日韩一区二区| 97超碰成人在线| 国产·精品毛片| 波多野结衣 在线| 中文字幕在线视频一区| 青青草在线观看视频| 黑丝美女久久久| 波多野结衣在线电影| 这里只有精品免费| 五月天婷婷社区| 丝袜一区二区三区| 污污的网站在线免费观看| 欧美在线观看日本一区| 欧美日韩视频免费看| 国产九色91| 欧美色图一区| 91免费黄视频| 美国一区二区三区在线播放| 日本人妻一区二区三区| 久久你懂得1024| www.毛片com| 色噜噜狠狠色综合欧洲selulu| 99久久免费国产精精品| 国产午夜精品久久久| 好吊日视频在线观看| 97人人做人人爱| 国产欧美88| 青娱乐一区二区| 影音先锋一区| 激情在线观看视频| 久久久久久**毛片大全| 欧美成人综合色| 欧美日韩精品三区| 天堂av在线播放| 欧美高清视频在线| 国产福利一区二区三区在线播放| 国产精选一区二区| 一本一道久久a久久精品蜜桃| 日本精品一区二区三区四区| 国产精品中文字幕欧美| 精品亚洲aⅴ无码一区二区三区| 亚洲二区在线视频| 国产免费不卡视频| 在线观看成人黄色| 在线男人天堂| 久久大香伊蕉在人线观看热2| 亚洲手机在线| 男人女人拔萝卜视频| 欧美激情一区二区三区在线| 日本一区二区免费在线观看| 国产欧美88| 亚洲精品免费网站| 波多野结衣一区| 久久香蕉频线观| 欧美a级片免费看| 888av在线视频| 成人免费看吃奶视频网站| 伊人成综合网yiren22| 日韩美女爱爱视频| 国产高清一区日本| 免费黄色国产视频| 欧美少妇bbb| 国产乱子伦三级在线播放| 欧美又大又硬又粗bbbbb| 欧美人体视频| 免费在线激情视频| 91小视频免费看| 日本一区二区欧美| 国产欧美丝祙| 中文字幕色网站| 中文字幕一区二区三区精华液 | 成人精品一区| 国产精品va在线播放我和闺蜜| 亚洲人成网亚洲欧洲无码| 浮妇高潮喷白浆视频| 99re这里都是精品| 久久久久亚洲av成人毛片韩| 日韩精品极品视频免费观看| 美女的胸无遮挡在线观看| 国语精品中文字幕| 国产精品久久久久毛片大屁完整版| 中文字幕在线视频播放| 亚洲不卡在线观看| 台湾av在线二三区观看| 欧美中文在线视频| 国产伦精品一区二区三区千人斩| 激情网站五月天| 亚洲国产高清不卡| 97精品人妻一区二区三区| 久久天天躁狠狠躁老女人| 日韩在线观看中文字幕| www婷婷av久久久影片| 国产成a人亚洲精| 99热在线观看免费精品| 亚洲视频第一页| 青娱乐极品盛宴一区二区| 手机看片日韩国产| 成人夜色视频网站在线观看| 草久久免费视频| 色综合影院在线| 亚洲欧美日本国产| 欧美a在线视频| 国产女人18毛片水真多成人如厕| 亚洲一区二区三区网站| 欧美片一区二区三区| 日韩在线影视| 亚洲一级免费在线观看| 一区二区久久久久| 深夜福利在线观看直播| 国产精品揄拍一区二区| 国内综合精品午夜久久资源| 香蕉视频久久久| 欧美一区二区三区白人| 在线精品亚洲欧美日韩国产| 一区二区三区四区五区精品| 国产91精品久久久久久久网曝门| 黄色片免费观看视频| 啊v视频在线一区二区三区| 国产亚洲成av人片在线观黄桃| 岛国av在线播放| 亚洲一区二区三区视频| 在线视频日韩| 2017亚洲天堂| 亚洲第一天堂av| 欧美综合影院| 凹凸国产熟女精品视频| 综合久久久久久| 日韩欧美电影在线观看| 91性高湖久久久久久久久_久久99|