Diagnozowanie i rozwiązywanie problemów w usłudze Durable Functions

Durable Functions udostępnia kilka narzędzi diagnostycznych do rozwiązywania problemów z orkiestracjami. W tym artykule opisano sposób konfigurowania śledzenia i rejestrowania, pisania kodu bezpiecznego do odtwarzania, inspekcji rozproszonych śladów i debugowania lokalnego.

W tym artykule dowiesz się, jak:

Konfigurowanie śledzenia usługi Application Insights

Application Insights jest zalecanym sposobem monitorowania Durable Functions. Rozszerzenie Durable emituje zdarzenia śledzenia, które umożliwiają prześledzenie całościowego wykonania orkiestracji. Możesz znaleźć i wykonać zapytania dotyczące tych zdarzeń śledzenia przy użyciu narzędzia Application Insights Analytics w portalu Azure.

Konfiguracja na poziomie dziennika

Skonfiguruj szczegółowość danych śledzenia emitowanych do usługi Application Insights w pliku host.json :

{
    "logging": {
        "logLevel": {
            "Host.Triggers.DurableTask": "Information",
        },
    }
}

Domyślnie wszystkie zdarzenia śledzenia bez powtarzania są emitowane. Ilość danych można zmniejszyć, ustawiając wartość Host.Triggers.DurableTask na "Warning" lub "Error", co oznacza, że zdarzenia śledzenia są emitowane tylko w wyjątkowych sytuacjach. Aby włączyć emitowanie szczegółowych zdarzeń odtwarzania orkiestracji, ustaw wartość logReplayEvents na true w pliku konfiguracyjnym host.json.

Uwaga / Notatka

Domyślnie środowisko uruchomieniowe usługi Azure Functions próbkuje dane telemetryczne usługi Application Insights, aby uniknąć zbyt częstego emitowania danych. Próbkowanie może spowodować utratę informacji śledzenia w przypadku wystąpienia wielu zdarzeń cyklu życia w krótkim czasie. W artykule Azure Functions Monitoring wyjaśniono, jak skonfigurować to zachowanie.

Rejestrowanie danych wejściowych i wyjściowych

Domyślnie orkiestrator, działanie i dane wejściowe i dane wyjściowe funkcji jednostki nie są rejestrowane. Jest to 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 rejestrowana jest liczba bajtów dla danych wejściowych i wyjściowych funkcji. Jeśli chcesz, aby rozszerzenie Durable Functions rejestrowało pełne ładunki wejściowe i wyjściowe, ustaw właściwość traceInputsAndOutputs na true w pliku konfiguracji host.json.

Instancje orkiestracji

Użyj następujących zapytań Kusto w Application Insights Analytics, aby zbadać wystąpienia orkiestracji.

Zapytanie o pojedyncze wystąpienie

Poniższe zapytanie przedstawia historyczne dane śledzenia dla pojedynczego wystąpienia orkiestracji funkcji Hello Sequence . Filtruje odtwarzanie wykonywania, aby pokazać tylko logiczna ścieżka wykonywania. Zdarzenia można porządkować według timestamp i 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ń monitorowania, które pokazują ścieżkę wykonywania orkiestracji, w tym wszystkie funkcje aktywności uporządkowane według czasu wykonywania w kolejności rosnącej.

Zrzut ekranu usługi Application Insights przedstawiający wyniki zapytania uporządkowanego w jednym wystąpieniu z zdarzeniami śledzenia.

Zapytanie o podsumowanie instancji

Poniższe zapytanie wyświetla stan wszystkich instancji orkiestracji, które zostały uruchomione w określonym przedziale czasowym.

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.

Zrzut ekranu usługi Application Insights przedstawiający wyniki zapytania podsumowania pojedynczego wystąpienia z identyfikatorami wystąpień i stanem.

Dokumentacja danych śledzenia

Każde wystąpienie orkiestracji generuje zdarzenia śledzenia w miarę postępu cyklu życia. Każde zdarzenie cyklu życia zawiera ładunek customDimensions z kilkoma polami. Nazwy pól są poprzedzane ciągiem prop__.

