public async Task WritesToTextFile() { var mockSystemDateTime = new MockSystemDateTime { Now = _today }; var path = Path.Combine(TempPath, Path.GetRandomFileName()); try { string fileName; var options = new W3CLoggerOptions() { LogDirectory = path }; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.SystemDateTime = mockSystemDateTime; logger.EnqueueMessage(_messageOne); fileName = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0000.txt")); // Pause for a bit before disposing so logger can finish logging await WaitForFile(fileName, _messageOne.Length).DefaultTimeout(); } Assert.True(File.Exists(fileName)); Assert.Equal(_messageOne + Environment.NewLine, File.ReadAllText(fileName)); } finally { Helpers.DisposeDirectory(path); } }
public async Task WritesToNewFileOnOptionsChange() { var now = DateTimeOffset.Now; if (now.Hour == 23) { // Don't bother trying to run this test when it's almost midnight. return; } var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); try { var options = new W3CLoggerOptions() { LogDirectory = path, LoggingFields = W3CLoggingFields.Time, FileSizeLimit = 10000 }; var fileName1 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0000.txt")); var fileName2 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0001.txt")); var monitor = new OptionsWrapperMonitor <W3CLoggerOptions>(options); await using (var logger = new FileLoggerProcessor(monitor, new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.EnqueueMessage(_messageOne); await WaitForFile(fileName1, _messageOne.Length).DefaultTimeout(); options.LoggingFields = W3CLoggingFields.Date; monitor.InvokeChanged(); logger.EnqueueMessage(_messageTwo); // Pause for a bit before disposing so logger can finish logging await WaitForFile(fileName2, _messageTwo.Length).DefaultTimeout(); } var actualFiles = new DirectoryInfo(path) .GetFiles() .Select(f => f.Name) .OrderBy(f => f) .ToArray(); Assert.Equal(2, actualFiles.Length); Assert.True(File.Exists(fileName1)); Assert.True(File.Exists(fileName2)); Assert.Equal(_messageOne + Environment.NewLine, File.ReadAllText(fileName1)); Assert.Equal(_messageTwo + Environment.NewLine, File.ReadAllText(fileName2)); } finally { Helpers.DisposeDirectory(path); } }
public async Task RespectsMaxFileCount() { var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); File.WriteAllText(Path.Combine(path, "randomFile.txt"), "Text"); var mockSystemDateTime = new MockSystemDateTime { Now = _today }; try { string lastFileName; var options = new W3CLoggerOptions() { LogDirectory = path, RetainedFileCountLimit = 3, FileSizeLimit = 5 }; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.SystemDateTime = mockSystemDateTime; for (int i = 0; i < 10; i++) { logger.EnqueueMessage(_messageOne); } lastFileName = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0009.txt")); // Pause for a bit before disposing so logger can finish logging await WaitForFile(lastFileName, _messageOne.Length).DefaultTimeout(); for (int i = 0; i < 6; i++) { await WaitForRoll(Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.{i:0000}.txt"))).DefaultTimeout(); } } var actualFiles = new DirectoryInfo(path) .GetFiles() .Select(f => f.Name) .OrderBy(f => f) .ToArray(); Assert.Equal(4, actualFiles.Length); Assert.Equal("randomFile.txt", actualFiles[0]); for (int i = 1; i < 4; i++) { Assert.True((actualFiles[i].StartsWith($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}", StringComparison.InvariantCulture))); } } finally { Helpers.DisposeDirectory(path); } }
public async Task RollsTextFiles() { var path = Path.Combine(TempPath, Path.GetRandomFileName()); try { string fileName1; string fileName2; var now = DateTimeOffset.Now; var options = new W3CLoggerOptions() { LogDirectory = path, FileSizeLimit = 5 }; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.EnqueueMessage(_messageOne); logger.EnqueueMessage(_messageTwo); fileName1 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0000.txt")); fileName2 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0001.txt")); // Pause for a bit before disposing so logger can finish logging try { await WaitForFile(fileName2, _messageTwo.Length).DefaultTimeout(); } catch { // Midnight could have struck between taking the DateTime & writing the log // It also could have struck between writing file 1 & file 2 var tomorrow = now.AddDays(1); if (!File.Exists(fileName1)) { fileName1 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{tomorrow.Year:0000}{tomorrow.Month:00}{tomorrow.Day:00}.0000.txt")); fileName2 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{tomorrow.Year:0000}{tomorrow.Month:00}{tomorrow.Day:00}.0001.txt")); } else if (!File.Exists(fileName2)) { fileName2 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{tomorrow.Year:0000}{tomorrow.Month:00}{tomorrow.Day:00}.0000.txt")); } } } Assert.True(File.Exists(fileName1)); Assert.True(File.Exists(fileName2)); Assert.Equal(_messageOne + Environment.NewLine, File.ReadAllText(fileName1)); Assert.Equal(_messageTwo + Environment.NewLine, File.ReadAllText(fileName2)); } finally { Helpers.DisposeDirectory(path); } }
public async Task RollsTextFilesBasedOnDate() { var mockSystemDateTime = new MockSystemDateTime { Now = _today }; var tomorrow = _today.AddDays(1); var path = Path.Combine(TempPath, Path.GetRandomFileName()); var options = new W3CLoggerOptions() { LogDirectory = path }; try { string fileNameToday; string fileNameTomorrow; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.SystemDateTime = mockSystemDateTime; logger.EnqueueMessage(_messageOne); fileNameToday = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0000.txt")); await WaitForFile(fileNameToday, _messageOne.Length).DefaultTimeout(); mockSystemDateTime.Now = tomorrow; logger.EnqueueMessage(_messageTwo); fileNameTomorrow = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{tomorrow.Year:0000}{tomorrow.Month:00}{tomorrow.Day:00}.0000.txt")); await WaitForFile(fileNameTomorrow, _messageTwo.Length).DefaultTimeout(); } Assert.True(File.Exists(fileNameToday)); Assert.Equal(_messageOne + Environment.NewLine, File.ReadAllText(fileNameToday)); Assert.True(File.Exists(fileNameTomorrow)); Assert.Equal(_messageTwo + Environment.NewLine, File.ReadAllText(fileNameTomorrow)); } finally { Helpers.DisposeDirectory(path); } }
public async Task WritesToNewFileOnNewInstance() { var mockSystemDateTime = new MockSystemDateTime { Now = _today }; var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); try { var options = new W3CLoggerOptions() { LogDirectory = path, FileSizeLimit = 5 }; var fileName1 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0000.txt")); var fileName2 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0001.txt")); var fileName3 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0002.txt")); await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.SystemDateTime = mockSystemDateTime; logger.EnqueueMessage(_messageOne); logger.EnqueueMessage(_messageTwo); // Pause for a bit before disposing so logger can finish logging await WaitForFile(fileName2, _messageTwo.Length).DefaultTimeout(); } // Even with a big enough FileSizeLimit, we still won't try to write to files from a previous instance. options.FileSizeLimit = 10000; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.SystemDateTime = mockSystemDateTime; logger.EnqueueMessage(_messageThree); // Pause for a bit before disposing so logger can finish logging await WaitForFile(fileName3, _messageThree.Length).DefaultTimeout(); } var actualFiles = new DirectoryInfo(path) .GetFiles() .Select(f => f.Name) .OrderBy(f => f) .ToArray(); Assert.Equal(3, actualFiles.Length); Assert.True(File.Exists(fileName1)); Assert.True(File.Exists(fileName2)); Assert.True(File.Exists(fileName3)); Assert.Equal(_messageOne + Environment.NewLine, File.ReadAllText(fileName1)); Assert.Equal(_messageTwo + Environment.NewLine, File.ReadAllText(fileName2)); Assert.Equal(_messageThree + Environment.NewLine, File.ReadAllText(fileName3)); } finally { Helpers.DisposeDirectory(path); } }
public async Task InstancesWriteToSameDirectory() { var mockSystemDateTime = new MockSystemDateTime { Now = _today }; var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); try { var options = new W3CLoggerOptions() { LogDirectory = path, RetainedFileCountLimit = 10, FileSizeLimit = 5 }; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.SystemDateTime = mockSystemDateTime; for (int i = 0; i < 3; i++) { logger.EnqueueMessage(_messageOne); } var filePath = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0002.txt")); // Pause for a bit before disposing so logger can finish logging await WaitForFile(filePath, _messageOne.Length).DefaultTimeout(); } // Second instance should pick up where first one left off await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.SystemDateTime = mockSystemDateTime; for (int i = 0; i < 3; i++) { logger.EnqueueMessage(_messageOne); } var filePath = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0005.txt")); // Pause for a bit before disposing so logger can finish logging await WaitForFile(filePath, _messageOne.Length).DefaultTimeout(); } var actualFiles1 = new DirectoryInfo(path) .GetFiles() .Select(f => f.Name) .OrderBy(f => f) .ToArray(); Assert.Equal(6, actualFiles1.Length); for (int i = 0; i < 6; i++) { Assert.Contains($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.{i:0000}.txt", actualFiles1[i]); } // Third instance should roll to 5 most recent files options.RetainedFileCountLimit = 5; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.SystemDateTime = mockSystemDateTime; logger.EnqueueMessage(_messageOne); // Pause for a bit before disposing so logger can finish logging await WaitForFile(Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0006.txt")), _messageOne.Length).DefaultTimeout(); await WaitForRoll(Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0000.txt"))).DefaultTimeout(); await WaitForRoll(Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0001.txt"))).DefaultTimeout(); } var actualFiles2 = new DirectoryInfo(path) .GetFiles() .Select(f => f.Name) .OrderBy(f => f) .ToArray(); Assert.Equal(5, actualFiles2.Length); for (int i = 0; i < 5; i++) { Assert.Equal($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.{i + 2:0000}.txt", actualFiles2[i]); } } finally { Helpers.DisposeDirectory(path); } }
public async Task RespectsMaxFileCount() { var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); File.WriteAllText(Path.Combine(path, "randomFile.txt"), "Text"); try { string lastFileName; var now = DateTimeOffset.Now; var tomorrow = now.AddDays(1); var options = new W3CLoggerOptions() { LogDirectory = path, RetainedFileCountLimit = 3, FileSizeLimit = 5 }; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { for (int i = 0; i < 10; i++) { logger.EnqueueMessage(_messageOne); } lastFileName = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0009.txt")); // Pause for a bit before disposing so logger can finish logging try { await WaitForFile(lastFileName, _messageOne.Length).DefaultTimeout(); for (int i = 0; i < 6; i++) { await WaitForRoll(Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.{i:0000}.txt"))).DefaultTimeout(); } } catch { // Midnight could have struck between taking the DateTime & writing the log. // It also could have struck any time after writing the first file. // So we keep going even if waiting timed out, in case we're wrong about the assumed file name } } var actualFiles = new DirectoryInfo(path) .GetFiles() .Select(f => f.Name) .OrderBy(f => f) .ToArray(); Assert.Equal(4, actualFiles.Length); Assert.Equal("randomFile.txt", actualFiles[0]); for (int i = 1; i < 4; i++) { // File name will either start with today's date or tomorrow's date (if midnight struck during the execution of the test) Assert.True((actualFiles[i].StartsWith($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}", StringComparison.InvariantCulture)) || (actualFiles[i].StartsWith($"{options.FileName}{tomorrow.Year:0000}{tomorrow.Month:00}{tomorrow.Day:00}", StringComparison.InvariantCulture))); } } finally { Helpers.DisposeDirectory(path); } }
public async Task WritesToNewFileOnNewInstance() { var now = DateTimeOffset.Now; if (now.Hour == 23) { // Don't bother trying to run this test when it's almost midnight. return; } var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); try { var options = new W3CLoggerOptions() { LogDirectory = path, FileSizeLimit = 5 }; var fileName1 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0000.txt")); var fileName2 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0001.txt")); var fileName3 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0002.txt")); await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.EnqueueMessage("Message one"); logger.EnqueueMessage("Message two"); // Pause for a bit before disposing so logger can finish logging await WaitForFile(fileName2).DefaultTimeout(); } // Even with a big enough FileSizeLimit, we still won't try to write to files from a previous instance. options.FileSizeLimit = 10000; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { logger.EnqueueMessage("Message three"); // Pause for a bit before disposing so logger can finish logging await WaitForFile(fileName3).DefaultTimeout(); } var actualFiles = new DirectoryInfo(path) .GetFiles() .Select(f => f.Name) .OrderBy(f => f) .ToArray(); Assert.Equal(3, actualFiles.Length); Assert.True(File.Exists(fileName1)); Assert.True(File.Exists(fileName2)); Assert.True(File.Exists(fileName3)); Assert.Equal("Message one" + Environment.NewLine, File.ReadAllText(fileName1)); Assert.Equal("Message two" + Environment.NewLine, File.ReadAllText(fileName2)); Assert.Equal("Message three" + Environment.NewLine, File.ReadAllText(fileName3)); } finally { Helpers.DisposeDirectory(path); } }