You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何捕获ILogger.LogCritical调用并在调试器中触发断点?

如何让ILogger.LogCritical()在调试时自动触发断点

完全可以实现!而且不需要替换整个底层日志库,也不用让开发者改调用方式——核心思路是用装饰器模式包装原生的ILogger实例,在不改变原有调用逻辑的前提下,插入断点触发的逻辑。

具体实现步骤

1. 写一个Logger装饰器类

这个类会包装原生的ILogger<T>,在Log方法里(所有扩展方法比如LogCritical最终都会调用这个方法)判断日志级别和调试状态,触发断点后再转发调用给原生Logger:

using System.Diagnostics;
using Microsoft.Extensions.Logging;

public class DebugBreakLogger<T> : ILogger<T>
{
    private readonly ILogger<T> _originalLogger;

    public DebugBreakLogger(ILogger<T> originalLogger)
    {
        _originalLogger = originalLogger;
    }

    public IDisposable BeginScope<TState>(TState state) => _originalLogger.BeginScope(state);

    public bool IsEnabled(LogLevel logLevel) => _originalLogger.IsEnabled(logLevel);

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        // 仅当日志级别为Critical且调试器已附加时触发断点
        if (logLevel == LogLevel.Critical && Debugger.IsAttached)
        {
            Debugger.Break(); // 会在当前调试器中暂停程序
            // 如果需要启动新调试器,可以用 Debugger.Launch()
        }

        // 继续执行原生的日志记录逻辑
        _originalLogger.Log(logLevel, eventId, state, exception, formatter);
    }
}

2. 替换DI容器中的Logger注册

在你的Program.cs(或者Startup.cs)里,把原生的ILogger<T>注册替换成我们的装饰器。这样所有依赖注入ILogger<T>的地方,都会拿到包装后的实例:

var builder = WebApplication.CreateBuilder(args);

// 保留原有的日志配置(比如AddConsole、AddSerilog等)
builder.Services.AddLogging();

// 替换所有ILogger<T>的实现为我们的装饰器
builder.Services.Replace(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(DebugBreakLogger<>)));

// ... 其他服务注册和应用启动逻辑

为什么这个方案满足你的需求

  • 无需修改现有代码:开发者还是像之前一样调用_logger.LogCritical(),完全不用区分原生还是自定义方法,也不用改命名空间。
  • 不绑定底层日志库:不管你用的是原生ConsoleLogger、Serilog还是NLog,只要是基于Microsoft.Extensions.Logging抽象的,这个逻辑都能生效,未来换日志库也不用改动这部分代码。
  • 仅调试环境生效:通过Debugger.IsAttached判断,生产环境不会触发断点,完全不影响线上运行。
  • 实现成本极低:只需要一个几十行的装饰器类和一行注册代码,不用实现一堆繁琐的日志接口。

额外注意点

  • 确保引用了System.Diagnostics命名空间,否则Debugger类会找不到。
  • 如果你的项目中有用到直接实例化的ILogger(不是通过DI注入的),那这种情况需要单独处理,但绝大多数.NET项目都是用DI注入ILogger<T>的,所以这个方案覆盖了绝大多数场景。

内容的提问来源于stack exchange,提问作者ChrisTorng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:57:35