ASP.NET Coreソース学習のLogging[2]:Configure
10519 ワード
前章ではASPについてNET Loggingシステムは全体的に紹介されていますが、本章では最も基本的な構成から始まり、ソースコードに深く入り込みます.
ASP.NET Core 2.0では,デフォルト構成を大幅に簡略化し,いくつかの基本構成をプログラムのエントリポイント
以上のように、基本的な構成は
1.0でよく知られているコードがいくつか見られますが、
まず、ロギングシステムの基本サービスのデフォルトインプリメンテーションを登録し、ロギングシステムをアクティブにし、
次に、
この方法は、ログ・システムのグローバル構成です.
まずOptionsモードを使用して
デフォルトの実装
コードを使用すると、プロファイルは次のフォーマットで定義されることがわかります.
一方、IOptionsChangeTokenSourceは、上記のIConfigureOptionsの補足であり、OptionsMonitorを取得するために必要なサービスを注入しています.Optionsについての詳細は、私の前の記事IOptionsMonitorを参照してください.
ロギングシステムでは、
前述したように、プロファイルではProviderの構成を指定できますが、
以上のコードはMicrosoft.Extensions.Logging.Console Packageでは、まず
AddDebugはAddConsoleと似ており、Debugウィンドウにログを出力するにすぎません.
Providerの構成については、後で詳しく検討します.
以上、ASPについて説明する.NET Coreのログシステムのデフォルト構成ですが、他の構成を追加したい場合はどうすればいいですか?
1.0時代には、Startupクラスのコンフィギュレーションメソッドに
上記の
EventSourceProviderを追加し、
最終的には
本章では、ログレベルフィルタリングとログプロバイダの2つの構成に分けて、ログのフィルタリング原理を分析します.
デフォルト設定
ASP.NET Core 2.0では,デフォルト構成を大幅に簡略化し,いくつかの基本構成をプログラムのエントリポイント
Program
クラスに移動し,より簡潔にした.public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup()
.Build();
}
以上のように、基本的な構成は
CreateDefaultBuilder
メソッドに組み込まれていることが分かるが、WebHost
はMetaPackagesにおいて、いくつかの簡略化された方法を提供している.public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
var builder = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
if (env.IsDevelopment())
{
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
config.AddUserSecrets(appAssembly, optional: true);
}
}
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
.UseIISIntegration()
.UseDefaultServiceProvider((context, options) =>
{
options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
});
return builder;
}
1.0でよく知られているコードがいくつか見られますが、
ConfigureLogging
はIWebHostBuilder
クラスの拡張方法です.public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action configureLogging)
{
return hostBuilder.ConfigureServices((context, collection) => collection.AddLogging(builder => configureLogging(context, builder)));
}
AddLogging
はLoggingシステムのエントリポイントであり、Microsoft.Extensions.Logging
によって提供される拡張方法である.public static IServiceCollection AddLogging(this IServiceCollection services, Action configure)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddOptions();
services.TryAdd(ServiceDescriptor.Singleton());
services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>)));
services.TryAddEnumerable(ServiceDescriptor.Singleton>(
new DefaultLoggerLevelConfigureOptions(LogLevel.Information)));
configure(new LoggingBuilder(services));
return services;
}
まず、ロギングシステムの基本サービスのデフォルトインプリメンテーションを登録し、ロギングシステムをアクティブにし、
LoggingBuilder
オブジェクトを作成し、その後、ログシステムの一連の構成は、呼び出されたオブジェクトの拡張方法である.internal class LoggingBuilder : ILoggingBuilder
{
public LoggingBuilder(IServiceCollection services)
{
Services = services;
}
public IServiceCollection Services { get; }
}
次に、
CreateDefaultBuilder
メソッドにおけるConfigureLogging
によるログシステムのデフォルト構成を振り返ってみましょう.AddConfiguration
この方法は、ログ・システムのグローバル構成です.
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
public static ILoggingBuilder AddConfiguration(this ILoggingBuilder builder, IConfiguration configuration)
{
builder.Services.AddSingleton>(new LoggerFilterConfigureOptions(configuration));
builder.Services.AddSingleton>(new ConfigurationChangeTokenSource(configuration));
return builder;
}
まずOptionsモードを使用して
LoggerFilterOptions
を登録しました.public class LoggerFilterOptions
{
public LogLevel MinLevel { get; set; }
public IList Rules { get; } = new List();
}
public class LoggerFilterRule
{
...
public string ProviderName { get; }
public string CategoryName { get; }
public LogLevel? LogLevel { get; }
public Func Filter { get; }
....
}
デフォルトの実装
LoggerFilterConfigureOptions
の論理は簡単で、プロファイルからLogLevel
の構成を読み取ることです.internal class LoggerFilterConfigureOptions : IConfigureOptions
{
...
private void LoadDefaultConfigValues(LoggerFilterOptions options)
{
if (_configuration == null)
{
return;
}
foreach (var configurationSection in _configuration.GetChildren())
{
if (configurationSection.Key == "LogLevel")
{
// Load global category defaults
LoadRules(options, configurationSection, null);
}
else
{
var logLevelSection = configurationSection.GetSection("LogLevel");
if (logLevelSection != null)
{
// Load logger specific rules
var logger = configurationSection.Key;
LoadRules(options, logLevelSection, logger);
}
}
}
}
private void LoadRules(LoggerFilterOptions options, IConfigurationSection configurationSection, string logger)
{
foreach (var section in configurationSection.AsEnumerable(true))
{
if (TryGetSwitch(section.Value, out var level))
{
var category = section.Key;
if (category == "Default")
{
category = null;
}
var newRule = new LoggerFilterRule(logger, category, level, null);
options.Rules.Add(newRule);
}
}
}
...
}
コードを使用すると、プロファイルは次のフォーマットで定義されることがわかります.
{
"Logging": {
"LogLevel": { //
"Default": "Warning" // CategoryName, Category
},
"Console":{ // ProviderName, ConsoleProvider
"Default": "Warning",
"Microsoft": "Error" // CategoryName Microsoft Error
}
}
}
一方、IOptionsChangeTokenSourceは、上記のIConfigureOptionsの補足であり、OptionsMonitorを取得するために必要なサービスを注入しています.Optionsについての詳細は、私の前の記事IOptionsMonitorを参照してください.
ロギングシステムでは、
IOptionsMonitor
を注入することによってロギングFilterOptionsを使用しています.public LoggerFactory(IEnumerable providers, IOptionsMonitor filterOption)
{
_providerRegistrations = providers.Select(provider => new ProviderRegistration { Provider = provider }).ToList();
_changeTokenRegistration = filterOption.OnChange(RefreshFilters);
RefreshFilters(filterOption.CurrentValue);
}
AddConsole
前述したように、プロファイルではProviderの構成を指定できますが、
AddConsole
はコンソールにログを記録するためにコンソールタイプのProviderを追加するために使用されます.public static ILoggingBuilder AddConsole(this ILoggingBuilder builder)
{
builder.Services.AddSingleton();
return builder;
}
public static ILoggingBuilder AddConsole(this ILoggingBuilder builder, Action configure)
{
if (configure == null)
{
throw new ArgumentNullException(nameof(configure));
}
builder.AddConsole();
builder.Services.Configure(configure);
return builder;
}
以上のコードはMicrosoft.Extensions.Logging.Console Packageでは、まず
ILoggerProvider
の注入方法を提供し、コンソールのログ記録機能を有効にし、ConsoleProviderの構成を指定する方法をリロードします.AddDebug
AddDebugはAddConsoleと似ており、Debugウィンドウにログを出力するにすぎません.
Providerの構成については、後で詳しく検討します.
カスタム構成
以上、ASPについて説明する.NET Coreのログシステムのデフォルト構成ですが、他の構成を追加したい場合はどうすればいいですか?
1.0時代には、Startupクラスのコンフィギュレーションメソッドに
ILoggerFactory
を注入して構成することができました.もちろん、2.0ではそうすることができますが、Programエントリメソッドで構成することがより推奨され、コンフィギュレーションメソッドはミドルウェアの構成です.上記の
ConfigureLogging
拡張方法を使用して、独自の構成を追加できます.public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args).ConfigureLogging(build =>
{
build.AddFilter(f => f == LogLevel.Debug);
build.AddEventSourceLogger();
})
.UseStartup()
.Build();
EventSourceProviderを追加し、
AddFilter
拡張メソッドを使用してログのフィルタリングを構成しました.AddFilterの役割は、前述したAddConfigurationに似ていますが、プロファイルからコードに構成方法を変更しただけです.public static class FilterLoggingBuilderExtensions
{
// ,
public static ILoggingBuilder AddFilter(this ILoggingBuilder builder, Func filter) =>
builder.ConfigureFilter(options => options.AddFilter(filter));
private static ILoggingBuilder ConfigureFilter(this ILoggingBuilder builder, Action configureOptions)
{
builder.Services.Configure(configureOptions);
return builder;
}
}
最終的には
ConfigureOptions
の構成であり、その後実行される構成は前の構成を上書きすることがわかる.まとめ
本章では、ログレベルフィルタリングとログプロバイダの2つの構成に分けて、ログのフィルタリング原理を分析します.