追蹤概念

附註: 這個頁面是關於分散式追蹤的一般概念,以及如何在 Instana AutoTrace™中實作它。 如需相關資訊,請參閱 Instana 中的追蹤 ,以瞭解可以使用 Instana 來追蹤哪些技術和執行時期。

追蹤或根據 Gartner 使用者定義交易側寫,是每一個 Application Performance Management 工具的核心。 Instana 透過瞭解所有已連接元件的交易流程,提供應用程式架構及分散式呼叫型樣的綜合性視圖。 此方法在處理高度分散式及微服務環境時特別相關。

追蹤

追蹤 代表透過服務系統的單一要求及其路徑。 這可能是客戶瀏覽器所起始之要求的直接結果,但也可能是排定工作或任何其他內部執行所起始。 每一個追蹤都是由一或多個呼叫所組成。

呼叫

呼喚 代表兩個服務之間的通訊; 要求和回應 (非同步)。 每個呼叫都是一組資料和時間測量值,對應於特定 RPC 或服務呼叫。 在使用者介面內,會強調顯示每一種類型的呼叫,例如 HTTP、傳訊、資料庫、批次或內部。

為了擷取此資料,會同時測量呼叫端和被呼叫端,這在分散式系統中很重要。 在 分散式追蹤中,這些個別測量稱為 跨距

內部呼叫是特定類型的呼叫,代表在服務內完成的工作。 它可以從透過自訂追蹤傳送的中間文字段建立。 如果您偏好實作自訂追蹤來撰寫自己的自訂檢測,則 Instana 支援 OpenTelemetryOpenTracingOpenCensusJaegerZipkin Web 追蹤 SDK 或許多語言型 追蹤 SDK之一。

呼叫可以代表發生錯誤的作業。 例如,代表 HTTP 作業的呼叫可能會導致 5xx 狀態碼,或透過 Java RMI 呼叫 API 可能會導致異常狀況。 這類呼叫被視為 錯誤 ,並在 Instana 使用者介面中相應地標示。

附註: 導致狀態碼的 HTTP 呼叫 4xx 不會被視為錯誤,因為 4xx 定義為用戶端錯誤。

追蹤視圖

如上述影像所示,錯誤日誌會顯示在它們相關聯的呼叫中。 Instana 會自動收集具有層次 WARNERROR (以及對等項目,視記載架構而定) 的日誌。 在上述影像中,呼叫是錯誤的,且有一個相關聯的錯誤日誌。 不過,一般而言,呼叫可能錯誤,且沒有相關聯的錯誤日誌,反之亦然。

跨距

名稱 span 衍生自 Google的 Dapher paper ,並且是 timespan的縮寫。 跨距代表程式碼執行的計時; 換句話說,是具有開始及結束時間的動作。 它也包含一組由時間戳記及持續時間組成的資料。 不同類型的文字段可以有一或多組這些文字段,以 meta 資料註釋完成。 每個追蹤模型都由階層式集中的文字段區塊組成,依用於母項 (呼叫程式) 與子項 (被呼叫程式) 文字段之間參照的 64 位元 ID 排序。 在每一個追蹤中,第一個文字段是作為根目錄,其 64 位元 ID 是整個追蹤的 ID。

特定服務的第一個跨距指出呼叫已進入服務,稱為 項目跨距 (在 Dapper 報告中,這稱為「伺服器跨距」)。 離開服務的呼叫跨距稱為 結束跨距 (在 Dapper 報告中,這稱為「用戶端跨距」)。 除了進入和結束跨距之外,中間跨距會標示程式碼的重要區段,因此追蹤執行時期可以明確地歸屬於正確的程式碼。

跨距模型

每一個文字段都有相關聯的類型 (例如 HTTP 呼叫或資料庫連線) ,且視文字段的類型而定,也會關聯其他環境定義資料。 為了遵循服務之間的跨距順序, Instana 會自動傳送具有已檢測結束程式的相關性標頭,且 Instana 的項目會自動讀取那些相關性標頭。 如需相關資訊,請參閱 HTTP 追蹤標頭

瞭解追蹤

Callstacks

呼叫堆疊 是代碼執行的排序清單。 每當程式碼呼叫其他程式碼時,新程式碼會放在堆疊頂端。 Callstacks 是由所有程式設計語言的執行時期所使用,且通常列印為 堆疊追蹤。 當發生錯誤時,堆疊追蹤可讓您追蹤回導致錯誤的呼叫。

