Azure Alerts for Exceptions in .NET
Reading Time: 7 minutes
The Problem
Applications fail in production long before anyone opens the Azure portal.
An exception gets thrown, requests start failing, and the system is already in a degraded state before the team notices. The real issue is rarely just logging. Most teams already have logs somewhere. The problem is that logs on their own are passive.
What you actually want is this:
- exceptions are captured automatically
- the right failures are turned into alerts
- alerts reach the right people quickly
- noisy, low-value failures do not spam the whole team
Without that, exception monitoring usually falls into one of two bad states:
- everything is logged but nothing is actioned
- everything is alerted and people start ignoring the alerts
For .NET systems on Azure, the gap is usually between exception telemetry and operational alerting. Capturing exceptions is one concern. Routing useful signals to email, Teams, or Slack is another.
The Solution
The clean Azure-native model is:
- send application telemetry to Application Insights through Azure Monitor
- let exceptions flow into the
exceptionstelemetry table - create an Azure Monitor alert rule based on that exception signal
- connect the alert rule to an action group
- use the action group to notify by email or call out to integration endpoints that post into Teams or Slack
This separation matters.
Your .NET application should focus on emitting telemetry correctly. Azure Monitor should decide when a condition is serious enough to alert. Action groups should decide who gets notified and through which channel.
That gives you a monitoring setup that is:
- easier to manage centrally
- safer to tune without redeploying code
- less coupled to any single chat platform
- easier to extend over time
Capture Exceptions in a .NET App
For an ASP.NET Core application, the first step is making sure exceptions are actually reaching Azure Monitor.
One solid approach is to use the Azure Monitor OpenTelemetry distribution.
Install the package:
dotnet add package Azure.Monitor.OpenTelemetry.AspNetCore
Then configure it in Program.cs:
using Azure.Monitor.OpenTelemetry.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenTelemetry().UseAzureMonitor(options =>
{
options.ConnectionString = builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"];
});
var app = builder.Build();
app.MapGet("/", () => "Healthy");
app.MapGet("/boom", () =>
{
throw new InvalidOperationException("Simulated production failure.");
});
app.Run();
For many ASP.NET Core failures, unhandled exceptions will automatically be captured once the telemetry pipeline is configured.
You can also record handled exceptions explicitly when you catch them and still want visibility:
using Microsoft.Extensions.Logging;
app.MapPost("/orders", (ILogger<Program> logger) =>
{
try
{
throw new InvalidOperationException("Order processing failed.");
}
catch (Exception ex)
{
logger.LogError(ex, "Order processing failed.");
return Results.Problem("The order could not be processed.");
}
});
The important point is not to send emails or chat notifications from the application itself when an exception occurs. That creates duplicated logic, notification drift, and deployment-time coupling. Emit telemetry from the app, then let Azure Monitor own alerting.
Where the Exception Data Goes
Once Application Insights is connected, Azure Monitor stores exception telemetry where alert rules can evaluate it.
In practice, a common alert condition is based on:
- exception count over a time window
- specific exception types
- a spike in server exceptions
- failed request rate correlated with exception volume
This matters because not every exception deserves an alert.
Examples:
- a one-off client cancellation probably should not page anyone
- repeated
SqlExceptionfailures in five minutes probably should - a burst of
NullReferenceExceptionafter a deployment definitely deserves attention
That is why alert criteria should be deliberate rather than simply “alert on any exception.”
Creating the Alert Rule
In Azure, the alert usually lives in Azure Monitor Alerts and targets the Application Insights resource or the Log Analytics-backed telemetry data behind it.
Two common models are:
Metric-based alert
Use this when Azure already exposes a suitable metric and you want a straightforward threshold alert.
This is simple, but less flexible when you want to filter by exception type, operation name, or environment.
Log query alert
Use this when you need precision.
For example, you can alert only when a query over the exceptions table returns a count above some threshold.
A representative KQL query might look like this:
exceptions
| where timestamp > ago(5m)
| where type !in ("TaskCanceledException", "OperationCanceledException")
| summarize ExceptionCount = count() by type
| where ExceptionCount >= 5
This is usually the better pattern because it lets you filter noisy exception types and tune the threshold around real operational behavior.
Action Groups: Email, Teams, and Slack
Alert rules decide when to alert. Action groups decide what happens next.
This is the part that sends notifications outward.
This is the simplest option.
Create or reuse an action group and add an Email/SMS/Push/Voice action. For many teams, email is still the right default for non-paging alerts such as:
- repeated exceptions in a non-production environment
- warning-level operational anomalies
- release validation issues after deployment
Email is low-friction and built in.
Teams channel
Azure Monitor alerts do not need to be hardwired into your .NET application to reach Teams. The usual pattern is:
- the alert fires
- the action group calls an integration endpoint
- that integration posts a formatted message to Teams
In practice, teams commonly use one of these:
- a Logic App that posts to Teams
- a workflow endpoint that transforms the alert payload
- a webhook-capable intermediary service
That indirection is useful because it lets you:
- format the message cleanly
- route alerts to different channels by severity
- enrich the message with links to dashboards, KQL, or incident runbooks
Slack channel
Slack follows the same operational model.
The alert should trigger an action group, and the action group should call something that can post into Slack, such as:
- a Logic App
- an Azure Function
- a secure webhook endpoint that forwards the message
This keeps Slack delivery outside the application and inside the monitoring workflow where it belongs.
Why Not Alert Directly from Application Code?
It is tempting to write code like this:
- catch exception
- call Slack webhook
- send email
- maybe also post to Teams
That is almost always the wrong design.
It causes several problems:
- the app becomes responsible for notification policy
- every service implements alerting differently
- changing recipients requires code or configuration churn in each app
- outages can break both the application and its alerting path at the same time
The application should emit telemetry. Azure Monitor should evaluate conditions. Action groups and downstream integrations should route the alert.
A Practical Alerting Strategy
A good default exception alert strategy for a .NET system might be:
- capture all meaningful exceptions in Application Insights
- exclude expected cancellation-style exceptions from alert queries
- alert on repeated failures over a short time window rather than single isolated exceptions
- send warning-level alerts to email
- send higher-severity alerts to Teams or Slack through an action group integration
- include direct links to the affected resource, query, and dashboard in the notification payload
That gives you signal without drowning the team in noise.
Example Operational Thresholds
These are not universal, but they are better than starting with “everything alerts”:
- 5 or more unexpected exceptions in 5 minutes: notify email distribution list
- 15 or more unexpected exceptions in 5 minutes: post to Teams or Slack operations channel
- sustained exception spike for 15 minutes: escalate to on-call workflow
The exact numbers depend on traffic volume and application shape, but the idea is the same: tune alerts against patterns, not against isolated events.
Summary
Azure alerting for exceptions works best when you separate responsibilities clearly.
- your .NET app emits telemetry to Application Insights
- Azure Monitor evaluates exception conditions
- alert rules trigger action groups
- action groups send notifications to email or integration paths for Teams and Slack
That is the model that scales.
It avoids pushing notification logic into application code, gives you cleaner operational control, and makes exception monitoring something the platform can manage consistently across services.
If you want a robust setup, think in this order:
- collect exception telemetry correctly
- define alert conditions that reflect real incidents
- route alerts through action groups to the right channels
- tune out noise before people start ignoring the alerts
References
- Azure Monitor alerts overview: https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-overview
- Create and manage action groups: https://learn.microsoft.com/azure/azure-monitor/alerts/action-groups
- Application Insights for ASP.NET Core applications: https://learn.microsoft.com/azure/azure-monitor/app/asp-net-core
- Azure Monitor OpenTelemetry for ASP.NET Core: https://learn.microsoft.com/azure/azure-monitor/app/opentelemetry-enable?tabs=aspnetcore
- Log search alert rules in Azure Monitor: https://learn.microsoft.com/azure/azure-monitor/alerts/alerts-create-log-alert-rule