user2906011
user2906011

Reputation: 119

Azure Orchestrator function failing without running code inside, what could be the cause?

I have an http triggered azure function that starts an orchestrator function. In my dev tenant the code runs without a problem but when deploying to another tenant there has been nothing but trouble, in terms of security settings that affect the azure function.

Right now we are able to call the http trigger when connected to the company network via VPN, and the http triggered function runs without a problem. In the logs we can se that the orchestrator function starts, but immediately fails.

We have tested that we are able to connect to the storage account, and we have tried removing all the code inside the orchestrator besides a log-statement. But it still fails.

Is there some settings in the Azure portal that may have been made that only would affect the orchestrator, and not the Http-triggered function?

[FunctionName(nameof(PlannerOrchestrator))]
public async Task<string> PlannerOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
    log.LogInformation("Starting orchestration for Planner request");
    return string.Empty;
}
[FunctionName(nameof(PostPlannerTask))]
public async Task<IActionResult> PostPlannerTask(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
    [DurableClient] IDurableClient client,
    ILogger log)
{

    log.LogInformation("C# HTTP trigger function processed a request.");
    var incomingAccessToken = req.Headers.TryGetValue("Authorization", out var tokenHeaderValue) ? tokenHeaderValue.FirstOrDefault()?.Replace("Bearer ", string.Empty) : null;

    try
    {
        bool validToken = ValidateToken(incomingAccessToken);
        log.LogInformation("Valid token: {validToken}", validToken);
        if (!validToken)
        {
            return new UnauthorizedResult();
        }
    }
    catch (Exception ex)
    {
        log.LogError("Invalid token: {ex}", ex.Message);
        
        return new BadRequestResult();
    }


    var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    var plannerRequest = JsonConvert.DeserializeObject<PlannerRequest>(requestBody);

    log.LogInformation("Request received: {request}", requestBody);

    var instanceId = nameof(PlannerOrchestrator) + "-" + Guid.NewGuid();

    instanceId = await client.StartNewAsync(nameof(PlannerOrchestrator), instanceId, plannerRequest);
    log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
    return await client.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromSeconds(60));
}

Upvotes: 0

Views: 100

Answers (2)

user2906011
user2906011

Reputation: 119

Figured out the problem. We had no control over creating the function and we found out that they had set it to .NET8 isolated worker, instead of .NET6 In-process.

Had to rewrite the code to .NET8 isolated, then it were able to run successfully.

Upvotes: 0

Pravallika KV
Pravallika KV

Reputation: 8694

Check the error logs in LogStream=>App Insights Logs:

enter image description here

Use the below query to check the error logs related to Durable function as mentioned in MSDOC:

let orchestrationInstanceID = "XXXXXX"; 
let start = datetime(XXXX-XX-XXTXX:XX:XX); 
traces  
| where timestamp > start and timestamp < start + 1h
| extend instanceId = iif(isnull(customDimensions["prop__InstanceId"] ) , customDimensions["prop__instanceId"], customDimensions["prop__InstanceId"] ) 
| extend logLevel = customDimensions["LogLevel"]
| extend functionName = customDimensions["prop__functionName"]
| extend status = customDimensions["prop__status"]
| extend details = customDimensions["prop__Details"] 
| extend reason = customDimensions["prop__reason"]
| where severityLevel > 1 // to see all logs of  severity level "Information" or greater.
| where instanceId == orchestrationInstanceID
| sort by timestamp asc

I have deployed your code to Azure function app and able to run the function as expected.

Code Snippet:

public static async Task<IActionResult> PostPlannerTask(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
[DurableClient] IDurableClient client,
ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
        var incomingAccessToken = req.Headers.TryGetValue("Authorization", out var tokenHeaderValue) ? tokenHeaderValue.FirstOrDefault()?.Replace("Bearer ", string.Empty) : null;

        try
        {
            bool validToken = ValidateToken(incomingAccessToken);
            log.LogInformation("Valid token: {validToken}", validToken);
            if (!validToken)
            {
                return new UnauthorizedResult();
            }
        }
        catch (Exception ex)
        {
            log.LogError("Invalid token: {ex}", ex.Message);

            return new BadRequestResult();
        }
        var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        var plannerRequest = JsonConvert.DeserializeObject<PlannerRequest>(requestBody);

        log.LogInformation("Request received: {request}", requestBody);

        var instanceId = nameof(Function1) + "-" + Guid.NewGuid();

        instanceId = await client.StartNewAsync(nameof(Function1), instanceId, plannerRequest);
        log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
        return await client.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromSeconds(60));
    }
    private static bool ValidateToken(string token)
    {
        return !string.IsNullOrEmpty(token);
    }

Durable function:

[FunctionName("Function1")]
public static async Task<List<string>> RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var outputs = new List<string>();
    outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo"));
    outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Seattle"));
    outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "London"));
    return outputs;
}

[FunctionName(nameof(SayHello))]
public static string SayHello([ActivityTrigger] string name, ILogger log)
{
    log.LogInformation("Saying hello to {name}.", name);
    return $"Hello {name}!";
}

[FunctionName("Function1_HttpStart")]
public static async Task<HttpResponseMessage> HttpStart(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
    [DurableClient] IDurableOrchestrationClient starter,
    ILogger log)
{
    string instanceId = await starter.StartNewAsync("Function1", null);

    log.LogInformation("Started orchestration with ID = '{instanceId}'.", instanceId);

    return starter.CreateCheckStatusResponse(req, instanceId);
}

Deployed to Azure function App.

Portal:

enter image description here

Provide Bearer token in Auth section while running the function:

enter image description here

Response:

enter image description here

Upvotes: 0

Related Questions