Durable Function-indelingen worden geïmplementeerd in code en kunnen gebruikmaken van de ingebouwde functies voor foutafhandeling van de programmeertaal. Er zijn echt geen nieuwe concepten die u moet leren om foutafhandeling en compensatie toe te voegen aan uw indelingen. Er zijn echter enkele gedragingen waar u rekening mee moet houden.
Notitie
Versie 4 van het Node.js programmeermodel voor Azure Functions is algemeen beschikbaar. Het nieuwe v4-model is ontworpen voor een flexibelere en intuïtievere ervaring voor JavaScript- en TypeScript-ontwikkelaars. Meer informatie over de verschillen tussen v3 en v4 in de migratiehandleiding.
In de volgende codefragmenten geeft JavaScript (PM4) het programmeermodel V4 aan, de nieuwe ervaring.
Fouten in activiteitsfuncties en suborkestraties
In Durable Functions worden niet-verwerkte uitzonderingen die worden gegenereerd binnen activiteitsfuncties of subindelingen teruggezet naar de orchestratorfunctie met behulp van gestandaardiseerde uitzonderingstypen.
Denk bijvoorbeeld aan de volgende orchestratorfunctie waarmee een fondsoverdracht tussen twee accounts wordt uitgevoerd:
In Durable Functions C# in-process worden onverwerkte uitzonderingen weergegeven als FunctionFailedException.
Het uitzonderingsbericht geeft doorgaans aan welke activiteitsfuncties of subindelingen de fout hebben veroorzaakt. Als u meer gedetailleerde foutinformatie wilt bekijken, inspecteert u de InnerException eigenschap.
[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
});
}
}
Notitie
De vorige C#-voorbeelden zijn voor Durable Functions 2.x. Voor Durable Functions 1.x moet u in DurableOrchestrationContext plaats van IDurableOrchestrationContext. Zie het artikel Over Durable Functions-versies voor meer informatie over de verschillen tussen versies.
In Durable Functions C# Isolated worden niet-verwerkte uitzonderingen weergegeven als TaskFailedException.
Het uitzonderingsbericht geeft doorgaans aan welke activiteitsfuncties of subindelingen de fout hebben veroorzaakt. Inspecteer de eigenschap FailureDetails voor meer gedetailleerde informatie over fouten.
[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
});
}
}
Notitie
- Het uitzonderingsbericht geeft doorgaans aan welke activiteitsfuncties of subindelingen de fout hebben veroorzaakt. Als u meer gedetailleerde foutinformatie wilt bekijken, inspecteert u de
FailureDetails eigenschap.
- Standaard bevat
FailureDetails het fouttype, foutbericht, stack trace en geneste binnenuitzonderingen (elk weergegeven als recursief FailureDetails object). Zie Aangepaste uitzonderingseigenschappen opnemen voor FailureDetails (.NET Isolated) als u aanvullende uitzonderingseigenschappen wilt opnemen in de uitvoer van de fout.
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)
Cmdlets in PowerShell genereren standaard geen uitzonderingen die kunnen worden afgevangen met try/catch-blokken. U hebt twee opties voor het wijzigen van dit gedrag:
- Gebruik de vlag bij het
-ErrorAction Stop aanroepen van cmdlets, zoals Invoke-DurableActivity.
- Stel de voorkeursvariabele
$ErrorActionPreference in op "Stop" de orchestrator-functie voordat u cmdlets aanroept.
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 }
}
Zie de PowerShell-documentatie van Try-Catch-Finally voor meer informatie over foutafhandeling in PowerShell.
@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();
}
}
Als de eerste aanroep van de functie CreditAccount mislukt, compenseert de orchestrator-functie door het geld terug te schrijven naar de bronaccount.
Fouten in entiteitsfuncties
Gedrag van uitzonderingsafhandeling voor entiteitsfuncties verschilt op basis van het Durable Functions-hostingmodel:
In Durable Functions waarbij C# wordt gebruikt, worden oorspronkelijke uitzonderingstypen die door entiteitsfuncties worden gegenereerd, rechtstreeks naar de orchestrator geretourneerd.
[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;
}
}
In Durable Functions C# Isolated worden uitzonderingen aan de orchestrator als een EntityOperationFailedException weergegeven. Om toegang te krijgen tot de oorspronkelijke uitzonderingsgegevens, inspecteer de eigenschap FailureDetails.
[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
Entiteitsfuncties worden momenteel niet ondersteund in PowerShell.
Entiteitsfuncties worden momenteel niet ondersteund in Java.
Automatisch opnieuw proberen bij fout
Wanneer u activiteitsfuncties of subindelingsfuncties aanroept, kunt u een beleid voor automatisch opnieuw proberen opgeven. In het volgende voorbeeld wordt geprobeerd een functie tot drie keer aan te roepen en wacht vijf seconden tussen elke nieuwe poging:
[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);
// ...
}
Notitie
De vorige C#-voorbeelden zijn voor Durable Functions 2.x. Voor Durable Functions 1.x moet u in DurableOrchestrationContext plaats van IDurableOrchestrationContext. Zie het artikel Over Durable Functions-versies voor meer informatie over de verschillen tussen versies.
[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();
// ...
}
De aanroep van de activiteitsfunctie in het vorige voorbeeld gebruikt een parameter voor het configureren van een beleid voor automatisch opnieuw proberen. Er zijn verschillende opties voor het aanpassen van het beleid voor automatisch opnieuw proberen:
-
Maximum aantal pogingen: het maximum aantal pogingen. Als deze optie is ingesteld op 1, wordt het niet opnieuw geprobeerd.
-
Eerste interval voor opnieuw proberen: de hoeveelheid tijd die moet worden gewacht voor de eerste nieuwe poging.
-
Uitstelcoëfficiënt: de coëfficiënt die wordt gebruikt voor het bepalen van de snelheid van toename van de uitstel. Standaardwaarde is 1.
-
Maximuminterval voor opnieuw proberen: de maximale hoeveelheid tijd die moet worden gewacht tussen nieuwe pogingen.
-
Time-out voor opnieuw proberen: de maximale hoeveelheid tijd die moet worden besteed aan nieuwe pogingen. Het standaardgedrag is om het voor onbepaalde tijd opnieuw te proberen.
Aangepaste handlers voor opnieuw proberen
Wanneer u .NET of Java gebruikt, hebt u ook de mogelijkheid om handlers voor opnieuw proberen in code te implementeren. Dit is handig wanneer beleid voor declaratieve nieuwe pogingen niet expressief genoeg is. Voor talen die geen aangepaste handlers voor nieuwe pogingen ondersteunen, hebt u nog steeds de mogelijkheid om beleid voor opnieuw proberen te implementeren met behulp van lussen, afhandeling van uitzonderingen en timers voor het injecteren van vertragingen tussen nieuwe pogingen.
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 biedt momenteel geen ondersteuning voor aangepaste handlers voor opnieuw proberen. U hebt echter nog steeds de mogelijkheid om logica voor opnieuw proberen rechtstreeks in de orchestratorfunctie te implementeren met behulp van lussen, uitzonderingsafhandeling en timers voor het injecteren van vertragingen tussen nieuwe pogingen.
JavaScript biedt momenteel geen ondersteuning voor aangepaste handlers voor opnieuw proberen. U hebt echter nog steeds de mogelijkheid om logica voor opnieuw proberen rechtstreeks in de orchestratorfunctie te implementeren met behulp van lussen, uitzonderingsafhandeling en timers voor het injecteren van vertragingen tussen nieuwe pogingen.
Python biedt momenteel geen ondersteuning voor aangepaste handlers voor opnieuw proberen. U hebt echter nog steeds de mogelijkheid om logica voor opnieuw proberen rechtstreeks in de orchestratorfunctie te implementeren met behulp van lussen, uitzonderingsafhandeling en timers voor het injecteren van vertragingen tussen nieuwe pogingen.
PowerShell biedt momenteel geen ondersteuning voor aangepaste handlers voor opnieuw proberen. U hebt echter nog steeds de mogelijkheid om logica voor opnieuw proberen rechtstreeks in de orchestratorfunctie te implementeren met behulp van lussen, uitzonderingsafhandeling en timers voor het injecteren van vertragingen tussen nieuwe pogingen.
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...
}
Time-outs voor functies
Mogelijk wilt u een functieaanroep binnen een orchestratorfunctie afbreken als het te lang duurt voordat deze is voltooid. De juiste manier om dit vandaag te doen is door een duurzame timer te maken met een 'any'-taakkiezer, zoals in het volgende voorbeeld:
[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;
}
}
}
Notitie
De vorige C#-voorbeelden zijn voor Durable Functions 2.x. Voor Durable Functions 1.x moet u in DurableOrchestrationContext plaats van IDurableOrchestrationContext. Zie het artikel Over Durable Functions-versies voor meer informatie over de verschillen tussen versies.
[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;
}
}
Notitie
Dit mechanisme beëindigt de uitvoering van de activiteitsfunctie niet daadwerkelijk. In plaats daarvan kan de orchestratorfunctie het resultaat negeren en verdergaan. Zie de documentatie voor timers voor meer informatie.
Onverwerkte uitzonderingen
Als een orchestratorfunctie mislukt met een niet-verwerkte uitzondering, worden de details van de uitzondering geregistreerd en wordt de instantie voltooid met een Failed status.
Aangepaste uitzonderingseigenschappen opnemen voor FailureDetails (.NET Isolated)
Bij het uitvoeren van Durable Task-werkstromen in het .NET Isolated-model worden taakfouten automatisch geserialiseerd in een FailureDetails-object. Dit object bevat standaard standaardvelden zoals:
- ErrorType : de naam van het uitzonderingstype
- Bericht : het uitzonderingsbericht
- StackTrace : de geserialiseerde stacktracering
- InnerFailure : een geneste FailureDetails-object voor recursieve binnenuitzonderingen
Vanaf Microsoft.Azure.Functions.Worker.Extensions.DurableTask v1.9.0 kunt u dit gedrag uitbreiden door een IExceptionPropertiesProvider te implementeren (gedefinieerd in het Microsoft.DurableTask.Worker-pakket vanaf v1.16.1). Deze provider definieert welke uitzonderingstypen en welke van de eigenschappen moeten worden opgenomen in de woordenlijst FailureDetails.Properties.
Notitie
- Deze functie is alleen beschikbaar in .NET Isolated . Ondersteuning voor Java wordt toegevoegd in een toekomstige release.
- Zorg ervoor dat u Microsoft.Azure.Functions.Worker.Extensions.DurableTask v1.9.0 of hoger gebruikt.
- Zorg ervoor dat u Microsoft.DurableTask.Worker v1.16.1 of hoger gebruikt.
Een uitzonderingseigenschappenprovider implementeren
Implementeer een aangepaste IExceptionPropertiesProvider om geselecteerde eigenschappen te extraheren en te retourneren voor de uitzonderingen die u belangrijk vindt. De geretourneerde woordenlijst wordt geserialiseerd in het veld Eigenschappen van FailureDetails wanneer een overeenkomend uitzonderingstype wordt gegenereerd.
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
};
}
}
De provider registreren
Registreer uw aangepaste IExceptionPropertiesProvider in uw .NET Isolated-werkhost, meestal in 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();
Zodra deze is geregistreerd, bevat elke uitzondering die overeenkomt met een van de afgehandelde typen automatisch de geconfigureerde eigenschappen in de FailureDetails.
Voorbeeld van FailureDetails-uitvoer
Wanneer er een uitzondering optreedt die overeenkomt met de configuratie van uw provider, ontvangt de orkestratie een geserialiseerde FailureDetails-structuur zoals deze:
{
"errorType": "TaskFailedException",
"message": "Activity failed with an exception.",
"stackTrace": "...",
"innerFailure": {
"errorType": "ArgumentOutOfRangeException",
"message": "Specified argument was out of range.",
"properties": {
"ParamName": "count",
"ActualValue": 42
}
}
}
Volgende stappen