public void InitalizePaths() { TestHelper.InitalizePaths(); TestHelper.PrepareLogFolder("Gzip"); TestHelper.PrepareLogFolder("Termination"); TestHelper.PrepareLogFolder("TerminationLost"); }
public void BinaryGzip_reconfiguration() { string folder = TestHelper.PrepareLogFolder(nameof(BinaryGzip_reconfiguration)); var h = new Handlers.BinaryFileConfiguration() { Path = folder + @"\FirstPath", UseGzipCompression = false }; var c = new GrandOutputConfiguration().AddHandler(h); var m = new ActivityMonitor(applyAutoConfigurations: false); using (GrandOutput g = new GrandOutput(c)) { g.EnsureGrandOutputClient(m); m.Trace("No Compression."); // We must ensure that the log above will use the current configuration. // This is by design and is a good thing: there is no causality/ordering between log emission and sink reconfigurations. Thread.Sleep(100); h.UseGzipCompression = true; g.ApplyConfiguration(c, true); m.Trace("With Compression."); Thread.Sleep(100); h.Path = folder + @"\SecondPath"; g.ApplyConfiguration(c, true); m.Trace("With Compression (in second folder)."); Thread.Sleep(100); h.UseGzipCompression = false; g.ApplyConfiguration(c, true); m.Trace("No Compression (in second folder)."); } // First file is NOT compressed, the second one is. var fileNamesFirst = Directory.EnumerateFiles(folder + @"\FirstPath").ToList(); fileNamesFirst.Should().BeInAscendingOrder().And.HaveCount(2).And.NotContain(s => s.EndsWith(".tmp"), "Temporary files have been closed."); File.ReadAllText(fileNamesFirst[0]).Should().Contain("No Compression."); File.ReadAllText(fileNamesFirst[1]).Should().NotContain("With Compression.", "Cannot read it in clear text since it is compressed..."); using (var reader = LogReader.Open(fileNamesFirst[1])) { reader.MoveNext().Should().BeTrue(); reader.Current.Text.Should().Be("With Compression."); } // First file is compressed, not the second one. var fileNamesSecond = Directory.EnumerateFiles(folder + @"\SecondPath").ToList(); fileNamesSecond.Should().BeInAscendingOrder().And.HaveCount(2).And.NotContain(s => s.EndsWith(".tmp"), "Temporary files have been closed."); File.ReadAllText(fileNamesSecond[0]).Should().NotContain("With Compression (in second folder).", "The fist file is compressed..."); // We restrict the log entries to the one of our monitor: this filters out the logs from the DispatcherSink. using (var reader = LogReader.Open(fileNamesSecond[0], filter: new LogReader.MulticastFilter(m))) { reader.MoveNext().Should().BeTrue(); reader.Current.Text.Should().Be("With Compression (in second folder)."); } File.ReadAllText(fileNamesSecond[1]).Should().Contain("No Compression (in second folder)."); }
public void external_logs_filtering() { string folder = TestHelper.PrepareLogFolder("ExternalLogsFiltering"); var textConf = new Handlers.TextFileConfiguration() { Path = "ExternalLogsFiltering" }; var config = new GrandOutputConfiguration().AddHandler(textConf); ActivityMonitor.DefaultFilter.Line.Should().Be(LogLevelFilter.Trace); using (GrandOutput g = new GrandOutput(config)) { g.ExternalLog(LogLevel.Debug, message: "NOSHOW"); g.ExternalLog(LogLevel.Trace, message: "SHOW 0"); g.ExternalLogLevelFilter = LogLevelFilter.Debug; g.ExternalLog(LogLevel.Debug, message: "SHOW 1"); g.ExternalLogLevelFilter = LogLevelFilter.Error; g.ExternalLog(LogLevel.Warn, message: "NOSHOW"); g.ExternalLog(LogLevel.Error, message: "SHOW 2"); g.ExternalLog(LogLevel.Fatal, message: "SHOW 3"); g.ExternalLog(LogLevel.Trace | LogLevel.IsFiltered, message: "SHOW 4"); g.ExternalLogLevelFilter = LogLevelFilter.None; g.ExternalLog(LogLevel.Debug, message: "NOSHOW"); g.ExternalLog(LogLevel.Trace, message: "SHOW 4"); g.IsExternalLogEnabled(LogLevel.Debug).Should().BeFalse(); g.IsExternalLogEnabled(LogLevel.Trace).Should().BeTrue(); ActivityMonitor.Tags.AddFilter(_myTag, new LogClamper(LogFilter.Verbose, true)); // Verbose allows Info, not Trace lines. g.ExternalLog(LogLevel.Info, _myTag, message: "SHOW 5"); g.ExternalLog(LogLevel.Trace, _myTag, message: "NOSHOW"); g.IsExternalLogEnabled(LogLevel.Info, _myTag).Should().BeTrue(); g.IsExternalLogEnabled(LogLevel.Trace, _myTag).Should().BeFalse(); ActivityMonitor.Tags.RemoveFilter(_myTag); g.IsExternalLogEnabled(LogLevel.Trace, _myTag).Should().BeTrue(); g.ExternalLog(LogLevel.Trace, _myTag, message: "SHOW 6"); } string textLogged = File.ReadAllText(Directory.EnumerateFiles(folder).Single()); textLogged.Should() .Contain("SHOW 0") .And.Contain("SHOW 1") .And.Contain("SHOW 2") .And.Contain("SHOW 3") .And.Contain("SHOW 4") .And.Contain("SHOW 5") .And.Contain("SHOW 6") .And.NotContain("NOSHOW"); }
public void text_file_auto_delete_by_date() { string folder = TestHelper.PrepareLogFolder("AutoDelete_Date"); var textConf = new Handlers.TextFileConfiguration() { Path = "AutoDelete_Date" }; textConf.HousekeepingRate.Should().Be(1800, "Default HousekeepingRate configuration"); textConf.MinimumDaysToKeep.Should().Be(60, "Default HousekeepingRate configuration"); textConf.MinimumTimeSpanToKeep.Should().Be(TimeSpan.FromDays(60), "Default HousekeepingRate configuration"); textConf.MaximumTotalKbToKeep.Should().Be(100_000, "Default HousekeepingRate configuration"); // Change configuration for tests textConf.HousekeepingRate = 1; // Run every 500ms normally (here TimerDuration is set to 100ms). textConf.MaximumTotalKbToKeep = 0; // Always delete file beyond max size textConf.MinimumTimeSpanToKeep = TimeSpan.FromSeconds(3); // Delete files older than 3 seconds var config = new GrandOutputConfiguration().AddHandler(textConf); // Changes the default 500 ms to trigger OnTimerAsync more often. config.TimerDuration = TimeSpan.FromMilliseconds(100); // TEST DELETION BY DATE using (GrandOutput g = new GrandOutput(config)) { var m = new ActivityMonitor(false); g.EnsureGrandOutputClient(m); Thread.Sleep(5); m.Info("Hello world"); Thread.Sleep(30); string tempFile = Directory.EnumerateFiles(folder).Single(); File.Exists(tempFile).Should().BeTrue("Log file was created and exists"); // Wait for next flush (~100ms), and deletion threshold (3000ms) Thread.Sleep(3200); File.Exists(tempFile).Should().BeTrue("Log file wasn't deleted yet - it's still active"); } string finalLogFile = Directory.EnumerateFiles(folder).Single(); // Open another GrandOutput to trigger housekeeping using (GrandOutput g = new GrandOutput(config)) { // Wait for next flush (~100 ms) Thread.Sleep(200); } File.Exists(finalLogFile).Should().BeFalse("Inactive log file was deleted"); }
public void text_file_auto_delete_by_size() { string folder = TestHelper.PrepareLogFolder("AutoDelete_Size"); var textConf = new Handlers.TextFileConfiguration() { Path = "AutoDelete_Size" }; // Change configuration for tests textConf.HousekeepingRate = 1; // Run every 500ms normally (here TimerDuration is set to 100ms). textConf.MaximumTotalKbToKeep = 1; // Always delete file beyond max size textConf.MinimumTimeSpanToKeep = TimeSpan.Zero; // Make minimum timespan var config = new GrandOutputConfiguration().AddHandler(textConf); int lineLengthToLogToGet1000bytes = 500; // Changes the default 500 ms to trigger OnTimerAsync more often. config.TimerDuration = TimeSpan.FromMilliseconds(100); // Create 3*1 KB log files for (int i = 0; i < 3; i++) { using (GrandOutput g = new GrandOutput(config)) { var m = new ActivityMonitor(false); g.EnsureGrandOutputClient(m); m.Info(new string( 'X', lineLengthToLogToGet1000bytes )); } } long GetTotalLogSize() { return(Directory.EnumerateFiles(folder).Sum(x => new FileInfo(x).Length)); } var totalLogSize = GetTotalLogSize(); totalLogSize.Should().BeGreaterThan(2500); // Open another GrandOutput to trigger housekeeping. // Note: this DOES create a file! using (GrandOutput g = new GrandOutput(config)) { // Wait for next flush (~100 ms) Thread.Sleep(200); } var files = Directory.GetFiles(folder).Select(f => Path.GetFileName(f)); files.Should().HaveCount(2, $"Only 2 files should be kept - the last log file, and 1x~1KB file: {files.Concatenate()}"); }
public void sending_log_from_client() { string logPath = TestHelper.PrepareLogFolder("sending_log_from_client"); var c = new GrandOutputConfiguration() .AddHandler(new Handlers.TextFileConfiguration() { Path = logPath }) .AddHandler(new Handlers.BinaryFileConfiguration() { Path = logPath }); using (var g = new GrandOutput(c)) { var m = new ActivityMonitor(false); g.EnsureGrandOutputClient(m); var txt = new StupidStringClient(); m.Output.RegisterClient(txt); using (var r = SimpleLogPipeReceiver.Start(m, interProcess: false)) { RunClient(r.PipeName); r.WaitEnd(false).Should().Be(LogReceiverEndStatus.Normal); } var stupidLogs = txt.ToString(); stupidLogs.Should().Contain("From client.") .And.Contain("An Exception for the fun.") // StupidStringClient does not dump inner exception, only the top message. // .And.Contain( "With an inner exception!" ) .And.Contain("Info n°0") .And.Contain("Info n°19"); } // All temporary files have been closed. var fileNames = Directory.EnumerateFiles(logPath).ToList(); fileNames.Should().NotContain(s => s.EndsWith(".tmp")); // Brutallity here: opening the binary file as a text. // It is enough to check the serialized strings. var texts = fileNames.Select(n => File.ReadAllText(n)); foreach (var logs in texts) { logs.Should().Contain("From client.") .And.Contain("An Exception for the fun.") .And.Contain("With an inner exception!") .And.Contain("Info n°0") .And.Contain("Info n°19"); } }
public async Task external_logs_quick_test_Async() { string folder = TestHelper.PrepareLogFolder("ExternalLogsQuickTest"); var textConf = new Handlers.TextFileConfiguration() { Path = "ExternalLogsQuickTest" }; var config = new GrandOutputConfiguration().AddHandler(textConf); using (GrandOutput g = new GrandOutput(config)) { await Task.Run(() => { ActivityMonitor.StaticLogger.Info($"Async started from ActivityMonitor.StaticLogger."); g.ExternalLog(LogLevel.Info, message: "Async started."); }); var m = new ActivityMonitor(false); g.EnsureGrandOutputClient(m); m.Info("Normal monitor starts."); Task t = Task.Run(() => { for (int i = 0; i < 10; ++i) { ActivityMonitor.StaticLogger.Info($"Async n°{i} from ActivityMonitor.StaticLogger."); g.ExternalLog(LogLevel.Info, $"Async n°{i}."); } }); m.MonitorEnd("This is the end."); await t; } string textLogged = File.ReadAllText(Directory.EnumerateFiles(folder).Single()); textLogged.Should() .Contain("Normal monitor starts.") .And.Contain("Async started from ActivityMonitor.StaticLogger.") .And.Contain("Async started.") .And.Contain("Async n°0.") .And.Contain("Async n°9.") .And.Contain("Async n°0 from ActivityMonitor.StaticLogger.") .And.Contain("Async n°9 from ActivityMonitor.StaticLogger.") .And.Contain("This is the end."); }
public async Task CKMon_binary_files_can_be_GZip_compressed_Async() { string folder = TestHelper.PrepareLogFolder("Gzip"); var c = new GrandOutputConfiguration() .AddHandler(new Handlers.BinaryFileConfiguration() { Path = folder + @"\OutputGzip", UseGzipCompression = true }) .AddHandler(new Handlers.BinaryFileConfiguration() { Path = folder + @"\OutputRaw", UseGzipCompression = false }); using (GrandOutput g = new GrandOutput(c)) { var taskA = Task.Factory.StartNew(() => DumpMonitor1082Entries(CreateMonitorAndRegisterGrandOutput("Task A", g), 5), default, TaskCreationOptions.LongRunning, TaskScheduler.Default);
public void text_file_auto_flush_and_reconfiguration() { string folder = TestHelper.PrepareLogFolder("AutoFlush"); var textConf = new Handlers.TextFileConfiguration() { Path = "AutoFlush" }; textConf.AutoFlushRate.Should().Be(6, "Default AutoFlushRate configuration."); // Avoid relying on the internal 500ms default. var config = new GrandOutputConfiguration { TimerDuration = TimeSpan.FromMilliseconds(500) } .AddHandler(textConf); using (GrandOutput g = new GrandOutput(config)) { var m = new ActivityMonitor(false); g.EnsureGrandOutputClient(m); Thread.Sleep(5); m.Info("Must wait 3 seconds..."); Thread.Sleep(700); string tempFile = Directory.EnumerateFiles(folder).Single(); TestHelper.FileReadAllText(tempFile).Should().BeEmpty(); Thread.Sleep(3000); TestHelper.FileReadAllText(tempFile).Should().Contain("Must wait 3 seconds..."); textConf.AutoFlushRate = 1; m.Info("Reconfiguration triggers a flush..."); Thread.Sleep(10); g.ApplyConfiguration(new GrandOutputConfiguration().AddHandler(textConf), waitForApplication: true); TestHelper.FileReadAllText(tempFile).Should().Contain("Reconfiguration triggers a flush..."); m.Info("Wait only approx 500ms..."); Thread.Sleep(700); string final = TestHelper.FileReadAllText(tempFile); final.Should().Contain("Wait only approx 500ms"); } }
public void dumping_text_file_with_multiple_monitors() { string folder = TestHelper.PrepareLogFolder("TextFileMulti"); Random r = new Random(); GrandOutputConfiguration config = new GrandOutputConfiguration() .AddHandler(new Handlers.TextFileConfiguration() { Path = "TextFileMulti" }); using (GrandOutput g = new GrandOutput(config)) { Parallel.Invoke( () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs2(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs2(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs1(r, g), () => DumpSampleLogs2(r, g) ); } FileInfo f = new DirectoryInfo(LogFile.RootLogPath + "TextFileMulti").EnumerateFiles().Single(); string text = File.ReadAllText(f.FullName); Console.WriteLine(text); }