分享方式:


什麼是分散式追蹤和遙測相互關聯?

注意

下列文件以 Application Insights 傳統 API 為依據。 Application Insights 的長期計劃是使用 OpenTelemetry 收集資料。 如需詳細資訊,請參閱 啟用適用於 .NET、Node.js、Python 和 JAVA 應用程式的 Azure 監視器 OpenTelemetry我們的 OpenTelemetry 藍圖。 移轉指導適用於 .NETNode.jsPython

新式雲端和微服務架構造就了可獨立部署的簡單服務,因此能夠降低成本,同時提高可用性和輸送量。 但是也會讓整體系統更難以找出原因和偵錯。 分散式追蹤可提供效能分析工具來解決此問題,其運作方式類似雲端和微服務架構的呼叫堆疊。

Azure 監視器提供兩種使用分散式追蹤資料的體驗:單一交易/要求的交易診斷檢視,以及應用程式對應檢視來顯示系統互動的方式。

Application Insights 可以個別監視每個元件,並使用分散式遙測相互關聯來偵測哪個元件負責失敗或效能降低。 本文說明 Application Insights 所使用不同語言和平台上的資料模型、內容傳播技術、通訊協定和相互關聯策略實作。

啟用分散式追蹤

若要啟用應用程式的分散式追蹤,請根據其程式設計語言,將正確的代理程式、SDK 或程式庫新增至每個服務。

使用自動檢測或 SDK 透過 Application Insights 啟用

適用於 .NET、.NET Core、Java、Node.js 和 JavaScript 的 Application Insights 代理程式和 SDK 全都提供分散式追蹤的原生支援。 可取得安裝和設定每個 Application Insights SDK 的指示:

安裝和設定適當的 Application Insights SDK 後,SDK 相依性自動收集器就會針對熱門的架構、程式庫和技術自動收集追蹤資訊。 完整的支援技術清單位於相依性自動收集文件中。

只要在 TelemetryClient 上呼叫 TrackDependency,也可以手動追蹤任何技術。

透過 OpenTelemetry 啟用

Application Insights 現在支援透過 OpenTelemetry 的分散式追蹤。 OpenTelemetry 提供跨廠商通用檢測,用以將追蹤、計量和記錄傳送至 Application Insights。 OpenTelemetry 社群最初採用分散式追蹤。 計量和記錄仍在進行中。

完整的可檢視性案例包括這三個支柱。 檢查以 Azure 監視器 OpenTelemetry 為基礎的供應項目所呈現的狀態,以檢視包含項目的最新狀態、供應項目已正式推出,以及支援選項。

下列頁面包含各語言版本的指引,說明如何啟用及設定 Microsoft 的 OpenTelemetry 型供應項目。 重要的是,我們會分享每個供應項目的可用功能和限制,以便您判斷 OpenTelemetry 是否適合您的專案。

透過 OpenCensus 啟用

除了 Application Insights SDK,Application Insights 也支援透過 OpenCensus 的分散式追蹤。 OpenCensus 是開放原始碼、廠商中立的單一程式庫散發,可提供服務的計量收集和分散式追蹤。 也可讓開放原始碼社群,使用熱門的技術 (例如 Redis、Memcached 或 MongoDB) 進行分散式追蹤。 Microsoft 在 OpenCensus 上與其他數個監視和雲端夥伴共同作業

如需適用於 Python 的 OpenCensus 的詳細資訊,請參閱為 Python 應用程式設定 Azure 監視器

OpenCensus 網站會維護 PythonGo 的 API 參考文件,以及可供使用 OpenCensus 的各種指南。

遙測相互關聯的資料模型

Application Insights 會定義分散遙測相互關聯的資料模型。 為了將遙測與邏輯作業相關聯,每個遙測項目都有稱為 operation_Id 的內容欄位。 每個遙測項目會在分散式追蹤內共用這個識別碼。 因此,即使單一圖層中遺失遙測,您仍然可以將其他元件所回報的遙測相關聯。

分散式邏輯作業通常由一組較小的作業所組成,是由其中一個元件所處理的要求。 這些作業是由要求遙測所定義。 每個要求遙測項目都有自己的 id,用來作為其全域唯一識別。 與這個要求關聯的所有遙測 (例如追蹤和例外狀況) 都應該將 operation_parentId 設定為 id 要求的值。

