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

注意

下列文件依賴Application Insights傳統 API。 Application Insights 的長期計劃是使用 OpenTelemetry 收集數據。 如需詳細資訊,請參閱 為 .NET、Node.js、Python 和 Java 應用程式啟用 Azure 監視器 OpenTelemetry。

新式雲端和 微服務 架構已啟用簡單、獨立部署的服務,可降低成本,同時增加可用性和輸送量。 不過,它使得整體系統更難推理和偵錯。 分散式追蹤可藉由提供效能分析工具來解決此問題,其運作方式類似雲端和微服務架構的呼叫堆棧。

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

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

啟用分散式追蹤

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

透過 Application Insights 透過自動結構或 SDK 啟用

適用於 .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_parentIdrequest.id 搭配 dependency.id來建置分散式邏輯作業operation_Id的檢視。 這些欄位也會定義遙測呼叫的因果關係順序。

在微服務環境中,來自元件的追蹤可以移至不同的記憶體專案。 每個元件都可以在 Application Insights 中有自己的 連接字串。 若要取得邏輯作業的遙測數據,Application Insights 會查詢每個記憶體項目的數據。

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

如需使用 app 查詢表達式從多個不同實例查詢的資訊,請參閱 Azure 監視器查詢中的 app() 表達式。

範例

讓我們看看下列範例。 名為「股票價格」的應用程式會使用稱為 Stock 的外部 API 來顯示股票目前的市場價格。 股票價格應用程式有一個名為 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 股票頁面 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 追蹤內容,其定義:

  • traceparent:攜帶呼叫的全域唯一作業標識碼和唯一標識符。
  • tracestate:攜帶系統特定的追蹤內容。

最新版的 Application Insights SDK 支援追蹤內容通訊協定,但您可能需要選擇加入該通訊協定。 (會維護與 Application Insights SDK 所支援先前相互關聯通訊協定的回溯相容性。

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

  • Request-Id:攜帶呼叫的全域唯一標識符。
  • Correlation-Context:攜帶分散式追蹤屬性的名稱/值組集合。

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

W3C 追蹤內容和 Application Insights 數據模型會以下列方式對應:

Application Insights W3C TraceContext
Id和的RequestDependency parent-id
Operation_Id trace-id
Operation_ParentId 這個範圍的父範圍父代標識碼 。 如果欄位是根範圍,則此欄位必須為空白。

如需詳細資訊,請參閱 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 應用程式,請將下列程式代碼新增至 <TelemetryModules> ApplicationInsights.xml 中的標記:

    <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。 如果您設定 enableCorsCorrelationtrue,則所有 XMLHttpRequest 和 Fetch Ajax 要求都包含相互關聯標頭。 因此,如果所呼叫之伺服器上的應用程式不支持 traceparent 標頭,則要求可能會失敗,取決於瀏覽器/版本是否可以根據伺服器接受的標頭來驗證要求。 您可以使用元件 correlationHeaderExcludedDomains 的欄位 ,從跨元件相互關聯標頭插入中排除伺服器的網域。 例如,您可以使用 correlationHeaderExcludedDomains: ['*.auth0.com'] 將相互關聯標頭從傳送至 Auth0 識別提供者的要求中排除。

重要

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

OpenCensus Python 中的遙測相互關聯

OpenCensus Python 支援 W3C 追蹤內容 ,而不需要額外的設定。

如需參考,您可以在此 GitHub 頁面上找到 OpenCensus 數據模型

連入要求相互關聯

OpenCensus Python 會將 W3C 追蹤內容標頭與從要求本身產生的範圍相互關聯。 OpenCensus 會自動與這些熱門 Web 應用程式架構的整合相互關聯:Flask、Django 和 Pyramid。 您只需要以正確的格式填入 W3C 追蹤內容標頭,並以要求傳送它們。

探索此範例 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

藉由查看 追蹤內容標頭格式,您可以衍生下列資訊:

version: 00

trace-id: 4bf92f3577b34da6a3ce929d0e0e4736

parent-id/span-id: 00f067aa0ba902b7

trace-flags: 01

如果您查看傳送至 Azure 監視器的要求專案,您可以看到填入追蹤標頭資訊的欄位。 您可以在 Azure 監視器 Application Insights 資源中找到 [記錄] (Analytics) 底下的數據。

Screenshot that shows Request telemetry in Logs (Analytics).

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

    Screenshot that shows Application Insights overview and connection string.

    <?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 Starter,請在 application.properties 檔案中設定應用程式的自定義名稱:

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

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

下一步