public async Task request_monitor_handles_exceptions_but_does_not_swallow_them_by_default(bool swallow) { var text = new TextGrandOutputHandlerConfiguration(); var config = new GrandOutputConfiguration(); config.AddHandler(text); GrandOutput.EnsureActiveDefault(config); int rootExceptionCount = 0; try { var b = Tester.WebHostBuilderFactory.Create(null, null, services => { services.AddSingleton <StupidService>(); }, app => { app.Use(async(context, next) => { try { await next.Invoke(); } catch { ++rootExceptionCount; context.Response.StatusCode = StatusCodes.Status500InternalServerError; } }); app.UseRequestMonitor(o => { o.SwallowErrors = swallow; }); app.UseMiddleware <StupidMiddleware>(); }); using (var client = new TestServerClient(new TestServer(b))) { using (HttpResponseMessage bug = await client.Get("?bug")) { bug.StatusCode.Should().Be(HttpStatusCode.InternalServerError); text.GetText().Should().Contain("Bug!"); } using (HttpResponseMessage asyncBug = await client.Get("?asyncBug")) { asyncBug.StatusCode.Should().Be(HttpStatusCode.InternalServerError); text.GetText().Should().Contain("AsyncBug!"); } } } finally { GrandOutput.Default.Dispose(); } if (swallow) { Assert.That(rootExceptionCount, Is.EqualTo(0)); } else { Assert.That(rootExceptionCount, Is.EqualTo(2)); } }
public void dumping_text_file() { string folder = TestHelper.PrepareLogFolder("TextFile"); Random r = new Random(); GrandOutputConfiguration config = new GrandOutputConfiguration() .AddHandler(new Handlers.TextFileConfiguration() { Path = "TextFile" }); using (GrandOutput g = new GrandOutput(config)) { DumpSampleLogs1(r, g); DumpSampleLogs2(r, g); } FileInfo f = new DirectoryInfo(LogFile.RootLogPath + "TextFile").EnumerateFiles().Single(); string text = File.ReadAllText(f.FullName); Console.WriteLine(text); text.Should().Contain("First Activity..."); text.Should().Contain("End of first activity."); text.Should().Contain("another one"); text.Should().Contain("Something must be said"); text.Should().Contain("My very first conclusion."); text.Should().Contain("My second conclusion."); string lineWithSecondConclusion = text.Split("\n").Single(s => s.Contains("My second conclusion.")); lineWithSecondConclusion .Replace("My second conclusion.", "") .Replace(" ", "") .Replace("|", "") .Replace("\n", "") .Replace("\r", "") .Should().BeEmpty(); }
private static void SetupActivityMonitor() { System.Console.OutputEncoding = System.Text.Encoding.Unicode; ActivityMonitor.DefaultFilter = LogFilter.Debug; ActivityMonitor.AutoConfiguration += monitor => monitor.Output.RegisterClient(new ActivityMonitorConsoleClient()); LogFile.RootLogPath = GetLogDirectory(); var grandOutputConfig = new GrandOutputConfiguration(); grandOutputConfig.AddHandler(new TextFileConfiguration { MaxCountPerFile = 10000, Path = "Text", }); grandOutputConfig.AddHandler(new TcpHandlerConfiguration { Host = "127.0.0.1", Port = 33698, IsSecure = false, AppName = typeof(Program).GetTypeInfo().Assembly.GetName().Name, PresentEnvironmentVariables = true, PresentMonitoringAssemblyInformation = true, HandleSystemActivityMonitorErrors = true, }); GrandOutput.EnsureActiveDefault(grandOutputConfig); }
static GrandOutput CreateGrandOutputWithFakeHandler(int handlerExtralLoad, bool useAdaptive, int dispatcherMaxCapacity) { IActivityMonitor mLoad = new ActivityMonitor(false); GrandOutputConfiguration c = new GrandOutputConfiguration(); var textConfig = @"<GrandOutputConfiguration><Channel><Add Type=""FakeHandler, CK.Monitoring.Tests"" Name=""GlobalCatch"" ExtraLoad=""" + handlerExtralLoad.ToString() + @""" /></Channel></GrandOutputConfiguration>"; Assert.That(c.Load(XDocument.Parse(textConfig).Root, mLoad)); Assert.That(c.ChannelsConfiguration.Configurations.Count, Is.EqualTo(1)); IGrandOutputDispatcherStrategy strat; if (useAdaptive) { strat = new Impl.EventDispatcherLocalTestStrategy(dispatcherMaxCapacity); } else { strat = new Impl.EventDispatcherBasicStrategy(dispatcherMaxCapacity); } GrandOutput g = new GrandOutput(strat); g.SetConfiguration(c, mLoad); return(g); }
public void ApplyConfigSimple() { GrandOutputConfiguration c = new GrandOutputConfiguration(); Assert.That(c.Load(XDocument.Parse(@" <GrandOutputConfiguration AppDomainDefaultFilter=""Release"" > <Channel MinimalFilter=""{Trace,Info}""> <Add Type=""BinaryFile"" Name=""GlobalCatch"" Path=""Configuration/ApplyConfig"" /> </Channel> </GrandOutputConfiguration>").Root, TestHelper.ConsoleMonitor)); Assert.That(c.ChannelsConfiguration.Configurations.Count, Is.EqualTo(1)); ActivityMonitor m = new ActivityMonitor(false); using (GrandOutput g = new GrandOutput()) { m.Info().Send("Before Registering - NOSHOW"); g.Register(m); m.Info().Send("Before configuration - NOSHOW"); Assert.That(g.SetConfiguration(c, TestHelper.ConsoleMonitor)); m.Info().Send("After configuration. INFO1"); Assert.That(m.ActualFilter, Is.EqualTo(new LogFilter(LogLevelFilter.Trace, LogLevelFilter.Info))); m.Trace().Send("TRACE1-NOSHOW (MinimalFilter of the Channel)."); Assert.That(g.SetConfiguration(new GrandOutputConfiguration(), TestHelper.ConsoleMonitor)); g.Dispose(TestHelper.ConsoleMonitor); m.Info().Send("After disposing - NOSHOW."); Assert.That(m.ActualFilter, Is.EqualTo(LogFilter.Undefined)); } }
public async Task external_logs_stress_test_Async() { string folder = TestHelper.PrepareLogFolder("ExternalLogsStressTest"); var textConf = new Handlers.TextFileConfiguration() { Path = "ExternalLogsStressTest" }; var config = new GrandOutputConfiguration().AddHandler(textConf); int taskCount = 20; int logCount = 10; using (GrandOutput g = new GrandOutput(config)) { var tasks = Enumerable.Range(0, taskCount).Select(c => Task.Run(() => { for (int i = 0; i < logCount; ++i) { Thread.Sleep(2); g.ExternalLog(LogLevel.Info, message: $"{c} n°{i}."); } })).ToArray(); await Task.WhenAll(tasks); } string textLogged = File.ReadAllText(Directory.EnumerateFiles(folder).Single()); for (int c = 0; c < taskCount; ++c) { for (int i = 0; i < logCount; ++i) { textLogged.Should() .Contain($"{c} n°{i}."); } } }
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 FilteringBySource() { TestHelper.CleanupFolder(SystemActivityMonitor.RootLogPath + "FilteringBySource"); using (GrandOutput g = new GrandOutput()) { GrandOutputConfiguration config = new GrandOutputConfiguration(); config.Load(XDocument.Parse(@" <GrandOutputConfiguration> <Channel MinimalFilter=""Debug""> <Add Type=""BinaryFile"" Name=""All"" Path=""FilteringBySource"" /> <Channel Name=""HiddenTopic"" MinimalFilter=""Off"" TopicRegex=""(hidden\s+topic|hide\s+this\s+topic)"" MatchOptions=""CultureInvariant, ExplicitCapture, Compiled, Multiline"" /> </Channel> <SourceOverrideFilter> <Add File=""SourceFile-Debug.cs"" Filter=""Debug"" /> <Add File=""SourceFile-Off.cs"" Filter=""Off"" /> <Add File=""SourceFile-Strange.cs"" Filter=""{Trace,Fatal}"" /> </SourceOverrideFilter> </GrandOutputConfiguration>", LoadOptions.SetLineInfo).Root, TestHelper.ConsoleMonitor); Assert.That(g.SetConfiguration(config, TestHelper.ConsoleMonitor)); var m = new ActivityMonitor(false); g.Register(m); m.Fatal(fileName: "SourceFile-Off.cs").Send("NOSHOW"); m.SetTopic("This is a hidden topic..."); m.Trace(0, "SourceFile-Debug.cs").Send("Trace-1"); m.Trace().Send("NOSHOW"); m.SetTopic("Please, hide this topic!"); m.Trace(fileName: "SourceFile-Strange.cs").Send("NOSHOW"); using (m.OpenTrace(fileName: "SourceFile-Strange.cs").Send("Trace-2")) { m.Trace(fileName: "SourceFile-Strange.cs").Send("NOSHOW"); m.Fatal(fileName: "SourceFile-Strange.cs").Send("Fatal-1"); m.Fatal(fileName: "SourceFile-Off.cs").Send("NOSHOW"); } m.SetTopic(null); m.Trace(fileName: "SourceFile-Strange.cs").Send("NOSHOW"); m.Fatal(fileName: "SourceFile-Off.cs").Send("NOSHOW"); m.Trace().Send("Trace-3"); } List <StupidStringClient> logs = TestHelper.ReadAllLogs(new DirectoryInfo(SystemActivityMonitor.RootLogPath + "FilteringBySource"), false); Assert.That(logs.Count, Is.EqualTo(1)); Assert.That(logs[0].ToString(), Does.Not.Contain("NOSHOW")); var texts = logs[0].Entries.Select(e => e.Text).ToArray(); CollectionAssert.AreEqual(new string[] { "Trace-1", "Trace-2", "Fatal-1", ActivityMonitor.SetTopicPrefix, "Trace-3", }, texts, StringComparer.Ordinal); }
public void ConfigObjectAttributeRequired() { GrandOutputConfiguration c = new GrandOutputConfiguration(); Assert.That(c.Load(XDocument.Parse(@"<GrandOutputConfiguration><Add /></GrandOutputConfiguration>").Root, TestHelper.ConsoleMonitor), Is.False); Assert.That(c.Load(XDocument.Parse(@"<GrandOutputConfiguration><Channel><Add Type=""BinaryFile"" /></Channel></GrandOutputConfiguration>").Root, TestHelper.ConsoleMonitor), Is.False); Assert.That(c.Load(XDocument.Parse(@"<GrandOutputConfiguration><Channel><Add Type=""BinaryFile"" Name=""GlobalCatch"" /></Channel></GrandOutputConfiguration>").Root, TestHelper.ConsoleMonitor), Is.False); // This is okay: Type, Name and Path for BinaryFile. Assert.That(c.Load(XDocument.Parse(@"<GrandOutputConfiguration><Channel><Add Type=""BinaryFile"" Name=""GlobalCatch"" Path=""In-Root-Log-Path"" /></Channel></GrandOutputConfiguration>").Root, TestHelper.ConsoleMonitor)); }
private static void DuplicateTestWith6Entries(int nbEntries1, int nbEntries2, bool gzip = false) { var folder = String.Format("{0}\\ReadDuplicates", TestHelper.TestFolder); TestHelper.CleanupFolder(folder); string config = String.Format(@" <GrandOutputConfiguration> <Channel> <Add Type=""BinaryFile"" Name=""All-1"" MaxCountPerFile=""{1}"" Path=""{0}"" UseGzipCompression=""{3}"" /> <Add Type=""BinaryFile"" Name=""All-2"" MaxCountPerFile=""{2}"" Path=""{0}"" UseGzipCompression=""{3}"" /> </Channel> </GrandOutputConfiguration> ", folder, nbEntries1, nbEntries2, gzip); using (var o = new GrandOutput()) { GrandOutputConfiguration c = new GrandOutputConfiguration(); Assert.That(c.Load(XDocument.Parse(config).Root, TestHelper.ConsoleMonitor), Is.True); Assert.That(o.SetConfiguration(c, TestHelper.ConsoleMonitor), Is.True); var m = new ActivityMonitor(); o.Register(m); var direct = m.Output.RegisterClient(new CKMonWriterClient(folder, Math.Min(nbEntries1, nbEntries2), LogFilter.Debug, gzip)); // 6 traces that go to the GrandOutput but also to the direct CKMonWriterClient. m.Trace().Send("Trace 1"); m.OpenTrace().Send("OpenTrace 1"); m.Trace().Send("Trace 1.1"); m.Trace().Send("Trace 1.2"); m.CloseGroup(); m.Trace().Send("Trace 2"); System.Threading.Thread.Sleep(100); m.Output.UnregisterClient(direct); } var files = TestHelper.WaitForCkmonFilesInDirectory(folder, 3); for (int pageReadLength = 1; pageReadLength < 10; ++pageReadLength) { MultiLogReader reader = new MultiLogReader(); reader.Add(files); var map = reader.GetActivityMap(); Assert.That(map.ValidFiles.All(rawFile => rawFile.IsValidFile), Is.True, "All files are correctly closed with the final 0 byte and no exception occurred while reading them."); var readMonitor = map.Monitors.Single(); List <ParentedLogEntry> allEntries = new List <ParentedLogEntry>(); using (var pageReader = readMonitor.ReadFirstPage(pageReadLength)) { do { allEntries.AddRange(pageReader.Entries); }while(pageReader.ForwardPage() > 0); } CollectionAssert.AreEqual(new[] { "Trace 1", "OpenTrace 1", "Trace 1.1", "Trace 1.2", null, "Trace 2" }, allEntries.Select(e => e.Entry.Text).ToArray(), StringComparer.Ordinal); } }
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"); }
private static void DuplicateTestWith6Entries(int nbEntries1, int nbEntries2, bool gzip = false) { var folder = TestHelper.PrepareLogFolder("ReadDuplicates"); var config = new GrandOutputConfiguration() .AddHandler(new Handlers.BinaryFileConfiguration() { Path = folder, MaxCountPerFile = nbEntries1, UseGzipCompression = gzip }) .AddHandler(new Handlers.BinaryFileConfiguration() { Path = folder, MaxCountPerFile = nbEntries2, UseGzipCompression = gzip }); using (var o = new GrandOutput(config)) { var m = new ActivityMonitor(); o.EnsureGrandOutputClient(m); var direct = m.Output.RegisterClient(new CKMonWriterClient(folder, Math.Min(nbEntries1, nbEntries2), LogFilter.Debug, gzip)); // 6 traces that go to the GrandOutput but also to the direct CKMonWriterClient. m.Trace("Trace 1"); m.OpenTrace("OpenTrace 1"); m.Trace("Trace 1.1"); m.Trace("Trace 1.2"); m.CloseGroup(); m.Trace("Trace 2"); Thread.Sleep(100); m.Output.UnregisterClient(direct); } var files = TestHelper.WaitForCkmonFilesInDirectory(folder, 3); for (int pageReadLength = 1; pageReadLength < 10; ++pageReadLength) { using MultiLogReader reader = new MultiLogReader(); reader.Add(files); var map = reader.GetActivityMap(); map.ValidFiles.All(rawFile => rawFile.IsValidFile).Should().BeTrue("All files are correctly closed with the final 0 byte and no exception occurred while reading them."); map.Monitors.Should().HaveCount(2); var allEntries1 = map.Monitors[0].ReadAllEntries().ToList(); var allEntries2 = map.Monitors[1].ReadAllEntries().ToList(); var allEntries = allEntries1.Any(e => e.Entry.Text == "Topic: CK.Monitoring.DispatcherSink") ? allEntries2 : allEntries1; allEntries.Select(e => e.Entry.Text) .SequenceEqual(new[] { "Trace 1", "OpenTrace 1", "Trace 1.1", "Trace 1.2", null, "Trace 2" }) .Should().BeTrue(); } }
private static void DuplicateTestWith6Entries( int nbEntries1, int nbEntries2, bool gzip = false ) { var folder = String.Format( "{0}\\ReadDuplicates", TestHelper.TestFolder ); TestHelper.CleanupFolder( folder ); string config = String.Format( @" <GrandOutputConfiguration> <Channel> <Add Type=""BinaryFile"" Name=""All-1"" MaxCountPerFile=""{1}"" Path=""{0}"" UseGzipCompression=""{3}"" /> <Add Type=""BinaryFile"" Name=""All-2"" MaxCountPerFile=""{2}"" Path=""{0}"" UseGzipCompression=""{3}"" /> </Channel> </GrandOutputConfiguration> ", folder, nbEntries1, nbEntries2, gzip ); using( var o = new GrandOutput() ) { GrandOutputConfiguration c = new GrandOutputConfiguration(); Assert.That( c.Load( XDocument.Parse( config ).Root, TestHelper.ConsoleMonitor ), Is.True ); Assert.That( o.SetConfiguration( c, TestHelper.ConsoleMonitor ), Is.True ); var m = new ActivityMonitor(); o.Register( m ); var direct = m.Output.RegisterClient( new CKMonWriterClient( folder, Math.Min( nbEntries1, nbEntries2 ), LogFilter.Debug, gzip ) ); // 6 traces that go to the GrandOutput but also to the direct CKMonWriterClient. m.Trace().Send( "Trace 1" ); m.OpenTrace().Send( "OpenTrace 1" ); m.Trace().Send( "Trace 1.1" ); m.Trace().Send( "Trace 1.2" ); m.CloseGroup(); m.Trace().Send( "Trace 2" ); System.Threading.Thread.Sleep( 100 ); m.Output.UnregisterClient( direct ); } var files = TestHelper.WaitForCkmonFilesInDirectory( folder, 3 ); for( int pageReadLength = 1; pageReadLength < 10; ++pageReadLength ) { MultiLogReader reader = new MultiLogReader(); reader.Add( files ); var map = reader.GetActivityMap(); Assert.That( map.ValidFiles.All( rawFile => rawFile.IsValidFile ), Is.True, "All files are correctly closed with the final 0 byte and no exception occurred while reading them." ); var readMonitor = map.Monitors.Single(); List<ParentedLogEntry> allEntries = new List<ParentedLogEntry>(); using( var pageReader = readMonitor.ReadFirstPage( pageReadLength ) ) { do { allEntries.AddRange( pageReader.Entries ); } while( pageReader.ForwardPage() > 0 ); } CollectionAssert.AreEqual( new[] { "Trace 1", "OpenTrace 1", "Trace 1.1", "Trace 1.2", null, "Trace 2" }, allEntries.Select( e => e.Entry.Text ).ToArray(), StringComparer.Ordinal ); } }
public void GrandOutputHasSameCompressedAndUncompressedLogs() { string rootPath = SystemActivityMonitor.RootLogPath + @"\GrandOutputGzip"; TestHelper.CleanupFolder(rootPath); GrandOutputConfiguration c = new GrandOutputConfiguration(); Assert.That(c.Load(XDocument.Parse(@" <GrandOutputConfiguration GlobalDefaultFilter=""Release"" > <Channel> <Add Type=""BinaryFile"" Name=""GzipGlobalCatch"" Path=""" + rootPath + @"\OutputGzip"" MaxCountPerFile=""200000"" UseGzipCompression=""True"" /> <Add Type=""BinaryFile"" Name=""RawGlobalCatch"" Path=""" + rootPath + @"\OutputRaw"" MaxCountPerFile=""200000"" UseGzipCompression=""False"" /> </Channel> </GrandOutputConfiguration>" ).Root, TestHelper.ConsoleMonitor)); Assert.That(c.ChannelsConfiguration.Configurations.Count, Is.EqualTo(2)); using (GrandOutput g = new GrandOutput()) { Assert.That(g.SetConfiguration(c, TestHelper.ConsoleMonitor), Is.True); var taskA = Task.Factory.StartNew <int>(() => { DumpMonitorOutput(CreateMonitorAndRegisterGrandOutput("Task A", g)); return(1); }); var taskB = Task.Factory.StartNew <int>(() => { DumpMonitorOutput(CreateMonitorAndRegisterGrandOutput("Task B", g)); return(1); }); var taskC = Task.Factory.StartNew <int>(() => { DumpMonitorOutput(CreateMonitorAndRegisterGrandOutput("Task C", g)); return(1); }); Task.WaitAll(taskA, taskB, taskC); } string[] gzipCkmons = TestHelper.WaitForCkmonFilesInDirectory(rootPath + @"\OutputGzip", 1); string[] rawCkmons = TestHelper.WaitForCkmonFilesInDirectory(rootPath + @"\OutputRaw", 1); Assert.That(gzipCkmons, Has.Length.EqualTo(1)); Assert.That(rawCkmons, Has.Length.EqualTo(1)); FileInfo gzipCkmonFile = new FileInfo(gzipCkmons.Single()); FileInfo rawCkmonFile = new FileInfo(rawCkmons.Single()); Assert.That(gzipCkmonFile.Exists, Is.True); Assert.That(rawCkmonFile.Exists, Is.True); // Test file size Assert.That(gzipCkmonFile.Length, Is.LessThan(rawCkmonFile.Length)); // Test de-duplication between Gzip and non-Gzip MultiLogReader mlr = new MultiLogReader(); var fileList = mlr.Add(new string[] { gzipCkmonFile.FullName, rawCkmonFile.FullName }); Assert.That(fileList, Has.Count.EqualTo(2)); var map = mlr.GetActivityMap(); Assert.That(map.Monitors.Count, Is.EqualTo(3)); }
static GrandOutputConfiguration CreateDefaultConfig( string subFolder ) { GrandOutputConfiguration def = new GrandOutputConfiguration(); Debug.Assert( def.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.None ); Debug.Assert( def.GlobalDefaultFilter == null ); var route = new RouteConfiguration(); route.ConfigData = new GrandOutputChannelConfigData(); route.AddAction( new BinaryFileConfiguration( "All" ) { Path = subFolder } ); def.ChannelsConfiguration = route; return def; }
public void FilteringBySource() { TestHelper.CleanupFolder( SystemActivityMonitor.RootLogPath + "FilteringBySource" ); using( GrandOutput g = new GrandOutput() ) { GrandOutputConfiguration config = new GrandOutputConfiguration(); config.Load( XDocument.Parse( @" <GrandOutputConfiguration> <Channel MinimalFilter=""Debug""> <Add Type=""BinaryFile"" Name=""All"" Path=""FilteringBySource"" /> <Channel Name=""HiddenTopic"" MinimalFilter=""Off"" TopicRegex=""(hidden\s+topic|hide\s+this\s+topic)"" MatchOptions=""CultureInvariant, ExplicitCapture, Compiled, Multiline"" /> </Channel> <SourceOverrideFilter> <Add File=""SourceFile-Debug.cs"" Filter=""Debug"" /> <Add File=""SourceFile-Off.cs"" Filter=""Off"" /> <Add File=""SourceFile-Strange.cs"" Filter=""{Trace,Fatal}"" /> </SourceOverrideFilter> </GrandOutputConfiguration>", LoadOptions.SetLineInfo ).Root, TestHelper.ConsoleMonitor ); Assert.That( g.SetConfiguration( config, TestHelper.ConsoleMonitor ) ); var m = new ActivityMonitor( false ); g.Register( m ); m.Fatal( fileName: "SourceFile-Off.cs" ).Send( "NOSHOW" ); m.SetTopic( "This is a hidden topic..." ); m.Trace( 0, "SourceFile-Debug.cs" ).Send( "Trace-1" ); m.Trace().Send( "NOSHOW" ); m.SetTopic( "Please, hide this topic!" ); m.Trace( fileName: "SourceFile-Strange.cs" ).Send( "NOSHOW" ); using( m.OpenTrace( fileName: "SourceFile-Strange.cs" ).Send( "Trace-2" ) ) { m.Trace( fileName: "SourceFile-Strange.cs" ).Send( "NOSHOW" ); m.Fatal( fileName: "SourceFile-Strange.cs" ).Send( "Fatal-1" ); m.Fatal( fileName: "SourceFile-Off.cs" ).Send( "NOSHOW" ); } m.SetTopic( null ); m.Trace( fileName: "SourceFile-Strange.cs" ).Send( "NOSHOW" ); m.Fatal( fileName: "SourceFile-Off.cs" ).Send( "NOSHOW" ); m.Trace().Send( "Trace-3" ); } List<StupidStringClient> logs = TestHelper.ReadAllLogs( new DirectoryInfo( SystemActivityMonitor.RootLogPath + "FilteringBySource" ), false ); Assert.That( logs.Count, Is.EqualTo( 1 ) ); Assert.That( logs[0].ToString(), Does.Not.Contain( "NOSHOW" ) ); var texts = logs[0].Entries.Select( e => e.Text ).ToArray(); CollectionAssert.AreEqual( new string[] { "Trace-1", "Trace-2", "Fatal-1", ActivityMonitor.SetTopicPrefix, "Trace-3", }, texts, StringComparer.Ordinal ); }
public void GrandOutputHasSameCompressedAndUncompressedLogs() { string rootPath = SystemActivityMonitor.RootLogPath + @"\GrandOutputGzip"; TestHelper.CleanupFolder( rootPath ); GrandOutputConfiguration c = new GrandOutputConfiguration(); Assert.That( c.Load( XDocument.Parse( @" <GrandOutputConfiguration GlobalDefaultFilter=""Release"" > <Channel> <Add Type=""BinaryFile"" Name=""GzipGlobalCatch"" Path=""" + rootPath + @"\OutputGzip"" MaxCountPerFile=""200000"" UseGzipCompression=""True"" /> <Add Type=""BinaryFile"" Name=""RawGlobalCatch"" Path=""" + rootPath + @"\OutputRaw"" MaxCountPerFile=""200000"" UseGzipCompression=""False"" /> </Channel> </GrandOutputConfiguration>" ).Root, TestHelper.ConsoleMonitor ) ); Assert.That( c.ChannelsConfiguration.Configurations.Count, Is.EqualTo( 2 ) ); using( GrandOutput g = new GrandOutput() ) { Assert.That( g.SetConfiguration( c, TestHelper.ConsoleMonitor ), Is.True ); var taskA = Task.Factory.StartNew<int>( () => { DumpMonitorOutput( CreateMonitorAndRegisterGrandOutput( "Task A", g ) ); return 1; } ); var taskB = Task.Factory.StartNew<int>( () => { DumpMonitorOutput( CreateMonitorAndRegisterGrandOutput( "Task B", g ) ); return 1; } ); var taskC = Task.Factory.StartNew<int>( () => { DumpMonitorOutput( CreateMonitorAndRegisterGrandOutput( "Task C", g ) ); return 1; } ); Task.WaitAll( taskA, taskB, taskC ); } string[] gzipCkmons = TestHelper.WaitForCkmonFilesInDirectory( rootPath + @"\OutputGzip", 1 ); string[] rawCkmons = TestHelper.WaitForCkmonFilesInDirectory( rootPath + @"\OutputRaw", 1 ); Assert.That( gzipCkmons, Has.Length.EqualTo( 1 ) ); Assert.That( rawCkmons, Has.Length.EqualTo( 1 ) ); FileInfo gzipCkmonFile = new FileInfo( gzipCkmons.Single() ); FileInfo rawCkmonFile = new FileInfo( rawCkmons.Single() ); Assert.That( gzipCkmonFile.Exists, Is.True ); Assert.That( rawCkmonFile.Exists, Is.True ); // Test file size Assert.That( gzipCkmonFile.Length, Is.LessThan( rawCkmonFile.Length ) ); // Test de-duplication between Gzip and non-Gzip MultiLogReader mlr = new MultiLogReader(); var fileList = mlr.Add( new string[] { gzipCkmonFile.FullName, rawCkmonFile.FullName } ); Assert.That( fileList, Has.Count.EqualTo( 2 ) ); var map = mlr.GetActivityMap(); Assert.That( map.Monitors.Count, Is.EqualTo( 3 ) ); }
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"); } }
private static void SetupActivityMonitor() { System.Console.OutputEncoding = System.Text.Encoding.Unicode; ActivityMonitor.DefaultFilter = LogFilter.Debug; ActivityMonitor.AutoConfiguration += monitor => monitor.Output.RegisterClient(new ActivityMonitorConsoleClient()); LogFile.RootLogPath = GetLogDirectory(); var grandOutputConfig = new GrandOutputConfiguration(); grandOutputConfig.AddHandler(new TextFileConfiguration { MaxCountPerFile = 10000, Path = "Text", }); GrandOutput.EnsureActiveDefault(grandOutputConfig); }
static GrandOutputConfiguration CreateDefaultConfig(string subFolder) { GrandOutputConfiguration def = new GrandOutputConfiguration(); Debug.Assert(def.SourceOverrideFilterApplicationMode == SourceFilterApplyMode.None); Debug.Assert(def.GlobalDefaultFilter == null); var route = new RouteConfiguration(); route.ConfigData = new GrandOutputChannelConfigData(); route.AddAction(new BinaryFileConfiguration("All") { Path = subFolder }); def.ChannelsConfiguration = route; return(def); }
private void SetupActivityMonitor() { Console.OutputEncoding = Encoding.UTF8; SystemActivityMonitor.RootLogPath = GetTestLogDirectory(); ActivityMonitor.DefaultFilter = LogFilter.Debug; ActivityMonitor.AutoConfiguration += (monitor) => { monitor.Output.RegisterClient(new ActivityMonitorConsoleClient()); }; GrandOutputConfiguration grandOutputConfig = new GrandOutputConfiguration(); grandOutputConfig.AddHandler(new TextFileConfiguration() { MaxCountPerFile = 10000, Path = "Text", }); GrandOutput.EnsureActiveDefault(grandOutputConfig); }
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 void dumping_text_file_with_multiple_monitors() { TestHelper.CleanupFolder(SystemActivityMonitor.RootLogPath + "TextFileMulti"); Random r = new Random(); using (GrandOutput g = new GrandOutput()) { GrandOutputConfiguration config = new GrandOutputConfiguration(); config.Load(XDocument.Parse(@" <GrandOutputConfiguration> <Channel MinimalFilter=""Debug""> <Add Type=""TextFile"" Name=""All"" Path=""TextFileMulti"" /> </Channel> </GrandOutputConfiguration>", LoadOptions.SetLineInfo).Root, TestHelper.ConsoleMonitor); Assert.That(g.SetConfiguration(config, TestHelper.ConsoleMonitor)); 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(SystemActivityMonitor.RootLogPath + "TextFileMulti").EnumerateFiles().Single(); string text = File.ReadAllText(f.FullName); Console.WriteLine(text); }
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);
static void Main(string[] args) { NormalizedPath userHostPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); userHostPath = userHostPath.AppendPart("CKli"); LogFile.RootLogPath = userHostPath.AppendPart("Logs"); var logConfig = new GrandOutputConfiguration().AddHandler( new CK.Monitoring.Handlers.TextFileConfiguration() { Path = "Text" }); GrandOutput.EnsureActiveDefault(logConfig); var monitor = new ActivityMonitor(); monitor.Output.RegisterClient(new ColoredActivityMonitorConsoleClient()); monitor.MinimalFilter = LogFilter.Debug; IBasicApplicationLifetime appLife = new FakeApplicationLifetime(); try { using (var host = new UserHost(appLife, userHostPath)) { host.Initialize(monitor); OpenKeyVault(monitor, host); if (host.UserKeyVault.IsKeyVaultOpened) { host.Initialize(monitor); } DumpWorlds(host.WorldStore.ReadWorlds(monitor)); InteractiveRun(monitor, host); } } catch (Exception ex) { monitor.Fatal(ex); Console.ReadLine(); } }
public void ApplyConfigWithError() { GrandOutputConfiguration c = new GrandOutputConfiguration(); Assert.That(c.Load(XDocument.Parse(@" <GrandOutputConfiguration AppDomainDefaultFilter=""Release"" > <Channel> <Add Type=""BinaryFile"" Name=""GlobalCatch"" Path=""Configuration/ invalid path? (? is forbidden)"" /> </Channel> </GrandOutputConfiguration>" ).Root, TestHelper.ConsoleMonitor)); Assert.That(c.ChannelsConfiguration.Configurations.Count, Is.EqualTo(1)); GrandOutput g = new GrandOutput(); Assert.That(g.SetConfiguration(c, TestHelper.ConsoleMonitor), Is.False); Assert.That(g.IsDisposed, Is.False); g.Dispose(TestHelper.ConsoleMonitor); Assert.That(g.IsDisposed); }
public void dumping_text_file_with_multiple_monitors() { TestHelper.CleanupFolder( SystemActivityMonitor.RootLogPath + "TextFileMulti" ); Random r = new Random(); using( GrandOutput g = new GrandOutput() ) { GrandOutputConfiguration config = new GrandOutputConfiguration(); config.Load( XDocument.Parse( @" <GrandOutputConfiguration> <Channel MinimalFilter=""Debug""> <Add Type=""TextFile"" Name=""All"" Path=""TextFileMulti"" /> </Channel> </GrandOutputConfiguration>", LoadOptions.SetLineInfo ).Root, TestHelper.ConsoleMonitor ); Assert.That( g.SetConfiguration( config, TestHelper.ConsoleMonitor ) ); 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( SystemActivityMonitor.RootLogPath + "TextFileMulti" ).EnumerateFiles().Single(); string text = File.ReadAllText( f.FullName ); Console.WriteLine( text ); }
public void dumping_text_file() { TestHelper.CleanupFolder( SystemActivityMonitor.RootLogPath + "TextFile" ); Random r = new Random(); using( GrandOutput g = new GrandOutput() ) { GrandOutputConfiguration config = new GrandOutputConfiguration(); config.Load( XDocument.Parse( @" <GrandOutputConfiguration> <Channel MinimalFilter=""Debug""> <Add Type=""TextFile"" Name=""All"" Path=""TextFile"" /> </Channel> </GrandOutputConfiguration>", LoadOptions.SetLineInfo ).Root, TestHelper.ConsoleMonitor ); Assert.That( g.SetConfiguration( config, TestHelper.ConsoleMonitor ) ); DumpSampleLogs1( r, g ); DumpSampleLogs2( r, g ); } CheckSampleTextFile(); }
public void Console_handler_demo() { var a = new ActivityMonitor(); a.Output.RegisterClient(new ActivityMonitorConsoleClient()); a.Info("This is an ActivityMonitor Console demo."); LogDemo(a); var c = new GrandOutputConfiguration(); c.AddHandler(new Handlers.ConsoleConfiguration()); c.AddHandler(new Handlers.TextFileConfiguration() { Path = "test" }); using (var g = new GrandOutput(c)) { var m = CreateMonitorAndRegisterGrandOutput("Hello Console!", g); m.Info("This is the same demo, but with the GrandOutputConsole."); LogDemo(m); } }
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); }
public void dumping_text_file() { TestHelper.CleanupFolder(SystemActivityMonitor.RootLogPath + "TextFile"); Random r = new Random(); using (GrandOutput g = new GrandOutput()) { GrandOutputConfiguration config = new GrandOutputConfiguration(); config.Load(XDocument.Parse(@" <GrandOutputConfiguration> <Channel MinimalFilter=""Debug""> <Add Type=""TextFile"" Name=""All"" Path=""TextFile"" /> </Channel> </GrandOutputConfiguration>", LoadOptions.SetLineInfo).Root, TestHelper.ConsoleMonitor); Assert.That(g.SetConfiguration(config, TestHelper.ConsoleMonitor)); DumpSampleLogs1(r, g); DumpSampleLogs2(r, g); } CheckSampleTextFile(); }
public void artificially_generated_missing_log_entries_are_detected() { var folder = TestHelper.PrepareLogFolder("MissingEntries"); var emptyConfig = new GrandOutputConfiguration(); var binaryConfig = new GrandOutputConfiguration().AddHandler(new Handlers.BinaryFileConfiguration() { Path = "MissingEntries" }); using (var g = new GrandOutput(emptyConfig)) { var m = new ActivityMonitor(false); g.EnsureGrandOutputClient(m); m.Trace("NoShow-1"); g.ApplyConfiguration(emptyConfig, true); m.Trace("NoShow-2"); // We must let the trace to be handled by the previous configuration: // entries are not processed before a change of the configuration since // we want to apply the new configuration as soon as possible. Thread.Sleep(200); g.ApplyConfiguration(binaryConfig, true); m.Trace("Show-1"); Thread.Sleep(200); g.ApplyConfiguration(emptyConfig, true); m.Trace("NoShow-3"); } var replayed = new ActivityMonitor(false); var c = replayed.Output.RegisterClient(new StupidStringClient()); TestHelper.ReplayLogs(new DirectoryInfo(folder), true, mon => replayed, TestHelper.ConsoleMonitor); var entries = c.Entries.Select(e => e.Text).Concatenate("|"); // We may have "<Missing log data>|Initializing..." followed by "<Missing log data>|Show-1" or the opposite. entries.Should().Contain("<Missing log data>|Initializing BinaryFile handler (MaxCountPerFile = 20000).") .And.Contain("<Missing log data>|Show-1"); }
public void FilteringByTopic() { TestHelper.CleanupFolder( SystemActivityMonitor.RootLogPath + "FilteringByTopic" ); using( GrandOutput g = new GrandOutput() ) { GrandOutputConfiguration config = new GrandOutputConfiguration(); config.Load( XDocument.Parse( @" <GrandOutputConfiguration> <Channel MinimalFilter=""Debug""> <Add Type=""BinaryFile"" Name=""All"" Path=""FilteringByTopic"" /> <Channel Name=""HiddenTopic"" MinimalFilter=""Off"" TopicFilter=""*H*T?pic*"" > <Channel Name=""SavedHiddenTopic"" MinimalFilter=""Release"" TopicFilter=""*DOSHOW*"" > </Channel> </Channel> <Channel Name=""MonitoredTopic"" MinimalFilter=""Monitor"" TopicFilter=""*MONITOR*"" > </Channel> </Channel> </GrandOutputConfiguration>", LoadOptions.SetLineInfo ).Root, TestHelper.ConsoleMonitor ); Assert.That( g.SetConfiguration( config, TestHelper.ConsoleMonitor ) ); var fullyHidden = new ActivityMonitor( false ); g.Register( fullyHidden ); fullyHidden.SetTopic( "A fully hidden topic: setting the topic before any send, totally hides the monitor if the Actual filter is Off. - NOSHOW" ); fullyHidden.Fatal().Send( "NOSHOW" ); using( fullyHidden.OpenFatal().Send( "NOSHOW" ) ) { fullyHidden.Fatal().Send( "NOSHOW" ); } var m = new ActivityMonitor( false ); g.Register( m ); m.Trace().Send( "Trace-1" ); m.SetTopic( "This is a Hidden Topic - NOSHOW" ); m.Fatal().Send( "NOSHOW" ); m.SetTopic( "Visible Topic" ); m.Trace().Send( "Trace-2" ); m.SetTopic( "This is a Hidden Topic but DOSHOW puts it in Release mode." ); m.Trace().Send( "NOSHOW" ); m.Info().Send( "NOSHOW" ); m.Warn().Send( "NOSHOW" ); m.Error().Send( "Error-1" ); m.Fatal().Send( "Fatal-1" ); m.SetTopic( "This is a HT?PIC (off). Match is case insensitive - NOSHOW" ); m.Fatal().Send( "NOSHOW" ); m.SetTopic( null ); m.Trace().Send( "Trace-3" ); m.SetTopic( "A MONITORed topic: If i wrote This is a t.o.p.i.c (without the dots), this would have matched the HiddenT.o.p.i.c channel..." ); m.Trace().Send( "NOSHOW" ); m.Warn().Send( "Warn-1" ); } List<StupidStringClient> logs = TestHelper.ReadAllLogs( new DirectoryInfo( SystemActivityMonitor.RootLogPath + "FilteringByTopic" ), false ); Assert.That( logs.Count, Is.EqualTo( 1 ), "Fully hidden monitor does not appear." ); Assert.That( logs[0].ToString(), Does.Not.Contain( "NOSHOW" ) ); var texts = logs[0].Entries.Select( e => e.Text ).ToArray(); CollectionAssert.AreEqual( new string[] { "Trace-1", ActivityMonitor.SetTopicPrefix + "Visible Topic", "Trace-2", ActivityMonitor.SetTopicPrefix + "This is a Hidden Topic but DOSHOW puts it in Release mode.", "Error-1", "Fatal-1", ActivityMonitor.SetTopicPrefix, "Trace-3", ActivityMonitor.SetTopicPrefix + "A MONITORed topic: If i wrote This is a t.o.p.i.c (without the dots), this would have matched the HiddenT.o.p.i.c channel...", "Warn-1" }, texts, StringComparer.Ordinal ); }
static GrandOutputConfiguration CreateConfigurationFromSection(IConfigurationSection section) { GrandOutputConfiguration c; var gSection = section.GetSection(nameof(GrandOutput)); if (gSection.Exists()) { var ctorPotentialParams = new[] { typeof(IConfigurationSection) }; c = new GrandOutputConfiguration(); gSection.Bind(c); var hSection = gSection.GetSection("Handlers"); foreach (var hConfig in hSection.GetChildren()) { // Checks for single value and not section. // This is required for handlers that have no configuration properties: // "Handlers": { "Console": true } does the job. // The only case of "falseness" we consider here is "false": we ignore the key in this case. string value = hConfig.Value; if (!String.IsNullOrWhiteSpace(value) && String.Equals(value, "false", StringComparison.OrdinalIgnoreCase)) { continue; } // Resolve configuration type using one of two available strings: // 1. From "ConfigurationType" property, inside the value object Type? resolved = null; string configTypeProperty = hConfig.GetValue("ConfigurationType", string.Empty); if (string.IsNullOrEmpty(configTypeProperty)) { // No ConfigurationType property: // Resolve using the key, outside the value object resolved = TryResolveType(hConfig.Key); } else { // With ConfigurationType property: // Try and resolve property and key, in that order resolved = TryResolveType(configTypeProperty); if (resolved == null) { resolved = TryResolveType(hConfig.Key); } } if (resolved == null) { if (string.IsNullOrEmpty(configTypeProperty)) { throw new CKException($"Unable to resolve type '{hConfig.Key}'."); } else { throw new CKException($"Unable to resolve type '{configTypeProperty}' (from Handlers.{hConfig.Key}.ConfigurationType) or '{hConfig.Key}'."); } } var ctorWithConfig = resolved.GetConstructor(ctorPotentialParams); object config; if (ctorWithConfig != null) { config = ctorWithConfig.Invoke(new[] { hConfig }); } else { config = Activator.CreateInstance(resolved) !; hConfig.Bind(config); } c.AddHandler((IHandlerConfiguration)config); } } else { c = new GrandOutputConfiguration() .AddHandler(new Handlers.TextFileConfiguration() { Path = "Text" }); } return(c); }
static GrandOutput CreateGrandOutputWithFakeHandler( int handlerExtralLoad, bool useAdaptive, int dispatcherMaxCapacity ) { IActivityMonitor mLoad = new ActivityMonitor( false ); GrandOutputConfiguration c = new GrandOutputConfiguration(); var textConfig = @"<GrandOutputConfiguration><Channel><Add Type=""FakeHandler, CK.Monitoring.Tests"" Name=""GlobalCatch"" ExtraLoad=""" + handlerExtralLoad.ToString() + @""" /></Channel></GrandOutputConfiguration>"; Assert.That( c.Load( XDocument.Parse( textConfig ).Root, mLoad ) ); Assert.That( c.ChannelsConfiguration.Configurations.Count, Is.EqualTo( 1 ) ); IGrandOutputDispatcherStrategy strat; if( useAdaptive ) { strat = new Impl.EventDispatcherLocalTestStrategy( dispatcherMaxCapacity ); } else { strat = new Impl.EventDispatcherBasicStrategy( dispatcherMaxCapacity ); } GrandOutput g = new GrandOutput( strat ); g.SetConfiguration( c, mLoad ); return g; }