Merge Netcore: Use serilog to log all messages and use appsettings as config into Netcore/feature/migrate logging

This commit is contained in:
Mole
2020-09-22 15:09:16 +02:00
23 changed files with 362 additions and 305 deletions

View File

@@ -7,7 +7,5 @@
/// The physical path where logs are stored
/// </summary>
string LogDirectory { get; }
string LogConfigurationFile { get; }
string UserLogConfigurationFile { get; }
}
}

View File

@@ -4,17 +4,11 @@ namespace Umbraco.Core.Logging
{
public class LoggingConfiguration : ILoggingConfiguration
{
public LoggingConfiguration(string logDirectory, string logConfigurationFile, string userLogConfigurationFile)
public LoggingConfiguration(string logDirectory)
{
LogDirectory = logDirectory ?? throw new ArgumentNullException(nameof(logDirectory));
LogConfigurationFile = logConfigurationFile ?? throw new ArgumentNullException(nameof(logConfigurationFile));
UserLogConfigurationFile = userLogConfigurationFile ?? throw new ArgumentNullException(nameof(userLogConfigurationFile));
}
public string LogDirectory { get; }
public string LogConfigurationFile { get; }
public string UserLogConfigurationFile { get; }
}
}

View File

@@ -26,7 +26,6 @@ namespace Umbraco.Core.Composing
/// <param name="umbracoServiceProviderFactory"></param>
/// <returns></returns>
public static IHostBuilder UseUmbraco(this IHostBuilder builder, UmbracoServiceProviderFactory umbracoServiceProviderFactory)
=> builder.UseServiceProviderFactory(umbracoServiceProviderFactory)
.UseSerilog();
=> builder.UseServiceProviderFactory(umbracoServiceProviderFactory);
}
}

View File