例如,下列錯誤訊息指出 Apple 不是數字。 結合呼叫堆疊,可以縮小複雜系統中發生錯誤的範圍。 訊息本身通常不足,因為 NumberUtil 演算法可能在許多地方使用。

Thread.run()
  HttpFramework.service()
    HttpFramework.dispatch()
      ShoppingCart.update()
        ShoppingCart.updateCart()
          ShoppingCart.parseQuantity()
            ShoppingCart.convertParams()
              NumberUtil.convert()  <-- Error: "Apple is not a number"

如果要瞭解發生錯誤的原因,請使用呼叫堆疊,從錯誤往回追蹤至相關的商業方法,在本例中是 ShoppingCart.parseQuantity()

呼叫堆疊本身不足以進行監視。 它們不容易閱讀,且不會提供資訊來使系統的效能和可用性與整體性能產生關聯。 若要查看程式碼執行所發生的情況,並使更多資訊 (例如程序活動、資源使用、佇列作業、存取型樣、負載及傳輸量、系統及應用程式性能) 產生關聯,則需要考量這些資訊。

分散式追蹤

引進 服務導向架構 (SOA) 之後,呼叫堆疊已中斷。 例如, ShoppingCart 邏輯現在可能位於伺服器 A 上,而 NumberUtil 則位於伺服器 B 上。 伺服器 B 上的錯誤追蹤只包含剖析錯誤的簡短呼叫堆疊,而在伺服器 A 上產生新的錯誤,指出伺服器 B 上發生錯誤,但未指出問題。

您最後發現兩個呼叫堆疊有兩個錯誤,而不是容易疑難排解的單一錯誤呼叫堆疊。 與此同時,兩者之間沒有關聯,因此無法同時存取兩者。

伺服器 A:

Thread.run()
  HttpFramework.service()
    HttpFramework.dispatch()
      ShoppingCart.update()
        ShoppingCart.updateCart()
          ShoppingCart.parseQuantity()
            ShoppingCart.convertParams()
              RestClient.invokeConversion() <-- Error: Unkown

伺服器 B:

Thread.run()
  HttpFramework.service()
    HttpFramework.dispatch()
      NumberUtil.convert()  <-- Error: "Apple is not a number"

分散式追蹤 背後的構想是透過將兩個錯誤呼叫堆疊彼此連接來修正此問題。 大部分實作都使用簡單機制; 當伺服器 A 呼叫伺服器 B 時, APM 工具會將 ID 新增至呼叫,作為 APM 系統中呼叫堆疊之間的一般參照點。 此機制稱為 相關性 ,為了產生一個錯誤,它會結合兩個呼叫堆疊。

Thread.run()
  HttpFramework.service()
    HttpFramework.dispatch()
      ShoppingCart.update()
        ShoppingCart.updateCart()
          ShoppingCart.parseQuantity()
            ShoppingCart.convertParams()
              RestClient.invokeConversion()
                Thread.run()
                  HttpFramework.service()
                    HttpFramework.dispatch()
                      NumberUtil.convert()  <-- Error: "Apple is not a number"

透過新增裝飾,在其中進行遠端呼叫,以及在呼叫堆疊的哪些伺服器部分上執行,可讓您發現 ShoppingCart 是錯誤的環境定義,且 NumberUtil 導致購物車活動失敗。

測量效能

不過,前述範例已說明錯誤追蹤 APM 工具使用相同的機制來取得及呈現效能測量。 追蹤會標上如下所示的效能號碼:

413 Thread.run()
413   HttpFramework.service()
413     HttpFramework.dispatch()
412       ShoppingCart.update()
411         ShoppingCart.updateCart()
211           ShoppingCart.parseQuantity()
210             ShoppingCart.convertParams()
200               RestClient.invokeConversion()
 10                 Thread.run()
 10                   HttpFramework.service()
 10                     HttpFramework.dispatch()
  5                       NumberUtil.convert()

執行購物車更新的時間總計大約為 413 毫秒。 數字轉換 (NumberUtil.convert()) 花費 5 毫秒。 花在中間的時間分散在許多電話中,因此您正在尋找更大的懸崖。 在範例中,更新購物車 (ShoppingCart.updateCart()) 總共需要 411 毫秒,而剖析 (ShoppingCart.parseQuantity()) 只需要 211 毫秒,其本身花費大部分時間來執行遠端呼叫。

使用 Instana 追蹤

