【问题标题】:ASP.NET Core Web API Logging from a Static Class来自静态类的 ASP.NET Core Web API 日志记录
【发布时间】:2018-07-18 11:19:43
【问题描述】:

我在我的控制器上使用依赖注入记录得很好,现在我需要记录一些来自静态类的东西。

如何静态类记录?

我不能使用依赖注入,因为它是静态的,而且我不能只将现有的记录器对象传递给静态类,因为它会在日志文件中使用错误的类名。

换句话说,我如何从我的静态类中的 loggerfactory 获取一个记录器?

我遇到了一个类似的问题,他们指出了一篇关于静态类中的 loggerfactory 的文章,但这实际上不起作用,因为我无法从中获取新的记录器,因为它不接受静态类作为参数:

“静态类型不能用作类型参数”

【问题讨论】:

标签: logging asp.net-core dependency-injection asp.net-core-webapi static-classes


【解决方案1】:

我在 Startup 类中添加了 ILoggerFactory 的静态成员,因此它可以在其他类中使用。

public class Startup
{
    internal static ILoggerFactory LogFactory { get; set; }
    …

    public void Configure(…, ILoggerFactory logFactory)
    {
        …
        LogFactory = logFactory;
    }
}

然后在静态类中使用。

static class YourClass
{
    private static ILogger<YourClass> Logger = Startup.LogFactory.CreateLogger<YourClass>();
…

但是,当 CreateLogger 抛出异常时,这段代码会导致 TypeInitializationException,所以你应该尝试做得更好。 [1]

【讨论】:

    【解决方案2】:

    我发现这个问题的答案很有用,但我记得我已经安装了 Serilog。我可以使用 Serilog 的默认实现,而不是实现自定义静态实例。

    它带有多个不错的日志记录功能和多个重载版本。
    这里有两个例子:

    using Serilog;
    ...
        Log.Error(myException, "my message");
        Log.Warning("My message", myValue);
    

    Serilog.Log 是一个静态实例,在 Program.cs 或 Startup.cs 中配置后即可使用。

    【讨论】:

    • 如果您不需要使用关注点分离原则,您可以在需要时轻松替换日志框架。
    • 是的,如果想在自定义记录器中使用 Serilog,可以让自定义记录器基本上成为 Serilog 的包装器:) 如 OP 所要求的,要绑定到调用类, 可以实现类似 factorymethod 的方法,其类型参数为 @Adrian 所描述的。
    • 您是在编写具体的代码,而不是编写接口。未来的读者,只要“注意”这种情况。
    【解决方案3】:

    您可以将静态LoggerFactory 实例与以下扩展方法一起使用,该方法接受Type 类型的常规参数,而不是泛型类型参数: CreateLogger(ILoggerFactory, Type)

    loggerFactory.CreateLogger(typeof(T)) 而不是 loggerFactory.CreateLogger&lt;T&gt;()

    【讨论】:

    • 您的意思是“a static LoggerFactory instance”吗?除非您设置一个,否则没有可用的静态 LoggerFactory 实例。
    【解决方案4】:

    解决方案是在启动时初始化的实用程序静态类中对 LoggerFactory 进行静态引用:

    /// <summary>
        /// Shared logger
        /// </summary>
        internal static class ApplicationLogging
        {
            internal static ILoggerFactory LoggerFactory { get; set; }// = new LoggerFactory();
            internal static ILogger CreateLogger<T>() => LoggerFactory.CreateLogger<T>();        
            internal static ILogger CreateLogger(string categoryName) => LoggerFactory.CreateLogger(categoryName);
    
        }
    

    您在 Startup.cs 上初始化的内容:

     public Startup(ILogger<Startup> logger, ILoggerFactory logFactory, IHostingEnvironment hostingEnvironment)
            {
                _log = logger;
                _hostingEnvironment = hostingEnvironment;
                Util.ApplicationLogging.LoggerFactory = logFactory;//<===HERE
    
            }
    

    然后您可以构建一个记录器以从您的静态类中使用,如下所示:

    internal static class CoreJobSweeper
        {
            private static ILogger log = Util.ApplicationLogging.CreateLogger("CoreJobSweeper");
    

    【讨论】:

    • 完美!然而,值得添加一个强类型 CreateLogger 的示例,特别是对于我们复制/粘贴爱好者来说只是寻找快速解决问题的方法:) 即 private static ILogger log = Util.ApplicationLogging.CreateLogger();跨度>
    • 这不再像github.com/aspnet/Announcements/issues/353 中的公告那样起作用。注入 ILogger 和 ILoggerFactory 不起作用。 “新的 ApplicationInsightsLoggerProvider 可以在应用程序启动管道的早期捕获日志。尽管 ApplicationInsightsLoggerProvider 在 Application Insights 中自动启用(从版本 2.7.1 开始),但直到管道后期才设置检测密钥。所以,只会捕获来自控制器/其他类的日志..."
    • 解决方法是将 ILogger logger, ILoggerFactory logFactory 移到 Configure()
    • 建议:将返回类型更改为 ILogger :内部静态 ILogger CreateLogger() => LoggerFactory.CreateLogger();用法:私有静态 ILogger log = Util.ApplicationLogging.CreateLogger();否则显式强制转换是强制性的
    • 但是如果静态类在 project/dll 中,而启动时没有对服务器项目的引用呢?
    【解决方案5】:

    首先,我同意NightOwl888 的回答。

    但作为一种选择(将其视为一种解决方法),您可以通过方法参数注入 ILogger 依赖项 => 因此将调用此静态方法的类应该负责提供 ILogger 的正确实现。

    static class YourClass
    {
        public static void DoSomething(ILogger logger)
        {
             // do something
             // call log.Log();
        }
    }
    

    【讨论】:

    • Nightowl 根本没有回答这个问题,而是发表了一个不受欢迎的演讲,我在我的问题中专门讨论了你的建议以及为什么我不能这样做。
    • 为了能够在任何地方记录,您必须在数万行代码中强制要求对每个方法/对象的记录器依赖。这对我来说听起来是个可怕的主意。在这种情况下,静态工厂是更明智的选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 2013-11-13
    • 2023-04-08
    • 2023-03-18
    相关资源
    最近更新 更多