Diagnostyka w usłudze Durable Functions na platformie Azure
Istnieje kilka opcji diagnozowania problemów z rozszerzeniem Durable Functions. Niektóre opcje są takie same jak w przypadku funkcji regularnych, a niektóre z nich są unikatowe dla usługi Durable Functions.
Szczegółowe dane dotyczące aplikacji
Usługa Application Insights to zalecany sposób wykonywania diagnostyki i monitorowania w usłudze Azure Functions. To samo dotyczy rozszerzenia Durable Functions. Aby zapoznać się z omówieniem sposobu wykorzystania usługi Application Insights w aplikacji funkcji, zobacz Monitorowanie usługi Azure Functions.
Rozszerzenie Durable Extension usługi Azure Functions emituje również zdarzenia śledzenia, które umożliwiają śledzenie kompleksowego wykonywania orkiestracji. Te zdarzenia śledzenia można znaleźć i wykonywać zapytania za pomocą narzędzia analizy usługi Application Insights w witrynie Azure Portal.
Dane śledzenia
Każde zdarzenie cyklu życia wystąpienia orkiestracji powoduje zapisanie zdarzenia śledzenia w kolekcji śladów w usłudze Application Insights. To zdarzenie zawiera ładunek customDimensions z kilkoma polami. Nazwy pól są poprzedzane ciągiem prop__
.
- hubName: nazwa centrum zadań, w którym są uruchomione aranżacje.
- appName: nazwa aplikacji funkcji. To pole jest przydatne, gdy masz wiele aplikacji funkcji współużytkowania tego samego wystąpienia usługi Application Insights.
- slotName: miejsce wdrożenia, w którym jest uruchomiona bieżąca aplikacja funkcji. To pole jest przydatne w przypadku używania miejsc wdrożenia do obsługi wersji aranżacji.
- functionName: nazwa funkcji orkiestratora lub działania.
- functionType: typ funkcji, taki jak Orchestrator lub Activity.
- instanceId: unikatowy identyfikator wystąpienia aranżacji.
- state: stan wykonywania cyklu życia wystąpienia. Prawidłowe wartości to:
- Zaplanowane: funkcja została zaplanowana na wykonanie, ale nie została jeszcze uruchomiona.
- Rozpoczęto: funkcja została uruchomiona, ale nie została jeszcze wyczekiwana ani ukończona.
- Awaited: Orkiestrator zaplanował pewną pracę i czeka na jego ukończenie.
- Nasłuchiwanie: orkiestrator nasłuchuje powiadomienia o zdarzeniach zewnętrznych.
- Ukończono: funkcja została pomyślnie ukończona.
- Niepowodzenie: funkcja nie powiodła się z powodu błędu.
- przyczyna: Dodatkowe dane skojarzone ze zdarzeniem śledzenia. Jeśli na przykład wystąpienie oczekuje na powiadomienie o zdarzeniu zewnętrznym, to pole wskazuje nazwę zdarzenia, na które czeka. Jeśli funkcja nie powiodła się, to pole będzie zawierać szczegóły błędu.
- isReplay: wartość logiczna wskazująca, czy zdarzenie śledzenia jest przeznaczone do ponownego wykonania.
- extensionVersion: wersja rozszerzenia Durable Task. Informacje o wersji są szczególnie ważne podczas raportowania możliwych usterek w rozszerzeniu. Długotrwałe wystąpienia mogą zgłaszać wiele wersji w przypadku wystąpienia aktualizacji podczas jej działania.
- sequenceNumber: numer sekwencji wykonywania zdarzenia. W połączeniu ze znacznikiem czasu pomaga uporządkować zdarzenia według czasu wykonania. Należy pamiętać, że ta liczba zostanie zresetowana do zera, jeśli host zostanie uruchomiony ponownie podczas działania wystąpienia, dlatego ważne jest, aby zawsze sortować według znacznika czasu, a następnie sequenceNumber.
Szczegółowość danych śledzenia emitowanych do usługi Application Insights można skonfigurować w logger
sekcji host.json
(Functions 1.x) lub logging
(Functions 2.0) pliku.
Functions 1.0
{
"logger": {
"categoryFilter": {
"categoryLevels": {
"Host.Triggers.DurableTask": "Information"
}
}
}
}
Functions 2.0
{
"logging": {
"logLevel": {
"Host.Triggers.DurableTask": "Information",
},
}
}
Domyślnie wszystkie zdarzenia śledzenia niepotwarzania są emitowane. Ilość danych można zmniejszyć, ustawiając wartość Host.Triggers.DurableTask
na "Warning"
lub "Error"
w takim przypadku zdarzenia śledzenia będą emitowane tylko w wyjątkowych sytuacjach. Aby włączyć emitowanie pełnych zdarzeń odtwarzania orkiestracji, ustaw logReplayEvents
wartość na true
w pliku konfiguracji host.json .
Uwaga
Domyślnie dane telemetryczne usługi Application Insights są próbkowane przez środowisko uruchomieniowe usługi Azure Functions, aby uniknąć zbyt częstego emitowania danych. Może to spowodować utratę informacji śledzenia w przypadku wystąpienia wielu zdarzeń cyklu życia w krótkim czasie. W artykule Monitorowanie usługi Azure Functions wyjaśniono, jak skonfigurować to zachowanie.
Dane wejściowe i wyjściowe funkcji orkiestratora, działania i jednostki nie są domyślnie rejestrowane. To domyślne zachowanie jest zalecane, ponieważ rejestrowanie danych wejściowych i wyjściowych może zwiększyć koszty usługi Application Insights. Ładunki wejściowe i wyjściowe funkcji mogą również zawierać poufne informacje. Zamiast tego liczba bajtów dla danych wejściowych i wyjściowych funkcji jest rejestrowana zamiast rzeczywistych ładunków domyślnie. Jeśli chcesz, aby rozszerzenie Durable Functions rejestrowało pełne ładunki wejściowe i wyjściowe, ustaw traceInputsAndOutputs
właściwość na true
w pliku konfiguracji host.json .
Zapytanie o pojedyncze wystąpienie
Poniższe zapytanie przedstawia historyczne dane śledzenia dla pojedynczego wystąpienia orkiestracji funkcji Hello Sequence . Jest on napisany przy użyciu język zapytań Kusto. Filtruje wykonywanie odtwarzania w taki sposób, aby była wyświetlana tylko logiczna ścieżka wykonywania. Zdarzenia można porządkować według i timestamp
sequenceNumber
, jak pokazano w poniższym zapytaniu:
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
Wynikiem jest lista zdarzeń śledzenia, które pokazują ścieżkę wykonywania aranżacji, w tym wszystkie funkcje działania uporządkowane według czasu wykonywania w kolejności rosnącej.
Zapytanie podsumowania wystąpienia
Poniższe zapytanie wyświetla stan wszystkich wystąpień aranżacji, które zostały uruchomione w określonym zakresie czasu.
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
Wynikiem jest lista identyfikatorów wystąpień i ich bieżący stan środowiska uruchomieniowego.
Trwałe rejestrowanie struktury zadań
Dzienniki rozszerzenia Durable są przydatne do zrozumienia zachowania logiki aranżacji. Jednak te dzienniki nie zawsze zawierają wystarczające informacje, aby debugować problemy z wydajnością i niezawodnością na poziomie platformy. Począwszy od wersji 2.3.0 rozszerzenia Durable, dzienniki emitowane przez podstawową platformę Durable Task Framework (DTFx) są również dostępne dla kolekcji.
Podczas przeglądania dzienników emitowanych przez dtFx ważne jest, aby zrozumieć, że aparat DTFx składa się z dwóch składników: podstawowego aparatu wysyłania () i jednego z wielu obsługiwanych dostawców magazynu (DurableTask.Core
rozszerzenia Durable Functions używa DurableTask.AzureStorage
domyślnie, ale są dostępne inne opcje).
- DurableTask.Core: podstawowe wykonywanie orkiestracji i dzienniki planowania niskiego poziomu oraz dane telemetryczne.
- DurableTask.AzureStorage: dzienniki zaplecza specyficzne dla dostawcy stanu usługi Azure Storage. Te dzienniki obejmują szczegółowe interakcje z wewnętrznymi kolejkami, obiektami blob i tabelami magazynu używanymi do przechowywania i pobierania wewnętrznego stanu aranżacji.
- DurableTask.Netherite: dzienniki zaplecza specyficzne dla dostawcy magazynu Netherite, jeśli są włączone.
- DurableTask.SqlServer: dzienniki zaplecza specyficzne dla dostawcy magazynu Microsoft SQL (MSSQL), jeśli są włączone.
Te dzienniki można włączyć, aktualizując sekcję logging/logLevel
pliku host.json aplikacji funkcji. W poniższym przykładzie pokazano, jak włączyć dzienniki ostrzegawcze i dzienniki błędów z obu DurableTask.Core
systemów i DurableTask.AzureStorage
:
{
"version": "2.0",
"logging": {
"logLevel": {
"DurableTask.AzureStorage": "Warning",
"DurableTask.Core": "Warning"
}
}
}
Jeśli masz włączoną usługę Application Insights, te dzienniki zostaną automatycznie dodane do kolekcji trace
. Możesz wyszukiwać je w taki sam sposób, jak w przypadku wyszukiwania innych trace
dzienników przy użyciu zapytań Kusto.
Uwaga
W przypadku aplikacji produkcyjnych zaleca się włączenie DurableTask.Core
i zastosowanie odpowiednich dzienników dostawcy magazynu (np. DurableTask.AzureStorage
) przy użyciu filtru "Warning"
. Wyższe filtry szczegółowości, takie jak "Information"
, są bardzo przydatne do debugowania problemów z wydajnością. Jednak te zdarzenia dziennika mogą być duże i mogą znacznie zwiększyć koszty magazynowania danych usługi Application Insights.
Poniższe zapytanie Kusto pokazuje, jak wykonywać zapytania dotyczące dzienników DTFx. Najważniejszą częścią zapytania jest where customerDimensions.Category startswith "DurableTask"
to, że filtruje wyniki do dzienników w DurableTask.Core
kategoriach i DurableTask.AzureStorage
.
traces
| where customDimensions.Category startswith "DurableTask"
| project
timestamp,
severityLevel,
Category = customDimensions.Category,
EventId = customDimensions.EventId,
message,
customDimensions
| order by timestamp asc
Wynikiem jest zestaw dzienników napisanych przez dostawców dzienników platformy Durable Task Framework.
Aby uzyskać więcej informacji na temat dostępnych zdarzeń dziennika, zobacz dokumentację rejestrowania strukturalnego platformy Durable Task Framework w witrynie GitHub.
Rejestrowanie aplikacji
Ważne jest, aby zachować zachowanie powtarzania orkiestratora podczas pisania dzienników bezpośrednio z funkcji orkiestratora. Rozważmy na przykład następującą funkcję orkiestratora:
[FunctionName("FunctionChain")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger 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!");
}
Wynikowe dane dziennika będą wyglądać podobnie do następujących przykładowych danych wyjściowych:
Calling F1.
Calling F1.
Calling F2.
Calling F1.
Calling F2.
Calling F3.
Calling F1.
Calling F2.
Calling F3.
Done!
Uwaga
Należy pamiętać, że podczas gdy dzienniki twierdzą, że są wywoływane nazwy F1, F2 i F3, te funkcje są wywoływane tylko po raz pierwszy. Kolejne wywołania wykonywane podczas odtwarzania są pomijane, a dane wyjściowe są odtwarzane do logiki orkiestratora.
Jeśli chcesz tylko zapisywać dzienniki w wykonaniach nieodtworzania, możesz napisać wyrażenie warunkowe w celu rejestrowania tylko wtedy, gdy flaga "jest odtwarzana" to false
. Rozważmy powyższy przykład, ale tym razem za pomocą testów odtwarzania.
[FunctionName("FunctionChain")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger log)
{
if (!context.IsReplaying) log.LogInformation("Calling F1.");
await context.CallActivityAsync("F1");
if (!context.IsReplaying) log.LogInformation("Calling F2.");
await context.CallActivityAsync("F2");
if (!context.IsReplaying) log.LogInformation("Calling F3");
await context.CallActivityAsync("F3");
log.LogInformation("Done!");
}
Począwszy od rozszerzenia Durable Functions 2.0, funkcje orkiestratora platformy .NET mają również możliwość utworzenia modułu ILogger
, który automatycznie filtruje instrukcje dziennika podczas odtwarzania. To automatyczne filtrowanie odbywa się przy użyciu interfejsu API IDurableOrchestrationContext.CreateReplaySafeLogger(ILogger).
[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!");
}
Uwaga
Poprzednie przykłady języka C# dotyczą rozszerzenia Durable Functions 2.x. W przypadku rozszerzenia Durable Functions 1.x należy użyć funkcji DurableOrchestrationContext
IDurableOrchestrationContext
zamiast . Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł Wersje rozszerzenia Durable Functions.
Po wprowadzeniu wcześniej wymienionych zmian dane wyjściowe dziennika są następujące:
Calling F1.
Calling F2.
Calling F3.
Done!
Stan niestandardowy
Niestandardowy stan orkiestracji umożliwia ustawienie niestandardowej wartości stanu dla funkcji orkiestratora. Ten stan niestandardowy jest następnie widoczny dla klientów zewnętrznych za pośrednictwem interfejsu API zapytania stanu HTTP lub za pośrednictwem wywołań interfejsu API specyficznych dla języka. Stan orkiestracji niestandardowej umożliwia bogatsze monitorowanie funkcji orkiestratora. Na przykład kod funkcji orkiestratora może wywołać interfejs API "ustaw stan niestandardowy", aby zaktualizować postęp długotrwałej operacji. Klient, taki jak strona internetowa lub inny system zewnętrzny, może okresowo wysyłać zapytania do interfejsów API zapytań o stan HTTP, aby uzyskać bardziej zaawansowane informacje o postępie. Poniżej przedstawiono przykładowy kod ustawiania niestandardowej wartości stanu w funkcji orkiestratora:
[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...
}
Uwaga
Poprzedni przykład w języku C# dotyczy rozszerzenia Durable Functions 2.x. W przypadku rozszerzenia Durable Functions 1.x należy użyć funkcji DurableOrchestrationContext
IDurableOrchestrationContext
zamiast . Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł Wersje rozszerzenia Durable Functions.
Gdy orkiestracja jest uruchomiona, klienci zewnętrzni mogą pobrać ten stan niestandardowy:
GET /runtime/webhooks/durabletask/instances/instance123?code=XYZ
Klienci otrzymają następującą odpowiedź:
{
"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"
}
Ostrzeżenie
Ładunek stanu niestandardowego jest ograniczony do 16 KB tekstu JSON UTF-16, ponieważ musi być w stanie zmieścić się w kolumnie usługi Azure Table Storage. Jeśli potrzebujesz większego ładunku, możesz użyć magazynu zewnętrznego.
Śledzenie rozproszone
Śledzenie rozproszone śledzi żądania i pokazuje, jak różne usługi współdziałają ze sobą. W usłudze Durable Functions koreluje również aranżacje i działania. Jest to pomocne, aby zrozumieć, ile czasu zajmuje aranżacja w stosunku do całej aranżacji. Warto również zrozumieć, gdzie aplikacja ma problem lub gdzie został zgłoszony wyjątek. Ta funkcja jest obsługiwana dla wszystkich języków i dostawców magazynu.
Uwaga
Śledzenie rozproszone w wersji 2 wymaga rozszerzenia Durable Functions w wersji 2.12.0 lub nowszej. Ponadto śledzenie rozproszone w wersji 2 jest w stanie wersji zapoznawczej i dlatego niektóre wzorce durable functions nie są instrumentowane. Na przykład operacje trwałe jednostek nie są instrumentowane i ślady nie będą wyświetlane w usłudze Application Insights.
Konfigurowanie śledzenia rozproszonego
Aby skonfigurować śledzenie rozproszone, zaktualizuj host.json i skonfiguruj zasób usługi Application Insights.
host.json
"durableTask": {
"tracing": {
"distributedTracingEnabled": true,
"Version": "V2"
}
}
Szczegółowe dane dotyczące aplikacji
Jeśli aplikacja funkcji nie jest skonfigurowana przy użyciu zasobu usługi Application Insights, skonfiguruj ją zgodnie z instrukcjami podanymi tutaj.
Sprawdzanie śladów
W zasobie usługi Application Insights przejdź do pozycji Wyszukiwanie transakcji. W wynikach sprawdź, czy zdarzenia Dependency
Request
zaczynają się od prefiksów specyficznych dla rozszerzenia Durable Functions (np. orchestration:
, activity:
itp.). Wybranie jednego z tych zdarzeń spowoduje otwarcie wykresu Gantta, który pokaże koniec do końca rozproszonego śledzenia.
Rozwiązywanie problemów
Jeśli ślady nie są widoczne w usłudze Application Insights, pamiętaj, aby poczekać około pięciu minut po uruchomieniu aplikacji, aby upewnić się, że wszystkie dane są propagowane do zasobu usługi Application Insights.
Debugowanie
Usługa Azure Functions obsługuje bezpośrednio kod funkcji debugowania i ta sama obsługa jest przekazywana do rozszerzenia Durable Functions, niezależnie od tego, czy działa na platformie Azure, czy lokalnie. Istnieje jednak kilka zachowań, które należy wziąć pod uwagę podczas debugowania:
- Powtarzanie: funkcja Orchestrator regularnie powtarza się po odebraniu nowych danych wejściowych. To zachowanie oznacza, że pojedyncze logiczne wykonanie funkcji orkiestratora może spowodować wielokrotne trafienie tego samego punktu przerwania, zwłaszcza jeśli jest ono ustawione na początku kodu funkcji.
- Await: za każdym razem, gdy wystąpi błąd
await
w funkcji orkiestratora, zwraca kontrolę z powrotem do dyspozytora platformy Durable Task Framework. Jeśli napotkano go po raz pierwszyawait
, skojarzone zadanie nigdy nie zostanie wznowione. Ponieważ zadanie nigdy nie jest wznawiane, przechodzenie przez oczekiwanie (F10 w programie Visual Studio) nie jest możliwe. Przechodzenie do kroku działa tylko wtedy, gdy zadanie jest odtwarzane. - Limity czasu obsługi komunikatów: funkcja Durable Functions wewnętrznie używa komunikatów kolejek do wykonywania funkcji orkiestratora, działania i jednostki. W środowisku z wieloma maszynami wirtualnymi włamanie do debugowania przez dłuższy czas może spowodować, że inna maszyna wirtualna odebrała komunikat, co spowoduje zduplikowanie wykonania. To zachowanie istnieje również w przypadku zwykłych funkcji wyzwalacza kolejki, ale ważne jest, aby wskazać w tym kontekście, ponieważ kolejki są szczegółami implementacji.
- Zatrzymywanie i uruchamianie: komunikaty w funkcjach Durable są utrwalane między sesjami debugowania. Jeśli zatrzymasz debugowanie i zakończysz proces hosta lokalnego podczas wykonywania funkcji trwałej, ta funkcja może zostać wykonana ponownie automatycznie w przyszłej sesji debugowania. To zachowanie może być mylące, jeśli nie jest oczekiwane. Użycie nowego centrum zadań lub wyczyszczenie zawartości centrum zadań między sesjami debugowania jest jedną z technik, aby uniknąć tego zachowania.
Napiwek
W przypadku ustawiania punktów przerwania w funkcjach orkiestratora, jeśli chcesz przerwać tylko wykonywanie nieodtwarzania, można ustawić warunkowy punkt przerwania, który przerywa tylko wtedy, gdy wartość "jest odtwarzana" to false
.
Storage
Domyślnie rozszerzenie Durable Functions przechowuje stan w usłudze Azure Storage. To zachowanie oznacza, że można sprawdzić stan aranżacji przy użyciu narzędzi, takich jak Eksplorator usługi Microsoft Azure Storage.
Jest to przydatne do debugowania, ponieważ zobaczysz, w jakim stanie może znajdować się aranżacja. Komunikaty w kolejkach można również zbadać, aby dowiedzieć się, jaka praca jest oczekująca (lub zablokowana w niektórych przypadkach).
Ostrzeżenie
Chociaż jest to wygodne, aby wyświetlić historię wykonywania w magazynie tabel, unikaj podejmowania zależności od tej tabeli. Może się to zmienić w miarę rozwoju rozszerzenia Durable Functions.
Uwaga
Innych dostawców magazynu można skonfigurować zamiast domyślnego dostawcy usługi Azure Storage. W zależności od dostawcy magazynu skonfigurowanego dla aplikacji może być konieczne użycie różnych narzędzi do sprawdzenia stanu bazowego. Aby uzyskać więcej informacji, zobacz dokumentację dostawców magazynu durable functions.
Durable Functions Monitor
Durable Functions Monitor to graficzne narzędzie do monitorowania, zarządzania i debugowania wystąpień jednostek oraz zarządzania nimi. Jest ona dostępna jako rozszerzenie programu Visual Studio Code lub autonomiczna aplikacja. Informacje o konfigurowaniu i liście funkcji można znaleźć w tej witrynie typu wiki.
Przewodnik rozwiązywania problemów z usługą Durable Functions
Aby rozwiązać typowe objawy problemu, takie jak blokowanie aranżacji, brak uruchamiania, powolne działanie itp., zapoznaj się z tym przewodnikiem rozwiązywania problemów.