Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Logging 在后台作业中使用记录器时出现异常(ASP.NET Core/Serilog)_Logging_Dependency Injection_Asp.net Core_Hangfire - Fatal编程技术网

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

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似乎无法根据应用程序引导中指示的参数解析记录器的实例 我确

我在使用ASP.NET Core WebApi执行fire and forget后台作业时遇到问题。 使用logger.LogInformation(“某些消息”)时。出现以下异常:

Newtonsoft.Json.JsonSerializationException:无法创建Microsoft.Extensions.Logging.ILogger类型的实例。类型是接口或抽象类,无法实例化。路径“”,第1行,位置2

显然,hangfire似乎无法根据应用程序引导中指示的参数解析记录器的实例

我确信:

  • Hangfire已正确配置并工作
  • 记录器(使用Serilog)在与应用程序(不在backgorund)相同的范围内使用时工作
  • 服务注入适用于ILogger以外的其他服务的后台作业
以下是我的配置:

Program.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" });
        }
}
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模块开箱即用。。。