告警系统.NET Core:异常通知

告警系统.NET Core:异常通知

【免费下载链接】core dotnet/core: 是 .NET Core 的官方仓库,包括 .NET Core 运行时、库和工具。适合对 .NET Core、跨平台开发和想要使用 .NET Core 进行跨平台开发的开发者。 【免费下载链接】core 项目地址: https://gitcode.com/GitHub_Trending/core82/core

在.NET Core应用开发中,异常处理和实时告警是保障系统稳定性的关键环节。当生产环境中出现未捕获异常或性能问题时,及时的告警通知能帮助开发团队快速响应并解决问题,减少业务损失。本文将介绍如何基于.NET Core构建轻量级异常告警系统,涵盖异常捕获、通知渠道集成和最佳实践。

异常捕获机制

全局异常处理中间件

ASP.NET Core提供了全局异常处理中间件,可统一捕获Web请求过程中抛出的异常。通过自定义中间件,可实现异常日志记录和告警触发。

public class ExceptionAlertMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IAlertService _alertService;

    public ExceptionAlertMiddleware(RequestDelegate next, IAlertService alertService)
    {
        _next = next;
        _alertService = alertService;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            // 记录异常详情
            var exceptionDetails = new ExceptionDetails
            {
                Message = ex.Message,
                StackTrace = ex.StackTrace,
                Path = context.Request.Path,
                Timestamp = DateTime.UtcNow
            };
            
            // 触发告警
            await _alertService.SendAlertAsync(exceptionDetails);
            throw; // 继续抛出异常以返回500响应
        }
    }
}

// 在Program.cs中注册
app.UseMiddleware<ExceptionAlertMiddleware>();

非Web应用异常捕获

对于控制台应用或Windows服务,可通过AppDomain.CurrentDomain.UnhandledException事件捕获未处理异常:

AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
{
    var exception = args.ExceptionObject as Exception;
    if (exception != null)
    {
        // 处理异常并发送告警
        _alertService.SendAlertAsync(new ExceptionDetails
        {
            Message = exception.Message,
            StackTrace = exception.StackTrace,
            Timestamp = DateTime.UtcNow
        }).Wait();
    }
};

告警通知渠道

邮件通知

通过SmtpClient或第三方邮件服务(如SendGrid)发送异常详情邮件:

public class EmailAlertService : IAlertService
{
    private readonly string _smtpServer;
    private readonly int _smtpPort;
    private readonly string _username;
    private readonly string _password;

    public async Task SendAlertAsync(ExceptionDetails details)
    {
        using (var client = new SmtpClient(_smtpServer, _smtpPort))
        {
            client.Credentials = new NetworkCredential(_username, _password);
            client.EnableSsl = true;

            var message = new MailMessage(
                from: "alerts@example.com",
                to: "dev-team@example.com",
                subject: $"[ERROR] {details.Message}",
                body: $"<h3>Exception Details</h3><p>Path: {details.Path}</p><p>Time: {details.Timestamp}</p><pre>{details.StackTrace}</pre>"
            );
            message.IsBodyHtml = true;

            await client.SendMailAsync(message);
        }
    }
}

企业微信/钉钉机器人

集成企业微信或钉钉机器人Webhook,实现即时消息告警:

public class WeChatAlertService : IAlertService
{
    private readonly HttpClient _httpClient;
    private readonly string _webhookUrl;

    public async Task SendAlertAsync(ExceptionDetails details)
    {
        var payload = new
        {
            msgtype = "markdown",
            markdown = new
            {
                content = $"## 系统异常告警\n" +
                          $"**时间**: {details.Timestamp}\n" +
                          $"**消息**: {details.Message}\n" +
                          $"**路径**: {details.Path}\n" +
                          $"**堆栈**: \n```\n{details.StackTrace}\n```"
            }
        };

        await _httpClient.PostAsJsonAsync(_webhookUrl, payload);
    }
}

告警系统最佳实践

异常聚合与限流

频繁重复的异常可能导致告警风暴,可通过滑动窗口算法实现告警限流:

public class ThrottlingAlertService : IAlertService
{
    private readonly IAlertService _innerService;
    private readonly ConcurrentDictionary<string, Queue<DateTime>> _alertTimestamps = new();

    public async Task SendAlertAsync(ExceptionDetails details)
    {
        var key = $"{details.Message}:{details.Path}";
        var now = DateTime.UtcNow;
        var window = TimeSpan.FromMinutes(5);
        var maxCount = 3;

        // 清理过期记录
        _alertTimestamps.TryGetValue(key, out var timestamps);
        timestamps?.RemoveAll(t => now - t > window);

        // 检查是否超过阈值
        if (timestamps?.Count < maxCount)
        {
            timestamps ??= new Queue<DateTime>();
            timestamps.Enqueue(now);
            _alertTimestamps[key] = timestamps;
            await _innerService.SendAlertAsync(details);
        }
    }
}

结合日志系统

将告警系统与日志框架(如Serilog、NLog)集成,通过日志级别触发告警:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("logs/app.log")
    .WriteTo.Sink(new AlertSink(alertService)) // 自定义告警Sink
    .CreateLogger();

// 自定义日志Sink
public class AlertSink : ILogEventSink
{
    private readonly IAlertService _alertService;

    public void Emit(LogEvent logEvent)
    {
        if (logEvent.Level >= LogEventLevel.Error)
        {
            _alertService.SendAlertAsync(new ExceptionDetails
            {
                Message = logEvent.MessageTemplate.Render(logEvent.Properties),
                StackTrace = logEvent.Exception?.StackTrace,
                Timestamp = logEvent.Timestamp.UtcDateTime
            }).Wait();
        }
    }
}

参考资源

通过以上方案,可构建一个灵活可靠的异常告警系统,帮助开发团队及时发现并解决.NET Core应用中的问题。实际部署时,建议根据业务需求选择合适的通知渠道,并结合监控系统(如Prometheus、Grafana)实现更全面的系统观测。

【免费下载链接】core dotnet/core: 是 .NET Core 的官方仓库,包括 .NET Core 运行时、库和工具。适合对 .NET Core、跨平台开发和想要使用 .NET Core 进行跨平台开发的开发者。 【免费下载链接】core 项目地址: https://gitcode.com/GitHub_Trending/core82/core

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值