Nazwa pola Opis
hubName Nazwa centrum zadań, w którym są wykonywane orkiestracje.
appName Nazwa aplikacji funkcji. To pole jest przydatne, gdy masz wiele aplikacji funkcji, które współdzielą to samo wystąpienie usługi Application Insights.
slotName Slot wdrożeniowy, w którym bieżąca aplikacja funkcji jest uruchomiona. To pole jest przydatne, gdy używasz miejsc wdrożeniowych do wersjonowania swoich orkiestracji.
functionName Nazwa funkcji orkiestratora lub funkcji aktywności.
functionType Typ funkcji, taki jak Orchestrator lub Activity.
instanceId Unikatowy identyfikator wystąpienia orkiestracji.
state Stan działania procesu cyklu życia wystąpienia.
state.Scheduled Funkcja została zaplanowana na wykonanie, ale jeszcze nie została uruchomiona.
state.Started Funkcja została uruchomiona, ale jeszcze nie oczekiwano na jej wykonanie ani nie została ukończona.
state.Awaited Orkiestrator zaplanował pewną pracę i czeka na jego zakończenie.
state.Listening Orkiestrator nasłuchuje powiadomienia o zdarzeniach zewnętrznych.
state.Completed Funkcja została pomyślnie ukończona.
state.Failed Funkcja nie powiodła się z powodu błędu.
reason 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 powiedzie się, to pole 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 instancje mogą zgłaszać wiele wersji, jeśli aktualizacja zostanie przeprowadzona podczas działania instancji.
sequenceNumber Numer sekwencji wykonywania zdarzenia. W połączeniu ze znacznikiem czasu pomaga to uporządkować zdarzenia według czasu wykonania. Należy pamiętać, że ta liczba jest resetowana do zera, jeśli host zostanie ponownie uruchomiony w trakcie działania instancji, dlatego ważne jest, aby zawsze sortować najpierw według znacznika czasu, a dopiero potem według sequenceNumber.

Trwałe rejestrowanie struktury zadań (DTFx)

Dzienniki rozszerzenia Durable są przydatne do zrozumienia zachowania logiki orchestracji. 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 ma dwa składniki: podstawowy silnik dyspozytora (DurableTask.Core) i jeden z wielu obsługiwanych dostawców magazynu.

Składnik Opis
DurableTask.Core Podstawowe wykonywanie orkiestracji i dzienniki planowania niskiego poziomu oraz dane telemetryczne.
DurableTask.DurableTaskScheduler Dzienniki zaplecza specyficzne dla harmonogramu zadań trwałych.
DurableTask.AzureStorage Dzienniki zaplecza specyficzne dla dostawcy stanu 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 orkiestracji.
DurableTask.Netherite Jeśli włączono dzienniki zaplecza specyficzne dla dostawcy magazynu Netherite.
DurableTask.SqlServer Dzienniki zaplecza specyficzne dla dostawcy magazynu Microsoft SQL (MSSQL), jeśli 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 ostrzeżeń i błędów z obu DurableTask.Core 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 są automatycznie dodawane do trace kolekcji. Możesz wyszukiwać je w taki sam sposób, jak w przypadku wyszukiwania innych trace dzienników przy użyciu zapytań Kusto.

Uwaga / Notatka

W przypadku aplikacji produkcyjnych zalecamy włączenie logów DurableTask.Core i odpowiedniego dostawcy pamięci masowej (na przykład DurableTask.AzureStorage) za pomocą filtru "Warning". Wyższe filtry szczegółowości, takie jak "Information" , są 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", ponieważ filtruje wyniki do dzienników w kategoriach DurableTask.Core 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.

Zrzut ekranu usługi Application Insights przedstawiający wyniki zapytania DTFx z dziennikami 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.

Śledzenie rozproszone

Śledzenie rozproszone śledzi żądania i pokazuje, jak różne usługi współdziałają ze sobą. W Durable Functions koreluje ze sobą aranżacje, jednostki i działania. Śledzenie rozproszone pokazuje czas wykonywania dla każdego kroku aranżacji względem całej aranżacji i określa, gdzie występują problemy lub wyjątki. Ta funkcja jest obsługiwana w usłudze Application Insights dla wszystkich języków i dostawców usług magazynowania.

Wymagania wstępne

Śledzenie rozproszone wymaga określonych minimalnych wersji rozszerzeń:

Konfigurowanie śledzenia rozproszonego

Aby skonfigurować śledzenie rozproszone, zaktualizuj host.json i skonfiguruj zasób usługi Application Insights.

