Durable Functions는 오케스트레이션 문제를 해결하기 위한 몇 가지 진단 도구를 제공합니다. 이 문서에서는 추적 및 로깅을 구성하고, 재생이 안전한 코드를 작성하고, 분산 추적을 검사하고, 로컬로 디버그하는 방법을 설명합니다.
이 문서에서는 다음 방법을 알아봅니다.
- 수명 주기 이벤트에 대한 Application Insights 추적 구성
- Kusto를 사용하여 오케스트레이션 인스턴스 쿼리
- 하위 수준 진단을 위해 DTFx(Durable Task Framework) 로깅 사용
- 분산 추적을 설정 하여 엔드 투 엔드 오케스트레이션 흐름 시각화
- 오케스트레이터 함수에서 재생이 안전한 로그 작성
- 외부 클라이언트에 사용자 지정 오케스트레이션 상태 보고
- 로컬에서 중단점을 설정하여 오케스트레이션을 디버깅
Application Insights 추적 설정
Application Insights 는 지속성 함수를 모니터링하는 권장 방법입니다. 지속성 확장은 오케스트레이션의 엔드투엔드 실행을 추적할 수 있는 추적 이벤트를 내보냅니다. Azure 포털에서 Application Insights Analytics 도구를 사용하여 이러한 추적 이벤트를 찾아 쿼리할 수 있습니다.
로그 수준 구성
host.json 파일에서 Application Insights로 내보내는 추적 데이터의 상세도 수준을 구성합니다.
{
"logging": {
"logLevel": {
"Host.Triggers.DurableTask": "Information",
},
}
}
기본적으로 모든 재생되지 않는 추적 이벤트를 내보냅니다. 예외적인 상황에서만 추적 이벤트를 내보내는 것을 의미하거나 Host.Triggers.DurableTask설정하여 "Warning""Error" 데이터 볼륨을 줄일 수 있습니다. 자세한 오케스트레이션 재생 이벤트를 활성화하려면
메모
기본적으로 Azure Functions 런타임은 데이터를 너무 자주 내보내지 않도록 Application Insights 원격 분석을 샘플링합니다. 샘플링으로 인해 짧은 기간 동안 많은 수명 주기 이벤트가 발생할 때 추적 정보가 손실될 수 있습니다. Azure Functions 모니터링 문서 이 동작을 구성하는 방법을 설명합니다.
입력 및 출력 로깅
기본적으로 오케스트레이터, 활동 및 엔터티 함수 입력 및 출력은 기록되지 않습니다. 입력 및 출력을 로깅하면 Application Insights 비용이 증가할 수 있으므로 이 방법을 사용하는 것이 좋습니다. 함수 입력 및 출력 페이로드에도 중요한 정보가 포함될 수 있습니다. 대신 함수 입력 및 출력에 대한 바이트 수가 기록됩니다. Durable Functions 확장에서 전체 입력 및 출력 페이로드를 기록하도록 하려면 traceInputsAndOutputs 속성을 true 구성 파일에서 설정합니다.
쿼리 오케스트레이션 인스턴스
Application Insights Analytics에서 다음 Kusto 쿼리를 사용하여 오케스트레이션 인스턴스를 검사합니다.
단일 인스턴스 쿼리
다음 쿼리에서는 Hello 시퀀스 함수 오케스트레이션의 단일 인스턴스에 대한 추적 기록 데이터를 보여 줍니다.
논리 실행 경로만 표시되도록 재생 실행을 필터링합니다. 다음 쿼리와 같이 정렬하여 timestampsequenceNumber 이벤트를 정렬할 수 있습니다.
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__가 추가됩니다.
| 필드 이름 | 설명 |
|---|---|
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 |
지속성 작업 확장의 버전입니다. 버전 정보는 확장에서 가능한 버그를 보고할 때 특히 중요한 데이터입니다. 장기 실행 인스턴스는 인스턴스가 실행되는 동안 업데이트가 발생하는 경우 여러 버전을 보고할 수 있습니다. |
sequenceNumber |
이벤트에 대한 실행 시퀀스 번호입니다. 타임스탬프와 결합하면 실행 시간별로 이벤트를 정렬하는 데 도움이 됩니다. 인스턴스가 실행되는 동안 호스트가 다시 시작되면 이 숫자가 0으로 다시 설정되므로 항상 먼저 타임스탬프를 기준으로 정렬한 다음 sequenceNumber를 정렬하는 것이 중요합니다. |
지속성 작업 프레임워크 로깅(DTFx)
지속성 확장 로그는 오케스트레이션 논리의 동작을 이해하는 데 유용합니다. 그러나 이러한 로그에는 프레임워크 수준 성능 및 안정성 문제를 디버깅하는 데 충분한 정보가 항상 포함되지는 않습니다. 지속성 확장 v2.3.0에서 시작하여 기본 지속성 작업 프레임워크(DTFx)에서 내보낸 로그를 컬렉션에도 사용할 수 있습니다.
DTFx에서 내보낸 로그를 살펴볼 때 DTFx 엔진에는 핵심 디스패치 엔진(DurableTask.Core)과 지원되는 여러 스토리지 공급자 중 하나의 두 가지 구성 요소가 있음을 이해하는 것이 중요합니다.
| 구성 요소 | 설명 |
|---|---|
DurableTask.Core |
핵심 오케스트레이션 수행 및 하위 수준 스케줄링 로그 및 원격 분석. |
DurableTask.DurableTaskScheduler |
지속성 작업 스케줄러와 관련된 백 엔드 로그입니다. |
DurableTask.AzureStorage |
Azure Storage 상태 공급자와 관련된 백 엔드 로그입니다. 이러한 로그에는 내부 오케스트레이션 상태를 저장하고 가져오는 데 사용되는 내부 큐, Blob 및 스토리지 테이블과의 자세한 상호 작용이 포함됩니다. |
DurableTask.Netherite |
사용하도록 설정된 경우 Netherite 스토리지 공급자와 관련된 백 엔드 로그입니다. |
DurableTask.SqlServer |
사용하도록 설정된 경우 MSSQL(Microsoft SQL) 스토리지 공급자와 관련된 백 엔드 로그입니다. |
함수 앱 logging/logLevel 파일의 섹션을 업데이트하여 이러한 로그를 사용하도록 설정할 수 있습니다. 다음 예에서는 DurableTask.Core 및 DurableTask.AzureStorage 모두에서 경고 및 오류 로그를 사용하도록 설정하는 방법을 보여줍니다.
{
"version": "2.0",
"logging": {
"logLevel": {
"DurableTask.AzureStorage": "Warning",
"DurableTask.Core": "Warning"
}
}
}
Application Insights를 사용하도록 설정한 경우 이러한 로그가 컬렉션에 trace 자동으로 추가됩니다. Kusto 쿼리를 사용하여 다른 trace 로그를 검색하는 것과 동일한 방식으로 검색할 수 있습니다.
메모
프로덕션 애플리케이션의 경우 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 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에서 사용할 수 있습니다.
분산 추적 설정
분산 추적을 구성하려면 Application Insights 리소스를 host.json 업데이트하고 설정합니다.
host.json
{
"extensions": {
"durableTask": {
"tracing": {
"distributedTracingEnabled": true,
"version": "V2"
}
}
}
}
Application Insights (애플리케이션 인사이트)
Application Insights 리소스를 사용하여 함수 앱을 구성합니다.
추적 검사
Application Insights 리소스에서 트랜잭션 검색으로 이동합니다. 결과에서 지속성에 특정된 접두사(예: Request, Dependency 등)로 시작하는 이벤트를 찾습니다. 이러한 이벤트 중 하나를 선택하면 엔드 투 엔드 분산 추적을 보여 주는 Gantt 차트가 열립니다. 차트는 각 오케스트레이션 단계를 가로 막대로 표시하며, 작업 및 하위 오케스트레이션 호출은 부모 오케스트레이션 아래에 중첩됩니다. 막대 길이는 각 단계의 벽시계 기간을 나타내므로 병목 현상이나 예기치 않게 느린 활동을 쉽게 발견할 수 있습니다.
메모
Application Insights에서 추적이 표시되지 않나요? 애플리케이션을 실행한 후 약 5분 정도 기다렸다가 모든 데이터가 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"
}
경고
사용자 지정 상태 페이로드는 Azure Table Storage 열에 맞아야 하므로 16KB의 UTF-16 JSON 텍스트로 제한됩니다. 더 큰 페이로드가 필요한 경우 외부 스토리지를 사용할 수 있습니다.
디버깅
Azure Functions 함수 코드 디버깅을 직접 지원하며, Azure 또는 로컬에서 실행되는지 여부에 관계없이 동일한 지원이 Durable Functions 전달됩니다. 최상의 디버깅 환경을 위해 다음 워크플로를 사용합니다.
새 작업 허브를 사용하여 새 디버그 세션을 시작하거나 세션 간의 작업 허브 콘텐츠를 지웁니다. 이전 실행에서 남은 메시지로 인해 예기치 않은 다시 실행이 발생할 수 있습니다.
오케스트레이터 또는 작업 함수에서 중단점을 설정합니다. 오케스트레이터 함수의 경우, "재생 중" 값이
false일 때만 중단되도록 하는 조건부 중단점을 사용하여 재생 중에 동일한 중단점을 여러 번 치는 것을 방지합니다.코드를 정상적으로 단계별로 실행합니다. 다음 동작에 유의하세요.
재생:
오케스트레이터 함수는 새 입력이 수신될 때 정기적으로 재생 됩니다. 오케스트레이터 함수의 단일 논리적 실행은 특히 함수 코드 초기에 설정된 경우 동일한 중단점에 여러 번 도달할 수 있습니다.기다리고:
오케스트레이터 함수에서await이 발견될 때마다, 제어권은 Durable Task Framework 디스패처로 다시 넘겨집니다. 특정await작업이 처음 발생하는 경우 연결된 작업은 다시 시작 되지 않습니다 . 작업이 다시 시작되지 않으므로 Visual Studio에서 F10을 사용하여 await를 건너뛸 수 없습니다. 작업이 재생되는 경우에만 단계별 실행이 작동합니다.메시징 시간 제한:
Durable Functions는 내부적으로 큐 메시지를 사용하여 오케스트레이터, 작업 및 엔터티 함수의 실행을 구동합니다. 다중 VM 환경에서 확장된 디버깅 세션으로 인해 다른 VM이 메시지를 처리하여 중복 실행이 발생할 수 있습니다. 이 동작은 일반 큐 트리거 함수에도 존재하지만 큐가 구현 세부 정보이므로 이 컨텍스트를 강조 표시해야 합니다.중지 및 시작:
지속성 함수의 메시지는 디버그 세션 간에 유지됩니다. 지속성 함수가 실행되는 동안 디버깅을 중지하고 로컬 호스트 프로세스를 종료하는 경우 해당 함수는 이후 디버그 세션에서 자동으로 다시 실행될 수 있습니다.
추가 도구
스토리지 상태 검사
기본적으로 Durable Functions 상태를 Azure Storage 저장합니다. Microsoft Azure Storage Explorer와 같은 도구를 사용하여 오케스트레이션 상태 및 메시지를 검사할 수 있습니다.
경고
Table Storage의 실행 기록을 확인하는 것이 편리하지만 이 테이블에 대한 종속성은 사용하지 마세요. Durable Functions 확장이 진화함에 따라 변경될 수 있습니다.
메모
기본 Azure Storage 공급자 대신 다른 스토리지 공급자를 구성할 수 있습니다. 앱에 대해 구성된 스토리지 공급자에 따라 다른 도구를 사용하여 기본 상태를 검사해야 할 수 있습니다.
듀러블 펑션스 모니터
Durable Functions Monitor는 오케스트레이션 및 엔터티 인스턴스를 모니터링, 관리 및 디버깅하기 위한 그래픽 도구입니다. Visual Studio Code 확장 또는 독립 실행형 앱으로 사용할 수 있습니다. 설치 지침 및 기능 목록은 Durable Functions Monitor Wiki를 참조하십시오.
Azure 포털 진단
Azure 포털은 함수 앱에 대한 기본 제공 진단 도구를 제공합니다.
문제 진단 및 해결: Azure Function App Diagnostics는 애플리케이션에서 잠재적인 문제를 모니터링하고 진단하는 데 유용한 리소스입니다. 또한 진단에 따라 문제를 해결하는 데 도움이 되는 제안도 제공합니다. 자세한 내용은 Azure 함수 앱 진단 참조하세요.
오케스트레이션 추적: Azure Portal은 각 오케스트레이션 인스턴스 및 추적 엔드 투 엔드 실행의 상태를 이해하는 데 도움이 되는 오케스트레이션 추적 세부 정보를 제공합니다. Azure Functions 앱 내의 함수 목록을 보면 추적에 대한 링크가 포함된 모니터 열이 표시됩니다. 이 정보에 액세스하려면 앱에 Application Insights를 사용하도록 설정해야 합니다.
Roslyn 분석기
Durable Functions Roslyn Analyzer는 C# 개발자가 Durable Functions 특정 code 제약 조건 따르도록 안내하는 라이브 코드 분석기입니다. Visual Studio 및 Visual Studio Code에서 사용 설정 방법에 대한 지침은 Durable Functions Roslyn Analyzer를 참조하세요.
Troubleshooting
오케스트레이션이 중단되거나 시작되지 않거나 느리게 실행되는 것과 같은 일반적인 문제를 해결하려면 Durable Functions 문제 해결 가이드 참조하세요.