每個連出作業 (例如對另一個元件的 HTTP 呼叫) 都會由相依性遙測代表。 這也會定義本身的全域唯一 id。 由這個相依性呼叫起始的要求遙測會使用 這個 id 作為其 operation_parentId

您可以將 operation_Idoperation_parentIdrequest.iddependency.id 搭配使用,來建置分散式邏輯作業的檢視。 這些欄位也會定義遙測呼叫的因果順序。

在微服務環境中,來自元件的追蹤可能會前往不同的儲存體項目。 每個元件在 Application Insights 中都可能有自己的連接字串。 若要取得邏輯作業的遙測,Application Insights 會向每個儲存體項目查詢資料。

儲存體項目的數目很龐大時,您將需要有關下一個尋找位置的提示。 Application Insights 資料模型會定義兩個欄位來解決這個問題:request.sourcedependency.target。 第一個欄位會識別起始相依性要求的元件。 第二個欄位會識別哪個元件傳回相依性呼叫的回應。

如需使用 app 查詢運算式從多個不同執行個體進行查詢的相關資訊,請參閱 Azure 監視器查詢中的 app() 運算式

範例

讓我們看看下列範例。 名為 Stock Prices 的應用程式會使用名為 Stock 的外部 API 來顯示目前的股市價格。 Stock Prices 應用程式有一個名為 Stock 的頁面,用戶端網頁瀏覽器會使用 GET /Home/Stock 來開啟此頁面。 應用程式會使用 HTTP 呼叫 GET /api/stock/value 來查詢 Stock API。

您可以執行查詢來分析產生的遙測︰

(requests | union dependencies | union pageViews)
| where operation_Id == "STYz"
| project timestamp, itemType, name, id, operation_ParentId, operation_Id

在結果中,所有遙測項目都共用 operation_Id 這個根。 從此頁面發出 Ajax 呼叫時,系統會將新的唯一識別碼 (qJSXU) 指派給相依性遙測,並使用 pageView 的識別碼作為 operation_ParentId。 接著,伺服器要求會使用 Ajax 識別碼作為 operation_ParentId

itemType NAME 識別碼 operation_ParentId operation_Id
pageView Stock 頁面 STYz STYz
相依性 GET /Home/Stock qJSXU STYz STYz
要求 GET Home/Stock KqKwlrSt9PA= qJSXU STYz
相依性 GET /api/stock/value bBrf2L7mm2g= KqKwlrSt9PA= STYz

向外部服務發出 GET /api/stock/value 呼叫時,您需要知道該伺服器的身分識別,以便適當地設定 dependency.target 欄位。 外部服務不支援監視時,將 target 設定為服務的主機名稱。 例如 stock-prices-api.com。 但是如果服務會藉由傳回預先定義的 HTTP 標頭來識別其本身,則 target 包含的服務識別可讓 Application Insights 透過向該服務查詢遙測來建置分散式追蹤。

使用 W3C TraceCoNtext 的相互關聯標頭

Application Insights 會轉換為 W3C Trace-Context,這會定義:

  • traceparent:裝載全域唯一的作業識別碼和唯一的呼叫識別碼。
  • tracestate:裝載系統特定的追蹤內容。

最新版本的 Application Insights SDK 支援 Trace-Context 通訊協定,但是您可能需要選擇加入。 (會保留 Application Insights SDK 對於先前相互關聯通訊協定所支援的回溯相容性。)

相互關聯 HTTP 通訊協定,也稱為 Request-Id 即將淘汰。 此通訊協定會定義兩個標頭:

  • Request-Id:裝載呼叫的全域唯一識別碼。
  • Correlation-Context:裝載分散式追蹤屬性的名稱值組集合。

Application Insights 也會定義相互關聯 HTTP 通訊協定的延伸。 它會使用 Request-Context 名稱值組,來傳播立即呼叫端或被呼叫端所使用的屬性集合。 Application Insights SDK 會使用此標頭來設定 dependency.targetrequest.source 欄位。