@@ -7,7 +7,6 @@ using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting;
using Serilog.Formatting.Compact;
using Umbraco.Core.IO;
using Umbraco.Core.Hosting;
using Umbraco.Core.Logging.Serilog.Enrichers;
@@ -48,6 +47,11 @@ namespace Umbraco.Core.Logging.Serilog
.Enrich.With<Log4NetLevelMapperEnricher>()
.Enrich.FromLogContext(); // allows us to dynamically enrich
logConfig.WriteTo.UmbracoFile(
Path.Combine(loggingConfiguration.LogDirectory, $"UmbracoTraceLog.{Environment.MachineName}..json")
);
return logConfig;
}
@@ -61,7 +65,7 @@ namespace Umbraco.Core.Logging.Serilog
public static LoggerConfiguration OutputDefaultTextFile(
this LoggerConfiguration logConfig,
IHostingEnvironment hostingEnvironment,
ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null)
LogEventLevel minimumLevel = LogEventLevel.Verbose)
{
//Main .txt logfile - in similar format to older Log4Net output
//Ends with ..txt as Date is inserted before file extension substring
@@ -79,18 +83,25 @@ namespace Umbraco.Core.Logging.Serilog
/// <remarks>
/// Used in config - If renamed or moved to other assembly the config file also has be updated.
/// </remarks>
public static LoggerConfiguration File(this LoggerSinkConfiguration configuration, ITextFormatter formatter,
public static LoggerConfiguration UmbracoFile(this LoggerSinkConfiguration configuration,
string path,
ITextFormatter formatter = null,
LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose,
LoggingLevelSwitch levelSwitch = null,
long? fileSizeLimitBytes = 1073741824,
TimeSpan? flushToDiskInterval = null,
RollingInterval rollingInterval = RollingInterval.Infinite,
RollingInterval rollingInterval = RollingInterval.Day,
bool rollOnFileSizeLimit = false,
int? retainedFileCountLimit = 31,
Encoding encoding = null
)
{
if (formatter is null)
{
formatter = new CompactJsonFormatter();
}
return configuration.Async(
asyncConfiguration => asyncConfiguration.Map(AppDomainId, (_,mapConfiguration) =>
mapConfiguration.File(
@@ -136,34 +147,5 @@ namespace Umbraco.Core.Logging.Serilog
return logConfig;
}
/// <summary>
/// Reads settings from /config/serilog.config
/// That allows the main logging pipeline to be configured
/// </summary>
/// <param name="logConfig">A Serilog LoggerConfiguration</param>
/// <param name="loggingConfiguration"></param>
public static LoggerConfiguration ReadFromConfigFile(this LoggerConfiguration logConfig, ILoggingConfiguration loggingConfiguration)
{
//Read from main serilog.config file
logConfig.ReadFrom.AppSettings(filePath: loggingConfiguration.LogConfigurationFile);
return logConfig;
}
/// <summary>
/// Reads settings from /config/serilog.user.config
/// That allows a separate logging pipeline to be configured that will not affect the main Umbraco log
/// </summary>
/// <param name="logConfig">A Serilog LoggerConfiguration</param>
/// <param name="loggingConfiguration"></param>
public static LoggerConfiguration ReadFromUserConfigFile(this LoggerConfiguration logConfig, ILoggingConfiguration loggingConfiguration)
{
//A nested logger - where any user configured sinks via config can not effect the main 'umbraco' logger above
logConfig.WriteTo.Logger(cfg =>
cfg.ReadFrom.AppSettings(filePath: loggingConfiguration.UserLogConfigurationFile));
return logConfig;
}
}
}

View File

@@ -0,0 +1,221 @@
using System;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Events;
using Serilog.Extensions.Logging;
using Umbraco.Core.Hosting;
namespace Umbraco.Core.Logging.Serilog
{
///<summary>
/// Implements <see cref="ILogger"/> on top of Serilog.
///</summary>
public class SerilogLogger : IDisposable
{
public global::Serilog.ILogger SerilogLog { get; }
/// <summary>
/// Initialize a new instance of the <see cref="SerilogLogger"/> class with a configuration file.
/// </summary>
/// <param name="logConfigFile"></param>
public SerilogLogger(FileInfo logConfigFile)
{
SerilogLog = new LoggerConfiguration()
.ReadFrom.AppSettings(filePath: logConfigFile.FullName)
.CreateLogger();
}
public SerilogLogger(LoggerConfiguration logConfig)
{
//Configure Serilog static global logger with config passed in
SerilogLog = logConfig.CreateLogger();
}
/// <summary>
/// Creates a logger with some pre-defined configuration and remainder from config file
/// </summary>
/// <remarks>Used by UmbracoApplicationBase to get its logger.</remarks>
public static SerilogLogger CreateWithDefaultConfiguration(
IHostingEnvironment hostingEnvironment,
ILoggingConfiguration loggingConfiguration,
IConfiguration configuration)
{
var loggerConfig = new LoggerConfiguration()
.MinimalConfiguration(hostingEnvironment, loggingConfiguration)
.ReadFrom.Configuration(configuration);
return new SerilogLogger(loggerConfig);
}
/// <summary>
/// Gets a contextualized logger.
/// </summary>
private global::Serilog.ILogger LoggerFor(Type reporting)
=> SerilogLog.ForContext(reporting);
/// <summary>
/// Maps Umbraco's log level to Serilog's.
/// </summary>
private LogEventLevel MapLevel(LogLevel level)
{
switch (level)
{
case LogLevel.Debug:
return LogEventLevel.Debug;
case LogLevel.Error:
return LogEventLevel.Error;
case LogLevel.Fatal:
return LogEventLevel.Fatal;
case LogLevel.Information:
return LogEventLevel.Information;
case LogLevel.Verbose:
return LogEventLevel.Verbose;
case LogLevel.Warning:
return LogEventLevel.Warning;
}
throw new NotSupportedException($"LogLevel \"{level}\" is not supported.");
}
/// <inheritdoc/>
public bool IsEnabled(Type reporting, LogLevel level)
=> LoggerFor(reporting).IsEnabled(MapLevel(level));
/// <inheritdoc/>
public void Fatal(Type reporting, Exception exception, string message)
{
var logger = LoggerFor(reporting);
logger.Fatal(exception, message);
}
/// <inheritdoc/>
public void Fatal(Type reporting, Exception exception)
{
var logger = LoggerFor(reporting);
var message = "Exception.";
logger.Fatal(exception, message);
}
/// <inheritdoc/>
public void Fatal(Type reporting, string message)
{
LoggerFor(reporting).Fatal(message);
}
/// <inheritdoc/>
public void Fatal(Type reporting, string messageTemplate, params object[] propertyValues)
{
LoggerFor(reporting).Fatal(messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Fatal(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
var logger = LoggerFor(reporting);
logger.Fatal(exception, messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Error(Type reporting, Exception exception, string message)
{
var logger = LoggerFor(reporting);
logger.Error(exception, message);
}
/// <inheritdoc/>
public void Error(Type reporting, Exception exception)
{
var logger = LoggerFor(reporting);
var message = "Exception";
logger.Error(exception, message);
}
/// <inheritdoc/>
public void Error(Type reporting, string message)
{
LoggerFor(reporting).Error(message);
}
/// <inheritdoc/>
public void Error(Type reporting, string messageTemplate, params object[] propertyValues)
{
LoggerFor(reporting).Error(messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Error(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
var logger = LoggerFor(reporting);
logger.Error(exception, messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Warn(Type reporting, string message)
{
LoggerFor(reporting).Warning(message);
}
/// <inheritdoc/>
public void Warn(Type reporting, string message, params object[] propertyValues)
{
LoggerFor(reporting).Warning(message, propertyValues);
}
/// <inheritdoc/>
public void Warn(Type reporting, Exception exception, string message)
{
LoggerFor(reporting).Warning(exception, message);
}
/// <inheritdoc/>
public void Warn(Type reporting, Exception exception, string messageTemplate, params object[] propertyValues)
{
LoggerFor(reporting).Warning(exception, messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Info(Type reporting, string message)
{
LoggerFor(reporting).Information(message);
}
/// <inheritdoc/>
public void Info(Type reporting, string messageTemplate, params object[] propertyValues)
{
LoggerFor(reporting).Information(messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Debug(Type reporting, string message)
{
LoggerFor(reporting).Debug(message);
}
/// <inheritdoc/>
public void Debug(Type reporting, string messageTemplate, params object[] propertyValues)
{
LoggerFor(reporting).Debug(messageTemplate, propertyValues);
}
/// <inheritdoc/>
public void Verbose(Type reporting, string message)
{
LoggerFor(reporting).Verbose(message);
}
/// <inheritdoc/>
public void Verbose(Type reporting, string messageTemplate, params object[] propertyValues)
{
LoggerFor(reporting).Verbose(messageTemplate, propertyValues);
}
public void Dispose()
{
SerilogLog.DisposeIfDisposable();
}
}
}

View File

@@ -11,16 +11,6 @@ namespace Umbraco.Core.Logging.Viewer
{
public void Compose(Composition composition)
{
composition.RegisterUnique<ILoggingConfiguration>(factory =>
{
var hostingEnvironment = factory.GetInstance<IHostingEnvironment>();
return new LoggingConfiguration(
Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "App_Data", "Logs"),
Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config", "serilog.config"),
Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config", "serilog.user.config"));
});
composition.RegisterUnique<ILogViewerConfig, LogViewerConfig>();
composition.SetLogViewer<SerilogJsonLogViewer>();
composition.RegisterUnique<ILogViewer>(factory =>

View File

@@ -34,6 +34,7 @@
<PackageReference Include="Serilog.Formatting.Compact" Version="1.1.0" />
<PackageReference Include="Serilog.Formatting.Compact.Reader" Version="1.0.3" />
<PackageReference Include="Serilog.Settings.AppSettings" Version="2.2.2" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Map" Version="1.0.0" />

View File

@@ -146,9 +146,7 @@ namespace Umbraco.Tests.Common
{
hostingEnv = hostingEnv ?? GetHostingEnvironment();
return new LoggingConfiguration(
Path.Combine(hostingEnv.ApplicationPhysicalPath, "App_Data","Logs"),
Path.Combine(hostingEnv.ApplicationPhysicalPath, "config","serilog.config"),
Path.Combine(hostingEnv.ApplicationPhysicalPath, "config","serilog.user.config"));
Path.Combine(hostingEnv.ApplicationPhysicalPath, "umbraco","logs"));
}
}
}

View File

@@ -123,7 +123,7 @@ namespace Umbraco.Tests.Integration
// Add it!
services.AddUmbracoConfiguration(hostContext.Configuration);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, AppCaches.NoCache, testHelper.GetLoggingConfiguration(), out _);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, AppCaches.NoCache, testHelper.GetLoggingConfiguration(), hostContext.Configuration,out _);
});
var host = await hostBuilder.StartAsync();
@@ -163,7 +163,7 @@ namespace Umbraco.Tests.Integration
// Add it!
services.AddUmbracoConfiguration(hostContext.Configuration);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, AppCaches.NoCache, testHelper.GetLoggingConfiguration(), out _);
services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly, AppCaches.NoCache, testHelper.GetLoggingConfiguration(),hostContext.Configuration, out _);
});
var host = await hostBuilder.StartAsync();

View File

@@ -22,37 +22,38 @@ namespace Umbraco.Tests.Integration.TestServerTest
Action<CoreRuntime, RuntimeEssentialsEventArgs> dbInstallEventHandler)
{
return builder.AddWith(nameof(global::Umbraco.Web.Common.Builder.UmbracoBuilderExtensions.WithCore),
() =>
{
builder.Services.AddUmbracoCore(
builder.WebHostEnvironment,
container,
typeof(UmbracoBuilderExtensions).Assembly,
AppCaches.NoCache, // Disable caches in integration tests
testHelper.GetLoggingConfiguration(),
(globalSettings, connectionStrings, umbVersion, ioHelper, logger, factory, profiler, hostingEnv,
backOfficeInfo, typeFinder, appCaches, dbProviderFactoryCreator) =>
{
var runtime = UmbracoIntegrationTest.CreateTestRuntime(
globalSettings,
connectionStrings,
umbVersion,
ioHelper,
logger,
factory,
profiler,
hostingEnv,
backOfficeInfo,
typeFinder,
appCaches,
dbProviderFactoryCreator,
testHelper.MainDom, // SimpleMainDom
dbInstallEventHandler); // DB Installation event handler
() =>
{
builder.Services.AddUmbracoCore(
builder.WebHostEnvironment,
container,
typeof(UmbracoBuilderExtensions).Assembly,
AppCaches.NoCache, // Disable caches in integration tests
testHelper.GetLoggingConfiguration(),
builder.Config,
// TODO: Yep that's extremely ugly
(globalSettings, connectionStrings, umbVersion, ioHelper, logger, factory, profiler, hostingEnv, backOfficeInfo, typeFinder, appCaches, dbProviderFactoryCreator) =>
{
var runtime = UmbracoIntegrationTest.CreateTestRuntime(
globalSettings,
connectionStrings,
umbVersion,
ioHelper,
logger,
factory,
profiler,
hostingEnv,
backOfficeInfo,
typeFinder,
appCaches,
dbProviderFactoryCreator,
testHelper.MainDom, // SimpleMainDom
dbInstallEventHandler); // DB Installation event handler
return runtime;
},
out _);
});
return runtime;
},
out _);
});
}
}
}

View File

@@ -236,6 +236,7 @@ namespace Umbraco.Tests.Integration.Testing
GetType().Assembly,
AppCaches.NoCache, // Disable caches for integration tests
TestHelper.GetLoggingConfiguration(),
Configuration,
CreateTestRuntime,
out _);

View File

@@ -26,7 +26,7 @@ namespace Umbraco.Web.Common.Builder
=> builder.AddWith(nameof(WithConfiguration), () => builder.Services.AddUmbracoConfiguration(builder.Config));
public static IUmbracoBuilder WithCore(this IUmbracoBuilder builder)
=> builder.AddWith(nameof(WithCore), () => builder.Services.AddUmbracoCore(builder.WebHostEnvironment, out _));
=> builder.AddWith(nameof(WithCore), () => builder.Services.AddUmbracoCore(builder.WebHostEnvironment, builder.Config, out _));
public static IUmbracoBuilder WithMiniProfiler(this IUmbracoBuilder builder)
=> builder.AddWith(nameof(WithMiniProfiler), () =>

View File

@@ -103,19 +103,20 @@ namespace Umbraco.Extensions
/// <param name="umbContainer"></param>
/// <param name="entryAssembly"></param>
/// <param name="appCaches"></param>
/// <param name="httpContextAccessor"></param>
/// <param name="loggingConfiguration"></param>
/// <param name="factory"></param>
/// <param name="configuration"></param>
/// <param name="httpContextAccessor"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoCore(
this IServiceCollection services,
public static IServiceCollection AddUmbracoCore(this IServiceCollection services,
IWebHostEnvironment webHostEnvironment,
IRegister umbContainer,
Assembly entryAssembly,
AppCaches appCaches,
ILoggingConfiguration loggingConfiguration,
IConfiguration configuration,
out IFactory factory)
=> services.AddUmbracoCore(webHostEnvironment, umbContainer, entryAssembly, appCaches, loggingConfiguration, GetCoreRuntime, out factory);
=> services.AddUmbracoCore(webHostEnvironment, umbContainer, entryAssembly, appCaches, loggingConfiguration, configuration, GetCoreRuntime, out factory);
/// <summary>
/// Adds the Umbraco Configuration requirements
@@ -159,10 +160,11 @@ namespace Umbraco.Extensions
/// </summary>
/// <param name="services"></param>
/// <param name="webHostEnvironment"></param>
/// <param name="configuration"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment)
public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IConfiguration configuration)
{
return services.AddUmbracoCore(webHostEnvironment, out _);
return services.AddUmbracoCore(webHostEnvironment, configuration, out _);
}
/// <summary>
@@ -170,9 +172,10 @@ namespace Umbraco.Extensions
/// </summary>
/// <param name="services"></param>
/// <param name="webHostEnvironment"></param>
/// <param name="configuration"></param>
/// <param name="factory"></param>
/// <returns></returns>
public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, out IFactory factory)
public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IConfiguration configuration, out IFactory factory)
{
if (!UmbracoServiceProviderFactory.IsActive)
throw new InvalidOperationException("Ensure to add UseUmbraco() in your Program.cs after ConfigureWebHostDefaults to enable Umbraco's service provider factory");
@@ -180,12 +183,11 @@ namespace Umbraco.Extensions
var umbContainer = UmbracoServiceProviderFactory.UmbracoContainer;
var loggingConfig = new LoggingConfiguration(
Path.Combine(webHostEnvironment.ContentRootPath, "App_Data", "Logs"),
Path.Combine(webHostEnvironment.ContentRootPath, "config", "serilog.config"),
Path.Combine(webHostEnvironment.ContentRootPath, "config", "serilog.user.config"));
Path.Combine(webHostEnvironment.ContentRootPath, "umbraco", "logs"));
IHttpContextAccessor httpContextAccessor = new HttpContextAccessor();
services.AddSingleton<IHttpContextAccessor>(httpContextAccessor);
services.AddSingleton<ILoggingConfiguration>(loggingConfig);
var requestCache = new GenericDictionaryRequestAppCache(() => httpContextAccessor.HttpContext?.Items);
var appCaches = new AppCaches(
@@ -198,6 +200,7 @@ namespace Umbraco.Extensions
Assembly.GetEntryAssembly(),
appCaches,
loggingConfig,
configuration,
GetCoreRuntime,
out factory);
@@ -224,6 +227,7 @@ namespace Umbraco.Extensions
Assembly entryAssembly,
AppCaches appCaches,
ILoggingConfiguration loggingConfiguration,
IConfiguration configuration,
//TODO: Yep that's extremely ugly
Func<GlobalSettings, ConnectionStrings, IUmbracoVersion, IIOHelper, ILogger, ILoggerFactory, IProfiler, IHostingEnvironment, IBackOfficeInfo, ITypeFinder, AppCaches, IDbProviderFactoryCreator, IRuntime> getRuntime,
out IFactory factory)
@@ -267,6 +271,7 @@ namespace Umbraco.Extensions
hostingSettings,
webHostEnvironment,
loggingConfiguration,
configuration,
out var logger, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler);
var umbracoVersion = new UmbracoVersion();
@@ -288,6 +293,13 @@ namespace Umbraco.Extensions
factory = coreRuntime.Configure(container);
services.Configure<HostingSettings>(hostingSettings =>
{
hostingSettings.Debug = false;
});
return services;
}
@@ -339,6 +351,7 @@ namespace Umbraco.Extensions
IOptionsMonitor<HostingSettings> hostingSettings,
IWebHostEnvironment webHostEnvironment,
ILoggingConfiguration loggingConfiguration,
IConfiguration configuration,
out ILogger logger,
out IIOHelper ioHelper,
out Core.Hosting.IHostingEnvironment hostingEnvironment,
@@ -350,8 +363,7 @@ namespace Umbraco.Extensions
hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment);
ioHelper = new IOHelper(hostingEnvironment);
logger = AddLogger(services, hostingEnvironment, loggingConfiguration);
logger = AddLogger(services, hostingEnvironment, loggingConfiguration, configuration);
backOfficeInfo = new AspNetCoreBackOfficeInfo(globalSettings);
profiler = GetWebProfiler(hostingEnvironment);
@@ -362,24 +374,29 @@ namespace Umbraco.Extensions
/// Create and configure the logger
/// </summary>
/// <param name="hostingEnvironment"></param>
private static ILogger AddLogger(IServiceCollection services, Core.Hosting.IHostingEnvironment hostingEnvironment, ILoggingConfiguration loggingConfiguration)
private static ILogger AddLogger(IServiceCollection services, Core.Hosting.IHostingEnvironment hostingEnvironment, ILoggingConfiguration loggingConfiguration, IConfiguration configuration)
{
// // Create a serilog logger
// var logger = SerilogLogger<object>.CreateWithDefaultConfiguration(hostingEnvironment, loggingConfiguration);
//
// // Wire up all the bits that serilog needs. We need to use our own code since the Serilog ext methods don't cater to our needs since
// // we don't want to use the global serilog `Log` object and we don't have our own ILogger implementation before the HostBuilder runs which
// // is the only other option that these ext methods allow.
// // I have created a PR to make this nicer https://github.com/serilog/serilog-extensions-hosting/pull/19 but we'll need to wait for that.
// // Also see : https://github.com/serilog/serilog-extensions-hosting/blob/dev/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs
//
// services.AddSingleton<ILoggerFactory>(services => new SerilogLoggerFactory(logger.SerilogLog, false));
// Create a serilog logger
var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, loggingConfiguration, configuration);
var factory = LoggerFactory.Create(builder =>
// This is nessasary to pick up all the loggins to MS ILogger.
Log.Logger = logger.SerilogLog;
// Wire up all the bits that serilog needs. We need to use our own code since the Serilog ext methods don't cater to our needs since
// we don't want to use the global serilog `Log` object and we don't have our own ILogger implementation before the HostBuilder runs which
// is the only other option that these ext methods allow.
// I have created a PR to make this nicer https://github.com/serilog/serilog-extensions-hosting/pull/19 but we'll need to wait for that.
// Also see : https://github.com/serilog/serilog-extensions-hosting/blob/dev/src/Serilog.Extensions.Hosting/SerilogHostBuilderExtensions.cs
services.AddLogging(configure =>
{
builder.AddSerilog();
configure.AddSerilog(logger.SerilogLog, false);
});
//services.AddSingleton<ILoggerFactory>(services => new SerilogLoggerFactory(logger.SerilogLog, false));
// // This won't (and shouldn't) take ownership of the logger.
// services.AddSingleton(logger.SerilogLog);
//
@@ -391,8 +408,8 @@ namespace Umbraco.Extensions
//
// // Consumed by user code
// services.AddSingleton<IDiagnosticContext>(diagnosticContext);
return factory.CreateLogger("FakeSiriLogger");
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger("Generic Logger");
}
private static IProfiler GetWebProfiler(Umbraco.Core.Hosting.IHostingEnvironment hostingEnvironment)