如果發生錯誤或效能緩慢,則會提供詳細環境定義,以便可以使用疑難排解特定案例所需的所有資料。 此資料 (包括呼叫堆疊) 不是針對每個呼叫收集的,因為它是可能導致處理額外負擔的侵入性作業。

請參閱前述範例,這是 Instana 顯示交易的方式:

Service A |   ShoppingCart.update - 412ms                       |
Service A        | RestClient.invokeConversion - 200ms |
Service B                    | NumberService - 5ms|

這是對呼叫巢狀和長度的更好的視覺化表示,因為它會減少到重要部分,顯示花費時間的位置,以及發生遠端呼叫的位置。 它也會連接至「動態圖形」,其知道服務 B 伺服器上的 CPU 已超載,而且它可以將此與交易產生關聯,以進行主要原因分析。 也會擷取其他相關資訊,例如服務 URL 或資料庫查詢。

追蹤連續性

追蹤連續性表示將一個外部要求所觸發的呼叫收集到一個追蹤中。 Instana 採用特定通訊協定專用的方法來新增 meta 資料,例如 HTTP 標頭、 gRPC meta 資料、 Kafka 訊息標頭、AMQP 標頭、JMS 標頭等。 這可確保所有通訊協定和服務之間的追蹤連續性。

不支援任何 meta 資料的通訊協定不支援追蹤連續性。 這表示當透過這類通訊協定呼叫另一個服務時,送出呼叫是追蹤樹狀結構中的葉節點。 在呼叫的接收器中發生的工作不是該追蹤的一部分。 相反地,接收呼叫會啟動新的追蹤,而在接收端中觸發的所有後續呼叫都屬於這個新的追蹤。

在下列情況下,不支援追蹤連續性:

  • Kafka 最高版本 0.10 (Kafka 在 0.11版中引進了標頭) ,
  • 使用 Node.js 套件 kafka-node 傳送或接收 Kafka 訊息 (該套件不支援標頭。 在 Node.js中使用 Kafka 時,建議使用 npm 套件 kafkajs 而非 kafka-node 。 使用 kafkajs,支援追蹤連續性,請注意這些 其他註解 ,以繼續追蹤送入訊息)。
  • NATS 及 NATS 串流傳訊
  • Microsoft 訊息-佇列

W3C 追蹤環境定義支援

除了 專有標頭 X-INSTANA-T/X-INSTANA-S之外,下列 Instana 追蹤器還支援 HTTP/HTTPS 通訊的 W3C 追蹤環境定義 規格:

下列 Instana 追蹤程式目前不支援 W3C 追蹤環境定義 指定。 僅支援 專有標頭 X-INSTANA-T/X-INSTANA-S :

追蹤標頭

為了確保不同服務之間的 追蹤連續性 , Instana 追蹤程式會根據通訊協定使用不同的標頭或 meta 資料內容。

HTTP 追蹤標頭

Instana 追蹤程式支援兩組 HTTP 標頭來進行追蹤相關性。 第一個集 (X-INSTANA-*) 是 Instana 的供應商特定標頭,第二個集是 W3C 追蹤環境定義規格中的標準標頭。 Instana 追蹤程式會將這兩組標頭新增至下游要求。 如果送入要求中同時存在這兩組標頭,則 X-INSTANA-* 標頭會優先於 W3C 標頭。 如果只存在一組標頭,則會從該組標頭繼續追蹤。 這可確保與其他 W3C 相容檢測 (例如 OpenTelemetry) 的交互作業能力,同時提供與仍在現場部署之較舊 Instana 追蹤器 (不含 W3C 支援) 的舊版相容性。

Instana 特定的追蹤相關性標頭:

  • X-INSTANA-T: 進行中追蹤的追蹤 ID。 Instana 追蹤程式支援追蹤 ID ,其長度為字元範圍 [0-9a-f]中的 16 或 32 個字元。 當啟動新的追蹤時,追蹤程式會產生長度為 16 個字元的隨機追蹤 ID。 範例: "7fa8b643c98711ef"
  • X-INSTANA-S: HTTP 結束程式跨距的跨距 ID ,代表用戶端上的送出 HTTP 要求。 Instana 追蹤程式支援從字元範圍 [0-9a-f]開始,長度為 16 個字元的跨距 ID。 此 ID 將成為接收端伺服器上項目跨距的母項跨距 ID。 範例: "ff1938c2b29a8010"
  • X-INSTANA-L: 追蹤層次。 值 0 表示不會建立任何文字段 (也稱為追蹤抑制) ,值 1 表示將建立文字段。 如果遺漏此標頭,則會假設值 1 。 當您傳送 X-INSTANA-L=0時,省略 X-INSTANA-TX-INSTANA-S