W3C Trace-Context 與 Application Insights 資料模型的對應方式如下:

Application Insights W3C TraceContext
RequestDependencyId parent-id
Operation_Id trace-id
Operation_ParentId 此範圍父代範圍的 parent-id。 如果欄位是根範圍,則此欄位必須是空白的。

如需詳細資訊,請參閱 Application Insights 遙測資料模型

啟用 .NET 應用程式的 W3C 分散式追蹤支援

W3C TraceContext 型分散式追蹤預設會在所有最新的 .NET Framework/.NET Core SDK 中啟用,並且具有與舊版 Request-Id 通訊協定的回溯相容性。

啟用 Java 應用程式的 W3C 分散式追蹤支援

Java 3.0 代理程式

Java 3.0 代理程式支援現成可用的 W3C,且不需要再進行任何設定。

Java SDK

  • 連入設定

    針對 Java EE 應用程式,將下列程式碼新增至 ApplicationInsights.xml 中的 <TelemetryModules> 標記:

    <Add type="com.microsoft.applicationinsights.web.extensibility.modules.WebRequestTrackingTelemetryModule>
       <Param name = "W3CEnabled" value ="true"/>
       <Param name ="enableW3CBackCompat" value = "true" />
    </Add>
    

    針對 Spring Boot 應用程式,新增下列屬性:

    • azure.application-insights.web.enable-W3C=true
    • azure.application-insights.web.enable-W3C-backcompat-mode=true
  • 連出設定

    將下列程式碼新增至 AI-Agent.xml

    <Instrumentation>
      <BuiltIn enabled="true">
        <HTTP enabled="true" W3C="true" enableW3CBackCompat="true"/>
      </BuiltIn>
    </Instrumentation>
    

    注意

    預設會啟用回溯相容性模式,而 enableW3CBackCompat 參數則為選擇性。 請只在您想要關閉回溯相容性功能時,才使用它。

    理想的情況是,所有服務都已更新為支援 W3C 通訊協定的新版 SDK 時,您將關閉此模式。 強烈建議您儘快移轉至這些較新版的 SDK。

請務必確定傳入和傳出設定完全相同。

啟用 Web 應用程式的 W3C 分散式追蹤支援

根據預設,JavaScript 會啟用這項功能,而且主控頁面網域與傳送要求的網域相同時,會自動包含標頭 (例如,主控頁面是 example.com,而 Ajax 要求會傳送至 example.com)。 若要變更分散式追蹤模式,請使用distributedTracingMode設定欄位。 預設提供 AI_AND_W3C 以與任何 Application Insights 檢測的舊版服務達成回溯相容性。

如果 XMLHttpRequest 或 Fetch Ajax 要求傳送至不同的網域主機,包括子網域,則預設不會包含相互關聯標頭。 若要開啟這項功能,請將 enableCorsCorrelation 設定欄位設定為 true。 如果將 enableCorsCorrelation 設定為 true,則全部 XMLHttpRequest 和 Fetch Ajax 要求都包含相互關聯標頭。 因此,視瀏覽器/版本是否可以根據伺服器將接受的標頭來驗證要求而定,如果所呼叫的伺服器上的應用程式不支援 traceparent 標頭,則要求可能會失敗。 您可以使用 [correlationHeaderExcludedDomains 組態] 欄位,將伺服器的網域從跨元件相互關聯標題插入中排除。 例如,您可以使用 correlationHeaderExcludedDomains: ['*.auth0.com'],從傳送至 Auth0 識別提供者的要求中排除相互關聯標題。

重要

若要查看啟用相互關聯所需的所有設定,請參閱 JavaScript 相互關聯文件

OpenCensus Python 中的遙測相互關聯

OpenCensus Python 支援 W3C Trace-Context,不需任何額外的設定。

如需參考,您可以在此 GitHub 頁面上找到 OpenCensus 資料模型。

連入要求相互關聯

OpenCensus Python 會將來自傳入要求的 W3C Trace-Context 標頭,相互關聯到從要求本身產生的範圍。 OpenCensus 會自動針對以下這些熱門 Web 應用程式架構進行相互關聯:Flask、Django 和 Pyramid。 您只需要以正確的格式填入 W3C Trace-Context 標頭,並且與要求一起傳送。

