Orchestrace Durable Function jsou implementovány v kódu a mohou používat integrované funkce zpracování chyb programovacího jazyka. Ve skutečnosti nejsou k dispozici žádné nové koncepty, které byste se měli naučit přidávat do orchestrací zpracování chyb a kompenzaci. Existuje však několik chování, o které byste měli vědět.
Poznámka:
Verze 4 programovacího modelu Node.js pro Azure Functions je obecně dostupná. Nový model v4 je navržený tak, aby měl flexibilnější a intuitivnější prostředí pro vývojáře v JavaScriptu a TypeScriptu. Další informace o rozdílech mezi v3 a v4 najdete v průvodci migrací.
V následujících fragmentech kódu JavaScript (PM4) označuje programovací model V4, nové prostředí.
Chyby ve funkcích aktivit a dílčích orchestracích
V Durable Functions jsou neošetřené výjimky vyvolané v rámci funkcí aktivit nebo dílčí orchestrace zařazovány zpět do funkce orchestrátoru pomocí standardizovaných typů výjimek.
Představte si například následující funkci orchestrátoru, která provádí převod fondu mezi dvěma účty:
V jazyce C# v procesu Durable Functions jsou neošetřené výjimky vyvolány jako functionFailedException.
Zpráva o výjimce obvykle identifikuje, které funkce aktivit nebo dílčí orchestrace způsobily selhání. Pokud chcete získat přístup k podrobnějším informacím o chybách, zkontrolujte InnerException vlastnost.
[FunctionName("TransferFunds")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var transferDetails = context.GetInput<TransferOperation>();
await context.CallActivityAsync("DebitAccount",
new
{
Account = transferDetails.SourceAccount,
Amount = transferDetails.Amount
});
try
{
await context.CallActivityAsync("CreditAccount",
new
{
Account = transferDetails.DestinationAccount,
Amount = transferDetails.Amount
});
}
catch (FunctionFailedException)
{
// Refund the source account.
// Another try/catch could be used here based on the needs of the application.
await context.CallActivityAsync("CreditAccount",
new
{
Account = transferDetails.SourceAccount,
Amount = transferDetails.Amount
});
}
}
Poznámka:
Předchozí příklady jazyka C# jsou pro Durable Functions 2.x. Pro Durable Functions 1.x je nutné použít DurableOrchestrationContext místo IDurableOrchestrationContext. Další informace o rozdílech mezi verzemi najdete v článku o verzích Durable Functions.
V izolovaném prostředí Durable Functions C# se neošetřené výjimky zobrazují jako TaskFailedException.
Zpráva o výjimce obvykle identifikuje, které funkce aktivit nebo dílčí orchestrace způsobily selhání. Pokud chcete získat přístup k podrobnějším informacím o chybě, zkontrolujte vlastnost FailureDetails .
[FunctionName("TransferFunds")]
public static async Task Run(
[OrchestrationTrigger] TaskOrchestrationContext context, TransferOperation transferDetails)
{
await context.CallActivityAsync("DebitAccount",
new
{
Account = transferDetails.SourceAccount,
Amount = transferDetails.Amount
});
try
{
await context.CallActivityAsync("CreditAccount",
new
{
Account = transferDetails.DestinationAccount,
Amount = transferDetails.Amount
});
}
catch (TaskFailedException)
{
// Refund the source account.
// Another try/catch could be used here based on the needs of the application.
await context.CallActivityAsync("CreditAccount",
new
{
Account = transferDetails.SourceAccount,
Amount = transferDetails.Amount
});
}
}
Poznámka:
- Zpráva o výjimce obvykle identifikuje, které funkce aktivit nebo dílčí orchestrace způsobily selhání. Pokud chcete získat přístup k podrobnějším informacím o chybách, zkontrolujte
FailureDetails vlastnost.
- Ve výchozím nastavení
FailureDetails zahrnuje typ chyby, chybovou zprávu, sledování zásobníku a všechny vnořené vnitřní výjimky (každý reprezentovaný jako rekurzivní FailureDetails objekt). Pokud chcete do výstupu selhání zahrnout další vlastnosti výjimky, přečtěte si téma Zahrnout vlastní vlastnosti výjimky pro FailureDetails (.NET Isolated).
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
const transferDetails = context.df.getInput();
yield context.df.callActivity("DebitAccount", {
account: transferDetails.sourceAccount,
amount: transferDetails.amount,
});
try {
yield context.df.callActivity("CreditAccount", {
account: transferDetails.destinationAccount,
amount: transferDetails.amount,
});
} catch (error) {
// Refund the source account.
// Another try/catch could be used here based on the needs of the application.
yield context.df.callActivity("CreditAccount", {
account: transferDetails.sourceAccount,
amount: transferDetails.amount,
});
}
})
const df = require("durable-functions");
df.app.orchestration("transferFunds", function* (context) {
const transferDetails = context.df.getInput();
yield context.df.callActivity("debitAccount", {
account: transferDetails.sourceAccount,
amount: transferDetails.amount,
});
try {
yield context.df.callActivity("creditAccount", {
account: transferDetails.destinationAccount,
amount: transferDetails.amount,
});
} catch (error) {
// Refund the source account.
// Another try/catch could be used here based on the needs of the application.
yield context.df.callActivity("creditAccount", {
account: transferDetails.sourceAccount,
amount: transferDetails.amount,
});
}
});
import azure.functions as func
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
transfer_details = context.get_input()
yield context.call_activity('DebitAccount', {
'account': transfer_details['sourceAccount'],
'amount' : transfer_details['amount']
})
try:
yield context.call_activity('CreditAccount', {
'account': transfer_details['destinationAccount'],
'amount': transfer_details['amount'],
})
except:
yield context.call_activity('CreditAccount', {
'account': transfer_details['sourceAccount'],
'amount': transfer_details['amount']
})
main = df.Orchestrator.create(orchestrator_function)
Rutiny v PowerShellu ve výchozím nastavení nevyvolají výjimky, které je možné zachytit pomocí bloků try/catch. Toto chování můžete změnit dvěma způsoby:
-
-ErrorAction Stop Příznak použijte při vyvolání rutin, například Invoke-DurableActivity.
- Před vyvoláním rutin nastavte proměnnou
$ErrorActionPreference předvoleb na "Stop" funkci orchestrátoru.
param($Context)
$ErrorActionPreference = "Stop"
$transferDetails = $Context.Input
Invoke-DurableActivity -FunctionName 'DebitAccount' -Input @{ account = transferDetails.sourceAccount; amount = transferDetails.amount }
try {
Invoke-DurableActivity -FunctionName 'CreditAccount' -Input @{ account = transferDetails.destinationAccount; amount = transferDetails.amount }
} catch {
Invoke-DurableActivity -FunctionName 'CreditAccount' -Input @{ account = transferDetails.sourceAccount; amount = transferDetails.amount }
}
Další informace o zpracování chyb v PowerShellu najdete v dokumentaci k PowerShellu Try-Catch-Finally .
@FunctionName("TransferFunds")
public void transferFunds(
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
TransferOperation transfer = ctx.getInput(TransferOperation.class);
ctx.callActivity(
"DebitAccount",
new OperationArgs(transfer.sourceAccount, transfer.amount)).await();
try {
ctx.callActivity(
"CreditAccount",
new OperationArgs(transfer.destinationAccount, transfer.amount)).await();
} catch (TaskFailedException ex) {
// Refund the source account on failure
ctx.callActivity(
"CreditAccount",
new OperationArgs(transfer.sourceAccount, transfer.amount)).await();
}
}
Pokud první volání funkce CreditAccount selže, funkce orchestrátoru vyrovnává kredity zpět do zdrojového účtu.
Chyby ve funkcích entit
Chování výjimečného zpracování u funkcí entit se liší podle modelu hostování Durable Functions.
V Durable Functions využívajících režim v procesu jazyka C# jsou původní typy výjimek vyvolané funkcemi entit předávány přímo orchestrátoru.
[FunctionName("Function1")]
public static async Task<string> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
try
{
var entityId = new EntityId(nameof(Counter), "myCounter");
await context.CallEntityAsync(entityId, "Add", 1);
}
catch (Exception ex)
{
// The exception type will be InvalidOperationException with the message "this is an entity exception".
}
return string.Empty;
}
[FunctionName("Counter")]
public static void Counter([EntityTrigger] IDurableEntityContext ctx)
{
switch (ctx.OperationName.ToLowerInvariant())
{
case "add":
throw new InvalidOperationException("this is an entity exception");
case "get":
ctx.Return(ctx.GetState<int>());
break;
}
}
V izolovaném prostředí Durable Functions C# se výjimky zobrazují orchestrátoru jako EntityOperationFailedException. Pokud chcete získat přístup k podrobnostem o původní výjimce, zkontrolujte jeho FailureDetails vlastnost.
[Function(nameof(MyOrchestrator))]
public static async Task<List<string>> MyOrchestrator(
[Microsoft.Azure.Functions.Worker.OrchestrationTrigger] TaskOrchestrationContext context)
{
var entityId = new Microsoft.DurableTask.Entities.EntityInstanceId(nameof(Counter), "myCounter");
try
{
await context.Entities.CallEntityAsync(entityId, "Add", 1);
}
catch (EntityOperationFailedException ex)
{
// Add your error handling
}
return new List<string>();
}
df.app.orchestration("counterOrchestration", function* (context) {
const entityId = new df.EntityId(counterEntityName, "myCounter");
try {
const currentValue = yield context.df.callEntity(entityId, "get");
if (currentValue < 10) {
yield context.df.callEntity(entityId, "add", 1);
}
} catch (err) {
context.log(`Entity call failed: ${err.message ?? err}`);
}
});
df.app.orchestration("counterOrchestration", function* (context) {
const entityId = new df.EntityId(counterEntityName, "myCounter");
try {
const currentValue = yield context.df.callEntity(entityId, "get");
if (currentValue < 10) {
yield context.df.callEntity(entityId, "add", 1);
}
} catch (err) {
context.log(`Entity call failed: ${err.message ?? err}`);
}
});
@myApp.orchestration_trigger(context_name="context")
def run_orchestrator(context):
try:
entityId = df.EntityId("Counter", "myCounter")
yield context.call_entity(entityId, "get")
return "finished"
except Exception as e:
# Add your error handling
Funkce entit se v PowerShellu v současné době nepodporují.
Funkce entit nejsou v současné době v Javě podporované.
Automatické opakování při selhání
Při volání funkcí aktivity nebo dílčí orchestrace můžete zadat zásady automatického opakování. Následující příklad se pokusí volat funkci až třikrát a mezi jednotlivými opakováními počká 5 sekund:
[FunctionName("TimerOrchestratorWithRetry")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: 3);
await context.CallActivityWithRetryAsync("FlakyFunction", retryOptions, null);
// ...
}
Poznámka:
Předchozí příklady jazyka C# jsou pro Durable Functions 2.x. Pro Durable Functions 1.x je nutné použít DurableOrchestrationContext místo IDurableOrchestrationContext. Další informace o rozdílech mezi verzemi najdete v článku o verzích Durable Functions.
[FunctionName("TimerOrchestratorWithRetry")]
public static async Task Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
var options = TaskOptions.FromRetryPolicy(new RetryPolicy(
maxNumberOfAttempts: 3,
firstRetryInterval: TimeSpan.FromSeconds(5)));
await context.CallActivityAsync("FlakyFunction", options: options);
// ...
}
const df = require("durable-functions");
module.exports = df.orchestrator(function*(context) {
const firstRetryIntervalInMilliseconds = 5000;
const maxNumberOfAttempts = 3;
const retryOptions =
new df.RetryOptions(firstRetryIntervalInMilliseconds, maxNumberOfAttempts);
yield context.df.callActivityWithRetry("FlakyFunction", retryOptions);
// ...
});
const df = require("durable-functions");
df.app.orchestration("callActivityWithRetry", function* (context) {
const firstRetryIntervalInMilliseconds = 5000;
const maxNumberOfAttempts = 3;
const retryOptions = new df.RetryOptions(firstRetryIntervalInMilliseconds, maxNumberOfAttempts);
yield context.df.callActivityWithRetry("flakyFunction", retryOptions);
// ...
});
import azure.functions as func
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
first_retry_interval_in_milliseconds = 5000
max_number_of_attempts = 3
retry_options = df.RetryOptions(first_retry_interval_in_milliseconds, max_number_of_attempts)
yield context.call_activity_with_retry('FlakyFunction', retry_options)
main = df.Orchestrator.create(orchestrator_function)
param($Context)
$retryOptions = New-DurableRetryOptions `
-FirstRetryInterval (New-TimeSpan -Seconds 5) `
-MaxNumberOfAttempts 3
Invoke-DurableActivity -FunctionName 'FlakyFunction' -RetryOptions $retryOptions
@FunctionName("TimerOrchestratorWithRetry")
public void timerOrchestratorWithRetry(
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
final int maxAttempts = 3;
final Duration firstRetryInterval = Duration.ofSeconds(5);
RetryPolicy policy = new RetryPolicy(maxAttempts, firstRetryInterval);
TaskOptions options = new TaskOptions(policy);
ctx.callActivity("FlakeyFunction", options).await();
// ...
}
Volání funkce aktivity v předchozím příkladu přebírá parametr pro konfiguraci zásady automatického opakování. Pro přizpůsobení zásad automatického opakování existuje několik možností:
-
Maximální počet pokusů: Maximální počet pokusů. Pokud je nastavená hodnota 1, nebude se opakovat.
-
První interval opakování: Doba čekání před prvním pokusem o opakování.
-
Koeficient zpětného odsud: Koeficient použitý k určení míry zvýšení zásady. Výchozí hodnota je 1.
-
Maximální interval opakování: Maximální doba čekání mezi opakovanými pokusy.
-
Časový limit opakování: Maximální doba strávená opakováním. Výchozí chování je opakovat po neomezenou dobu.
Vlastní obslužné rutiny opakování
Při použití .NET nebo Javy máte také možnost implementovat obslužné rutiny opakování v kódu. To je užitečné v případě, že zásady deklarativních opakování nejsou dostatečně výrazné. U jazyků, které nepodporují vlastní obslužné rutiny opakování, máte stále možnost implementovat zásady opakování pomocí smyček, zpracování výjimek a časovačů pro vkládání zpoždění mezi opakováními.
RetryOptions retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: int.MaxValue)
{
Handle = exception =>
{
// True to handle and try again, false to not handle and throw.
if (exception is TaskFailedException failure)
{
// Exceptions from TaskActivities are always this type. Inspect the
// inner Exception to get more details.
}
return false;
};
}
await ctx.CallActivityWithRetryAsync("FlakeyActivity", retryOptions, null);
TaskOptions retryOptions = TaskOptions.FromRetryHandler(retryContext =>
{
// Don't retry anything that derives from ApplicationException
if (retryContext.LastFailure.IsCausedBy<ApplicationException>())
{
return false;
}
// Quit after N attempts
return retryContext.LastAttemptNumber < 3;
});
try
{
await ctx.CallActivityAsync("FlakeyActivity", options: retryOptions);
}
catch (TaskFailedException)
{
// Case when the retry handler returns false...
}
JavaScript v současné době nepodporuje vlastní obslužné rutiny opakování. Stále ale máte možnost implementovat logiku opakování přímo do funkce orchestrátoru pomocí smyček, zpracování výjimek a časovačů pro vkládání zpoždění mezi opakováními.
JavaScript v současné době nepodporuje vlastní obslužné rutiny opakování. Stále ale máte možnost implementovat logiku opakování přímo do funkce orchestrátoru pomocí smyček, zpracování výjimek a časovačů pro vkládání zpoždění mezi opakováními.
Python v současné době nepodporuje vlastní obslužné rutiny opakování. Stále ale máte možnost implementovat logiku opakování přímo do funkce orchestrátoru pomocí smyček, zpracování výjimek a časovačů pro vkládání zpoždění mezi opakováními.
PowerShell v současné době nepodporuje vlastní obslužné rutiny opakování. Stále ale máte možnost implementovat logiku opakování přímo do funkce orchestrátoru pomocí smyček, zpracování výjimek a časovačů pro vkládání zpoždění mezi opakováními.
RetryHandler retryHandler = retryCtx -> {
// Don't retry anything that derives from RuntimeException
if (retryCtx.getLastFailure().isCausedBy(RuntimeException.class)) {
return false;
}
// Quit after N attempts
return retryCtx.getLastAttemptNumber() < 3;
};
TaskOptions options = new TaskOptions(retryHandler);
try {
ctx.callActivity("FlakeyActivity", options).await();
} catch (TaskFailedException ex) {
// Case when the retry handler returns false...
}
Časové limity funkcí
Volání funkce v rámci funkce orchestrátoru můžete chtít opustit, pokud dokončení trvá příliš dlouho. Správným způsobem, jak to udělat dnes, je vytvoření trvalého časovače s "libovolným" selektorem úkolů, jak je znázorněno v následujícím příkladu:
[FunctionName("TimerOrchestrator")]
public static async Task<bool> Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
TimeSpan timeout = TimeSpan.FromSeconds(30);
DateTime deadline = context.CurrentUtcDateTime.Add(timeout);
using (var cts = new CancellationTokenSource())
{
Task activityTask = context.CallActivityAsync("FlakyFunction");
Task timeoutTask = context.CreateTimer(deadline, cts.Token);
Task winner = await Task.WhenAny(activityTask, timeoutTask);
if (winner == activityTask)
{
// success case
cts.Cancel();
return true;
}
else
{
// timeout case
return false;
}
}
}
Poznámka:
Předchozí příklady jazyka C# jsou pro Durable Functions 2.x. Pro Durable Functions 1.x je nutné použít DurableOrchestrationContext místo IDurableOrchestrationContext. Další informace o rozdílech mezi verzemi najdete v článku o verzích Durable Functions.
[Function("TimerOrchestrator")]
public static async Task<bool> Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
TimeSpan timeout = TimeSpan.FromSeconds(30);
DateTime deadline = context.CurrentUtcDateTime.Add(timeout);
using (var cts = new CancellationTokenSource())
{
Task activityTask = context.CallActivityAsync("FlakyFunction");
Task timeoutTask = context.CreateTimer(deadline, cts.Token);
Task winner = await Task.WhenAny(activityTask, timeoutTask);
if (winner == activityTask)
{
// success case
cts.Cancel();
return true;
}
else
{
// timeout case
return false;
}
}
}
const df = require("durable-functions");
const moment = require("moment");
module.exports = df.orchestrator(function*(context) {
const deadline = moment.utc(context.df.currentUtcDateTime).add(30, "s");
const activityTask = context.df.callActivity("FlakyFunction");
const timeoutTask = context.df.createTimer(deadline.toDate());
const winner = yield context.df.Task.any([activityTask, timeoutTask]);
if (winner === activityTask) {
// success case
timeoutTask.cancel();
return true;
} else {
// timeout case
return false;
}
});
const df = require("durable-functions");
const { DateTime } = require("luxon");
df.app.orchestration("timerOrchestrator", function* (context) {
const deadline = DateTime.fromJSDate(context.df.currentUtcDateTime).plus({ seconds: 30 });
const activityTask = context.df.callActivity("flakyFunction");
const timeoutTask = context.df.createTimer(deadline.toJSDate());
const winner = yield context.df.Task.any([activityTask, timeoutTask]);
if (winner === activityTask) {
// success case
timeoutTask.cancel();
return true;
} else {
// timeout case
return false;
}
});
import azure.functions as func
import azure.durable_functions as df
from datetime import datetime, timedelta
def orchestrator_function(context: df.DurableOrchestrationContext):
deadline = context.current_utc_datetime + timedelta(seconds = 30)
activity_task = context.call_activity('FlakyFunction')
timeout_task = context.create_timer(deadline)
winner = yield context.task_any(activity_task, timeout_task)
if winner == activity_task:
timeout_task.cancel()
return True
else:
return False
main = df.Orchestrator.create(orchestrator_function)
param($Context)
$expiryTime = New-TimeSpan -Seconds 30
$activityTask = Invoke-DurableActivity -FunctionName 'FlakyFunction'-NoWait
$timerTask = Start-DurableTimer -Duration $expiryTime -NoWait
$winner = Wait-DurableTask -Task @($activityTask, $timerTask) -NoWait
if ($winner -eq $activityTask) {
Stop-DurableTimerTask -Task $timerTask
return $True
}
else {
return $False
}
@FunctionName("TimerOrchestrator")
public boolean timerOrchestrator(
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
Task<Void> activityTask = ctx.callActivity("SlowFunction");
Task<Void> timeoutTask = ctx.createTimer(Duration.ofMinutes(30));
Task<?> winner = ctx.anyOf(activityTask, timeoutTask).await();
if (winner == activityTask) {
// success case
return true;
} else {
// timeout case
return false;
}
}
Poznámka:
Tento mechanismus ve skutečnosti neukončí probíhající provádění funkce aktivity. Místo toho jednoduše umožňuje funkci orchestrátoru ignorovat výsledek a pokračovat. Další informace najdete v dokumentaci k časovačům .
Neošetřené výjimky
Pokud funkce orchestrátoru selže s neošetřenou výjimkou, zaprotokolují se podrobnosti o výjimce a instance se dokončí se stavem Failed .
Zahrnout vlastní vlastnosti výjimky pro FailureDetails (izolované rozhraní .NET)
Při spouštění pracovních postupů Durable Task v izolovaném modelu .NET se selhání úkolů automaticky serializují do objektu FailureDetails. Ve výchozím nastavení tento objekt zahrnuje standardní pole, například:
- ErrorType – název typu výjimky
- Zpráva – zpráva o výjimce
- StackTrace – serializované trasování zásobníku
- InnerFailure – vnořený objekt FailureDetails pro rekurzivní vnitřní výjimky
Počínaje Microsoft.Azure.Functions.Worker.Extensions.DurableTask v1.9.0 můžete toto chování rozšířit implementací IExceptionPropertiesProvider (definovaného v Microsoft.DurableTask.Worker, počínaje balíčkem v1.16.1). Tento zprostředkovatel definuje, které typy výjimek a které z jejich vlastností by měly být zahrnuty ve slovníku FailureDetails.Properties.
Poznámka:
- Tato funkce je dostupná pouze v izolovaném prostředí .NET . Podpora pro Javu se přidá v budoucí verzi.
- Ujistěte se, že používáte Microsoft.Azure.Functions.Worker.Extensions.DurableTask verze 1.9.0 nebo novější.
- Ujistěte se, že používáte Microsoft.DurableTask.Worker verze 1.16.1 nebo novější.
Implementace zprostředkovatele vlastností výjimek
Implementujte vlastní IExceptionPropertiesProvider pro extrakci a vrácení vybraných vlastností pro výjimky, které vás zajímají. Vrácený slovník bude serializován do pole Vlastnosti FailureDetails při vyvolání odpovídajícího typu výjimky.
using Microsoft.DurableTask.Worker;
public class CustomExceptionPropertiesProvider : IExceptionPropertiesProvider
{
public IDictionary<string, object?>? GetExceptionProperties(Exception exception)
{
return exception switch
{
ArgumentOutOfRangeException e => new Dictionary<string, object?>
{
["ParamName"] = e.ParamName,
["ActualValue"] = e.ActualValue
},
InvalidOperationException e => new Dictionary<string, object?>
{
["CustomHint"] = "Invalid operation occurred",
["TimestampUtc"] = DateTime.UtcNow
},
_ => null // Other exception types not handled
};
}
}
Registrace poskytovatele
Zaregistrujte vlastního poskytovatele IExceptionPropertiesProvider v hostiteli pracovního procesu .NET Isolated, obvykle v Program.cs:
using Microsoft.DurableTask.Worker;
using Microsoft.Extensions.DependencyInjection;
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(builder =>
{
// Register custom exception properties provider
builder.Services.AddSingleton<IExceptionPropertiesProvider, CustomExceptionPropertiesProvider>();
})
.Build();
host.Run();
Po registraci všechny výjimky, které odpovídají některému z popisovaných typů, budou automaticky zahrnovat nakonfigurované vlastnosti v jeho FailureDetails.
Ukázkový výstup Podrobnosti o selhání
Pokud dojde k výjimce, která odpovídá konfiguraci vašeho poskytovatele, orchestrace obdrží serializovanou strukturu FailureDetails takto:
{
"errorType": "TaskFailedException",
"message": "Activity failed with an exception.",
"stackTrace": "...",
"innerFailure": {
"errorType": "ArgumentOutOfRangeException",
"message": "Specified argument was out of range.",
"properties": {
"ParamName": "count",
"ActualValue": 42
}
}
}
Další kroky