diff --git a/src/Middleware/HttpLogging/src/FileLoggerProcessor.cs b/src/Middleware/HttpLogging/src/FileLoggerProcessor.cs index 60b4a6265867012f1c1cda8d497738d3f843dfc1..10382b62e422b6c73de7f3af27730e35283a7564 100644 --- a/src/Middleware/HttpLogging/src/FileLoggerProcessor.cs +++ b/src/Middleware/HttpLogging/src/FileLoggerProcessor.cs @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.HttpLogging private bool _maxFilesReached; private TimeSpan _flushInterval; private W3CLoggingFields _fields; - private DateTime _today = DateTime.Now; + private DateTime _today; private bool _firstFile = true; private readonly IOptionsMonitor<W3CLoggerOptions> _options; @@ -40,6 +40,9 @@ namespace Microsoft.AspNetCore.HttpLogging private readonly Task _outputTask; private readonly CancellationTokenSource _cancellationTokenSource; + // Internal to allow for testing + internal ISystemDateTime SystemDateTime {get; set;} = new SystemDateTime(); + private readonly object _pathLock = new object(); public FileLoggerProcessor(IOptionsMonitor<W3CLoggerOptions> options, IHostEnvironment environment, ILoggerFactory factory) @@ -98,6 +101,8 @@ namespace Microsoft.AspNetCore.HttpLogging } }); + _today = SystemDateTime.Now; + // Start message queue processor _cancellationTokenSource = new CancellationTokenSource(); _outputTask = Task.Run(ProcessLogQueue); @@ -155,7 +160,7 @@ namespace Microsoft.AspNetCore.HttpLogging private async Task WriteMessagesAsync(List<string> messages, CancellationToken cancellationToken) { // Files are written up to _maxFileSize before rolling to a new file - DateTime today = DateTime.Now; + DateTime today = SystemDateTime.Now; if (!TryCreateDirectory()) { diff --git a/src/Middleware/HttpLogging/src/ISystemDateTime.cs b/src/Middleware/HttpLogging/src/ISystemDateTime.cs new file mode 100644 index 0000000000000000000000000000000000000000..654a42852c456b6c2f5f1db1fedd84dc994214fb --- /dev/null +++ b/src/Middleware/HttpLogging/src/ISystemDateTime.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.HttpLogging +{ + internal interface ISystemDateTime + { + /// <summary> + /// Retrieves the date and time currently set for this machine. + /// </summary> + DateTime Now { get; } + } +} diff --git a/src/Middleware/HttpLogging/src/SystemDateTime.cs b/src/Middleware/HttpLogging/src/SystemDateTime.cs new file mode 100644 index 0000000000000000000000000000000000000000..ca786711a127f90421807af6400154fd4645513c --- /dev/null +++ b/src/Middleware/HttpLogging/src/SystemDateTime.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.HttpLogging +{ + internal class SystemDateTime : ISystemDateTime + { + public DateTime Now => DateTime.Now; + } +} diff --git a/src/Middleware/HttpLogging/test/FileLoggerProcessorTests.cs b/src/Middleware/HttpLogging/test/FileLoggerProcessorTests.cs index fd00142756f4524ff07fdcc5d080909e2b86db3a..3d98815447c8e8f9cf1ecce84bc67f127aa74a6e 100644 --- a/src/Middleware/HttpLogging/test/FileLoggerProcessorTests.cs +++ b/src/Middleware/HttpLogging/test/FileLoggerProcessorTests.cs @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.HttpLogging private string _messageTwo = "Message two"; private string _messageThree = "Message three"; private string _messageFour = "Message four"; - private readonly DateTime _today = DateTime.UtcNow; + private readonly DateTime _today = new DateTime(2021, 01, 01, 12, 00, 00); public FileLoggerProcessorTests() { @@ -37,34 +37,26 @@ namespace Microsoft.AspNetCore.HttpLogging [Fact] public async Task WritesToTextFile() { + var mockSystemDateTime = new MockSystemDateTime + { + Now = _today + }; var path = Path.Combine(TempPath, Path.GetRandomFileName()); try { string fileName; - var now = DateTimeOffset.Now; 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}{now.Year:0000}{now.Month:00}{now.Day:00}.0000.txt")); + 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 - try - { - await WaitForFile(fileName, _messageOne.Length).DefaultTimeout(); - } - catch - { - // Midnight could have struck between taking the DateTime & writing the log - if (!File.Exists(fileName)) - { - var tomorrow = now.AddDays(1); - fileName = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{tomorrow.Year:0000}{tomorrow.Month:00}{tomorrow.Day:00}.0000.txt")); - } - } + await WaitForFile(fileName, _messageOne.Length).DefaultTimeout(); } Assert.True(File.Exists(fileName)); @@ -77,7 +69,56 @@ namespace Microsoft.AspNetCore.HttpLogging } [Fact] - public async Task RollsTextFiles() + 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); + } + } + + [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/34284")] + [Fact] + public async Task RollsTextFilesBasedOnSize() { var path = Path.Combine(TempPath, Path.GetRandomFileName()); @@ -85,7 +126,10 @@ namespace Microsoft.AspNetCore.HttpLogging { string fileName1; string fileName2; - var now = DateTimeOffset.Now; + var mockSystemDateTime = new MockSystemDateTime + { + Now = _today + }; var options = new W3CLoggerOptions() { LogDirectory = path, @@ -93,30 +137,13 @@ namespace Microsoft.AspNetCore.HttpLogging }; await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor<W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { + logger.SystemDateTime = mockSystemDateTime; 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")); + fileName1 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.0000.txt")); + fileName2 = Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.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")); - } - } + await WaitForFile(fileName2, _messageTwo.Length).DefaultTimeout(); } Assert.True(File.Exists(fileName1)); Assert.True(File.Exists(fileName2)); @@ -136,12 +163,14 @@ namespace Microsoft.AspNetCore.HttpLogging 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 now = DateTimeOffset.Now; - var tomorrow = now.AddDays(1); var options = new W3CLoggerOptions() { LogDirectory = path, @@ -150,25 +179,17 @@ namespace Microsoft.AspNetCore.HttpLogging }; 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}{now.Year:0000}{now.Month:00}{now.Day:00}.0009.txt")); + 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 - 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 + await WaitForFile(lastFileName, _messageOne.Length).DefaultTimeout(); + for (int i = 0; i < 6; i++) { - // 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 + await WaitForRoll(Path.Combine(path, FormattableString.Invariant($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.{i:0000}.txt"))).DefaultTimeout(); } } @@ -182,9 +203,7 @@ namespace Microsoft.AspNetCore.HttpLogging 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))); + Assert.True((actualFiles[i].StartsWith($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}", StringComparison.InvariantCulture))); } } finally @@ -198,6 +217,10 @@ namespace Microsoft.AspNetCore.HttpLogging { var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); + var mockSystemDateTime = new MockSystemDateTime + { + Now = _today + }; try { @@ -212,6 +235,7 @@ namespace Microsoft.AspNetCore.HttpLogging var testLogger = new TestLoggerFactory(testSink, enabled:true); await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor<W3CLoggerOptions>(options), new HostingEnvironment(), testLogger)) { + logger.SystemDateTime = mockSystemDateTime; for (int i = 0; i < 10000; i++) { logger.EnqueueMessage(_messageOne); @@ -237,6 +261,7 @@ namespace Microsoft.AspNetCore.HttpLogging { Assert.Equal(0, testSink2.Writes.Count); + logger.SystemDateTime = mockSystemDateTime; logger.EnqueueMessage(_messageOne); await WaitForCondition(() => testSink2.Writes.FirstOrDefault()?.EventId.Name == "MaxFilesReached").DefaultTimeout(); } @@ -250,12 +275,10 @@ namespace Microsoft.AspNetCore.HttpLogging [Fact] public async Task InstancesWriteToSameDirectory() { - var now = DateTimeOffset.Now; - if (now.Hour == 23) + var mockSystemDateTime = new MockSystemDateTime { - // Don't bother trying to run this test when it's almost midnight. - return; - } + Now = _today + }; var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); @@ -270,11 +293,12 @@ namespace Microsoft.AspNetCore.HttpLogging }; 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}{now.Year:0000}{now.Month:00}{now.Day:00}.0002.txt")); + 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(); } @@ -282,11 +306,12 @@ namespace Microsoft.AspNetCore.HttpLogging // 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}{now.Year:0000}{now.Month:00}{now.Day:00}.0005.txt")); + 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(); } @@ -300,18 +325,19 @@ namespace Microsoft.AspNetCore.HttpLogging Assert.Equal(6, actualFiles1.Length); for (int i = 0; i < 6; i++) { - Assert.Contains($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.{i:0000}.txt", actualFiles1[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}{now.Year:0000}{now.Month:00}{now.Day:00}.0006.txt")), _messageOne.Length).DefaultTimeout(); - await WaitForRoll(Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0000.txt"))).DefaultTimeout(); - await WaitForRoll(Path.Combine(path, FormattableString.Invariant($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.0001.txt"))).DefaultTimeout(); + 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) @@ -323,7 +349,7 @@ namespace Microsoft.AspNetCore.HttpLogging Assert.Equal(5, actualFiles2.Length); for (int i = 0; i < 5; i++) { - Assert.Equal($"{options.FileName}{now.Year:0000}{now.Month:00}{now.Day:00}.{i + 2:0000}.txt", actualFiles2[i]); + Assert.Equal($"{options.FileName}{_today.Year:0000}{_today.Month:00}{_today.Day:00}.{i + 2:0000}.txt", actualFiles2[i]); } } finally @@ -336,12 +362,10 @@ namespace Microsoft.AspNetCore.HttpLogging [Fact] public async Task WritesToNewFileOnNewInstance() { - var now = DateTimeOffset.Now; - if (now.Hour == 23) + var mockSystemDateTime = new MockSystemDateTime { - // Don't bother trying to run this test when it's almost midnight. - return; - } + Now = _today + }; var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); @@ -353,12 +377,13 @@ namespace Microsoft.AspNetCore.HttpLogging 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")); + 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 @@ -370,6 +395,7 @@ namespace Microsoft.AspNetCore.HttpLogging 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(); @@ -400,6 +426,11 @@ namespace Microsoft.AspNetCore.HttpLogging [Fact] public async Task RollsTextFilesWhenFirstLogOfDayIsMissing() { + var mockSystemDateTime = new MockSystemDateTime + { + Now = _today + }; + var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); @@ -418,6 +449,7 @@ namespace Microsoft.AspNetCore.HttpLogging await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor<W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { + logger.SystemDateTime = mockSystemDateTime; logger.EnqueueMessage(_messageOne); logger.EnqueueMessage(_messageTwo); logger.EnqueueMessage(_messageThree); @@ -430,6 +462,7 @@ namespace Microsoft.AspNetCore.HttpLogging await using (var logger = new FileLoggerProcessor(new OptionsWrapperMonitor<W3CLoggerOptions>(options), new HostingEnvironment(), NullLoggerFactory.Instance)) { + logger.SystemDateTime = mockSystemDateTime; logger.EnqueueMessage(_messageFour); // Pause for a bit before disposing so logger can finish logging await WaitForFile(fileName4, _messageFour.Length).DefaultTimeout(); @@ -461,12 +494,10 @@ namespace Microsoft.AspNetCore.HttpLogging [Fact] public async Task WritesToNewFileOnOptionsChange() { - var now = DateTimeOffset.Now; - if (now.Hour == 23) + var mockSystemDateTime = new MockSystemDateTime { - // Don't bother trying to run this test when it's almost midnight. - return; - } + Now = _today + }; var path = Path.Combine(TempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); @@ -479,12 +510,13 @@ namespace Microsoft.AspNetCore.HttpLogging 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 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 monitor = new OptionsWrapperMonitor<W3CLoggerOptions>(options); await using (var logger = new FileLoggerProcessor(monitor, new HostingEnvironment(), NullLoggerFactory.Instance)) { + logger.SystemDateTime = mockSystemDateTime; logger.EnqueueMessage(_messageOne); await WaitForFile(fileName1, _messageOne.Length).DefaultTimeout(); options.LoggingFields = W3CLoggingFields.Date; diff --git a/src/Middleware/HttpLogging/test/MockSystemDateTime.cs b/src/Middleware/HttpLogging/test/MockSystemDateTime.cs new file mode 100644 index 0000000000000000000000000000000000000000..17f8d3face6792909766f31d5fca0f4e5baf5a33 --- /dev/null +++ b/src/Middleware/HttpLogging/test/MockSystemDateTime.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.AspNetCore.HttpLogging +{ + internal class MockSystemDateTime : ISystemDateTime + { + public DateTime Now { get; set; } + } +}