Azure Function app .NET 7 isolated mode unhandled exception

493 Views Asked by At

Updated with another example.

I have an Azure Function app running on .NET 7 in isolated mode on a Linux app service plan.

I'm experiencing some issues related to a orchestration function is not marked as failed on unhandled exceptions.

I have isolated this behavior in 2 simple code examples below. Problem is the orchestration function TestOrchestrator are marked as successful run, se image below.

Why does it not report as failed? Note the throw in the catch block in example 1, and no try catch block in example 2.

I do suspect this have something to do with running the function app in isolated mode.

Then the next question will be, how can I mark the orchestration function as failed?

The comments below suggested that throwing the original exception after logging it in the catch block, caused the error to be handled. So in example 2 I removed the try catch. Added an activity function that throws the error.

The result. The acitivity functionDoSomeBusinessStuff is marked as failed, as suspected. Logs, errors etc are displayed in Application Insights.

Activity function error

The orchestration function TestOrchestrator, have not failed. In MS documentation for error handling in orchestration function, states this should have marked the TestOrchestrator as failed. But it does not.

Orchestration results

Original example, example 1

public class TestIsolatedError
{
    private readonly ILogger _logger;

    public TestIsolatedError(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<TestIsolatedError>();
    }

    [Function("TestIsolatedError")]
    public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
        [DurableClient] DurableTaskClient client,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("C# HTTP trigger function processed a request.");
                    
        await client.ScheduleNewOrchestrationInstanceAsync(nameof(TestOrchestrator), cancellationToken);
        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
        response.WriteString("Welcome to Azure Functions!");
        return response;
    }

    [Function(nameof(TestOrchestrator))]
    public async Task TestOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context,
        CancellationToken cancellationToken)
    {
        var logger = context.CreateReplaySafeLogger<TestIsolatedError>();

        try
        {
            logger.LogInformation("Starting orchestration TestOrchestrator");
            // remove warning
            await Task.Delay(1);

            //... do some stuff 

            // something fails
            throw new Exception("An exception occured in TestOrchestrator");
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Failed");
            throw;   // why does this not mark the orchestration as failed?
        }
    }
}

Example 2

public class TestIsolatedError
{
    private readonly ILogger _logger;

    public TestIsolatedError(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<TestIsolatedError>();
    }

    [Function("TestIsolatedError")]
    public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
        [DurableClient] DurableTaskClient client,
        CancellationToken cancellationToken)
    {
        _logger.LogInformation("C# HTTP trigger function processed a request.");

        await client.ScheduleNewOrchestrationInstanceAsync(nameof(TestOrchestrator), cancellationToken);
        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
        response.WriteString("Welcome to Azure Functions!");
        return response;
    }

    [Function(nameof(TestOrchestrator))]
    public async Task TestOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context,
        CancellationToken cancellationToken)
    {

        _logger.LogInformation("Starting orchestration TestOrchestrator");

        var options = TaskOptions.FromRetryPolicy(new RetryPolicy(maxNumberOfAttempts: 3, firstRetryInterval: TimeSpan.FromMinutes(1)));
        await context.CallActivityAsync(nameof(DoSomeBusinessStuff), options);

    }

    [Function(nameof(DoSomeBusinessStuff))]
    public async Task DoSomeBusinessStuff([ActivityTrigger] FunctionContext executionContext)
    {
        _logger.LogInformation("Starting doing some business stuff");
        //remove warning.
        await Task.Delay(1);
        // do some async business stuff
        throw new Exception("Failed to do the business stuff");
    }
}

Invocation Details

1

There are 1 best solutions below

8
Ikhtesam Afrin On

Why does it not report as failed?

Because your function ran successfully into completion. If you will see the logs in the application insight, it will show you the Function completion status as Succeeded, though the function has thrown an exception and got handled in function itself.

enter image description here

You will not get all the exceptions in function app's Monitor section except the uncaught ones.

how can I mark the orchestration function as failed?

Here you are handling the error using try/catch block, so orchestration function is not getting failed. As per ms docs, only an unhandled exception in an orchestrator function will complete the orchestration instance in a failed state.