Durable Functions 提供多種診斷工具,用於排查協調問題。 本文將介紹如何設定追蹤與記錄、撰寫重播安全程式碼、檢查分散式追蹤,以及本地除錯。
在本文中,您將學會如何:
- 設定 Application Insights 追蹤生命週期事件
- 使用 Kusto 查詢編排實例
- 啟用耐用任務框架(DTFx)日誌 以進行低階診斷
- 設置分散式追蹤 來視覺化端到端的協調流程
- 在編排器函式中寫入重播安全的日誌
- 向外部客戶端回報自訂編排狀態
- 使用中斷點在本機偵錯協調流程
設定應用程式洞察追蹤
Application Insights 是監控耐用功能的最佳方式。 Durable 擴充功能會發出 追蹤事件 ,讓你追蹤編排的端到端執行過程。 你可以在Azure入口網站中使用 Application Insights Analytics 工具來查找並查詢這些追蹤事件。
日誌層級配置
在host.json檔案中設定傳送到 Application Insights 的追蹤資料詳細程度:
{
"logging": {
"logLevel": {
"Host.Triggers.DurableTask": "Information",
},
}
}
根據預設,會發出所有「非重新執行」的追蹤事件。 你可以透過設定 Host.Triggers.DurableTask 為 "Warning" 或 "Error"來減少資料量,這表示追蹤事件只會在特殊情況下發出。 若要啟用冗長的編排重播事件,請在 logReplayEvents 設定檔中將 true 設定為 。
Note
根據預設,Azure Functions 執行時環境會對 Application Insights 的遙測數據進行取樣,以避免太頻繁地傳送數據。 當許多生命週期事件在短時間內發生時,取樣可能會導致追蹤資訊遺失。 Azure Functions Monitoring 文章 解釋了如何配置這種行為。
輸入與輸出記錄
預設情況下,Orchestrator、Activity 和 Entity 函式的輸入與輸出不會被記錄。 此方法被推薦,因為記錄輸入與輸出可能會增加 Application Insights 的成本。 函式輸入和輸出承載也可能包含敏感性資訊。 取而代之的是記錄函式輸入與輸出的位元組數。 如果你想用 Durable Functions 擴充來記錄完整的輸入和輸出有效載荷,可以在 traceInputsAndOutputs 設定檔中將 true 屬性設為 。
查詢協調案例
請在 Application Insights Analytics 中使用以下 Kusto 查詢來檢查編排實例。
單一執行個體查詢
下列查詢顯示 Hello Sequence 函式協調流程之單一執行個體的歷史追蹤資料。 它會篩選重新執行,以便僅顯示「邏輯」執行路徑。 你可以依timestamp和sequenceNumber排序事件,如以下查詢所示:
let targetInstanceId = "ddd1aaa685034059b545eb004b15d4eb";
let start = datetime(2018-03-25T09:20:00);
traces
| where timestamp > start and timestamp < start + 30m
| where customDimensions.Category == "Host.Triggers.DurableTask"
| extend functionName = customDimensions["prop__functionName"]
| extend instanceId = customDimensions["prop__instanceId"]
| extend state = customDimensions["prop__state"]
| extend isReplay = tobool(tolower(customDimensions["prop__isReplay"]))
| extend sequenceNumber = tolong(customDimensions["prop__sequenceNumber"])
| where isReplay != true
| where instanceId == targetInstanceId
| sort by timestamp asc, sequenceNumber asc
| project timestamp, functionName, state, instanceId, sequenceNumber, appName = cloud_RoleName
結果是一份追蹤事件的清單,顯示協調流程的執行路徑,包括依執行時間以遞增順序排序任何活動函式。
執行個體摘要查詢
下列查詢會顯示在指定時間範圍內執行之所有協調流程執行個體的狀態。
let start = datetime(2017-09-30T04:30:00);
traces
| where timestamp > start and timestamp < start + 1h
| where customDimensions.Category == "Host.Triggers.DurableTask"
| extend functionName = tostring(customDimensions["prop__functionName"])
| extend instanceId = tostring(customDimensions["prop__instanceId"])
| extend state = tostring(customDimensions["prop__state"])
| extend isReplay = tobool(tolower(customDimensions["prop__isReplay"]))
| extend output = tostring(customDimensions["prop__output"])
| where isReplay != true
| summarize arg_max(timestamp, *) by instanceId
| project timestamp, instanceId, functionName, state, output, appName = cloud_RoleName
| order by timestamp asc
結果是執行個體識別碼的清單,以及其目前的執行階段狀態。
追蹤資料參考
每個編排實例在其生命週期中都會產生追蹤事件。 每個生命週期事件包含一個包含多個欄位的 customDimensions 有效載荷。 欄位名稱前面都會加上 prop__。
| 欄位名稱 | Description |
|---|---|
hubName |
執行您協調流程的工作中樞名稱。 |
appName |
函式應用程式的名稱。 當您有多個函數應用程式共用相同的 Application Insights 執行個體時,此欄位會很有用。 |
slotName |
目前函式應用程式執行所在的部署位置。 當您使用部署位置來設定協調流程版本時,此欄位會很有用。 |
functionName |
調解器或活動函數的名稱。 |
functionType |
函式的類型,例如 編排器 或 活動。 |
instanceId |
編排實例的唯一 ID。 |
state |
實例的生命週期執行狀態。 |
state.Scheduled |
函式已排程執行,但尚未開始執行。 |
state.Started |
函數已經開始運行,但尚未進行等待或完成。 |
state.Awaited |
協調器已排定某些工作,並正在等候其完成。 |
state.Listening |
編排器正在監聽外部事件通知。 |
state.Completed |
功能已順利完成。 |
state.Failed |
該函式因錯誤而失敗。 |
reason |
與追蹤事件相關的額外資料。 例如,若實例正在等待外部事件通知,此欄位會顯示它正在等待的事件名稱。 如果函式失敗,此欄位會包含錯誤詳細數據。 |
isReplay |
布林值,指出追蹤事件是否用於重播執行。 |
extensionVersion |
Durable Task 擴充功能的版本。 版本資訊是報告延伸模組中可能 Bug 時特別重要的資料。 如果實例運行過程中發生更新,長時間運行的實例可能會回報多個版本。 |
sequenceNumber |
事件的執行序列號。 結合時間戳,這有助於依執行時間排序事件。 請注意,如果主機在執行實例時重新啟動,這個數位會重設為零,因此請務必先依時間戳排序,然後再按 sequenceNumber 排序。 |
持久任務框架記錄(DTFx)
Durable 延伸模組記錄可用於了解協調流程邏輯的行為。 不過,這些記錄不一定會包含足夠的資訊,以偵錯架構層級效能和可靠性問題。 從 Durable 延伸模組 v2.3.0 開始,基礎長期工作架構 (DTFx) 發出的記錄也可供收集。
在查看 DTFx 所發出的日誌時,重要的是要了解 DTFx 引擎包含兩個部分:核心派遣引擎(DurableTask.Core)以及 眾多支援的儲存供應商之一。
| 組件 | Description |
|---|---|
DurableTask.Core |
核心協調流程執行,以及低層級排程記錄與遙測。 |
DurableTask.DurableTaskScheduler |
後端日誌專門用於 持久任務排程器。 |
DurableTask.AzureStorage |
特定於 Azure 儲存體 狀態提供者的後端日誌。 這些記錄包含與用來儲存和擷取內部協調流程狀態之內部佇列、Blob 和儲存體資料表的詳細互動。 |
DurableTask.Netherite |
如果已啟用,則為 Netherite 儲存體提供者特有的後端記錄。 |
DurableTask.SqlServer |
若啟用,則後端日誌專為 Microsoft SQL(MSSQL)儲存提供者 而設。 |
您可以藉由更新函數應用程式 logging/logLevel 檔案的 區段來啟用這些記錄。 下列範例示範如何同時從 DurableTask.Core 和 DurableTask.AzureStorage 啟用警告和錯誤記錄檔:
{
"version": "2.0",
"logging": {
"logLevel": {
"DurableTask.AzureStorage": "Warning",
"DurableTask.Core": "Warning"
}
}
}
如果您已啟用Application Insights,這些記錄會自動新增至 trace 集合。 您可以使用 Kusto 查詢,以搜尋其他 trace 記錄的相同方式來搜尋這些記錄。
Note
對於生產應用程式,我們建議使用 DurableTask.Core 篩選條件,啟用 DurableTask.AzureStorage 以及適當的儲存體提供者 (例如 "Warning") 記錄。 更高冗長度的篩選器,例如 "Information",對於偵錯效能問題很有用。 不過,這些記錄事件的數量可能很大,而可能大幅增加 Application Insights 資料儲存成本。
下列 Kusto 查詢示範如何查詢 DTFx 記錄。 查詢中最重要的部分是 where customerDimensions.Category startswith "DurableTask",因為它會將結果篩選為 DurableTask.Core 和 DurableTask.AzureStorage 類別中的記錄。
traces
| where customDimensions.Category startswith "DurableTask"
| project
timestamp,
severityLevel,
Category = customDimensions.Category,
EventId = customDimensions.EventId,
message,
customDimensions
| order by timestamp asc
結果是一組由長期工作架構記錄提供者所寫入的記錄。
如需了解更多可用的日誌事件,請參閱GitHub上的Durable Task Framework 結構化日誌文件。
分散式追蹤
分散式追蹤會追蹤請求並顯示不同服務之間的互動方式。 在 Durable Functions 中,它會將協調流程、實體與活動彼此建立關聯。 分散式追蹤顯示每個調度步驟相對於整個編排的執行時間,並識別問題或異常發生的位置。 所有語言和記憶體提供者的 Application Insights 都支援此功能。
先決條件
分散式追蹤需要特定的最小擴充版本:
- 針對 .NET 獨立應用程式,Microsoft.Azure.Functions.Worker.Extensions.DurableTask>= v1.4.0。
- 針對 non-.NET 應用程式, 請依照這些指示 手動安裝 Microsoft.Azure.WebJobs.Extensions.DurableTask>= v3.2.0 。 分散式追蹤將以擴充套件>v4.24.x提供。
建立分散式追蹤
要配置分散式追蹤,請更新 host.json 並設定 Application Insights 資源。
host.json
{
"extensions": {
"durableTask": {
"tracing": {
"distributedTracingEnabled": true,
"version": "V2"
}
}
}
}
Application Insights
用 Application Insights 資源來配置你的函式應用程式。
檢查追蹤
在你的應用程式洞察資源中,請導覽至 交易搜尋。 在結果中,尋找以持久性專屬前綴開頭的Request事件和Dependency事件(例如 orchestration:、activity:)。 選擇其中一項事件會開啟甘特圖,顯示端到端分布的追蹤。 圖表會將每個協調流程步驟顯示為水平橫條,並將活動和子協調流程呼叫巢狀置於其父協調流程下。 橫條長度代表每個步驟的實際經過時間,因此可輕鬆找出瓶頸或速度異常緩慢的活動。
Note
在 Application Insights 裡找不到你的痕跡嗎? 執行應用程式後等待約五分鐘,確保所有資料都傳遞到應用程式洞察資源。
編排器函式中的重播安全日誌
編排器函式每次接收新輸入都會 重播 ,這表示編排器中的任何日誌陳述式在單一邏輯執行中會執行多次。 例如,一個包含三個活動呼叫的函式,在重播時會產生如下日誌輸出:
Calling F1.
Calling F1.
Calling F2.
Calling F1.
Calling F2.
Calling F3.
Calling F1.
Calling F2.
Calling F3.
Done!
若要避免重複記錄行,請檢查「正在重新執行」旗標,讓記錄只在第一次 (非重新執行) 傳遞時執行。 下列範例顯示各語言中的重新執行安全記錄。
從 Durable Functions 2.0 開始,使用 CreateReplaySafeLogger 來自動過濾重播時的日誌語句:
[FunctionName("FunctionChain")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger log)
{
log = context.CreateReplaySafeLogger(log);
log.LogInformation("Calling F1.");
await context.CallActivityAsync("F1");
log.LogInformation("Calling F2.");
await context.CallActivityAsync("F2");
log.LogInformation("Calling F3");
await context.CallActivityAsync("F3");
log.LogInformation("Done!");
}
使用重新執行安全記錄時,記錄輸出如下:
Calling F1.
Calling F2.
Calling F3.
Done!
自訂編排狀態
使用自訂編排狀態向外部客戶報告工作流程進度。 常見的模式包括完成率、步驟描述和錯誤摘要。 外部用戶端可透過 HTTP 狀態查詢 API 或特定語言的 API 呼叫查看自訂狀態。
以下程式碼展示了如何在編排器函式中設定自訂狀態值:
[FunctionName("SetStatusTest")]
public static async Task SetStatusTest([OrchestrationTrigger] IDurableOrchestrationContext context)
{
// ...do work...
// update the status of the orchestration with some arbitrary data
var customStatus = new { completionPercentage = 90.0, status = "Updating database records" };
context.SetCustomStatus(customStatus);
// ...do more work...
}
Note
上一個 C# 範例適用於 Durable Functions 2.x。 對於 Durable Functions 1.x,您必須使用 DurableOrchestrationContext 來代替 IDurableOrchestrationContext。 欲了解更多版本間差異,請參閱 Durable Functions versions 條目。
當協調流程執行時,外部用戶端能擷取該自訂狀態:
GET /runtime/webhooks/durabletask/instances/instance123?code=XYZ
用戶端會取得下列回應:
{
"runtimeStatus": "Running",
"input": null,
"customStatus": { "completionPercentage": 90.0, "status": "Updating database records" },
"output": null,
"createdTime": "2017-10-06T18:30:24Z",
"lastUpdatedTime": "2017-10-06T19:40:30Z"
}
Warning
自訂狀態載荷限制為 16 KB 的 UTF-16 JSON 文字,以便可放入 Azure 資料表儲存體 欄位。 如果需要更大的有效載荷,也可以使用外部儲存。
Debugging
Azure Functions 支援直接除錯函式程式碼,這項支援也延續到 Durable Functions,無論是在 Azure 或本地執行。 請使用以下工作流程以獲得最佳除錯體驗:
用 新的任務中心 啟動新的除錯工作階段,或在工作階段間清除任務中心的內容。 先前執行時的遺留訊息可能導致意外的重複執行。
在你的 orchestrator 或 activity 函式中設定斷點。 對於編排器函式,請使用條件斷點,僅在「正在重播」值
false時才中斷,以避免重播時多次觸及相同斷點。如往常逐步執行程式碼。 請記住以下行為:
重播:
當收到新輸入時,編排器功能會定期 重播 。 協調器函式單次邏輯執行,可能會多次命中同一個中斷點,尤其是當中斷點設在函式程式碼前段時。等待:
每當協調器函式遇到await時,就會將控制權交回 Durable 工作架構發送器。 如果是第一次遇到某個特定await事件,相關任務 就不會 再繼續。 由於工作永遠不會繼續執行,因此無法逐步略過 await (Visual Studio 中的 F10)。 跨越只有在重新執行工作時可行。訊息超時:
Durable Functions 內部使用佇列訊息來驅動 orchestrator、activity 和 entity 功能的執行。 在多虛擬機環境中,長時間的除錯會話可能導致另一台虛擬機處理該訊息,導致重複執行。 雖然這種行為也存在於一般的隊列觸發函式,但這個脈絡很重要,因為隊列本身就是實作細節。停停與啟動:
Durable Functions 中的訊息會在除錯會話間持續存在。 如果你在執行一個持久函式時停止除錯並終止本地主機程序,該函式可能會在未來的除錯時段自動重新執行。
其他工具
檢查儲存狀態
預設情況下,Durable Functions 會將狀態儲存在 Azure 儲存體。 你可以使用像 Microsoft Azure 儲存體總管 這類工具檢查編排狀態和訊息。
Warning
可以很方便地查看資料表儲存體中的執行歷程記錄,而且避免此資料表上有任何相依性。 隨著 Durable Functions 擴充的演進,這可能會有所改變。
Note
你可以配置其他儲存提供者,而不是預設的Azure 儲存體提供者。 根據你為應用程式設定的儲存供應商,你可能需要使用不同的工具來檢查底層狀態。
Durable Functions 監控器
Durable Functions Monitor 是一款用於監控、管理及除錯協調與實體實例的圖形化工具。 您可以使用它作為 Visual Studio Code 的擴充功能,或以獨立應用程式的形式使用。 關於設定說明及功能清單,請參閱 Durable Functions Monitor Wiki。
Azure 入口網站診斷
Azure 入口網站為你的功能應用程式提供內建的診斷工具。
診斷與解決問題: Azure Function App Diagnostics 是監控與診斷應用程式潛在問題的實用資源。 其也提供建議,以協助根據診斷解決問題。 欲了解更多資訊,請參閱 Azure 功能應用程式診斷。
編排追蹤: Azure 入口網站提供編排追蹤細節,幫助您了解每個編排實例的狀態並追蹤端對端執行。 當你在 Azure Functions 應用程式中查看功能清單時,你會看到一個 Monitor欄位,裡面有追蹤連結。 你需要啟用應用程式的 Application Insights 才能存取這些資訊。
Roslyn 分析器
Durable Functions Roslyn Analyzer 是一款即時程式碼分析器,指導 C# 開發者遵循Durable Functions特定的 code 限制。 關於如何在Visual Studio和Visual Studio Code中啟用的說明,請參見 Durable Functions Roslyn Analyzer。
Troubleshooting
要排除常見問題,例如編排卡住、無法啟動或運行緩慢,請參閱 Durable Functions 故障排除指南。