探索此範例 Flask 應用程式。 安裝 Flask、OpenCensus 和 Flask 與 Azure 的延伸模組。


pip install flask opencensus opencensus-ext-flask opencensus-ext-azure

您需要將 Application Insights 連接字串新增至環境變數。

APPLICATIONINSIGHTS_CONNECTION_STRING=<appinsights-connection-string>

範例 Flask 應用程式

from flask import Flask
from opencensus.ext.azure.trace_exporter import AzureExporter
from opencensus.ext.flask.flask_middleware import FlaskMiddleware
from opencensus.trace.samplers import ProbabilitySampler

app = Flask(__name__)
middleware = FlaskMiddleware(
    app,
    exporter=AzureExporter(
        connection_string='<appinsights-connection-string>', # or set environment variable APPLICATION_INSIGHTS_CONNECTION_STRING
    ), 
    sampler=ProbabilitySampler(rate=1.0),
)

@app.route('/')
def hello():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(host='localhost', port=8080, threaded=True)

此程式碼會在本機電腦上執行範例 Flask 應用程式,並接聽連接埠 8080。 若要將追蹤內容相互關聯,您可以將要求傳送至端點。 在此範例中,您可以使用 curl 命令:

curl --header "traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01" localhost:8080

藉由查看 Trace-CoNtext 標頭格式,您可以衍生下列資訊:

version: 00

trace-id: 4bf92f3577b34da6a3ce929d0e0e4736

parent-id/span-id: 00f067aa0ba902b7

trace-flags: 01

如果您查看傳送至 Azure 監視器的要求項目,您可以看到填入追蹤標頭資訊的欄位。 您可以在 Azure 監視器 Application Insights 資源的 [記錄 (分析)] 下找到此資料。

螢幕擷取畫面,其中顯示 [記錄 (分析)] 中的要求遙測。

id 欄位的格式為 <trace-id>.<span-id>,其中 trace-id 取自已傳入要求的追蹤標頭,而 span-id 是針對此範圍產生的 8 位元組陣列。

operation_ParentId 欄位的格式為 <trace-id>.<parent-id>,其中 trace-idparent-id 都是取自已傳入要求的追蹤標頭。

記錄相互關聯

OpenCensus Python 可讓您藉由將追蹤識別碼、範圍識別碼和取樣旗標新增至記錄檔記錄,讓記錄相互關聯。 您可以藉由安裝 OpenCensus 記錄整合來新增這些屬性。 下列屬性會新增至 Python LogRecord 物件:traceIdspanIdtraceSampled (僅適用於在整合之後建立的記錄器)。

安裝 OpenCensus 記錄整合:

python -m pip install opencensus-ext-logging

範例應用程式

import logging

from opencensus.trace import config_integration
from opencensus.trace.samplers import AlwaysOnSampler
from opencensus.trace.tracer import Tracer

config_integration.trace_integrations(['logging'])
logging.basicConfig(format='%(asctime)s traceId=%(traceId)s spanId=%(spanId)s %(message)s')
tracer = Tracer(sampler=AlwaysOnSampler())

logger = logging.getLogger(__name__)
logger.warning('Before the span')
with tracer.span(name='hello'):
    logger.warning('In the span')
logger.warning('After the span')

當此程式碼執行時,以下項目會列印在主控台中:

2019-10-17 11:25:59,382 traceId=c54cb1d4bbbec5864bf0917c64aeacdc spanId=0000000000000000 Before the span
2019-10-17 11:25:59,384 traceId=c54cb1d4bbbec5864bf0917c64aeacdc spanId=70da28f5a4831014 In the span
2019-10-17 11:25:59,385 traceId=c54cb1d4bbbec5864bf0917c64aeacdc spanId=0000000000000000 After the span

請注意,範圍內的記錄訊息有 spanId 顯示。 spanId 與屬於範圍名為 hello 的範圍相同。

您可以使用 AzureLogHandler 匯出記錄資料。 如需詳細資訊,請參閱為 Python 應用程式設定 Azure 監視器

