在使用ASP.NET Core WebApi进行即发即弃后台作业的上下文中使用记录器时遇到问题。 使用logger.LogInformation(“some message”)时。发生以下异常:
Newtonsoft.Json.JsonSerializationException:无法创建Microsoft.Extensions.Logging.ILogger类型的实例。 Type是接口或抽象类,无法实例化。路径'',第1行,第2位。
很明显,似乎hangfire无法根据应用程序引导程序中指示的参数来解决记录器的实例。
我确信:
这是我的配置:
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" });
}
}
我错过了什么吗? 任何帮助或相关主题的链接将不胜感激。谢谢你的帮助!
答案 0 :(得分:1)
我讨厌接受这样的答案,但是这种情况下通用的“不使用它”比浪费时间找到特定的解决方案更好。只是不要使用记录器提供程序至少用于后台作业(它可以为您提供哪些优势?)。如果您不想查看SerialLog引用 - 将其包装到您自己的接口和实现中。 LoggerProvider是一个巨大的抽象泄漏(https://github.com/aspnet/EntityFrameworkCore/issues/10420),因为它不是一个真正的DI,你可以期待但服务定位器具有奇特的行为。
甚至更多:DI根本无法提供良好的日志记录。良好的日志记录不仅仅是跟踪而是灵活的审计,并且总是每个会话,例如想象一下,您只想从特定测试用户启用详细日志记录,并将每个会话记录到特定文件(非常自然的要求,尝试重复用户问题并快速分析情况)。您无法通过您希望从IoC容器中使用它的每个位置获得的记录器实现此目的,相反,您应该在会话开始时构建它并“仔细”通过所有构造函数(有时是远程服务)“手动”。
不要依赖DI。功能齐全。更像node.js而不是MVC。这就像“少剃刀”比“更多剃刀”更好(使用应该是动机)。
正如我所说,我也讨厌得到这样的答案。
答案 1 :(得分:0)
侧面不是...使用静态Log类在Main()或Startup类中配置Serilog记录器,这使我能够解决serilog的错误...这对我有用:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.ColoredConsole()
.CreateLogger();
然后在Hangfire的Enqueue()方法中只需调用Log.Information($“”);