W3C 追蹤環境定義標頭:

  • traceparent: 包含追蹤 ID、母項跨距 ID 及其他旗標。 此標頭大致相當於 X-INSTANA-TX-INSTANA-S的組合。 如需相關資訊,請參閱 W3C 追蹤環境定義規格
  • tracestate: 在進行中追蹤期間收集的選用鍵值組清單。 如需相關資訊,請參閱 W3C 追蹤環境定義規格。 Instana 追蹤程式會將具有索引鍵 in 的鍵值組提供給此清單,格式如下: "in=trace-id;span-id"

附註: 如果您有任何防火牆、Proxy 或類似的基礎架構在 HTTP 標頭上運作,請將這五個標頭全部新增至其容許清單。

附註: 本節適用於 HTTP 的所有版本。 特別是在追蹤標頭方面, HTTP/1.1 與 HTTP/2 之間沒有差異。

通用傳訊標頭

對於許多傳訊通訊協定,使用相同的訊息標頭作為透過 HTTP 的訊息標頭,並使用底線 (_) 而非連字號 (-)。 亦即,標頭為 X_INSTANA_TX_INSTANA_SX_INSTANA_L。 請參閱 HTTP 追蹤標頭 一節,以瞭解個別標頭的語意。 若要找出哪些傳訊通訊協定使用此標頭格式,請參閱本節其餘部分中的資訊。

AMQP 訊息標頭

對於 AMQP 訊息,會使用與透過 HTTP (即 X-INSTANA-TX-INSTANA-SX-INSTANA-L) 相同的訊息標頭。 AMQP 訊息目前不支援 W3C 追蹤環境定義標頭 (因為該通訊協定尚無穩定的規格)。 如需相關資訊,請參閱 HTTP 追蹤標頭一節。

AWS SNS 訊息屬性

對於 AWS SNS ,會使用通用傳訊屬性,即 X_INSTANA_TX_INSTANA_SX_INSTANA_L。 AWS SNS 目前不支援 W3C 追蹤環境定義標頭 (因為該通訊協定尚無規格)。 如需相關資訊,請參閱 通用傳訊標頭一節。

AWS SQS

對於 AWS SQS ,會使用一般傳訊標頭,即 X_INSTANA_TX_INSTANA_SX_INSTANA_L。 AWS SQS 目前不支援 W3C 追蹤環境定義標頭 (因為該通訊協定尚無規格)。 如需相關資訊,請參閱 通用傳訊標頭一節。

Google Cloud Pub/Sub

對於 Google Cloud Pub/Sub,會透過 HTTP 使用相同的訊息標頭,但在所有小寫中,即 x-instana-tx-instana-sx-instana-l。 Google Cloud Pub/Sub 目前不支援 W3C 追蹤環境定義標頭 (因為該通訊協定尚無規格)。 如需相關資訊,請參閱 HTTP 追蹤標頭一節。

GraphQL

GraphQL 的追蹤相關性依賴基礎傳輸通訊協定。 如需透過 HTTP 的 GraphQL 相關資訊,請參閱 HTTP 追蹤標頭一節。 對於透過不同通訊協定 (例如 AMQP、 Kafka) 傳輸的 GraphQL 查詢及突變,請參閱該特定通訊協定的小節。

gRPC meta 資料

對於 gRPC,透過 HTTP 使用相同的訊息標頭,即 X-INSTANA-TX-INSTANA-SX-INSTANA-L。 gRPC 目前不支援 W3C 追蹤環境定義標頭 (因為該通訊協定尚無穩定的規格)。 如需相關資訊,請參閱 HTTP 追蹤標頭一節。

IBM MQ

對於 IBM MQ,會使用一般傳訊標頭,即 X_INSTANA_TX_INSTANA_SX_INSTANA_L。 IBM MQ 目前不支援 W3C 追蹤環境定義標頭 (因為該通訊協定尚無規格)。 如需相關資訊,請參閱 通用傳訊標頭一節。

JMS 追蹤標頭

