Cloud flows can error out due to various reasons, though a try-catch-finally pattern can help handle them, it is not as convenient as how one could just view the errors and analyze them without having to open each flow and go through the flow errors.
Logging errors to Application Insights in Azure could be very beneficial to know information about the record, the flow, the action that error out and more details about the flow that failed. It's easier to review the details in Application Insights.
Azure function to log telemetry into Application Insights.
I would not go into the process of creating azure functions or publishing them as it was done in the past article.
Creating Application Insights:
Go to portal.azure.com and create application insights shown below
After the creation go to the resource and get the connection string
Adding app settings:
Go to the function app and add the app insights connection string in the app setting
Azure Function :
Add the reference `Microsoft.Application.Insights`
local.settings.json
add the connection string in the file
"APP_INSIGHTS_KEY" : "<connection string copied from app insights>"
Azure Function code:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.DataContracts;
namespace FunctionReadQueueMessages
{
public static class LogToAppInsights
{
[FunctionName("LogToAppInsights")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
TelemetryConfiguration configuration = TelemetryConfiguration.CreateDefault();
configuration.ConnectionString = Environment.GetEnvironmentVariable("APP_INSIGHTS_KEY");
var telemetryClient = new TelemetryClient(configuration);
try
{
var content = await req.ReadAsStringAsync();
Root response = JsonConvert.DeserializeObject<Root>(content);
// Access flow name
string flowName = response.Workflow.name;
// Access error code and message & Access tags
string flowDisplayName = response.Workflow.tags.flowDisplayName;
string capabilities = response.Workflow.tags.capabilities;
string environmentName = response.Workflow.tags.environmentName;
string concatenatedMessage = $"Flow Name: {flowName}\n" +
$"Error Message: {response.ErrorMessage.error.message}\n" +
$"Flow Display Name: {flowDisplayName}\n" +
$"Capabilities: {capabilities}\n" +
$"Environment Name: {environmentName}\n";
telemetryClient.TrackTrace(concatenatedMessage, SeverityLevel.Error);
/*telemetryClient.TrackException(new Exception(), new Dictionary<string, string>
{
{ "ResponseData", JsonConvert.SerializeObject(response) }
});
return new OkObjectResult("Function executed successfully.");
} */
return new OkObjectResult("Function executed successfully.");
}
catch (Exception ex)
{
telemetryClient.TrackException(ex);
log.LogError(ex, "Function execution failed.");
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
}
finally
{
// Flush telemetry data
telemetryClient.Flush();
}
}
}
public class Error
{
public string code { get; set; }
public string message { get; set; }
}
public class ErrorMessage
{
public Error error { get; set; }
}
public class Root
{
public Workflow Workflow { get; set; }
[JsonProperty("Error Message")]
public ErrorMessage ErrorMessage { get; set; }
}
public class Run
{
public string id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
public class Tags
{
public string flowDisplayName { get; set; }
public string capabilities { get; set; }
public string environmentName { get; set; }
public string logicAppName { get; set; }
public string environmentWorkflowId { get; set; }
public string xrmWorkflowId { get; set; }
public string environmentFlowSuspensionReason { get; set; }
public string sharingType { get; set; }
public string state { get; set; }
public string createdTime { get; set; }
public string lastModifiedTime { get; set; }
public string createdBy { get; set; }
}
public class Workflow
{
public string id { get; set; }
public string name { get; set; }
public string type { get; set; }
public string location { get; set; }
public Tags tags { get; set; }
public Run run { get; set; }
}
}
Let's trigger this azure function from power automate cloud flow
The below is a simple flow, this triggers when the account is updated and tries querying a related record in the try block, which will fail, and when it fails, the azure function will be triggered and then the logs are sent to application insights.
Flow Run :
As expected by design the flow was bound to fail, and then the log will be sent to azure app insights.
Azure App Insights :
We can now see the trace in App Insights
For the example I have logged a trace., but one could log it as an exception as well.
Sample Trace Log :
Sample Exception Log :