A Durable Functions vezénylések kódban vannak implementálva, és használhatják a programozási nyelv beépített hibakezelési funkcióit. Valójában nincs olyan új fogalom, amit meg kell tanulnia, hogy hibakezelést és kompenzációt adjon hozzá a vezénylésekhez. Van azonban néhány viselkedés, amellyel tisztában kell lennie.
Feljegyzés
Az Azure Functions Node.js programozási modelljének 4- es verziója általánosan elérhető. Az új v4-modell úgy lett kialakítva, hogy rugalmasabb és intuitívabb felhasználói élményt nyújtson JavaScript- és TypeScript-fejlesztők számára. A migrálási útmutatóban további információt olvashat a v3 és a v4 közötti különbségekről.
A következő kódrészletekben a JavaScript (PM4) a V4 programozási modellt, az új felületet jelöli.
Tevékenységfüggvények és részvezénylések hibái
A Durable Functionsben a tevékenységfüggvényeken vagy al-vezényléseken belüli kezeletlen kivételek a szabványosított kivételtípusok használatával kerülnek vissza a vezénylő függvénybe.
Vegyük például a következő orkesztáló függvényt, amely két számla közötti pénzmozgást hajt végre.
A Durable Functions C# in-process használata esetén a nem kezelt kivételek FunctionFailedException néven jelennek meg.
A kivételüzenet általában azonosítja, hogy mely tevékenységfüggvények vagy al-vezénylések okozták a hibát. A részletesebb hibainformációk eléréséhez vizsgálja meg a tulajdonságot InnerException .
[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
});
}
}
Feljegyzés
Az előző C#-példák a Durable Functions 2.x-hez tartoznak. A Durable Functions 1.x esetén a helyett DurableOrchestrationContexta IDurableOrchestrationContext . A verziók közötti különbségekről további információt a Durable Functions verzióiról szóló cikkben talál.
A Durable Functions C# izolált, nem kezelt kivételei TaskFailedException néven jelennek meg.
A kivételüzenet általában azonosítja, hogy mely tevékenységfüggvények vagy al-vezénylések okozták a hibát. A részletesebb hibainformációk eléréséhez vizsgálja meg a FailureDetails tulajdonságot .
[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
});
}
}
Feljegyzés
- A kivételüzenet általában azonosítja, hogy mely tevékenységfüggvények vagy al-vezénylések okozták a hibát. A részletesebb hibainformációk eléréséhez vizsgálja meg a tulajdonságot
FailureDetails .
- Alapértelmezés szerint tartalmazza a
FailureDetails, a hibaüzenetet, a veremkövetést és a beágyazott belső kivételeket (mindegyik rekurzív objektumként van jelölveFailureDetails). Ha további kivételtulajdonságokat szeretne belefoglalni a hibakimenetbe, olvassa el a FailureDetails egyéni kivételtulajdonságainak belefoglalása (.NET izolált) című témakört.
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)
A PowerShell-parancsmagok alapértelmezés szerint nem generálnak kivételeket, amelyeket try/catch blokkokkal lehetne elkapni. Ennek a viselkedésnek a módosítására két lehetősége van:
- Használja a
-ErrorAction Stop jelölőt parancsmagok, például Invoke-DurableActivity.
- A parancsmagok meghívása előtt állítsa be a
$ErrorActionPreference beállítási változót "Stop" a vezénylő függvénybe.
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 }
}
A PowerShell hibakezelésével kapcsolatos további információkért tekintse meg a Try-Catch-Finally PowerShell dokumentációt.
@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();
}
}
Ha az első CreditAccount függvényhívás meghiúsul, a vezénylő függvény kompenzálja az összeget a forrásfiókba történő jóváírással.
Entitásfüggvények hibái
Az entitásfüggvények kivételkezelési viselkedése a Durable Functions üzemeltetési modelltől függően eltérő:
A C#-ot használó Durable Functionsben az entitásfüggvények által létrehozott eredeti kivételtípusok közvetlenül visszakerülnek a vezénylőhöz.
[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;
}
}
A Durable Functions C# Izolált funkciója esetén a rendszer kivételeket jelenít meg a vezénylő számára EntityOperationFailedException. Az eredeti kivétel részleteinek eléréséhez vizsgálja meg annak FailureDetails tulajdonságát.
[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
Az entitásfüggvények jelenleg nem támogatottak a PowerShellben.
A Java jelenleg nem támogatja az entitásfüggvényeket.
Automatikus újrapróbálkozás hiba esetén
Ha tevékenységfüggvényeket vagy részvezénylési függvényeket hív meg, megadhat egy automatikus újrapróbálkozási szabályzatot. Az alábbi példa legfeljebb háromszor próbál meghívni egy függvényt, és 5 másodpercet vár az egyes újrapróbálkozások között:
[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);
// ...
}
Feljegyzés
Az előző C#-példák a Durable Functions 2.x-hez tartoznak. A Durable Functions 1.x esetén a helyett DurableOrchestrationContexta IDurableOrchestrationContext . A verziók közötti különbségekről további információt a Durable Functions verzióiról szóló cikkben talál.
[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();
// ...
}
Az előző példában szereplő tevékenységfüggvény-hívás egy automatikus újrapróbálkozási szabályzat konfigurálására szolgáló paramétert vesz igénybe. Az automatikus újrapróbálkozási szabályzat testreszabásának számos lehetősége van:
-
Kísérletek maximális száma: A kísérletek maximális száma. Ha az 1 értékre van állítva, nem lesz újrapróbálkozás.
-
Első újrapróbálkozási időköz: Az első újrapróbálkozási kísérlet előtti várakozási idő.
-
Visszalépési együttható: A visszakapcsolás növekedésének sebességének meghatározására használt együttható. Alapértelmezett érték: 1.
-
Maximális újrapróbálkozási időköz: Az újrapróbálkozási kísérletek közötti várakozás maximális időtartama.
-
Újrapróbálkozás időtúllépése: Az újrapróbálkozással töltött idő maximális mennyisége. Az alapértelmezett viselkedés a határozatlan ideig történő újrapróbálkozás.
Egyéni újrapróbálkozás-kezelők
A .NET vagy a Java használatakor lehetősége van újrapróbálkoztatók implementálására is a kódban. Ez akkor hasznos, ha a deklaratív újrapróbálkozási szabályzatok nem elég kifejezőek. Az egyéni újrapróbálkozási kezelőket nem támogató nyelvek esetében továbbra is lehetősége van újrapróbálkozási szabályzatok implementálására hurkok, kivételkezelés és időzítők használatával az újrapróbálkozások közötti késések injektálására.
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...
}
A JavaScript jelenleg nem támogatja az egyéni újrapróbálkozás-kezelőket. Azonban továbbra is lehetősége van az újrapróbálkozási logika implementálására közvetlenül a vezénylő függvényben hurkok, kivételkezelés és időzítők használatával az újrapróbálkozások közötti késések injektálására.
A JavaScript jelenleg nem támogatja az egyéni újrapróbálkozás-kezelőket. Azonban továbbra is lehetősége van az újrapróbálkozási logika implementálására közvetlenül a vezénylő függvényben hurkok, kivételkezelés és időzítők használatával az újrapróbálkozások közötti késések injektálására.
A Python jelenleg nem támogatja az egyéni újrapróbálkozás-kezelőket. Azonban továbbra is lehetősége van az újrapróbálkozási logika implementálására közvetlenül a vezénylő függvényben hurkok, kivételkezelés és időzítők használatával az újrapróbálkozások közötti késések injektálására.
A PowerShell jelenleg nem támogatja az egyéni újrapróbálkozás-kezelőket. Azonban továbbra is lehetősége van az újrapróbálkozási logika implementálására közvetlenül a vezénylő függvényben hurkok, kivételkezelés és időzítők használatával az újrapróbálkozások közötti késések injektálására.
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...
}
Függvény időtúllépései
Ha túl sok időt vesz igénybe, érdemes lehet megszakítani egy függvényhívást egy vezénylő függvényen belül. Ennek ma a megfelelő módja, ha egy tartós időzítőt hoz létre egy "bármely" feladatválasztóval, ahogyan az alábbi példában is látható:
[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;
}
}
}
Feljegyzés
Az előző C#-példák a Durable Functions 2.x-hez tartoznak. A Durable Functions 1.x esetén a helyett DurableOrchestrationContexta IDurableOrchestrationContext . A verziók közötti különbségekről további információt a Durable Functions verzióiról szóló cikkben talál.
[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;
}
}
Feljegyzés
Ez a mechanizmus valójában nem szünteti meg a folyamatban lévő tevékenységfüggvény végrehajtását. Ehelyett egyszerűen lehetővé teszi, hogy a vezénylő függvény figyelmen kívül hagyja az eredményt, és továbblépjen. További információkért tekintse meg az Időzítők dokumentációját.
Nem kezelt kivételek
Ha egy vezénylő függvény nem kezelt kivétellel meghiúsul, a rendszer naplózza a kivétel részleteit, és a példány állapota befejeződik Failed .
Az egyéni kivételtulajdonságok belefoglalása a FailureDetails (.NET izolált) esetén.
Ha tartós feladat munkafolyamatait futtatja a .NET izolált modellben, a rendszer automatikusan egy FailureDetails objektumba szerializálja a feladathibákat. Alapértelmezés szerint ez az objektum szabványos mezőket tartalmaz, például:
- ErrorType – a kivételtípus neve
- Üzenet – a kivétel üzenete
- StackTrace – a szerializált verem nyomkövetése
- InnerFailure – beágyazott FailureDetails objektum rekurzív belső kivételekhez
A Microsoft.Azure.Functions.Worker.Extensions.DurableTask 1.9.0-s verziótól kezdve ezt a viselkedést kiterjesztheti egy IExceptionPropertiesProvider implementálásával (a Microsoft.DurableTask.Worker 1.16.1-escsomagtól kezdve). Ez a szolgáltató határozza meg, hogy mely kivételtípusokat és azok tulajdonságait kell szerepeltetni a FailureDetails.Properties szótárban.
Feljegyzés
- Ez a funkció csak .NET Izolált verzióban érhető el. A Java támogatása egy későbbi kiadásban lesz hozzáadva.
- Győződjön meg arról, hogy a Microsoft.Azure.Functions.Worker.Extensions.DurableTask 1.9.0-s vagy újabb verzióját használja.
- Győződjön meg arról, hogy a Microsoft.DurableTask.Worker 1.16.1-s vagy újabb verzióját használja.
Kivételtulajdonság-szolgáltató implementálása
Implementáljon egy egyéni IExceptionPropertiesProvidert a kiválasztott tulajdonságok kinyeréséhez és visszaadásához a fontos kivételekhez. A visszaadott szótár a FailureDetails Tulajdonság mezőjébe lesz szerializálva, ha egyező kivételtípust ad ki.
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
};
}
}
A szolgáltató regisztrálása
Regisztrálja az egyéni IExceptionPropertiesProvidert az izolált .NET munkavégzési kiszolgálóban, általában a Program.cs fájlban.
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();
A regisztrációt követően a kezelt típusok egyikének megfelelő kivétel automatikusan tartalmazza a konfigurált tulajdonságokat a FailureDetails fájlban.
Minta Hibamentrészek kimenete
Amikor olyan kivétel fordul elő, amely megfelel a szolgáltató konfigurációjának, az rendszervezérlés egy olyan szerializált FailureDetails-struktúrát kap, mint ez:
{
"errorType": "TaskFailedException",
"message": "Activity failed with an exception.",
"stackTrace": "...",
"innerFailure": {
"errorType": "ArgumentOutOfRangeException",
"message": "Specified argument was out of range.",
"properties": {
"ParamName": "count",
"ActualValue": 42
}
}
}
Következő lépések