public async Task ReloadOptionsSettingsMultipleProviders() { var fileProvider = new MemoryFileProvider(); var fileAppender = new MemoryFileAppender(fileProvider); dynamic settings = new JObject(); dynamic globalFilters = settings[nameof(LoggerFilterRule.LogLevel)] = new JObject(); globalFilters[LogFileOptions.DefaultCategoryName] = LogLevel.None.ToString(); settings[FileLoggerProvider.Alias] = new JObject(); dynamic fileFilters = settings[FileLoggerProvider.Alias][nameof(LoggerFilterRule.LogLevel)] = new JObject(); fileFilters[LogFileOptions.DefaultCategoryName] = LogLevel.Warning.ToString(); dynamic oneFile = new JObject(); oneFile.Path = "one.log"; settings[FileLoggerProvider.Alias][nameof(FileLoggerOptions.Files)] = new JArray(oneFile); settings[OtherFileLoggerProvider.Alias] = new JObject(); dynamic otherFileFilters = settings[OtherFileLoggerProvider.Alias][nameof(LoggerFilterRule.LogLevel)] = new JObject(); otherFileFilters[LogFileOptions.DefaultCategoryName] = LogLevel.Information.ToString(); dynamic otherFile = new JObject(); otherFile.Path = "other.log"; settings[OtherFileLoggerProvider.Alias][nameof(FileLoggerOptions.Files)] = new JArray(otherFile); var configJson = ((JObject)settings).ToString(); fileProvider.CreateFile("config.json", configJson); IConfigurationRoot config = new ConfigurationBuilder() .AddJsonFile(fileProvider, "config.json", optional: false, reloadOnChange: true) .Build(); var context = new TestFileLoggerContext(default, completionTimeout: Timeout.InfiniteTimeSpan);
public async Task ReloadOptionsSettings() { var configJson = $@"{{ ""{FileLoggerProvider.Alias}"": {{ ""{nameof(FileLoggerOptions.IncludeScopes)}"" : true, ""{nameof(FileLoggerOptions.Files)}"": [ {{ ""{nameof(LogFileOptions.Path)}"": ""test.log"", }}], ""{nameof(LoggerFilterRule.LogLevel)}"": {{ ""{LogFileOptions.DefaultCategoryName}"": ""{LogLevel.Trace}"" }} }} }}"; var fileProvider = new MemoryFileProvider(); fileProvider.CreateFile("config.json", configJson, Encoding.UTF8); var cb = new ConfigurationBuilder(); cb.AddJsonFile(fileProvider, "config.json", optional: false, reloadOnChange: true); IConfigurationRoot config = cb.Build(); var completeCts = new CancellationTokenSource(); var context = new TestFileLoggerContext(completeCts.Token, completionTimeout: Timeout.InfiniteTimeSpan); context.SetTimestamp(new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc)); var services = new ServiceCollection(); services.AddOptions(); services.AddLogging(b => { b.AddConfiguration(config); b.AddFile(context); }); var fileAppender = new MemoryFileAppender(fileProvider); services.Configure <FileLoggerOptions>(o => o.FileAppender ??= fileAppender); FileLoggerProvider[] providers; using (ServiceProvider sp = services.BuildServiceProvider()) { providers = context.GetProviders(sp).ToArray(); Assert.Equal(1, providers.Length); var resetTasks = new List <Task>(); foreach (FileLoggerProvider provider in providers) { provider.Reset += (s, e) => resetTasks.Add(e); } ILoggerFactory loggerFactory = sp.GetService <ILoggerFactory>(); ILogger <SettingsTest> logger1 = loggerFactory.CreateLogger <SettingsTest>(); using (logger1.BeginScope("SCOPE")) { logger1.LogTrace("This is a nice logger."); using (logger1.BeginScope("NESTED SCOPE")) { logger1.LogInformation("This is a smart logger."); // changing switch and scopes inclusion configJson = $@"{{ ""{FileLoggerProvider.Alias}"": {{ ""{nameof(FileLoggerOptions.Files)}"": [ {{ ""{nameof(LogFileOptions.Path)}"": ""test.log"", }}], ""{nameof(LoggerFilterRule.LogLevel)}"": {{ ""{LogFileOptions.DefaultCategoryName}"": ""{LogLevel.Information}"" }} }} }}"; Assert.Equal(0, resetTasks.Count); fileProvider.WriteContent("config.json", configJson); // reload is triggered twice due to a bug in the framework (https://github.com/aspnet/Logging/issues/874) Assert.Equal(1 * 2, resetTasks.Count); // ensuring that reset has been finished and the new settings are effective await Task.WhenAll(resetTasks); logger1 = loggerFactory.CreateLogger <SettingsTest>(); logger1.LogInformation("This one shouldn't include scopes."); logger1.LogTrace("This one shouldn't be included at all."); } } completeCts.Cancel(); // ensuring that all entries are processed await context.GetCompletion(sp); Assert.True(providers.All(provider => provider.Completion.IsCompleted)); } var logFile = (MemoryFileInfo)fileProvider.GetFileInfo("test.log"); Assert.True(logFile.Exists && !logFile.IsDirectory); var lines = logFile.ReadAllText(out Encoding encoding).Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.UTF8, encoding); Assert.Equal(new[] { $"trce: {typeof(SettingsTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" => SCOPE", $" This is a nice logger.", $"info: {typeof(SettingsTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" => SCOPE => NESTED SCOPE", $" This is a smart logger.", $"info: {typeof(SettingsTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This one shouldn't include scopes.", "" }, lines); }
public void ReloadOptionsSettingsMultipleProviders() { var fileProvider = new MemoryFileProvider(); var fileAppender = new MemoryFileAppender(fileProvider); dynamic settings = new JObject(); dynamic globalFilters = settings[ConfigurationFileLoggerSettings.LogLevelSectionName] = new JObject(); globalFilters[FileLoggerSettingsBase.DefaultCategoryName] = LogLevel.None.ToString(); settings[FileLoggerProvider.Alias] = new JObject(); dynamic fileFilters = settings[FileLoggerProvider.Alias][ConfigurationFileLoggerSettings.LogLevelSectionName] = new JObject(); fileFilters[FileLoggerSettingsBase.DefaultCategoryName] = LogLevel.Warning.ToString(); settings[OtherFileLoggerProvider.Alias] = new JObject(); settings[OtherFileLoggerProvider.Alias][nameof(FileLoggerOptions.FallbackFileName)] = "fallback.log"; dynamic otherFileFilters = settings[OtherFileLoggerProvider.Alias][ConfigurationFileLoggerSettings.LogLevelSectionName] = new JObject(); otherFileFilters[FileLoggerSettingsBase.DefaultCategoryName] = LogLevel.Information.ToString(); var settingsJson = ((JObject)settings).ToString(); fileProvider.CreateFile("config.json", settingsJson); IConfigurationRoot config = new ConfigurationBuilder() .AddJsonFile(fileProvider, "config.json", optional: false, reloadOnChange: true) .Build(); var context = new TestFileLoggerContext(); var completionTasks = new List <Task>(); context.Complete += (s, e) => completionTasks.Add(e); var services = new ServiceCollection(); services.AddOptions(); services.AddLogging(lb => { lb.AddConfiguration(config); lb.AddFile(context, o => o.FileAppender = o.FileAppender ?? fileAppender); lb.AddFile <OtherFileLoggerProvider>(context, o => o.FileAppender = o.FileAppender ?? fileAppender); }); using (ServiceProvider sp = services.BuildServiceProvider()) { ILoggerFactory loggerFactory = sp.GetRequiredService <ILoggerFactory>(); ILogger logger = loggerFactory.CreateLogger("X"); logger.LogInformation("This is an info."); logger.LogWarning("This is a warning."); fileFilters[FileLoggerSettingsBase.DefaultCategoryName] = LogLevel.Information.ToString(); otherFileFilters[FileLoggerSettingsBase.DefaultCategoryName] = LogLevel.Warning.ToString(); settingsJson = ((JObject)settings).ToString(); fileProvider.WriteContent("config.json", settingsJson); // reload is triggered twice due to a bug in the framework (https://github.com/aspnet/Logging/issues/874) Assert.Equal(2 * 2, completionTasks.Count); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); logger.LogInformation("This is another info."); logger.LogWarning("This is another warning."); } var logFile = (MemoryFileInfo)fileProvider.GetFileInfo(LoggingTest.FallbackFileName); Assert.True(logFile.Exists && !logFile.IsDirectory); var lines = logFile.Content.Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.UTF8, logFile.Encoding); Assert.Equal(new[] { $"warn: X[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is a warning.", $"info: X[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is another info.", $"warn: X[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is another warning.", "" }, lines); logFile = (MemoryFileInfo)fileProvider.GetFileInfo((string)settings[OtherFileLoggerProvider.Alias].FallbackFileName); Assert.True(logFile.Exists && !logFile.IsDirectory); lines = logFile.Content.Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.UTF8, logFile.Encoding); Assert.Equal(new[] { $"info: X[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is an info.", $"warn: X[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is a warning.", $"warn: X[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is another warning.", "" }, lines); }
public void ReloadOptionsSettings() { var configJson = $@"{{ '{FileLoggerProvider.Alias}': {{ '{nameof(ConfigurationFileLoggerSettings.IncludeScopes)}' : true, '{ConfigurationFileLoggerSettings.LogLevelSectionName}': {{ '{FileLoggerSettingsBase.DefaultCategoryName}': '{LogLevel.Trace}', }} }} }}"; var fileProvider = new MemoryFileProvider(); fileProvider.CreateFile("config.json", configJson, Encoding.UTF8); var cb = new ConfigurationBuilder(); cb.AddJsonFile(fileProvider, "config.json", optional: false, reloadOnChange: true); IConfigurationRoot config = cb.Build(); var cts = new CancellationTokenSource(); var context = new TestFileLoggerContext(cts.Token); var completionTasks = new List <Task>(); context.Complete += (s, e) => completionTasks.Add(e); context.SetTimestamp(new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc)); var services = new ServiceCollection(); services.AddOptions(); services.AddLogging(b => { b.AddConfiguration(config); b.AddFile(context); }); var fileAppender = new MemoryFileAppender(fileProvider); services.Configure <FileLoggerOptions>(o => o.FileAppender = o.FileAppender ?? fileAppender); using (ServiceProvider serviceProvider = services.BuildServiceProvider()) { ILoggerFactory loggerFactory = serviceProvider.GetService <ILoggerFactory>(); ILogger <LoggingTest> logger1 = loggerFactory.CreateLogger <LoggingTest>(); using (logger1.BeginScope("SCOPE")) { logger1.LogTrace("This is a nice logger."); using (logger1.BeginScope("NESTED SCOPE")) { logger1.LogInformation("This is a smart logger."); // changing switch and scopes inclusion configJson = $@"{{ '{FileLoggerProvider.Alias}': {{ '{ConfigurationFileLoggerSettings.LogLevelSectionName}': {{ '{FileLoggerSettingsBase.DefaultCategoryName}': '{LogLevel.Information}', }} }} }}"; fileProvider.WriteContent("config.json", configJson); // reload is triggered twice due to a bug in the framework (https://github.com/aspnet/Logging/issues/874) Assert.Equal(1 * 2, completionTasks.Count); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); logger1 = loggerFactory.CreateLogger <LoggingTest>(); logger1.LogInformation("This one shouldn't include scopes."); logger1.LogTrace("This one shouldn't be included at all."); } } // ensuring that the entry is processed completionTasks.Clear(); cts.Cancel(); Assert.Single(completionTasks); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); } var logFile = (MemoryFileInfo)fileProvider.GetFileInfo(LoggingTest.FallbackFileName); Assert.True(logFile.Exists && !logFile.IsDirectory); var lines = logFile.Content.Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.UTF8, logFile.Encoding); Assert.Equal(new[] { $"trce: {typeof(LoggingTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" => SCOPE", $" This is a nice logger.", $"info: {typeof(LoggingTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" => SCOPE => NESTED SCOPE", $" This is a smart logger.", $"info: {typeof(LoggingTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This one shouldn't include scopes.", "" }, lines); }
public void ReloadConfigurationSettings() { var configJson = $@"{{ '{nameof(ConfigurationFileLoggerSettings.MaxFileSize)}' : 10000, '{ConfigurationFileLoggerSettings.LogLevelSectionName}': {{ '{FileLoggerSettingsBase.DefaultCategoryName}': '{LogLevel.Information}', }} }}"; var fileProvider = new MemoryFileProvider(); fileProvider.CreateFile("config.json", configJson, Encoding.UTF8); var cb = new ConfigurationBuilder(); cb.AddJsonFile(fileProvider, "config.json", optional: false, reloadOnChange: true); IConfigurationRoot config = cb.Build(); var fileAppender = new MemoryFileAppender(fileProvider); var settings = new ConfigurationFileLoggerSettings(config, o => o.FileAppender = o.FileAppender ?? fileAppender); var cts = new CancellationTokenSource(); var context = new TestFileLoggerContext(cts.Token); var completionTasks = new List <Task>(); context.Complete += (s, e) => completionTasks.Add(e); context.SetTimestamp(new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc)); using (var loggerFactory = new LoggerFactory()) { loggerFactory.AddFile(context, settings); ILogger <LoggingTest> logger1 = loggerFactory.CreateLogger <LoggingTest>(); logger1.LogInformation("This is a nice logger."); // changing date format, counter format and max file size configJson = $@"{{ '{nameof(ConfigurationFileLoggerSettings.DateFormat)}' : 'yyyyMMdd', '{nameof(ConfigurationFileLoggerSettings.MaxFileSize)}' : 1, '{nameof(ConfigurationFileLoggerSettings.CounterFormat)}' : '00', '{ConfigurationFileLoggerSettings.LogLevelSectionName}': {{ '{FileLoggerSettingsBase.DefaultCategoryName}': '{LogLevel.Information}', }} }}"; fileProvider.WriteContent("config.json", configJson); Assert.Single(completionTasks); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); logger1.LogInformation("This is a smart logger."); // ensuring that the entry is processed completionTasks.Clear(); cts.Cancel(); Assert.Single(completionTasks); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); } var logFile = (MemoryFileInfo)fileProvider.GetFileInfo($@"{Path.ChangeExtension(LoggingTest.FallbackFileName, null)}-0{Path.GetExtension(LoggingTest.FallbackFileName)}"); Assert.True(logFile.Exists && !logFile.IsDirectory); var lines = logFile.Content.Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.UTF8, logFile.Encoding); Assert.Equal(new[] { $"info: {typeof(LoggingTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is a nice logger.", "" }, lines); logFile = (MemoryFileInfo)fileProvider.GetFileInfo($@"{Path.ChangeExtension(LoggingTest.FallbackFileName, null)}-{context.GetTimestamp().ToLocalTime():yyyyMMdd}-00{Path.GetExtension(LoggingTest.FallbackFileName)}"); Assert.True(logFile.Exists && !logFile.IsDirectory); lines = logFile.Content.Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.UTF8, logFile.Encoding); Assert.Equal(new[] { $"info: {typeof(LoggingTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is a smart logger.", "" }, lines); }
public void ReloadSettings() { var fileProvider = new MemoryFileProvider(); var cts = new CancellationTokenSource(); var settings = new FileLoggerSettings { FileAppender = new MemoryFileAppender(fileProvider), Switches = new Dictionary <string, LogLevel> { { FileLoggerSettingsBase.DefaultCategoryName, LogLevel.Information } }, ChangeToken = new CancellationChangeToken(cts.Token) }; var context = new TestFileLoggerContext(); var completionTasks = new List <Task>(); context.Complete += (s, e) => completionTasks.Add(e); context.SetTimestamp(new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc)); var otherFileAppender = new MemoryFileAppender(); using (var loggerFactory = new LoggerFactory()) { loggerFactory.AddFile(context, settings); ILogger <LoggingTest> logger1 = loggerFactory.CreateLogger <LoggingTest>(); logger1.LogInformation("This is a nice logger."); // changing text format settings.TextBuilder = new CustomLogEntryTextBuilder(); var newCts = new CancellationTokenSource(); settings.ChangeToken = new CancellationChangeToken(newCts.Token); cts.Cancel(); cts = newCts; Assert.Single(completionTasks); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); logger1.LogInformation("This is a smart logger."); // changing base path, file encoding and filename mapping settings.BasePath = "Logs"; settings.EnsureBasePath = true; settings.FileEncoding = Encoding.Unicode; settings.FileNameMappings = new Dictionary <string, string> { { typeof(LoggingTest).FullName, "test.log" } }; newCts = new CancellationTokenSource(); settings.ChangeToken = new CancellationChangeToken(newCts.Token); cts.Cancel(); cts = newCts; Assert.Equal(2, completionTasks.Count); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); logger1.LogWarning("This goes to another file."); // changing file appender and fallback filename settings.FileAppender = otherFileAppender; settings.FallbackFileName = "test.log"; settings.FileNameMappings = null; newCts = new CancellationTokenSource(); settings.ChangeToken = new CancellationChangeToken(newCts.Token); cts.Cancel(); cts = newCts; Assert.Equal(3, completionTasks.Count); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); logger1.LogWarning("This goes to another file provider."); // ensuring that the entry is processed cts.Cancel(); Assert.Equal(4, completionTasks.Count); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); } var logFile = (MemoryFileInfo)fileProvider.GetFileInfo(LoggingTest.FallbackFileName); Assert.True(logFile.Exists && !logFile.IsDirectory); var lines = logFile.Content.Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.UTF8, logFile.Encoding); Assert.Equal(new[] { $"info: {typeof(LoggingTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is a nice logger.", $"[info]: {typeof(LoggingTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is a smart logger.", "" }, lines); logFile = (MemoryFileInfo)fileProvider.GetFileInfo($@"Logs\test.log"); Assert.True(logFile.Exists && !logFile.IsDirectory); lines = logFile.Content.Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.Unicode, logFile.Encoding); Assert.Equal(new[] { $"[warn]: {typeof(LoggingTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This goes to another file.", "" }, lines); logFile = (MemoryFileInfo)otherFileAppender.FileProvider.GetFileInfo($@"Logs\test.log"); Assert.True(logFile.Exists && !logFile.IsDirectory); lines = logFile.Content.Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.Unicode, logFile.Encoding); Assert.Equal(new[] { $"[warn]: {typeof(LoggingTest).FullName}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This goes to another file provider.", "" }, lines); }