public void ShouldConsiderPriority_ForAllMessageTypes_Concurrent() { //Arrange var fileName = $"testlog{Guid.NewGuid()}"; var logDir = _logDir; _fileLoggerProvider = new FileLoggerProvider(new OptionsManager <FileLoggerOptions>(new List <IConfigureOptions <FileLoggerOptions> >() { new ConfigureOptions <FileLoggerOptions>( (x) => { x.FileName = fileName; x.LogDirectory = logDir; }) })); var logger = _fileLoggerProvider.CreateLogger(); var guid = Guid.NewGuid(); var guid2 = Guid.NewGuid(); var guid3 = Guid.NewGuid(); var guid4 = Guid.NewGuid(); var guid5 = Guid.NewGuid(); //Act new Thread(() => logger.Log(Severity.Debug, new Exception($"Simple debug error {guid}"))).Start(); new Thread(() => logger.Log(Severity.Info, new Exception($"Simple info error {guid2}"))).Start(); new Thread(() => logger.Log(Severity.Error, new Exception($"Simple error error {guid4}"))).Start(); new Thread(() => logger.Log(Severity.Critical, new Exception($"Simple critical error {guid5}"))).Start(); new Thread(() => logger.Log(Severity.Warn, new Exception($"Simple warn error {guid3}"))).Start(); //Assert Thread.Sleep(5000); var lastLines = File.ReadLines(GetFullName(fileName, (DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day))) .TakeLast(10).ToArray(); //10 - because every log puts 2 lines into log file Assert.True(lastLines[0].Contains(guid5.ToString())); Assert.True(lastLines[2].Contains(guid4.ToString())); Assert.True(lastLines[4].Contains(guid3.ToString())); Assert.True(lastLines[6].Contains(guid2.ToString())); Assert.True(lastLines[8].Contains(guid.ToString())); }
public void Dispose_ManyLogMessages_WaitsUntilAllWritten() { // ARRANGE var sut = new FileLoggerProvider(logFile, 1); var logger = sut.CreateLogger("name"); var blockWrite = true; // Imitate a file write delay. A.CallTo(() => logFile.Write(A <string> ._, A <bool> ._)).Invokes(() => { while (blockWrite) { } }); logger.LogInformation("some message"); var blocked = true; // ACT // Dispose the provider in background thread and ensure it remains // blocked because the file operation is not yet complete. ThreadPool.QueueUserWorkItem(state => { sut.Dispose(); blocked = false; }); // ASSERT Thread.Sleep(100); blocked.Should().BeTrue("The file operation is not yet complete, Dispose() must not return"); // ACT // Now complete the file operation. Since it was the last operation, // the Dispose must return as its' background thread has completed everything. blockWrite = false; Thread.Sleep(100); blocked.Should().BeFalse(); }
private async Task LoggingToMemoryWithoutDICore(LogFileAccessMode accessMode) { const string logsDirName = "Logs"; var fileProvider = new MemoryFileProvider(); var filterOptions = new LoggerFilterOptions { MinLevel = LogLevel.Trace }; var options = new FileLoggerOptions { FileAppender = new MemoryFileAppender(fileProvider), BasePath = logsDirName, FileAccessMode = accessMode, FileEncoding = Encoding.UTF8, MaxQueueSize = 100, DateFormat = "yyMMdd", CounterFormat = "000", MaxFileSize = 10, Files = new[] { new LogFileOptions { Path = "<date>/<date:MM>/logger.log", DateFormat = "yyyy", MinLevel = new Dictionary <string, LogLevel> { ["Karambolo.Extensions.Logging.File"] = LogLevel.None, [LogFileOptions.DefaultCategoryName] = LogLevel.Information, } }, new LogFileOptions { Path = "test-<date>-<counter>.log", MinLevel = new Dictionary <string, LogLevel> { ["Karambolo.Extensions.Logging.File"] = LogLevel.Information, [LogFileOptions.DefaultCategoryName] = LogLevel.None, } }, }, TextBuilder = new CustomLogEntryTextBuilder(), IncludeScopes = true, }; 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 ex = new Exception(); var provider = new FileLoggerProvider(context, Options.Create(options)); try { using (var loggerFactory = new LoggerFactory(new[] { provider }, filterOptions)) { ILogger <LoggingTest> logger1 = loggerFactory.CreateLogger <LoggingTest>(); logger1.LogInformation("This is a nice logger."); using (logger1.BeginScope("SCOPE")) { logger1.LogWarning(1, "This is a smart logger."); logger1.LogTrace("This won't make it."); using (logger1.BeginScope("NESTED SCOPE")) { ILogger logger2 = loggerFactory.CreateLogger("X"); logger2.LogWarning("Some warning."); logger2.LogError(0, ex, "Some failure!"); } } } } finally { #if NETCOREAPP3_0 await provider.DisposeAsync(); #else await Task.CompletedTask; provider.Dispose(); #endif } Assert.True(provider.Completion.IsCompleted); var logFile = (MemoryFileInfo)fileProvider.GetFileInfo($"{logsDirName}/test-{context.GetTimestamp().ToLocalTime():yyMMdd}-000.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[] { $"[info]: {typeof(LoggingTest)}[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This is a nice logger.", "" }, lines); logFile = (MemoryFileInfo)fileProvider.GetFileInfo($"{logsDirName}/test-{context.GetTimestamp().ToLocalTime():yyMMdd}-001.log"); Assert.True(logFile.Exists && !logFile.IsDirectory); lines = logFile.ReadAllText(out encoding).Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.UTF8, encoding); Assert.Equal(new[] { $"[warn]: {typeof(LoggingTest)}[1] @ {context.GetTimestamp().ToLocalTime():o}", $" => SCOPE", $" This is a smart logger.", "" }, lines); logFile = (MemoryFileInfo)fileProvider.GetFileInfo( $"{logsDirName}/{context.GetTimestamp().ToLocalTime():yyyy}/{context.GetTimestamp().ToLocalTime():MM}/logger.log"); Assert.True(logFile.Exists && !logFile.IsDirectory); lines = logFile.ReadAllText(out encoding).Split(new[] { Environment.NewLine }, StringSplitOptions.None); Assert.Equal(Encoding.UTF8, encoding); Assert.Equal(new[] { $"[warn]: X[0] @ {context.GetTimestamp().ToLocalTime():o}", $" => SCOPE => NESTED SCOPE", $" Some warning.", $"[fail]: X[0] @ {context.GetTimestamp().ToLocalTime():o}", $" => SCOPE => NESTED SCOPE", $" Some failure!", } .Concat(ex.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None)) .Append(""), lines); }
public void FailingEntryDontGetStuck() { var tempPath = Path.GetTempPath(); var logPath = Path.Combine(tempPath, LogsDirName); if (Directory.Exists(logPath)) { Directory.Delete(logPath, recursive: true); } Directory.CreateDirectory(logPath); try { var context = new TestFileLoggerContext(new PhysicalFileProvider(tempPath), "fallback.log"); context.SetWriteRetryDelay(TimeSpan.FromMilliseconds(250)); context.SetCompletionTimeout(TimeSpan.FromMilliseconds(2000)); var completionTasks = new List <Task>(); context.Complete += (s, e) => completionTasks.Add(e); var cts = new CancellationTokenSource(); var settings = new FileLoggerSettings { BasePath = LogsDirName, FileNameMappings = new Dictionary <string, string> { { "Default", "default.log" } }, Switches = new Dictionary <string, LogLevel> { { FileLoggerSettingsBase.DefaultCategoryName, LogLevel.Information } }, ChangeToken = new CancellationChangeToken(cts.Token) }; var filePath = Path.Combine(logPath, "default.log"); using (var loggerProvider = new FileLoggerProvider(context, settings)) { ILogger logger = loggerProvider.CreateLogger("X"); logger.LogInformation("This should get through."); var newCts = new CancellationTokenSource(); settings.ChangeToken = new CancellationChangeToken(newCts.Token); cts.Cancel(); cts = newCts; Assert.Single(completionTasks); Task.WhenAll(completionTasks).GetAwaiter().GetResult(); using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { logger.LogInformation("This shouldn't get through."); cts.Cancel(); Assert.Equal(2, completionTasks.Count); var delayTask = Task.Delay(5000); Assert.Equal(completionTasks[1], Task.WhenAny(completionTasks[1], delayTask).GetAwaiter().GetResult()); Assert.Equal(TaskStatus.RanToCompletion, completionTasks[1].Status); } } var lines = System.IO.File.ReadAllLines(filePath); Assert.Equal(lines, new[] { $"info: X[0] @ {context.GetTimestamp().ToLocalTime():o}", $" This should get through.", }); } finally { Directory.Delete(logPath, recursive: true); } }