對於 JMS ,會使用一般傳訊標頭,即 X_INSTANA_TX_INSTANA_SX_INSTANA_L。 JMS 目前不支援 W3C 追蹤環境定義標頭 (因為該通訊協定尚無規格)。 如需相關資訊,請參閱 通用傳訊標頭一節。

Kafka 追蹤標頭

Kafka 追蹤標頭目前正在進行移轉。 根據歷程,標頭 X_INSTANA_C 已與追蹤 ID 及母項跨距 ID 的二進位表示法搭配使用。 不幸的是,部分不完整或不符合標準的 Kafka 驅動程式及應用程式無法正確處理非字串標頭。 基於此原因, Instana 追蹤程式會向一組具有字串內容 (X_INSTANA_TX_INSTANA_S) 的標頭移動。 所有 Instana 追蹤程式仍支援舊式標頭 X_INSTANA_C,但它們也都已支援新的標頭格式 X_INSTANA_T/X_INSTANA_S。 如需這項移轉的相關資訊,請參閱 移轉

現代 Kafka 追蹤標頭 X_INSTANA_T 和 X_INSTANA_S

下列字串標頭用於 Kafka 追蹤相關性:

  • X_INSTANA_T: 追蹤 ID。 它是一個字串,長度一律為 32 個字元。 必要的話,以 "0" 為左鍵台。 範例: "00000000000000007fa8b643c98711ef"
  • X_INSTANA_S: 母項文字段 ID ,長度為 16 個字元。 範例: "ff1938c2b29a8010"
  • X_INSTANA_L_S: 追蹤層次 (選用,類型字串)。 值 "0" 表示不會建立任何文字段 (也稱為追蹤抑制) ,值 "1" 表示將建立文字段。 如果遺漏此標頭,則會假設值 "1" 。 傳送 X_INSTANA_L_S=0時省略 X_INSTANA_TX_INSTANA_S
舊式 Kafka 追蹤標頭 X_INSTANA_C

在標頭格式移轉之前,下列二進位標頭用於 Kafka 追蹤相關性:

  • X_INSTANA_C
  • X_INSTANA_L

標頭 X_INSTANA_C (追蹤環境定義) 會結合追蹤與跨距 ID。 其值為 24 位元組二進位標頭。 前 16 個位元組是追蹤 ID ,最後 8 個位元組是跨距 ID。 當使用 64 位元追蹤 ID 時,前 8 個位元組是 0。 當處理程序接收具有 X_INSTANA_C的 Kafka 訊息,且需要將此訊息轉換為追蹤 ID 及母項跨距 ID 的字串表示法時,必須套用下列規則: 如果 X_INSTANA_C 的前 8 個位元組都是 0 ,則 X_INSTANA_C 的位元組 9-16 會從英文字母 [0-9a-f]轉換為 16 個字元的字串。 如果 X_INSTANA_C 的位元組 1-8 至少包含非零位元組,則位元組 1-16 會從相同英文字母轉換成 32 個字元的字串。 在任一情況下,位元組 17-24 將從英文字母 [0-9a-f]轉換為 16 個字元的字串。

以下是追蹤和跨距 ID 字串與二進位 X_INSTANA_C 標頭之間的轉換範例。 該轉換所需要的只是將字串中的字元直接轉換成八位元組,反之亦然:

具有 64 位元追蹤 ID:

追蹤 ID 範圍 ID X_INSTANA_C
"8000000000000000" "ffffffffffffffff" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
"0000000000000001" "0000000000000002" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
"7fffffffffffffff" "0f0f0f0f0f0f0f0f" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f

具有 128 位元追蹤 ID. 請注意,在撰寫時, Instana 不會使用 128 位元追蹤 ID ,而且在移轉至 128 位元追蹤 ID 之前 ,將會發生從二進位 X_INSTANA_C 移轉至字串標頭 (請參閱上述) 的移轉,因此此表格僅具有理論值。 它實際上不會在實踐中適用。

追蹤 ID 範圍 ID X_INSTANA_C
"f0f0f0f0f0f0f0f08000000000000000" "ffffffffffffffff" 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
"00000000000000010000000000000002" "0000000000000003" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
"f0f0f0f0f0f0f0f07fffffffffffffff" "0f0f0f0f0f0f0f0f" 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f

標頭 X_INSTANA_L (整數類型) 表示追蹤層次。 值 0 表示不會建立任何文字段 (也稱為追蹤抑制) ,值 1 表示將建立文字段。 當您傳送 X_INSTANA_L=0時,請勿傳送 X_INSTANA_C