我們也可以將追蹤資訊從某個元件傳遞到另一個元件,以取得適當的相互關聯。 例如,請考慮有兩個元件 (module1module2) 的案例。 模組 1 會呼叫模組 2 中的函式。 若要從單一追蹤的 module1module2 中取得記錄,我們可以使用下列方法:

# module1.py
import logging

from opencensus.trace import config_integration
from opencensus.trace.samplers import AlwaysOnSampler
from opencensus.trace.tracer import Tracer
from module_2 import function_1

config_integration.trace_integrations(["logging"])
logging.basicConfig(
    format="%(asctime)s traceId=%(traceId)s spanId=%(spanId)s %(message)s"
)
tracer = Tracer(sampler=AlwaysOnSampler())

logger = logging.getLogger(__name__)
logger.warning("Before the span")

with tracer.span(name="hello"):
    logger.warning("In the span")
    function_1(logger, tracer)
logger.warning("After the span")
# module_2.py
import logging

from opencensus.trace import config_integration
from opencensus.trace.samplers import AlwaysOnSampler
from opencensus.trace.tracer import Tracer

config_integration.trace_integrations(["logging"])
logging.basicConfig(
    format="%(asctime)s traceId=%(traceId)s spanId=%(spanId)s %(message)s"
)
logger = logging.getLogger(__name__)
tracer = Tracer(sampler=AlwaysOnSampler())


def function_1(logger=logger, parent_tracer=None):
    if parent_tracer is not None:
        tracer = Tracer(
            span_context=parent_tracer.span_context,
            sampler=AlwaysOnSampler(),
        )
    else:
        tracer = Tracer(sampler=AlwaysOnSampler())

    with tracer.span("function_1"):
        logger.info("In function_1")

.NET 中的遙測相互關聯

在上線應用程式時,預設會處理相互關聯。 不需要任何特殊動作。

.NET 執行階段支援藉由 ActivityDiagnosticSource 的協助來散發

Application Insights .NET SDK 會使用 DiagnosticSourceActivity 來收集遙測並加以相互關聯。

Java 中的遙測相互關聯

Java 代理程式支援遙測的自動相互關聯。 會為在要求範圍內發出的所有遙測 (例如追蹤、例外狀況及自訂事件) 自動填入 operation_id。 如果設定 Java SDK 代理程式,則也會透過 HTTP 傳播服務對服務呼叫的相互關聯標頭,如先前所述。

注意

Application Insights Java 代理程式會自動收集 JMS、Kafka、Netty/Webflux 等等項目的要求和相依性。 針對 Java SDK,相互關聯功能僅支援透過 Apache HttpClient 發出的呼叫。 在 SDK 中不支援跨訊息技術 (例如 Kafka、RabbitMQ 和 Azure 服務匯流排) 的自動內容傳播。

若要收集自訂遙測,您需要使用 Java 2.6 SDK 來檢測應用程式。

角色名稱

您可以自訂元件名稱在應用程式對應中的顯示方式。 若要這樣做,您可以採用下列其中一個動作來手動設定 cloud_RoleName

  • 針對 Application Insights Java,請設定雲端角色名稱,如下所示:

    {
      "role": {
        "name": "my cloud role name"
      }
    }
    

    您也可以使用環境變數 APPLICATIONINSIGHTS_ROLE_NAME 來設定雲端角色名稱。

  • 使用 Application Insights Java SDK 2.5.0 和更新版本,您可以將 <RoleName> 新增至您的 ApplicationInsights.xml 檔案來指定 cloud_RoleName

    此螢幕擷取畫面顯示 Application Insights 概觀和連接字串。

    <?xml version="1.0" encoding="utf-8"?>
    <ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings" schemaVersion="2014-05-30">
       <ConnectionString>InstrumentationKey=00000000-0000-0000-0000-000000000000</ConnectionString>
       <RoleName>** Your role name **</RoleName>
       ...
    </ApplicationInsights>
    
  • 如果您搭配使用 Spring Boot 與 Application Insights Spring Boot 入門版,則請在 application.properties 檔案中設定應用程式的自訂名稱:

    spring.application.name=<name-of-app>

您也可以透過環境變數或系統屬性來設定雲端角色名稱。 如需詳細資料,請參閱設定雲端角色名稱

下一步