Logging 在后台作业中使用记录器时出现异常(ASP.NET Core/Serilog)
我在使用ASP.NET Core WebApi执行fire and forget后台作业时遇到问题。 使用logger.LogInformation(“某些消息”)时。出现以下异常: Newtonsoft.Json.JsonSerializationException:无法创建Microsoft.Extensions.Logging.ILogger类型的实例。类型是接口或抽象类,无法实例化。路径“”,第1行,位置2 显然,hangfire似乎无法根据应用程序引导中指示的参数解析记录器的实例 我确信:Logging 在后台作业中使用记录器时出现异常(ASP.NET Core/Serilog),logging,dependency-injection,asp.net-core,hangfire,Logging,Dependency Injection,Asp.net Core,Hangfire,我在使用ASP.NET Core WebApi执行fire and forget后台作业时遇到问题。 使用logger.LogInformation(“某些消息”)时。出现以下异常: Newtonsoft.Json.JsonSerializationException:无法创建Microsoft.Extensions.Logging.ILogger类型的实例。类型是接口或抽象类,无法实例化。路径“”,第1行,位置2 显然,hangfire似乎无法根据应用程序引导中指示的参数解析记录器的实例 我确
- Hangfire已正确配置并工作
- 记录器(使用Serilog)在与应用程序(不在backgorund)相同的范围内使用时工作
- 服务注入适用于ILogger以外的其他服务的后台作业
public static IWebHost BuildWebHost (string[] args) =>
WebHost.CreateDefaultBuilder (args)
.UseStartup<Startup> ()
.UseSerilog ()
.Build ();
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 ();
}
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" });
}
}
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 static IWebHost BuildWebHost (string[] args) =>
WebHost.CreateDefaultBuilder (args)
.UseStartup<Startup> ()
.UseSerilog ()
.Build ();
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 ();
}
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" });
}
}
公共类值控制器:控制器{
专用只读ILogger记录器;
私有只读SomeService SomeService;
公共价值控制器(ILogger logger,SomeService SomeService){
this.logger=记录器;
this.someService=someService;
}
[路线(“任务”)]
公共JsonResult StartTask(){
var server=newbackgroundjobserver();
BackgroundJob.Enqueue(()=>logger.LogInformation(“来自后台作业实例记录器的HELLO”);
返回新的JsonResult(new{Result=“task start”});
}
}
我错过什么了吗?
任何相关主题的帮助或链接都将不胜感激。谢谢你的帮助 我讨厌收到这样的答案,但在这种情况下,通用的“不要使用它”比浪费时间寻找具体的解决方案要好。只是至少不要在后台工作中使用记录器提供程序(它能为您提供什么优势?)。如果您不想看到SerialLog引用,请将其包装到您自己的接口和实现中。LoggerProvider是一个巨大的抽象漏洞(),因为它不是您所期望的真正的DI,而是具有奇特行为的服务定位器 更重要的是,DI根本无法提供良好的日志记录。良好的日志记录不仅是跟踪,而且是灵活的审计,并且始终是每个会话的日志记录。例如,假设您希望只启用特定测试用户的详细日志记录,并将其每个会话记录到特定文件中(这是很自然的要求,尝试重复用户问题并快速分析情况)。使用logger无法实现这一点,您希望在每个使用它的地方都能从IoC容器中获得它,相反,您应该在会话开始时构造它,并“手动”仔细地通过所有构造函数(有时是远程服务) 不要依赖DI。发挥作用。更像node.js,而不是MVC。这就像“少用剃须刀”比“多用剃须刀”好一样(使用应该有动机)
正如我所说,我也讨厌收到这样的回答。方不。。。使用静态日志类在Main()或Startup类中配置Serilog记录器使我能够使用Serilog绕过此错误。。。这对我很有用:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.ColoredConsole()
.CreateLogger();
然后在Hangfire的Enqueue()方法中,只需调用Log.Information($“”) 谢谢你的洞察力。令人遗憾的是,Hangfire让Serilog听起来像是用ASP.NETCore的DI模块开箱即用。。。