host.json

{
   "extensions": {
     "durableTask": {
       "tracing": {
         "distributedTracingEnabled": true,
         "version": "V2"
       }
     }
   }
 }

Application Insights

Skonfiguruj aplikację funkcji przy użyciu zasobu usługi Application Insights.

Sprawdzanie śladów

W zasobie usługi Application Insights przejdź do pozycji Wyszukiwanie transakcji. W wynikach poszukaj zdarzeń Request i Dependency, które zaczynają się od prefiksów specyficznych dla Durable (na przykład orchestration:, activity: itp.). Wybranie jednego z tych zdarzeń powoduje otwarcie wykresu Gantta, który pokazuje kompleksowe rozproszone śledzenie. Wykres przedstawia każdy krok aranżacji jako poziomy pasek z wywołaniami działania i podaranżacji zagnieżdżonych w ramach orkiestracji nadrzędnej. Długość paska reprezentuje czas rzeczywisty każdego etapu, co ułatwia wykrycie wąskich gardeł lub nieoczekiwanie powolnych aktywości.

Zrzut ekranu wykresu Gantta przedstawiający rozproszony ślad w Application Insights z osiami czasu orkiestracji i aktywności.

Uwaga / Notatka

Nie widzisz śladów w usłudze Application Insights? Poczekaj około pięciu minut po uruchomieniu aplikacji, aby upewnić się, że wszystkie dane są propagowane do zasobu usługi Application Insights.

Bezpieczne logowanie przed powtórzeniami w funkcjach orkiestratora

Funkcje programu Orchestrator powtarzają się za każdym razem, gdy odbierane są nowe dane wejściowe, co oznacza, że każda instrukcja dziennika w orkiestratorze jest uruchamiana wiele razy w przypadku pojedynczego wykonania logicznego. Na przykład funkcja z trzema wywołaniami aktywności tworzy log, który podczas odtwarzania wygląda następująco:

Calling F1.
Calling F1.
Calling F2.
Calling F1.
Calling F2.
Calling F3.
Calling F1.
Calling F2.
Calling F3.
Done!

Aby zapobiec zduplikowaniu wierszy dziennika, należy sprawdzić flagę „czy trwa odtwarzanie”, aby dzienniki były wykonywane tylko podczas pierwszego (nieodtwarzanego) przetwarzania. W poniższych przykładach pokazano bezpieczne przed powtórnym odtworzeniem logowanie w każdym języku.

Począwszy od Durable Functions 2.0, użyj CreateReplaySafeLogger, aby automatycznie odfiltrować wpisy dziennika podczas odtwarzania.

[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!");
}

W przypadku logowania bezpiecznego dla odtwarzania wyjście dziennika to:

Calling F1.
Calling F2.
Calling F3.
Done!

Niestandardowy stan orkiestracji

Użyj niestandardowego statusu orkiestracji, aby raportować postęp przepływu pracy zewnętrznym klientom. Typowe wzorce obejmują wartości procentowe ukończenia, opisy kroków i podsumowania błędów. Klienci zewnętrzni mogą wyświetlać niestandardowy stan za pośrednictwem interfejsu API zapytań o stan HTTP lub wywołań API specyficznych dla danego języka.

Poniższy kod pokazuje, jak ustawić niestandardową wartość 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 / Notatka

Poprzedni przykład języka C# dotyczy Durable Functions 2.x. W przypadku Durable Functions 1.x należy użyć DurableOrchestrationContext zamiast IDurableOrchestrationContext. Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł Wersje Durable Functions.

Gdy orkiestracja działa, klienci zewnętrzni mogą uzyskać dostęp do tego niestandardowego statusu.

GET /runtime/webhooks/durabletask/instances/instance123?code=XYZ

