Exemple #1
0
        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()));
        }
Exemple #2
0
        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();
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
            }
        }