using System.IO;
using System.Reflection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
using Serilog.Extensions.Hosting;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Logging;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
using Umbraco.Core.Runtime;
using Umbraco.Web.Common.AspNetCore;
using Umbraco.Web.Common.Profiler;
using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment;
namespace Umbraco.Extensions
{
public static class UmbracoCoreServiceCollectionExtensions
{
///
/// Create and configure the logger
///
public static IServiceCollection AddLogger(
this IServiceCollection services,
IHostingEnvironment hostingEnvironment,
ILoggingConfiguration loggingConfiguration,
IConfiguration configuration)
{
// Create a serilog logger
var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, loggingConfiguration, configuration);
// 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 =>
{
configure.AddSerilog(logger.SerilogLog, false);
});
// This won't (and shouldn't) take ownership of the logger.
services.AddSingleton(logger.SerilogLog);
// Registered to provide two services...
var diagnosticContext = new DiagnosticContext(logger.SerilogLog);
// Consumed by e.g. middleware
services.AddSingleton(diagnosticContext);
// Consumed by user code
services.AddSingleton(diagnosticContext);
services.AddSingleton(loggingConfiguration);
return services;
}
internal static ITypeFinder AddTypeFinder(
this IServiceCollection services,
ILoggerFactory loggerFactory,
IWebHostEnvironment webHostEnvironment,
Assembly entryAssembly,
IConfiguration config,
IProfilingLogger profilingLogger)
{
var typeFinderSettings = config.GetSection(Constants.Configuration.ConfigTypeFinder).Get() ?? new TypeFinderSettings();
var runtimeHashPaths = new RuntimeHashPaths().AddFolder(new DirectoryInfo(Path.Combine(webHostEnvironment.ContentRootPath, "bin")));
var runtimeHash = new RuntimeHash(profilingLogger, runtimeHashPaths);
var typeFinder = new TypeFinder(
loggerFactory.CreateLogger(),
new DefaultUmbracoAssemblyProvider(entryAssembly),
runtimeHash,
new TypeFinderConfig(Options.Create(typeFinderSettings))
);
services.AddUnique(typeFinder);
return typeFinder;
}
public static TypeLoader AddTypeLoader(
this IServiceCollection services,
Assembly entryAssembly,
IWebHostEnvironment webHostEnvironment,
IHostingEnvironment hostingEnvironment,
ILoggerFactory loggerFactory,
AppCaches appCaches,
IConfiguration configuration,
IProfiler profiler)
{
var profilingLogger = new ProfilingLogger(loggerFactory.CreateLogger(), profiler);
var typeFinder = services.AddTypeFinder(loggerFactory, webHostEnvironment, entryAssembly, configuration, profilingLogger);
var typeLoader = new TypeLoader(
typeFinder,
appCaches.RuntimeCache,
new DirectoryInfo(hostingEnvironment.LocalTempPath),
loggerFactory.CreateLogger(),
profilingLogger
);
services.AddUnique(typeLoader);
return typeLoader;
}
}
}