View File

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Umbraco.Core.Composing;
namespace Umbraco.Web.UI.NetCore
@@ -15,6 +16,10 @@ namespace Umbraco.Web.UI.NetCore
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(x =>
{
x.ClearProviders();
})
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); })
.UseUmbraco();
}

View File

@@ -59,11 +59,11 @@
<!-- We don't want to include the generated files, they will throw a lot of errors -->
<ItemGroup>
<None Remove="Umbraco/Models/all.generated.cs"/>
<Compile Remove="Umbraco/Models/all.generated.cs"/>
<None Remove="Umbraco/Models/models.generated.cs"/>
<None Remove="Umbraco/Models/all.generated.cs" />
<Compile Remove="Umbraco/Models/all.generated.cs" />
<None Remove="Umbraco/Models/models.generated.cs" />
<Compile Remove="Umbraco/Models/models.generated.cs" />
<Folder Remove="Umbraco/Models/Compiled"/>
<Folder Remove="Umbraco/Models/Compiled" />
<None Remove="Umbraco/Models/Compiled/**" />
<None Remove="Umbraco/Models/all.dll.path" />
<None Remove="Umbraco/Models/models.hash" />

View File

@@ -1,4 +0,0 @@
@inherits Umbraco.Web.Common.AspNetCore.UmbracoViewPage
@{
Layout = null;
}