Klienci otrzymują 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 mieścić się w kolumnie Azure Table Storage. Jeśli potrzebujesz większego ładunku, możesz użyć magazynu zewnętrznego.

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. Użyj następującego przepływu pracy, aby uzyskać najlepsze środowisko debugowania:

  1. Rozpocznij nową sesję debugowania przy użyciu nowego centrum zadań lub wyczyść zawartość centrum zadań między sesjami. Pozostawione komunikaty z poprzednich przebiegów mogą powodować nieoczekiwane ponowne uruchomienie procesu.

  2. Ustaw punkty przerwania w funkcjach orkiestratora lub działania. W przypadku funkcji orkiestratora należy użyć warunkowego punktu przerwania, które przerywa tylko wtedy, gdy wartość "jest powtarzany" jest false, aby uniknąć wielokrotnego trafienia tego samego punktu przerwania podczas ponownego odtwarzania.

  3. Wykonaj kroki kodu w zwykły sposób. Należy pamiętać o następujących zachowaniach:

    • Replay:
      Funkcje Orchestratora regularnie odtwarzają się po odebraniu nowych danych wejściowych. 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 element await występuje w funkcji orkiestratora, oddaje kontrolę z powrotem do dyspozytora Durable Task Framework. Jeśli jest to pierwszy raz, gdy zostanie napotkana określona wartość await , skojarzone zadanie nigdy nie zostanie wznowione. Ponieważ zadanie nigdy nie jest wznawiane, nie można przejść przez funkcję await (za pomocą F10 w Visual Studio). Przechodzenie do kroku działa tylko wtedy, gdy zadanie jest odtwarzane.

    • Limity czasu obsługi komunikatów:
      Funkcje Durable Functions wewnętrznie używają wiadomości w kolejce do napędzania wykonywania funkcji orkiestratora, aktywności i jednostki. W środowisku z wieloma maszynami wirtualnymi rozszerzone sesje debugowania mogą spowodować przetworzenie komunikatu przez inną maszynę wirtualną, co spowoduje zduplikowanie wykonania. Chociaż to zachowanie występuje również w przypadku standardowych funkcji wyzwalacza kolejki, ten kontekst jest ważny do podkreślenia, ponieważ kolejki są szczegółami implementacji.

    • Zatrzymywanie i uruchamianie:
      Komunikaty w usłudze Durable Functions 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ć ponownie wykonana automatycznie w przyszłej sesji debugowania.

Dodatkowe narzędzia

Sprawdzanie stanu magazynu

Domyślnie Durable Functions przechowuje stan w Azure Storage. Stan orkiestracji i komunikaty można sprawdzić przy użyciu narzędzi, takich jak Eksplorator usługi Microsoft Azure Storage.

Zrzut ekranu w Azure Storage Explorer pokazujący

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 / Notatka

Możesz konfigurować innych dostawców magazynu zamiast domyślnego dostawcy 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.

Monitor funkcji Durable

Durable Functions Monitor to graficzne narzędzie do monitorowania, zarządzania i debugowania wystąpień orkiestracji i jednostek. Jest ona dostępna jako rozszerzenie Visual Studio Code lub autonomiczna aplikacja. Aby uzyskać instrukcje dotyczące konfiguracji i listę funkcji, zobacz Durable Functions Monitor Wiki.

Diagnostyka portalu Azure

Portal Azure udostępnia wbudowane narzędzia diagnostyczne dla aplikacji funkcyjnych.

Diagnozowanie i rozwiązywanie problemów: Diagnostyka aplikacji funkcji platformy Azure to przydatny zasób do monitorowania i diagnozowania potencjalnych problemów w aplikacji. Zawiera również sugestie ułatwiające rozwiązywanie problemów na podstawie diagnozy. Aby uzyskać więcej informacji, zobacz Diagnostyka aplikacji funkcji Azure.

Ślady orkiestracji: Portal Azure zapewnia szczegóły śladów orkiestracji, które ułatwiają zrozumienie stanu każdego wystąpienia orkiestracji i śledzenie wykonania od początku do końca. Podczas wyświetlania listy funkcji w aplikacji Azure Functions zostanie wyświetlona kolumna Monitor zawierająca linki do śladów. Aby uzyskać dostęp do tych informacji, musisz mieć włączoną usługę Application Insights.

Analizator Roslyn

Analizator Roslyn dla Durable Functions to analizator kodu w czasie rzeczywistym, który pomaga programistom C# przestrzegać specyficznych ograniczeń kodu dla Durable Functions. Aby uzyskać instrukcje dotyczące włączania jej w Visual Studio i Visual Studio Code, zobacz Durable Functions Roslyn Analyzer.

Troubleshooting

Aby rozwiązywać typowe problemy, takie jak blokowanie się orkiestracji, nieuruchamianie się lub powolne działanie, zobacz przewodnik rozwiązywania problemów z Durable Functions.

Następne kroki