Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Durable Functions 提供了多种诊断工具,用于对业务流程进行故障排除。 本文介绍如何配置跟踪和日志记录、编写重播安全代码、检查分布式跟踪和本地调试。
在这篇文章中,你将学会如何:
- 为生命周期事件配置 Application Insights 跟踪
- 使用 Kusto 查询编排实例
- 为低级别诊断启用 Durable Task Framework (DTFx) 日志记录
- 设置分布式跟踪 以可视化端到端业务流程流
- 在协调器函数中写入重播安全日志
- 向外部客户端报告自定义业务流程状态
- 在本地使用断点调试业务流程
配置 Application Insights 跟踪
Application Insights 是监视 Durable Functions 的建议方法。 Durable 扩展发出 跟踪事件 ,让您可以跟踪协调任务的端到端执行。 可以在 Azure 门户中使用 Application Insights Analytics 工具查找和查询这些跟踪事件。
日志级别配置
在 host.json 文件中配置向 Application Insights 发出的跟踪数据的详细程度:
{
"logging": {
"logLevel": {
"Host.Triggers.DurableTask": "Information",
},
}
}
默认情况下,所有非重播的跟踪事件都会被触发。 可以通过设置为Host.Triggers.DurableTask"Warning"或"Error"减少数据量,这意味着仅针对异常情况发出跟踪事件。 若要启用发出详细业务流程重播事件,请将 logReplayEvents 配置文件中的 true 设置为 。
注意
默认情况下,Azure Functions 运行时对 Application Insights 遥测进行采样,以避免数据的过于频繁发出。 如果在短时间内发生了许多的生命周期事件,采样可能会导致跟踪信息丢失。 Azure Functions 监控文章解释了如何配置此行为。
输入和输出日志记录
默认情况下,不会记录业务流程协调程序、活动和实体函数输入和输出。 建议使用此方法,因为日志记录输入和输出可能会增加 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
结果是实例 ID 的列表及其当前运行时状态。
跟踪数据参考
每个编排实例在其生命周期进程中都会生成跟踪事件。 每个生命周期事件都包含一个 customDimensions 的有效负载,具有多个字段。 字段名称的前面都附有 prop__。
| 字段名称 | Description |
|---|---|
hubName |
运行业务流程的任务中心的名称。 |
appName |
函数应用的名称。 当有多个函数应用共享同一个 Application Insights 实例时,此字段非常有用。 |
slotName |
当前函数应用运行所在的 部署槽。 使用部署槽位控制业务流程的版本时,此字段非常有用。 |
functionName |
编排器或活动函数的名称。 |
functionType |
函数的类型,例如 Orchestrator 或 Activity。 |
instanceId |
编排实例的唯一 ID。 |
state |
实例的生命周期执行状态。 |
state.Scheduled |
该函数已计划执行,但尚未开始运行。 |
state.Started |
该函数已开始运行,但尚未等待或完成。 |
state.Awaited |
协调器调度了一些工作,并正在等待其完成。 |
state.Listening |
编排器正在侦听外部事件通知。 |
state.Completed |
函数成功完成。 |
state.Failed |
函数失败并出现错误。 |
reason |
与跟踪事件关联的其他数据。 例如,如果实例正在等待外部事件通知,则此字段指示它正在等待的事件的名称。 如果函数失败,此字段将包含错误详细信息。 |
isReplay |
指示跟踪事件是否用于重播执行的布尔值。 |
extensionVersion |
Durable Task 扩展的版本。 在报告扩展中可能存在的 bug 时,此版本信息是特别重要的数据。 如果实例运行时发生更新,长时间运行的实例可能会报告多个版本。 |
sequenceNumber |
事件的执行序列号。 结合时间戳,这有助于按执行时间对事件进行排序。 请注意,如果主机在实例正在运行时重新启动,则此数字将重置为零,因此始终先按时间戳然后按 sequenceNumber 排序很重要。 |
Durable Task Framework 日志记录 (DTFx)
Durable 扩展日志对于了解业务流程逻辑的行为很有帮助。 但这些日志并非始终包含足够的信息来调试框架级别的性能和可靠性问题。 从 Durable 扩展 v2.3.0 开始,由基础 Durable Task Framework (DTFx) 发出的日志也可用于集合。
查看 DTFx 发出的日志时,请务必了解 DTFx 引擎有两个组件:核心调度引擎(DurableTask.Core)和 许多支持的存储提供程序之一。
| 组件 | Description |
|---|---|
DurableTask.Core |
核心编排执行和低级调度日志与遥测。 |
DurableTask.DurableTaskScheduler |
特定于 Durable Task Scheduler 的后端日志。 |
DurableTask.AzureStorage |
与 Azure 存储 状态提供程序相关的后端日志。 这些日志包括与用于存储和提取内部业务流程状态的内部队列、blob 和存储表的详细交互。 |
DurableTask.Netherite |
特定于 Netherite 存储提供程序的后端日志(如果已启用)。 |
DurableTask.SqlServer |
特定于 Microsoft SQL(MSSQL)存储提供程序 的后端日志(如果已启用)。 |
可通过更新函数应用的 host.json 文件的 logging/logLevel 部分来启用这些日志。 下面的示例演示如何从 DurableTask.Core 和 DurableTask.AzureStorage 启用警告和错误日志:
{
"version": "2.0",
"logging": {
"logLevel": {
"DurableTask.AzureStorage": "Warning",
"DurableTask.Core": "Warning"
}
}
}
如果已启用 Application Insights,这些日志会自动添加到 trace 集合。 可以像搜索其他 trace 日志那样,使用 Kusto 查询来搜索它们。
注意
对于生产应用程序,我们建议使用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
结果是一组由 Durable Task Framework 日志提供程序生成的日志。
有关可用日志事件的详细信息,请参阅 GitHub 上的 Durable Task Framework 结构化日志记录文档。
分布式跟踪
分布式跟踪跟踪请求,并且显示不同的服务如何相互交互。 在Durable Functions中,它将业务流程、实体和活动关联在一起。 分布式跟踪显示每个业务流程步骤相对于整个业务流程的执行时间,并确定出现问题或异常的位置。 所有语言和存储提供程序的 Application Insights 都支持此功能。
先决条件
分布式跟踪需要特定的最低扩展版本:
- 对于 .NET 独立应用, Microsoft.Azure.Functions.Worker.Extensions.DurableTask>= v1.4.0。
- 对于非.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 资源。
检查跟踪
在 Application Insights 资源中,导航到 事务搜索。 在结果中,寻找由 Durable 特定的前缀(例如 Request, Dependency 等)开始的 orchestration: 和 activity: 事件。 选择其中一个事件将打开一个甘特图,该图表显示端到端分布式跟踪。 该图表将每个业务流程步骤显示为水平条,活动和子业务流程调用嵌套在其父业务流程下方。 条形的长度表示每个步骤的墙上时钟持续时间,便于发现瓶颈或意外缓慢的活动。
注意
在 Application Insights 中没有看到你的跟踪记录吗? 运行应用程序后等待大约五分钟,以确保所有数据传播到 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...
}
注意
前面的 C# 示例适用于 Durable Functions 2.x。 对于 Durable Functions 1.x,必须使用 DurableOrchestrationContext 而不是 IDurableOrchestrationContext。 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。
在编排运行时,外部客户端可以获取此自定义状态。
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 表存储 的列中。 如果需要更大的有效负载,可以使用外部存储。
调试
Azure Functions 支持直接调试函数代码,Durable Functions 承袭了这项支持,不管它是在 Azure 中还是在本地运行。 使用以下工作流获得最佳调试体验:
使用 新的任务中心 启动新的调试会话,或清除会话之间的任务中心内容。 上一次运行的剩余消息可能会导致意外的重新执行。
在编排器或活动函数中设置断点。 对于编排函数,使用条件断点,只有在“正在重播”的值为
false时才中断,以避免在重播期间多次命中同一断点。像平常一样单步执行代码。 请记住以下行为:
重播:
收到新输入时,协调器函数会 重播 。 流程编排器函数的单个 逻辑 执行可能会导致多次命中相同的断点,尤其是在代码的前期设置断点时。等待:
每当协调函数中遇到某个await时,它将控制权返回给 Durable Task Framework 调度程序。 如果这是第一次遇到特定的await,则关联的任务 绝不会 被恢复。 因为任务永远不会恢复,所以无法逐过程执行等待(Visual Studio 中的 F10)。 仅当任务正在重播时,才能跳过。消息传送超时:
Durable Functions 在内部使用队列消息驱动编排函数、活动函数和实体函数的执行。 在多 VM 环境中,扩展调试会话可能会导致另一个 VM 处理消息,从而导致重复执行。 尽管常规队列触发器函数也存在此行为,但因为队列属于实现细节,所以了解这种上下文非常重要。停止和启动:
Durable Functions 中的消息在调试会话之间持久存在。 如果在执行持久函数时停止调试并终止本地主机进程,该函数可能会在将来的调试会话中自动重新执行。
其他工具
检查存储状态
默认情况下,Durable Functions 在 Azure 存储中存储状态。 可以使用 Azure 存储资源管理器 等工具来检查业务流程状态和消息。
Warning
尽管可以在表存储中方便查看执行历史记录,但不要对此表有任何依赖。 随着Durable Functions扩展的发展,它可能会发生变化。
注意
可以配置其他存储提供程序而不是默认Azure 存储提供程序。 根据为应用配置的存储提供程序,可能需要使用不同的工具来检查基础状态。
Durable Functions 监视器
Durable Functions Monitor 是用于监视、管理和调试业务流程和实体实例的图形工具。 它可用作Visual Studio Code扩展或独立应用。 有关设置说明和功能列表,请参阅 Durable Functions Monitor Wiki。
Azure门户诊断
Azure门户为函数应用提供内置诊断工具。
诊断并解决问题: Azure Function App 诊断是一种有用的资源,可用于监视和诊断应用程序中的潜在问题。 它还提供建议,以帮助根据诊断解决问题。 有关详细信息,请参阅 Azure Function App Diagnostics。
业务流程跟踪: Azure 门户提供业务流程跟踪详细信息,可帮助你了解每个业务流程实例的状态和跟踪端到端执行。 查看Azure Functions应用中函数的列表时,会看到包含跟踪链接的 Monitor 列。 需要为应用启用 Application Insights 才能访问此信息。
Roslyn 分析器
Durable Functions Roslyn 分析器是一种实时代码分析器,指导 C# 开发人员遵循 Durable Functions特定代码约束。 有关如何在Visual Studio和Visual Studio Code中启用它的说明,请参阅 Durable Functions Roslyn Analyzer。
故障排除
若要排查业务流程停滞、无法启动或运行缓慢等常见问题,请参阅 Durable Functions 故障排除指南。