View File

@@ -1,4 +1,21 @@
{
"Serilog": {
"MinimumLevel": {
"Default": "Information"
},
"WriteTo":[
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "Console"
}
]
}
}
]
},
"Umbraco": {
"CMS": {
"Global":{

View File

@@ -2,6 +2,16 @@
"ConnectionStrings": {
"umbracoDbDSN": ""
},
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"System": "Warning"
}
}
},
"Umbraco": {
"CMS": {
"Content": {

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Used to toggle the log levels for the main Umbraco log files -->
<!-- Found at /app_data/logs/ -->
<!-- NOTE: Changing this will also flow down into serilog.user.config -->
<!-- VALID Values: Verbose, Debug, Information, Warning, Error, Fatal -->
<add key="serilog:minimum-level" value="Information" />
<!-- NOTE: This is how sources can have a different level -->
<!--
<add key="serilog:minimum-level:override:Umbraco.Core.Composing.TypeLoader" value="Warning" />
-->
<!-- NOTE: Only one logger below can be enabled, you cannot log JSON & TXT files at the same time -->
<!-- Default JSON log file -->
<!-- This is used by the default log viewer in the Umbraco backoffice -->
<add key="serilog:using:File" value="Umbraco.Infrastructure" />
<add key="serilog:write-to:File.formatter" value="Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" />
<add key="serilog:write-to:File.path" value="%UMBLOGDIR%\UmbracoTraceLog.%MACHINENAME%..json" />
<add key="serilog:write-to:File.restrictedToMinimumLevel" value="Debug" />
<add key="serilog:write-to:File.retainedFileCountLimit" value="" /> <!-- Number of log files to keep (or remove value to keep all files) -->
<add key="serilog:write-to:File.rollingInterval" value="Day" /> <!-- Create a new log file every Minute/Hour/Day/Month/Year/infinite -->
<!-- Optional TXT log file -->
<!--<add key="serilog:using:File" value="Serilog.Sinks.File" /> -->
<!--<add key="serilog:write-to:File.path" value="%UMBLOGDIR%\UmbracoTraceLog.%MACHINENAME%..txt" /> -->
<!--<add key="serilog:write-to:File.shared" value="true" /> -->
<!--<add key="serilog:write-to:File.restrictedToMinimumLevel" value="Debug" /> -->
<!--<add key="serilog:write-to:File.retainedFileCountLimit" value="" /> --> <!-- Number of log files to keep (or remove value to keep all files) -->
<!--<add key="serilog:write-to:File.rollingInterval" value="Day" /> --> <!-- Create a new log file every Minute/Hour/Day/Month/Year/infinite -->
<!--<add key="serilog:write-to:File.outputTemplate" value="{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}" /> -->
<!-- To write to new log locations (aka Sinks) such as your own .txt files with filtering, ELMAH.io, Elastic, SEQ -->
<!-- Please use the serilog.user.config file to configure your own logging needs -->
</appSettings>
</configuration>

View File

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Used to toggle the log levels for the main Umbraco log files -->
<!-- Found at /app_data/logs/ -->
<!-- NOTE: Changing this will also flow down into serilog.user.config -->
<!-- VALID Values: Verbose, Debug, Information, Warning, Error, Fatal -->
<add key="serilog:minimum-level" value="Information" />
<!-- NOTE: This is how sources can have a different level -->
<!--
<add key="serilog:minimum-level:override:Umbraco.Core.Composing.TypeLoader" value="Warning" />
-->
<!-- NOTE: Only one logger below can be enabled, you cannot log JSON & TXT files at the same time -->
<!-- Default JSON log file -->
<!-- This is used by the default log viewer in the Umbraco backoffice -->
<add key="serilog:using:File" value="Umbraco.Infrastructure" />
<add key="serilog:write-to:File.formatter" value="Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact" />
<add key="serilog:write-to:File.path" value="%UMBLOGDIR%/UmbracoTraceLog.%MACHINENAME%..json" /> <!-- folder seperator need to be / and not \ to support both windows and linux-->
<add key="serilog:write-to:File.restrictedToMinimumLevel" value="Debug" />
<add key="serilog:write-to:File.retainedFileCountLimit" value="" /> <!-- Number of log files to keep (or remove value to keep all files) -->
<add key="serilog:write-to:File.rollingInterval" value="Day" /> <!-- Create a new log file every Minute/Hour/Day/Month/Year/infinite -->
<!-- Optional TXT log file -->
<!--<add key="serilog:using:File" value="Serilog.Sinks.File" /> -->
<!--<add key="serilog:write-to:File.path" value="%UMBLOGDIR%\UmbracoTraceLog.%MACHINENAME%..txt" /> -->
<!--<add key="serilog:write-to:File.shared" value="true" /> -->
<!--<add key="serilog:write-to:File.restrictedToMinimumLevel" value="Debug" /> -->
<!--<add key="serilog:write-to:File.retainedFileCountLimit" value="" /> --> <!-- Number of log files to keep (or remove value to keep all files) -->
<!--<add key="serilog:write-to:File.rollingInterval" value="Day" /> --> <!-- Create a new log file every Minute/Hour/Day/Month/Year/infinite -->
<!--<add key="serilog:write-to:File.outputTemplate" value="{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}" /> -->
<!-- To write to new log locations (aka Sinks) such as your own .txt files with filtering, ELMAH.io, Elastic, SEQ -->
<!-- Please use the serilog.user.config file to configure your own logging needs -->
</appSettings>
</configuration>

View File

@@ -1,39 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Controls log levels for all user-defined child sub-logger sinks configured here (Set this higher than child sinks defined here) -->
<!-- VALID Values: Verbose, Debug, Information, Warning, Error, Fatal -->
<add key="serilog:minimum-level" value="Information" />
<!-- For Different Namespaces - Set different logging levels -->
<!--
<add key="serilog:minimum-level:override:Microsoft" value="Warning" />
<add key="serilog:minimum-level:override:Microsoft.AspNetCore.Mvc" value="Error" />
<add key="serilog:minimum-level:override:YourNameSpace" value="Information" />
-->
<!-- All logs defined via user.config will contain this property (won't be in main Umbraco logs) -->
<!--
<add key="serilog:enrich:with-property:websiteName" value="My Awesome Website - Development" />
-->
<!-- Write to a user log file -->
<!--
<add key="serilog:using:File" value="Serilog.Sinks.File" />
<add key="serilog:write-to:File.path" value="%BASEDIR%\logs\my-custom-logfile.txt" />
<add key="serilog:write-to:File.shared" value="true" />
<add key="serilog:write-to:File.restrictedToMinimumLevel" value="Debug" />
<add key="serilog:write-to:File.retainedFileCountLimit" value="32" />--> <!-- Number of log files to keep (or remove value to keep all files) -->
<!--<add key="serilog:write-to:File.rollingInterval" value="Day" />--> <!-- Create a new log file every Minute/Hour/Day/Month/Year/infinite -->
<!--<add key="serilog:write-to:File.outputTemplate" value="{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}" /> -->
<!-- Filters all above sink's to use this expression -->
<!-- Common use case is to include SourceType starting with your own namespace -->
<!--
<add key="serilog:using:FilterExpressions" value="Serilog.Filters.Expressions" />
<add key="serilog:filter:ByIncludingOnly.expression" value="StartsWith(SourceContext, 'Umbraco.Core')" />
-->
</appSettings>
</configuration>

View File

@@ -1,39 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Controls log levels for all user-defined child sub-logger sinks configured here (Set this higher than child sinks defined here) -->
<!-- VALID Values: Verbose, Debug, Information, Warning, Error, Fatal -->
<add key="serilog:minimum-level" value="Information" />
<!-- For Different Namespaces - Set different logging levels -->
<!--
<add key="serilog:minimum-level:override:Microsoft" value="Warning" />
<add key="serilog:minimum-level:override:Microsoft.AspNetCore.Mvc" value="Error" />
<add key="serilog:minimum-level:override:YourNameSpace" value="Information" />
-->
<!-- All logs defined via user.config will contain this property (won't be in main Umbraco logs) -->
<!--
<add key="serilog:enrich:with-property:websiteName" value="My Awesome Website - Development" />
-->
<!-- Write to a user log file -->
<!--
<add key="serilog:using:File" value="Serilog.Sinks.File" />
<add key="serilog:write-to:File.path" value="%BASEDIR%\logs\my-custom-logfile.txt" />
<add key="serilog:write-to:File.shared" value="true" />
<add key="serilog:write-to:File.restrictedToMinimumLevel" value="Debug" />
<add key="serilog:write-to:File.retainedFileCountLimit" value="32" />--> <!-- Number of log files to keep (or remove value to keep all files) -->
<!--<add key="serilog:write-to:File.rollingInterval" value="Day" />--> <!-- Create a new log file every Minute/Hour/Day/Month/Year/infinite -->
<!--<add key="serilog:write-to:File.outputTemplate" value="{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}" /> -->
<!-- Filters all above sink's to use this expression -->
<!-- Common use case is to include SourceType starting with your own namespace -->
<!--
<add key="serilog:using:FilterExpressions" value="Serilog.Filters.Expressions" />
<add key="serilog:filter:ByIncludingOnly.expression" value="StartsWith(SourceContext, 'Umbraco.Core')" />
-->
</appSettings>
</configuration>

View File

@@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Web;
using System.Web.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Serilog;
using Serilog.Context;
@@ -51,34 +54,18 @@ namespace Umbraco.Web
var hostingEnvironment = new AspNetHostingEnvironment(Options.Create(hostingSettings));
var loggingConfiguration = new LoggingConfiguration(
Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "App_Data\\Logs"),
Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config\\serilog.config"),
Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config\\serilog.user.config"));
Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "App_Data\\Logs"));
var ioHelper = new IOHelper(hostingEnvironment);
// TODO: Configure Serilog somewhere else
var loggerConfig = new LoggerConfiguration();
loggerConfig
.MinimalConfiguration(hostingEnvironment, loggingConfiguration)
.ReadFromConfigFile(loggingConfiguration)
.ReadFromUserConfigFile(loggingConfiguration);
Log.Logger = loggerConfig.CreateLogger();
_loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddSerilog();
});
var logger = _loggerFactory.CreateLogger<UmbracoApplicationBase>();
var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, loggingConfiguration, new ConfigurationRoot(new List<IConfigurationProvider>()));
var backOfficeInfo = new AspNetBackOfficeInfo(globalSettings, ioHelper, _loggerFactory.CreateLogger<AspNetBackOfficeInfo>(), Options.Create(webRoutingSettings));
var profiler = GetWebProfiler(hostingEnvironment);
Umbraco.Composing.Current.Initialize(logger,
Umbraco.Composing.Current.Initialize(NullLogger<object>.Instance,
_loggerFactory,
securitySettings,
globalSettings,
ioHelper, hostingEnvironment, backOfficeInfo, profiler);
Logger = logger;
Logger = NullLogger<UmbracoApplicationBase>.Instance;
}
}