Umbraco 10升级后启动报logger参数为空异常如何解决
问题现象
- 项目从Umbraco 9升级至Umbraco 10后,启动时抛出异常:"Value cannot be null. (Parameter 'logger')"
- 移除Program.cs中CreateHostBuilder方法内的如下Serilog配置代码后,异常消失:
.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration .ReadFrom.Configuration(hostingContext.Configuration) .WriteTo.ApplicationInsights(new TelemetryConfiguration { InstrumentationKey = hostingContext.Configuration["ApplicationInsights:InstrumentationKey"] }, TelemetryConverter.Traces));
- 异常堆栈跟踪:
Umbraco.Cms.Web.Common.Logging.RegisteredReloadableLogger..ctor(ReloadableLogger logger) Umbraco.Extensions.ServiceCollectionExtensions+<>c__DisplayClass1_0.<AddLogger>b__0(IServiceProvider sp) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType) System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>.GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<T>(IServiceProvider provider) Umbraco.Extensions.ServiceCollectionExtensions+<>c.<AddLogger>b__1_2(IServiceProvider sp) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType) System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>.GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType) Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<T>(IServiceProvider provider) Umbraco.Cms.Web.Common.ModelsBuilder.RefreshingRazorViewEngine..ctor(Func<IRazorViewEngine> defaultRazorViewEngineFactory, InMemoryModelFactory inMemoryModelFactory) Umbraco.Extensions.UmbracoBuilderDependencyInjectionExtensions+<>c__DisplayClass1_0.<AddInMemoryModelsRazorEngine>b__0(IServiceProvider s) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor<TArgument, TResult>.VisitCallSite(ServiceCallSite callSite, TArgument argument) Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType) System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>.GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<T>(IServiceProvider provider) Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.GetOrCreateDataSource(IEndpointRouteBuilder endpoints) Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapControllerRoute(IEndpointRouteBuilder endpoints, string name, string pattern, object defaults, object constraints, object dataTokens) Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapAreaControllerRoute(IEndpointRouteBuilder endpoints, string name, string areaName, string pattern, object defaults, object constraints, object dataTokens) Umbraco.Extensions.EndpointRouteBuilderExtensions.MapUmbracoRoute(IEndpointRouteBuilder endpoints, Type controllerType, string rootSegment, string areaName, string prefixPathSegment, string defaultAction, bool includeControllerNameInRoute, object constraints) Umbraco.Cms.Web.BackOffice.Routing.BackOfficeAreaRoutes.MapMinimalBackOffice(IEndpointRouteBuilder endpoints) Umbraco.Cms.Web.BackOffice.Routing.BackOfficeAreaRoutes.CreateRoutes(IEndpointRouteBuilder endpoints) Umbraco.Extensions.UmbracoApplicationBuilderExtensions.UseBackOfficeEndpoints(IUmbracoEndpointBuilderContext app) JemOgFix.Webshop.Startup+<>c.<Configure>b__4_2(IUmbracoEndpointBuilderContext u) in Startup.cs + u.UseBackOfficeEndpoints(); Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions.UseEndpoints(IApplicationBuilder builder, Action<IEndpointRouteBuilder> configure) Umbraco.Cms.Web.Common.ApplicationBuilder.UmbracoApplicationBuilder.WithEndpoints(Action<IUmbracoEndpointBuilderContext> configureUmbraco) JemOgFix.Webshop.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env) in Startup.cs + app.UseUmbraco() System.RuntimeMethodHandle.InvokeMethod(object target, ref Span<object> arguments, Signature sig, bool constructor, bool wrapExceptions) System.Reflection.RuntimeMethodInfo.Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(object instance, IApplicationBuilder builder) Microsoft.AspNetCore.Hosting.ConfigureBuilder+<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder) Microsoft.AspNetCore.Hosting.GenericWebHostBuilder+<>c__DisplayClass15_0.<UseStartup>b__1(IApplicationBuilder app) Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter+<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder) Microsoft.ApplicationInsights.AspNetCore.ApplicationInsightsStartupFilter+<>c__DisplayClass2_0.<Configure>b__0(IApplicationBuilder app) Microsoft.AspNetCore.Server.IIS.Core.IISServerSetupFilter+<>c__DisplayClass2_0.<Configure>b__0(IApplicationBuilder app) Microsoft.AspNetCore.HostFilteringStartupFilter+<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app) Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken) Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken) Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) JemOgFix.Webshop.Program.Main(string[] args) in Program.cs + => CreateHostBuilder(args)
故障原因
Umbraco 10 重构了内部日志初始化流程,依赖可重载的ReloadableLogger作为启动早期的日志实例,等宿主构建完成后再替换为正式日志配置。
原有代码存在两个问题:
- 手动
new TelemetryConfiguration()创建的实例未完成完整初始化,会导致Serilog接入时提前触发依赖解析,打断Umbraco的日志加载流程,最终传入RegisteredReloadableLogger构造函数的logger实例为null - 调用
UseSerilog时未开启writeToProviders参数,会覆盖Umbraco默认注册的日志提供器,导致后续框架内部无法解析到日志实例
修复方案
两种方案二选一即可,优先使用配置文件方式,兼容性更好。
方案1:修改代码层Serilog配置
将原有UseSerilog段替换为如下代码,不要手动实例化空的TelemetryConfiguration,同时开启必要的参数保证Umbraco日志流程正常:
.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration .ReadFrom.Configuration(hostingContext.Configuration) .WriteTo.ApplicationInsights( // 用CreateDefault自动加载配置中的ApplicationInsights节点,无需手动赋值InstrumentationKey TelemetryConfiguration.CreateDefault(), TelemetryConverter.Traces), writeToProviders: true, preserveStaticLogger: false);
如果需要手动指定InstrumentationKey,可以在CreateDefault()后赋值,不要直接new空对象:
var telemetryConfig = TelemetryConfiguration.CreateDefault(); telemetryConfig.InstrumentationKey = hostingContext.Configuration["ApplicationInsights:InstrumentationKey"];
方案2:将ApplicationInsights配置移入配置文件
这种方式完全不需要在代码中硬编码Sink配置,不会干扰Umbraco的日志初始化流程:
- 修改Program.cs中的UseSerilog配置,仅保留配置读取逻辑:
.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration), writeToProviders: true);
- 在appsettings.json的Serilog节点下添加ApplicationInsights的Sink配置:
{ "Serilog": { "MinimumLevel": "Information", "WriteTo": [ { "Name": "ApplicationInsights", "Args": { "telemetryConverter": "Serilog.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights", "instrumentationKey": "你的ApplicationInsights检测密钥" } } ] } }
修改完成后重新启动项目,异常会消失,日志可正常写入ApplicationInsights,同时Umbraco后台功能不受影响。
内容的提问来源于stack exchange,提问作者Ekaterina
相关产品推荐
相关产品推荐

