예제 #1
0
        public void ThrowsOnNegativeFileSizeLimit()
        {
            var options = new W3CLoggerOptions();
            var ex      = Assert.Throws <ArgumentOutOfRangeException>(() => options.FileSizeLimit = -1);

            Assert.Contains("FileSizeLimit must be positive", ex.Message);
        }
        private IOptionsMonitor <W3CLoggerOptions> CreateOptionsAccessor()
        {
            var options         = new W3CLoggerOptions();
            var optionsAccessor = Mock.Of <IOptionsMonitor <W3CLoggerOptions> >(o => o.CurrentValue == options);

            return(optionsAccessor);
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        public void ThrowsOnNegativeFlushInterval()
        {
            var options = new W3CLoggerOptions();
            var ex      = Assert.Throws <ArgumentOutOfRangeException>(() => options.FlushInterval = TimeSpan.FromSeconds(-1));

            Assert.Contains("FlushInterval must be positive", ex.Message);
        }
예제 #5
0
        public void DoesNotInitializeWithOptionalFields()
        {
            var options = new W3CLoggerOptions();

            // Optional fields shouldn't be logged by default
            Assert.False(options.LoggingFields.HasFlag(W3CLoggingFields.UserName));
            Assert.False(options.LoggingFields.HasFlag(W3CLoggingFields.Cookie));
        }
        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);
            }
        }
예제 #7
0
        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);
            }
        }
예제 #9
0
        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);
            }
        }
예제 #10
0
        public async Task WritesDateTime()
        {
            var path    = Path.GetTempFileName() + "_";
            var now     = DateTime.Now;
            var options = new W3CLoggerOptions()
            {
                LoggingFields = W3CLoggingFields.Date | W3CLoggingFields.Time | W3CLoggingFields.TimeTaken,
                LogDirectory  = path
            };

            try
            {
                await using (var logger = new TestW3CLogger(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance))
                {
                    var elements = new string[W3CLoggingMiddleware._fieldsLength];
                    AddToList(elements, W3CLoggingMiddleware._dateIndex, _timestampOne.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
                    AddToList(elements, W3CLoggingMiddleware._timeIndex, _timestampOne.ToString("HH:mm:ss", CultureInfo.InvariantCulture));

                    logger.Log(elements);
                    await logger.Processor.WaitForWrites(4).DefaultTimeout();

                    var lines = logger.Processor.Lines;
                    Assert.Equal("#Version: 1.0", lines[0]);

                    Assert.StartsWith("#Start-Date: ", lines[1]);
                    var startDate = DateTime.Parse(lines[1].Substring(13), CultureInfo.InvariantCulture);
                    // Assert that the log was written in the last 10 seconds
                    Assert.True(now.Subtract(startDate).TotalSeconds < 10);

                    Assert.Equal("#Fields: date time time-taken", lines[2]);

                    Assert.StartsWith("2021-01-02 03:04:05 ", lines[3]);
                    // Assert that the log's time-taken is within 10 seconds of DateTime.Now minus our arbitary start time (01/02/21 at 3:04:05)
                    Assert.True(now.Subtract(_timestampOne).TotalSeconds - Convert.ToDouble(lines[3].Substring(20), CultureInfo.InvariantCulture) < 10);
                }
            }
            finally
            {
                Helpers.DisposeDirectory(path);
            }
        }
예제 #11
0
        public async Task HandlesNullValuesAsync()
        {
            var path    = Path.GetTempFileName() + "_";
            var now     = DateTime.UtcNow;
            var options = new W3CLoggerOptions()
            {
                LoggingFields = W3CLoggingFields.UriQuery | W3CLoggingFields.Host | W3CLoggingFields.ProtocolStatus,
                LogDirectory  = path
            };

            try
            {
                await using (var logger = new TestW3CLogger(new OptionsWrapperMonitor <W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance))
                {
                    var elements = new string[W3CLoggingMiddleware._fieldsLength];
                    AddToList(elements, W3CLoggingMiddleware._uriQueryIndex, null);
                    AddToList(elements, W3CLoggingMiddleware._hostIndex, null);
                    AddToList(elements, W3CLoggingMiddleware._protocolStatusIndex, null);

                    logger.Log(elements);
                    await logger.Processor.WaitForWrites(4).DefaultTimeout();

                    var lines = logger.Processor.Lines;
                    Assert.Equal("#Version: 1.0", lines[0]);

                    Assert.StartsWith("#Start-Date: ", lines[1]);
                    var startDate = DateTime.Parse(lines[1].Substring(13), CultureInfo.InvariantCulture);
                    // Assert that the log was written in the last 10 seconds
                    Assert.True(now.Subtract(startDate).TotalSeconds < 10);

                    Assert.Equal("#Fields: cs-uri-query sc-status cs-host", lines[2]);
                    Assert.Equal("- - -", lines[3]);
                }
            }
            finally
            {
                Helpers.DisposeDirectory(path);
            }
        }
예제 #12
0
        public void ThrowsOnEmptyFileName()
        {
            var options = new W3CLoggerOptions();

            Assert.Throws <ArgumentNullException>(() => options.FileName = "");
        }
예제 #13
0
        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);
            }
        }
예제 #15
0
        public void ThrowsOnEmptyLogDirectory()
        {
            var options = new W3CLoggerOptions();

            Assert.Throws <ArgumentNullException>(() => options.LogDirectory = "");
        }
예제 #16
0
        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);
            }
        }
예제 #17
0
        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);
            }
        }