在后台作业中使用记录器时出现异常 (ASP.NET Core / Serilog)

Exception while using logger in background job (ASP.NET Core / Serilog)

我在使用 ASP.NET 核心 WebApi 的即发即弃后台作业的上下文中使用记录器时遇到问题。 使用 logger.LogInformation("some message") 时。发生以下异常:

Newtonsoft.Json.JsonSerializationException: Could not create an instance of type Microsoft.Extensions.Logging.ILogger. Type is an interface or abstract class and cannot be instantiated. Path '', line 1, position 2.

很明显,hangfire 似乎无法根据应用程序 bootstrap.

中指示的参数解析记录器的实例化

我确定:

这是我的配置:

Program.cs

public static IWebHost BuildWebHost (string[] args) =>
                WebHost.CreateDefaultBuilder (args)
                .UseStartup<Startup> ()
                .UseSerilog ()
                .Build ();

Startup.cs

public Startup (IHostingEnvironment env) {
              Log.Logger = new LoggerConfiguration ()
                .MinimumLevel.Debug ()
                .MinimumLevel.Override ("Microsoft", LogEventLevel.Information)
                .Enrich.FromLogContext ()
                .WriteTo.Console ()
                .WriteTo.Debug ()
                .WriteTo.RollingFile (System.IO.Path.Combine ("logs/{Date}-logs.txt"))
                .CreateLogger ();
        }

public void ConfigureServices (IServiceCollection services) {
    services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(dispose: true));
    // ... registering other services
    services.AddMvc ();
    services.AddHangfire (conf => conf.UseSqlServerStorage (Configuration.GetConnectionString ("HangFire")));
}

public void Configure (IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider) {
            app.UseMvc ();

            //hangfire
            GlobalConfiguration.Configuration.UseActivator(new HangfireActivator(serviceProvider));
            app.UseHangfireServer ();
            app.UseHangfireDashboard ();
}

HangfireActivator

public class HangfireActivator : Hangfire.JobActivator {
        private readonly IServiceProvider _serviceProvider;

        public HangfireActivator (IServiceProvider serviceProvider) {
            _serviceProvider = serviceProvider;
        }

        public override object ActivateJob (Type type) {
            Debug.WriteLine("ActivateJob() => " + type.Name);
            return _serviceProvider.GetService (type);
        }
}

ValueController.cs

public class ValuesController : Controller {

        private readonly ILogger<ValuesController> logger;
        private readonly SomeService someService;

        public ValuesController (ILogger<ValuesController> logger, SomeService someService) {
            this.logger = logger;
            this.someService = someService;
        }

        [Route ("task")]
        public  JsonResult StartTask () {
            var server = new BackgroundJobServer ();
            BackgroundJob.Enqueue(() => logger.LogInformation("HELLO from background job instanciated logger"));
            return new JsonResult (new { Result = "task started" });
        }
}

我错过了什么吗? 对相关主题的任何帮助或 link 将不胜感激。感谢您的帮助!

我讨厌收到那种答案,但在这种情况下,通用 "do not use it" 比浪费时间寻找具体解决方案要好。至少不要将记录器提供程序用于后台作业(它可以为您提供什么优势?)。如果您不想看到 SerialLog 引用 - 将其包装到您自己的接口和实现中。 LoggerProvider 是一个巨大的抽象泄漏 (https://github.com/aspnet/EntityFrameworkCore/issues/10420),因为它不是您所期望的真正的 DI,而是具有奇特行为的服务定位器。

甚至更多:DI 根本无法提供良好的日志记录。良好的日志记录不仅是跟踪,而且是灵活的审计,并且始终 每个会话 例如假设您只想启用来自特定测试用户的详细日志记录,并将他的每个会话记录到特定文件(很自然的要求,试图重复用户问题并快速分析情况)。您无法使用希望在每个使用它的地方从 IoC 容器获取的记录器来实现这一点,相反,您应该在会话开始时构建它并仔细传递所有构造函数(有时是远程服务)"manually".

不要依赖DI。功能齐全。更像 node.js 而不是 MVC。就像 "less razor" 比 "more razor" 好(使用应该有动力)。

正如我所说,我也讨厌收到这样的答案。

侧不是...在 Main() 或 Startup classes 中使用静态日志配置 Serilog 记录器 class 使我能够使用 serilog 解决此错误...这有效对我来说:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
    .Enrich.FromLogContext()
    .WriteTo.ColoredConsole()
    .CreateLogger();

然后在 Hangfire 的 Enqueue() 方法中调用 Log.Information($"");