/// <summary> /// Creates an instance of this class for the given engine event source. /// </summary> /// <param name="eventSource"></param> /// <param name="onlyLogCriticalEvents"></param> internal EngineLoggingServicesInProc(EventSource eventSource, bool onlyLogCriticalEvents, ManualResetEvent flushRequestEvent) { this.onlyLogCriticalEvents = onlyLogCriticalEvents; this.engineEventSource = eventSource; // Allocate the table mapping logger ids to event sources this.eventSources = new Dictionary<int, EventSource>(); RegisterEventSource(CENTRAL_ENGINE_EVENTSOURCE, eventSource); base.Initialize(flushRequestEvent); }
// engine should be invoked with path where binary files are // to find microsoft.build.tasks public Engine (string binPath) { this.binPath = binPath; this.buildEnabled = true; this.projects = new Dictionary <string, Project> (); this.eventSource = new EventSource (); this.loggers = new List <ILogger> (); this.buildStarted = false; this.global_properties = new BuildPropertyGroup (); this.builtTargetsOutputByName = new Dictionary<string, ITaskItem[]> (); this.currentlyBuildingProjectsStack = new Stack<Project> (); RegisterDefaultTasks (); }
public void NullEventFields() { EventSource es = new EventSource(); SimulatedConsole sc = new SimulatedConsole(); ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Diagnostic, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es); // Not all parameters are null here, but that's fine, we assume the engine will never // fire a ProjectStarted without a project name, etc. es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs(null, null)); es.RaiseProjectStartedEvent(null, new ProjectStartedEventArgs(null, null, "p", null, null, null)); es.RaiseTargetStartedEvent(null, new TargetStartedEventArgs(null, null, "t", null, null)); es.RaiseTaskStartedEvent(null, new TaskStartedEventArgs(null, null, null, null, "task")); es.RaiseMessageEvent(null, new BuildMessageEventArgs(null, null, null, MessageImportance.High)); es.RaiseWarningEvent(null, new BuildWarningEventArgs(null, null, null, 0, 0, 0, 0, null, null, null)); es.RaiseErrorEvent(null, new BuildErrorEventArgs(null, null, null, 0, 0, 0, 0, null, null, null)); es.RaiseTaskFinishedEvent(null, new TaskFinishedEventArgs(null, null, null, null, "task", true)); es.RaiseTargetFinishedEvent(null, new TargetFinishedEventArgs(null, null, "t", null, null, true)); es.RaiseProjectFinishedEvent(null, new ProjectFinishedEventArgs(null, null, "p", true)); es.RaiseBuildFinishedEvent(null, new BuildFinishedEventArgs(null, null, true)); es.RaiseAnyEvent(null, new BuildFinishedEventArgs(null, null, true)); es.RaiseStatusEvent(null, new BuildFinishedEventArgs(null, null, true)); es.RaiseCustomEvent(null, new MyCustomBuildEventArgs2()); // No exception raised }
/// <summary> /// Called to register distributed loggers with the engine. /// This method is not thread safe. All loggers should registered prior to /// starting the build in order to guarantee uniform behavior /// </summary> /// <exception cref="LoggerException">Logger indicating it failed in a controlled way</exception> /// <exception cref="InternalLoggerException">Logger threw arbitrary exception</exception> public void RegisterDistributedLogger(ILogger centralLogger, LoggerDescription forwardingLogger) { error.VerifyThrowArgumentNull(forwardingLogger, "forwardingLogger"); if (centralLogger == null) { centralLogger = new NullCentralLogger(); } // If this is the first distributed logger we need to create an event source for local // forwarding loggers if (eventSourceForForwarding == null) { eventSourceForForwarding = new EventSource(); ((EngineLoggingServicesInProc)primaryLoggingServices).RegisterEventSource (EngineLoggingServicesInProc.LOCAL_FORWARDING_EVENTSOURCE, eventSourceForForwarding); } // Assign a unique logger Id to this distributed logger int loggerId = lastUsedLoggerId; lastUsedLoggerId++; forwardingLogger.LoggerId = loggerId; //Create and configure the local node logger IForwardingLogger localForwardingLogger = null; try { localForwardingLogger = forwardingLogger.CreateForwardingLogger(); // Check if the class was not found in the assembly if (localForwardingLogger == null) { InternalLoggerException.Throw(null, null, "LoggerNotFoundError", true, forwardingLogger.Name); } // Configure the object EventRedirector newRedirector = new EventRedirector(forwardingLogger.LoggerId, primaryLoggingServices); localForwardingLogger.BuildEventRedirector = newRedirector; localForwardingLogger.Parameters = forwardingLogger.LoggerSwitchParameters; localForwardingLogger.Verbosity = forwardingLogger.Verbosity; localForwardingLogger.NodeId= nodeId; // Convert the path to the logger DLL to full path before passing it to the node provider forwardingLogger.ConvertPathsToFullPaths(); } // Polite logger failure catch (LoggerException) { throw; } // Logger class was not found catch (InternalLoggerException) { throw; } catch (Exception e) { InternalLoggerException.Throw(e, null, "LoggerCreationError", true, forwardingLogger.Name); } // Register the local forwarding logger to listen for all local events RegisterLoggerInternal(localForwardingLogger, eventSourceForForwarding, true); //Register this logger's node logger with the node manager so that all //the nodes instantiate this node logger and forward the events nodeManager.RegisterNodeLogger(forwardingLogger); // Create a private event source that will be used by this distributed logger and register // the central logger with the engine EventSource privateEventSource = new EventSource(); RegisterLoggerInternal(centralLogger, privateEventSource, false); // Register the private event source with the logging services so that the events from the local // node logger are forwarded to the central logger ((EngineLoggingServicesInProc)primaryLoggingServices).RegisterEventSource(forwardingLogger.LoggerId, privateEventSource); }
public void ResetConsoleLoggerState_Initialize() { // Create an event source EventSource es = new EventSource(); //Create a simulated console SimulatedConsole sc = new SimulatedConsole(); // error and warning string for 1 error and 1 warning // errorString = 1 Error(s) // warningString = 1 Warning(s) string errorString = ResourceUtilities.FormatResourceString("ErrorCount", 1); string warningString = ResourceUtilities.FormatResourceString("WarningCount", 1); // Create a ConsoleLogger with Normal verbosity ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Normal, sc.Write, sc.SetColor, sc.ResetColor); // Initialize ConsoleLogger L.Initialize(es); // BuildStarted Event es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); // Introduce a warning BuildWarningEventArgs bwea = new BuildWarningEventArgs("VBC", "31415", "file.vb", 42, 0, 0, 0, "Some long message", "help", "sender"); es.RaiseWarningEvent(null, bwea); // Introduce an error BuildErrorEventArgs beea = new BuildErrorEventArgs("VBC", "31415", "file.vb", 42, 0, 0, 0, "Some long message", "help", "sender"); es.RaiseErrorEvent(null, beea); // NOTE: We don't call the es.RaiseBuildFinishedEvent(...) here as this // would call ResetConsoleLoggerState and we will fail to detect if Initialize() // is not calling it. // Log so far string actualLog = sc.ToString(); Console.WriteLine("=="); Console.WriteLine(sc.ToString()); Console.WriteLine("=="); // Verify that the log has correct error and warning string Assertion.Assert(actualLog.Contains("<red>")); Assertion.Assert(actualLog.Contains("<yellow>")); // Clear the log obtained so far sc.Clear(); //Initilialize (This should call ResetConsoleLoggerState(...)) L.Initialize(es); // BuildStarted event es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); // BuildFinished es.RaiseBuildFinishedEvent(null, new BuildFinishedEventArgs("bf", null, true)); // Log so far actualLog = sc.ToString(); Console.WriteLine("=="); Console.WriteLine(sc.ToString()); Console.WriteLine("=="); // Verify that the error and warning from the previous build is not // reported in the subsequent build Assertion.Assert(!actualLog.Contains("<red>")); Assertion.Assert(!actualLog.Contains("<yellow>")); // errorString = 0 Error(s) errorString = ResourceUtilities.FormatResourceString("ErrorCount", 0); // warningString = 0 Warning(s) warningString = ResourceUtilities.FormatResourceString("WarningCount", 0); // Verify that the log has correct error and warning string Assertion.Assert(actualLog.Contains(errorString)); Assertion.Assert(actualLog.Contains(warningString)); }
public void SpecificVerbosity() { string log = null; try { log = GetTempFilename(); FileLogger fl = new FileLogger(); EventSource es = new EventSource(); fl.Parameters = "verbosity=diagnostic;logfile=" + log; // diagnostic specific setting fl.Verbosity = LoggerVerbosity.Quiet ; // quiet global setting fl.Initialize(es); fl.MessageHandler(null, new BuildMessageEventArgs("message here", null, null, MessageImportance.High)); fl.Shutdown(); // expect message to appear because diagnostic not quiet verbosity was used VerifyFileContent(log, "message here"); } finally { if (null != log) File.Delete(log); } }
public void ForwardingLoggingEventsBasedOnVerbosity() { EventSource source = new EventSource(); TestForwardingLogger logger = new TestForwardingLogger(); logger.BuildEventRedirector = null; logger.Parameters = "BUILDSTARTEDEVENT"; logger.Initialize(source, 4); RaiseEvents(source); Assert.IsTrue(logger.forwardedEvents.Count == 1); logger = new TestForwardingLogger(); logger.BuildEventRedirector = null; logger.Verbosity = LoggerVerbosity.Quiet; logger.Initialize(source, 4); RaiseEvents(source); Assert.IsTrue(logger.forwardedEvents.Count == 2); Assert.IsTrue(logger.forwardedEvents.Contains(error)); Assert.IsTrue(logger.forwardedEvents.Contains(warning)); logger = new TestForwardingLogger(); logger.BuildEventRedirector = null; logger.Verbosity = LoggerVerbosity.Minimal; logger.Initialize(source, 4); RaiseEvents(source); Assert.IsTrue(logger.forwardedEvents.Count == 3); Assert.IsTrue(logger.forwardedEvents.Contains(error)); Assert.IsTrue(logger.forwardedEvents.Contains(warning)); Assert.IsTrue(logger.forwardedEvents.Contains(highMessage)); logger = new TestForwardingLogger(); logger.BuildEventRedirector = null; logger.Verbosity = LoggerVerbosity.Normal; logger.Initialize(source, 4); RaiseEvents(source); Assert.IsTrue(logger.forwardedEvents.Count == 8); Assert.IsTrue(logger.forwardedEvents.Contains(error)); Assert.IsTrue(logger.forwardedEvents.Contains(warning)); Assert.IsTrue(logger.forwardedEvents.Contains(highMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(normalMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(projectStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(projectFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(targetStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(targetFinished)); logger = new TestForwardingLogger(); logger.BuildEventRedirector = null; logger.Verbosity = LoggerVerbosity.Detailed; logger.Initialize(source, 4); RaiseEvents(source); Assert.IsTrue(logger.forwardedEvents.Count == 12); Assert.IsTrue(logger.forwardedEvents.Contains(error)); Assert.IsTrue(logger.forwardedEvents.Contains(warning)); Assert.IsTrue(logger.forwardedEvents.Contains(highMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(lowMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(normalMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(projectStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(projectFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(targetStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(targetFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(taskStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(taskFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(commandLine)); logger = new TestForwardingLogger(); logger.BuildEventRedirector = null; logger.Verbosity = LoggerVerbosity.Diagnostic; logger.Initialize(source, 4); RaiseEvents(source); Assert.IsTrue(logger.forwardedEvents.Count == 13); Assert.IsTrue(logger.forwardedEvents.Contains(error)); Assert.IsTrue(logger.forwardedEvents.Contains(warning)); Assert.IsTrue(logger.forwardedEvents.Contains(highMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(lowMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(normalMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(projectStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(projectFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(targetStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(targetFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(taskStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(taskFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(externalStartedEvent)); Assert.IsTrue(logger.forwardedEvents.Contains(commandLine)); }
internal void RegisterEventSource(int loggerId, EventSource eventSource) { ErrorUtilities.VerifyThrow(!eventSources.ContainsKey(loggerId), "Should not see duplicate logger ids"); eventSources[loggerId] = eventSource; }
public void ErrorColorTest() { EventSource es = new EventSource(); SimulatedConsole sc = new SimulatedConsole(); ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Quiet, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es); BuildErrorEventArgs beea = new BuildErrorEventArgs("VBC", "31415", "file.vb", 42, 0, 0, 0, "Some long message", "help", "sender"); es.RaiseErrorEvent(null, beea); Assertion.AssertEquals("<red>file.vb(42): VBC error 31415: Some long message" + Environment.NewLine + "<reset color>", sc.ToString()); }
public void ForwardingLoggingShowCommandLine() { EventSource source = new EventSource(); TestForwardingLogger logger = new TestForwardingLogger(); logger.BuildEventRedirector = null; logger.Verbosity = LoggerVerbosity.Normal; logger.Parameters = "SHOWCOMMANDLINE"; logger.Initialize(source, 4); RaiseEvents(source); Assert.IsTrue(logger.forwardedEvents.Count == 9); Assert.IsTrue(logger.forwardedEvents.Contains(error)); Assert.IsTrue(logger.forwardedEvents.Contains(warning)); Assert.IsTrue(logger.forwardedEvents.Contains(highMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(normalMessage)); Assert.IsTrue(logger.forwardedEvents.Contains(projectStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(projectFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(targetStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(targetFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(commandLine)); }
public void TestPrintTargetNamePerMessage() { EventSource es = new EventSource(); //Create a simulated console SimulatedConsole sc = new SimulatedConsole(); // Create a ConsoleLogger with Normal verbosity ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Normal, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es, 2); es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); BuildEventContext context =new BuildEventContext(1, 1, 1, 1); BuildEventContext context2 =new BuildEventContext(2, 2, 2, 2); ProjectStartedEventArgs project = new ProjectStartedEventArgs(1, "Hello,", "HI", "None", "Build", null, null, context); project.BuildEventContext = context; es.RaiseProjectStartedEvent(null, project); ProjectStartedEventArgs project2 = new ProjectStartedEventArgs(2, "Hello,", "HI", "None", "Build", null, null, context2); project2.BuildEventContext = context2; es.RaiseProjectStartedEvent(null, project2); TargetStartedEventArgs targetStarted1 = new TargetStartedEventArgs(null, null, "t", null, null); targetStarted1.BuildEventContext = context; es.RaiseTargetStartedEvent(null, targetStarted1); TargetStartedEventArgs targetStarted2 = new TargetStartedEventArgs(null, null, "t2", null, null); targetStarted2.BuildEventContext = context2; es.RaiseTargetStartedEvent(null, targetStarted2); BuildMessageEventArgs messsage1 = new BuildMessageEventArgs("Message", null, null,MessageImportance.High); messsage1.BuildEventContext = context; BuildMessageEventArgs messsage2 = new BuildMessageEventArgs("Message2", null, null, MessageImportance.High); messsage2.BuildEventContext = context2; BuildMessageEventArgs messsage3 = new BuildMessageEventArgs("Message3", null, null, MessageImportance.High); messsage3.BuildEventContext = context; es.RaiseMessageEvent(null, messsage1); es.RaiseMessageEvent(null, messsage2); es.RaiseMessageEvent(null, messsage3); string actualLog = sc.ToString(); Assertion.Assert(actualLog.Contains("t:")); }
public void TestNewLineAfterProjectFinished() { for (int i = 0; i < 3; i++) { Console.Out.WriteLine("Iteration of I is {" + i + "}"); EventSource es = new EventSource(); //Create a simulated console SimulatedConsole sc = new SimulatedConsole(); ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Normal, sc.Write, sc.SetColor, sc.ResetColor); if (i < 2) { // On the second pass through use the MP single proc logger if (i == 1) { L.Parameters = "EnableMPLogging"; } // Use the old single proc logger L.Initialize(es, 1); } else { // Use the parallel logger L.Initialize(es, 2); } es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); BuildEventContext context = new BuildEventContext(1, 1, 1, 1); ProjectStartedEventArgs project = new ProjectStartedEventArgs(1, "Hello,", "HI", "None", "Build", null, null, context); project.BuildEventContext = context; es.RaiseProjectStartedEvent(null, project); TargetStartedEventArgs targetStarted1 = new TargetStartedEventArgs(null, null, "t", null, null); targetStarted1.BuildEventContext = context; es.RaiseTargetStartedEvent(null, targetStarted1); BuildMessageEventArgs messsage1 = new BuildMessageEventArgs("Message", null, null, MessageImportance.High); messsage1.BuildEventContext = context; es.RaiseMessageEvent(null, messsage1); ProjectFinishedEventArgs projectFinished = new ProjectFinishedEventArgs("Finished,", "HI", "projectFile", true); projectFinished.BuildEventContext = context; es.RaiseProjectFinishedEvent(null, projectFinished); string actualLog = sc.ToString(); switch(i) { case 0: // There is no project finished event printed in normal verbosity Assertion.Assert(!actualLog.Contains(projectFinished.Message)); break; // In both case 1 and case 2 verify that there is no extra newline after the done event (this is because the nunit console is seen as an unknown device // and we do not want the extra newline in something other than a console device. case 1: case 2: Assertion.Assert(actualLog.Contains(ResourceUtilities.FormatResourceString("ProjectFinishedPrefixWithTargetNamesMultiProc", "None", "Build") + Environment.NewLine)); Assertion.Assert(!actualLog.Contains(ResourceUtilities.FormatResourceString("ProjectFinishedPrefixWithTargetNamesMultiProc", "None", "Build") + Environment.NewLine + Environment.NewLine)); break; } } }
public void VerifyMPLoggerSwitch() { for (int i = 0; i < 2; i++) { EventSource es = new EventSource(); //Create a simulated console SimulatedConsole sc = new SimulatedConsole(); // Create a ConsoleLogger with Normal verbosity ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Normal, sc.Write, sc.SetColor, sc.ResetColor); //Make sure the MPLogger switch will property work on both Initialize methods L.Parameters = "EnableMPLogging"; if (i == 0) { L.Initialize(es, 1); } else { L.Initialize(es); } es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); BuildEventContext context = new BuildEventContext(1, 1, 1, 1); BuildEventContext context2 = new BuildEventContext(2, 2, 2, 2); ProjectStartedEventArgs project = new ProjectStartedEventArgs(1, "Hello,", "HI", "None", "Build", null, null, context); project.BuildEventContext = context; es.RaiseProjectStartedEvent(null, project); TargetStartedEventArgs targetStarted1 = new TargetStartedEventArgs(null, null, "t", null, null); targetStarted1.BuildEventContext = context; es.RaiseTargetStartedEvent(null, targetStarted1); BuildMessageEventArgs messsage1 = new BuildMessageEventArgs("Message", null, null, MessageImportance.High); messsage1.BuildEventContext = context; es.RaiseMessageEvent(null, messsage1); string actualLog = sc.ToString(); string resourceString = ResourceUtilities.FormatResourceString("ProjectStartedTopLevelProjectWithTargetNames", "None", 1, "Build"); Assertion.Assert(actualLog.Contains(resourceString)); } }
public void DeferredMessages() { EventSource es = new EventSource(); //Create a simulated console SimulatedConsole sc = new SimulatedConsole(); // Create a ConsoleLogger with Detailed verbosity ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Detailed, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es, 2); es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); TaskCommandLineEventArgs messsage1 = new TaskCommandLineEventArgs("Message", null, MessageImportance.High); messsage1.BuildEventContext = new BuildEventContext(1, 1, 1, 1); // Message Event es.RaiseMessageEvent(null, messsage1); es.RaiseBuildFinishedEvent(null, new BuildFinishedEventArgs("bf", null, true)); string actualLog = sc.ToString(); Assertion.Assert(actualLog.Contains(ResourceUtilities.FormatResourceString("DeferredMessages"))); es = new EventSource(); sc = new SimulatedConsole(); // Create a ConsoleLogger with Normal verbosity L = new ConsoleLogger(LoggerVerbosity.Normal, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es, 2); es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); BuildMessageEventArgs messsage2 = new BuildMessageEventArgs("Message", null, null, MessageImportance.High); messsage2.BuildEventContext = new BuildEventContext(1, 1, 1, 1); // Message Event es.RaiseMessageEvent(null, messsage2); es.RaiseBuildFinishedEvent(null, new BuildFinishedEventArgs("bf", null, true)); actualLog = sc.ToString(); Assertion.Assert(actualLog.Contains(ResourceUtilities.FormatResourceString("DeferredMessagesAvailiable"))); es = new EventSource(); sc = new SimulatedConsole(); // Create a ConsoleLogger with Normal verbosity L = new ConsoleLogger(LoggerVerbosity.Normal, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es, 2); es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); messsage2 = new BuildMessageEventArgs("Message", null, null, MessageImportance.High); messsage2.BuildEventContext = new BuildEventContext(1, 1, 1, 1); // Message Event es.RaiseMessageEvent(null, messsage2); ProjectStartedEventArgs project = new ProjectStartedEventArgs(1,"Hello,","HI","None","Build",null,null, messsage1.BuildEventContext); project.BuildEventContext = messsage1.BuildEventContext; es.RaiseProjectStartedEvent(null, project); es.RaiseBuildFinishedEvent(null, new BuildFinishedEventArgs("bf", null, true)); actualLog = sc.ToString(); Assertion.Assert(actualLog.Contains("Message")); }
public void ResetConsoleLoggerState_PerformanceCounters() { for (int i = 1; i <= 2; i++) { EventSource es = new EventSource(); //Create a simulated console SimulatedConsole sc = new SimulatedConsole(); // Create a ConsoleLogger with Normal verbosity ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Normal, sc.Write, sc.SetColor, sc.ResetColor); // Initialize ConsoleLogger L.Parameters = "Performancesummary"; L.Initialize(es, i); // prjPerfString = Project Performance Summary: string prjPerfString = ResourceUtilities.FormatResourceString("ProjectPerformanceSummary", null); // targetPerfString = Target Performance Summary: string targetPerfString = ResourceUtilities.FormatResourceString("TargetPerformanceSummary", null); // taskPerfString = Task Performance Summary: string taskPerfString = ResourceUtilities.FormatResourceString("TaskPerformanceSummary", null); // BuildStarted Event es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); //Project Started Event ProjectStartedEventArgs project1Started = new ProjectStartedEventArgs(1, null, null, "p", "t", null, null, new BuildEventContext(BuildEventContext.InvalidNodeId, BuildEventContext.InvalidTargetId, BuildEventContext.InvalidProjectContextId, BuildEventContext.InvalidTaskId)); project1Started.BuildEventContext = new BuildEventContext(1, 1, 1, 1); es.RaiseProjectStartedEvent(null, project1Started); TargetStartedEventArgs targetStarted1 = new TargetStartedEventArgs(null, null, "t", null, null); targetStarted1.BuildEventContext = project1Started.BuildEventContext; // TargetStarted Event es.RaiseTargetStartedEvent(null, targetStarted1); TaskStartedEventArgs taskStarted1 = new TaskStartedEventArgs(null, null, null, null, "task"); taskStarted1.BuildEventContext = project1Started.BuildEventContext; // TaskStarted Event es.RaiseTaskStartedEvent(null, taskStarted1); BuildMessageEventArgs messsage1 = new BuildMessageEventArgs(null, null, null, MessageImportance.High); messsage1.BuildEventContext = project1Started.BuildEventContext; // Message Event es.RaiseMessageEvent(null, messsage1); TaskFinishedEventArgs taskFinished1 = new TaskFinishedEventArgs(null, null, null, null, "task", true); taskFinished1.BuildEventContext = project1Started.BuildEventContext; // TaskFinished Event es.RaiseTaskFinishedEvent(null, taskFinished1); TargetFinishedEventArgs targetFinished1 = new TargetFinishedEventArgs(null, null, "t", null, null, true); targetFinished1.BuildEventContext = project1Started.BuildEventContext; // TargetFinished Event es.RaiseTargetFinishedEvent(null, targetFinished1); ProjectStartedEventArgs project2Started = new ProjectStartedEventArgs(2, null, null, "p2", "t2", null, null, project1Started.BuildEventContext); //Project Started Event project2Started.BuildEventContext = new BuildEventContext(2, 2, 2, 2); es.RaiseProjectStartedEvent(null, project2Started); TargetStartedEventArgs targetStarted2 = new TargetStartedEventArgs(null, null, "t2", null, null); targetStarted2.BuildEventContext = project2Started.BuildEventContext; // TargetStarted Event es.RaiseTargetStartedEvent(null, targetStarted2); TaskStartedEventArgs taskStarted2 = new TaskStartedEventArgs(null, null, null, null, "task2"); taskStarted2.BuildEventContext = project2Started.BuildEventContext; // TaskStarted Event es.RaiseTaskStartedEvent(null, taskStarted2); BuildMessageEventArgs messsage2 = new BuildMessageEventArgs(null, null, null, MessageImportance.High); messsage2.BuildEventContext = project2Started.BuildEventContext; // Message Event es.RaiseMessageEvent(null, messsage2); TaskFinishedEventArgs taskFinished2 = new TaskFinishedEventArgs(null, null, null, null, "task2", true); taskFinished2.BuildEventContext = project2Started.BuildEventContext; // TaskFinished Event es.RaiseTaskFinishedEvent(null, taskFinished2); TargetFinishedEventArgs targetFinished2 = new TargetFinishedEventArgs(null, null, "t2", null, null, true); targetFinished2.BuildEventContext = project2Started.BuildEventContext; // TargetFinished Event es.RaiseTargetFinishedEvent(null, targetFinished2); ProjectFinishedEventArgs finished2 = new ProjectFinishedEventArgs(null, null, "p2", true); finished2.BuildEventContext = project2Started.BuildEventContext; // ProjectFinished Event es.RaiseProjectFinishedEvent(null, finished2); // BuildFinished Event ProjectFinishedEventArgs finished1 = new ProjectFinishedEventArgs(null, null, "p", true); finished1.BuildEventContext = project1Started.BuildEventContext; // ProjectFinished Event es.RaiseProjectFinishedEvent(null, finished1); // BuildFinished Event es.RaiseBuildFinishedEvent(null, new BuildFinishedEventArgs("bf", null, true)); // Log so far string actualLog = sc.ToString(); Console.WriteLine("=="); Console.WriteLine(sc.ToString()); Console.WriteLine("=="); // Verify that the log has perf summary // Project perf summary Assertion.Assert(actualLog.Contains(prjPerfString)); // Target perf summary Assertion.Assert(actualLog.Contains(targetPerfString)); // Task Perf summary Assertion.Assert(actualLog.Contains(taskPerfString)); // Clear the log obtained so far sc.Clear(); // BuildStarted event es.RaiseBuildStartedEvent(null, new BuildStartedEventArgs("bs", null)); // BuildFinished es.RaiseBuildFinishedEvent(null, new BuildFinishedEventArgs("bf", null, true)); // Log so far actualLog = sc.ToString(); Console.WriteLine("=="); Console.WriteLine(sc.ToString()); Console.WriteLine("=="); // Verify that the log doesn't have perf summary Assertion.Assert(!actualLog.Contains(prjPerfString)); Assertion.Assert(!actualLog.Contains(targetPerfString)); Assertion.Assert(!actualLog.Contains(taskPerfString)); } }
/// <summary> /// Constructor to init all data except for BinPath which is initialized separately because /// a parameterless constructor is needed for COM interop /// </summary> internal Engine ( int numberOfCpus, bool isChildNode, int parentNodeId, string localNodeProviderParameters, BuildPropertyGroup globalProperties, ToolsetDefinitionLocations locations ) { // No need to check whether locations parameter // is null, because it is a value type this.startupDirectory = Environment.CurrentDirectory; this.engineGlobalProperties = globalProperties == null ? new BuildPropertyGroup() : globalProperties; this.environmentProperties = new BuildPropertyGroup(); this.toolsetStateMap = new Dictionary<string, ToolsetState>(StringComparer.OrdinalIgnoreCase); this.toolsets = new ToolsetCollection(this); // Every environment variable can be referenced just like a property // from the project file. Here, we go ahead and add all the environment // variables to the property bag, so they can be treated just like any // other property later on. this.environmentProperties.GatherEnvironmentVariables(); this.projectsLoadedByHost = new Hashtable(StringComparer.OrdinalIgnoreCase); this.cacheOfBuildingProjects = new ProjectManager(); this.eventSource = new EventSource(); this.buildEnabled = true; this.flushRequestEvent = new ManualResetEvent(false); this.primaryLoggingServices = new EngineLoggingServicesInProc(eventSource, false, flushRequestEvent); // Read any toolsets from the registry and config file PopulateToolsetStateMap(locations); this.nodeId = parentNodeId; this.localNodeProviderParameters = localNodeProviderParameters; this.numberOfCpus = numberOfCpus; if (this.numberOfCpus == 1 && !isChildNode) { this.primaryLoggingServices.FlushBuildEventsImmediatly = true; } this.buildRequests = new DualQueue<BuildRequest>(); this.taskOutputUpdates = new DualQueue<TaskExecutionContext>(); this.engineCommands = new DualQueue<EngineCommand>(); this.engineCallback = new EngineCallback(this); this.nodeManager = new NodeManager(this.numberOfCpus, isChildNode, this); this.scheduler = new Scheduler(this.nodeId, this); this.router = new Router(this, scheduler); this.cacheManager = new CacheManager(this.DefaultToolsVersion); this.lastUsedLoggerId = EngineLoggingServicesInProc.FIRST_AVAILABLE_LOGGERID; this.enabledCentralLogging = false; this.introspector = new Introspector(this, cacheOfBuildingProjects, nodeManager); // Initialize the node provider InitializeLocalNodeProvider(locations); }
public void WarningColorTestParallel() { EventSource es = new EventSource(); SimulatedConsole sc = new SimulatedConsole(); ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Quiet, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es, 2); BuildWarningEventArgs bwea = new BuildWarningEventArgs("VBC", "31415", "file.vb", 42, 0, 0, 0, "Some long message", "help", "sender"); bwea.BuildEventContext = new BuildEventContext(1, 2, 3, 4); es.RaiseWarningEvent(null, bwea); Assertion.AssertEquals( "<yellow>file.vb(42): VBC warning 31415: Some long message" + Environment.NewLine + "<reset color>", sc.ToString()); }
public void ForwardingLoggingPerformanceSummary() { EventSource source = new EventSource(); TestForwardingLogger logger = new TestForwardingLogger(); logger.BuildEventRedirector = null; logger.Parameters = "PERFORMANCESUMMARY"; logger.Verbosity = LoggerVerbosity.Quiet; logger.Initialize(source, 4); RaiseEvents(source); Assert.IsTrue(logger.forwardedEvents.Count == 8); Assert.IsTrue(logger.forwardedEvents.Contains(error)); Assert.IsTrue(logger.forwardedEvents.Contains(warning)); Assert.IsTrue(logger.forwardedEvents.Contains(projectStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(projectFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(targetStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(targetFinished)); Assert.IsTrue(logger.forwardedEvents.Contains(taskStarted)); Assert.IsTrue(logger.forwardedEvents.Contains(taskFinished)); }
public void LowMessageColorTest() { EventSource es = new EventSource(); SimulatedConsole sc = new SimulatedConsole(); ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Diagnostic, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es); BuildMessageEventArgs msg = new BuildMessageEventArgs("text", "help", "sender", MessageImportance.Low); es.RaiseMessageEvent(null, msg); Assertion.AssertEquals( "<darkgray>text" + Environment.NewLine + "<reset color>", sc.ToString()); }
private void RaiseEvents(EventSource source) { source.RaiseBuildStartedEvent(null, buildStarted); source.RaiseProjectStartedEvent(null, projectStarted); source.RaiseTargetStartedEvent(null, targetStarted); source.RaiseTaskStartedEvent(null, taskStarted); source.RaiseMessageEvent(null, lowMessage); source.RaiseMessageEvent(null, normalMessage); source.RaiseMessageEvent(null, highMessage); source.RaiseMessageEvent(null, commandLine); source.RaiseCustomEvent(null, externalStartedEvent); source.RaiseWarningEvent(null, warning); source.RaiseErrorEvent(null, error); source.RaiseTaskFinishedEvent(null, taskFinished); source.RaiseTargetFinishedEvent(null, targetFinished); source.RaiseProjectFinishedEvent(null, projectFinished); source.RaiseBuildFinishedEvent(null, buildFinished); }
public void ValidVerbosities() { string[] verbositySettings = new string[] {"Q", "quiet", "m", "minimal", "N", "normal", "d", "detailed", "diag", "DIAGNOSTIC"}; LoggerVerbosity[] verbosityEnumerations = new LoggerVerbosity[] {LoggerVerbosity.Quiet, LoggerVerbosity.Quiet, LoggerVerbosity.Minimal, LoggerVerbosity.Minimal, LoggerVerbosity.Normal, LoggerVerbosity.Normal, LoggerVerbosity.Detailed, LoggerVerbosity.Detailed, LoggerVerbosity.Diagnostic, LoggerVerbosity.Diagnostic}; for (int i = 0; i < verbositySettings.Length; i++) { FileLogger fl = new FileLogger(); fl.Parameters = "verbosity=" + verbositySettings[i] + ";"; EventSource es = new EventSource(); fl.Initialize(es); fl.Shutdown(); Assertion.AssertEquals(fl.Verbosity, verbosityEnumerations[i]); } // Do the same using the v shorthand for (int i = 0; i < verbositySettings.Length; i++) { FileLogger fl = new FileLogger(); fl.Parameters = "v=" + verbositySettings[i] + ";"; EventSource es = new EventSource(); fl.Initialize(es); fl.Shutdown(); Assertion.AssertEquals(fl.Verbosity, verbosityEnumerations[i]); } }
public void InvalidEncoding() { string log = null; try { log = GetTempFilename(); FileLogger fl = new FileLogger(); EventSource es = new EventSource(); fl.Parameters = "encoding=foo;logfile=" + log; fl.Initialize(es); } finally { if (null != log) File.Delete(log); } }
public void TestMinimalWithNormalMessage() { for (int i = 1; i <= 2; i++) { EventSource es = new EventSource(); SimulatedConsole sc = new SimulatedConsole(); ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Minimal, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es, i); BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4); BuildStartedEventArgs bse = new BuildStartedEventArgs("bs", null); bse.BuildEventContext = buildEventContext; es.RaiseBuildStartedEvent(null, bse); ProjectStartedEventArgs pse = new ProjectStartedEventArgs(1,"ps", null, "fname", "", null, null, new BuildEventContext(1, 1, 1, 1)); pse.BuildEventContext = buildEventContext; es.RaiseProjectStartedEvent(null, pse); TargetStartedEventArgs trse = new TargetStartedEventArgs("ts", null, "trname", "pfile", "tfile"); trse.BuildEventContext = buildEventContext; es.RaiseTargetStartedEvent(null, trse); TaskStartedEventArgs tase = new TaskStartedEventArgs("tks", null, "tname", "tfname", "tsname"); tase.BuildEventContext = buildEventContext; es.RaiseTaskStartedEvent(null, tase); BuildMessageEventArgs bmea = new BuildMessageEventArgs("foo!", null, "sender", MessageImportance.Normal); bmea.BuildEventContext = buildEventContext; es.RaiseMessageEvent(null, bmea); TaskFinishedEventArgs tafea = new TaskFinishedEventArgs("tkf", null, "fname", "tsname", "tfname", true); tafea.BuildEventContext = buildEventContext; es.RaiseTaskFinishedEvent(null, tafea); TargetFinishedEventArgs trfea = new TargetFinishedEventArgs("tf", null, "trname", "fname", "tfile", true); trfea.BuildEventContext = buildEventContext; es.RaiseTargetFinishedEvent(null, trfea); ProjectFinishedEventArgs pfea = new ProjectFinishedEventArgs("pf", null, "fname", true); pfea.BuildEventContext = buildEventContext; es.RaiseProjectFinishedEvent(null, pfea); BuildFinishedEventArgs bfea = new BuildFinishedEventArgs("bf", null, true); bfea.BuildEventContext = buildEventContext; es.RaiseBuildFinishedEvent(null, bfea); Assertion.AssertEquals(String.Empty, sc.ToString()); } }
public void NullEventFieldsParallel() { EventSource es = new EventSource(); SimulatedConsole sc = new SimulatedConsole(); ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Diagnostic, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es, 2); BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4); BuildStartedEventArgs bse = new BuildStartedEventArgs(null, null); bse.BuildEventContext = buildEventContext; ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, null, null, "p", null, null, null, buildEventContext); pse.BuildEventContext = buildEventContext; TargetStartedEventArgs trse = new TargetStartedEventArgs(null, null, "t", null, null); trse.BuildEventContext = buildEventContext; TaskStartedEventArgs tase = new TaskStartedEventArgs(null, null, null, null, "task"); tase.BuildEventContext = buildEventContext; BuildMessageEventArgs bmea = new BuildMessageEventArgs(null, null, null, MessageImportance.High); bmea.BuildEventContext = buildEventContext; BuildWarningEventArgs bwea = new BuildWarningEventArgs(null, null, null, 0, 0, 0, 0, null, null, null); bwea.BuildEventContext = buildEventContext; BuildErrorEventArgs beea = new BuildErrorEventArgs(null, null, null, 0, 0, 0, 0, null, null, null); beea.BuildEventContext = buildEventContext; TaskFinishedEventArgs trfea = new TaskFinishedEventArgs(null, null, null, null, "task", true); trfea.BuildEventContext = buildEventContext; TargetFinishedEventArgs tafea = new TargetFinishedEventArgs(null, null, "t", null, null, true); tafea.BuildEventContext = buildEventContext; ProjectFinishedEventArgs pfea = new ProjectFinishedEventArgs(null, null, "p", true); pfea.BuildEventContext = buildEventContext; BuildFinishedEventArgs bfea = new BuildFinishedEventArgs(null, null, true); bfea.BuildEventContext = buildEventContext; MyCustomBuildEventArgs2 mcea = new MyCustomBuildEventArgs2(); mcea.BuildEventContext = buildEventContext; // Not all parameters are null here, but that's fine, we assume the engine will never // fire a ProjectStarted without a project name, etc. es.RaiseBuildStartedEvent(null, bse); es.RaiseProjectStartedEvent(null, pse); es.RaiseTargetStartedEvent(null, trse); es.RaiseTaskStartedEvent(null, tase); es.RaiseMessageEvent(null, bmea); es.RaiseWarningEvent(null, bwea); es.RaiseErrorEvent(null, beea); es.RaiseTaskFinishedEvent(null, trfea); es.RaiseTargetFinishedEvent(null, tafea); es.RaiseProjectFinishedEvent(null, pfea); es.RaiseBuildFinishedEvent(null, bfea); es.RaiseAnyEvent(null, bfea); es.RaiseStatusEvent(null, bfea); es.RaiseCustomEvent(null, mcea); // No exception raised }
public void InvalidVerbosity() { FileLogger fl = new FileLogger(); fl.Parameters = "verbosity=CookiesAndCream"; EventSource es = new EventSource(); fl.Initialize(es); }
private static void SingleMessageTest(LoggerVerbosity v, MessageImportance j, bool shouldPrint) { for (int i = 1; i <= 2; i++) { SimulatedConsole sc = new SimulatedConsole(); EventSource es = new EventSource(); ConsoleLogger L = new ConsoleLogger(v, sc.Write, null, null); L.Initialize(es, i); string msg = "my 1337 message"; BuildMessageEventArgs be = new BuildMessageEventArgs(msg, "help", "sender", j); be.BuildEventContext = new BuildEventContext(1, 2, 3, 4); es.RaiseMessageEvent(null, be); if (i == 2 && v == LoggerVerbosity.Diagnostic) { string context =ResourceUtilities.FormatResourceString("BuildEventContext", LogFormatter.FormatLogTimeStamp(be.Timestamp), 0) + ">"; msg = context + ResourceUtilities.FormatResourceString("TaskMessageWithId", "my 1337 message", be.BuildEventContext.TaskId); } else if (i == 2 && v == LoggerVerbosity.Detailed) { string context = ResourceUtilities.FormatResourceString("BuildEventContext", string.Empty, 0) + ">"; msg = context + "my 1337 message"; } else if (i == 2) { msg = " " + msg; } Assertion.AssertEquals(shouldPrint ? msg + Environment.NewLine : String.Empty, sc.ToString()); } }
/// <summary> /// Creates a FileLogger, sets its parameters and initializes it, /// logs a message to it, and calls shutdown /// </summary> /// <param name="parameters"></param> /// <returns></returns> private void SetUpFileLoggerAndLogMessage(string parameters, BuildMessageEventArgs message) { FileLogger fl = new FileLogger(); EventSource es = new EventSource(); fl.Parameters = parameters; fl.Initialize(es); fl.MessageHandler(null, message); fl.Shutdown(); return; }
public void TestDirectEventHandlers() { for (int i = 1; i <= 2; i++) { EventSource es = new EventSource(); SimulatedConsole sc = new SimulatedConsole(); ConsoleLogger L = new ConsoleLogger(LoggerVerbosity.Quiet, sc.Write, sc.SetColor, sc.ResetColor); L.Initialize(es, i); BuildEventContext buildEventContext = new BuildEventContext(1, 2, 3, 4); BuildStartedEventArgs bse = new BuildStartedEventArgs("bs", null); bse.BuildEventContext = buildEventContext; L.BuildStartedHandler(null, bse); ProjectStartedEventArgs pse = new ProjectStartedEventArgs(-1, "ps", null, "fname", "", null, null, new BuildEventContext(1, 2, 3, 4)); pse.BuildEventContext = buildEventContext; L.ProjectStartedHandler(null, pse); TargetStartedEventArgs trse = new TargetStartedEventArgs("ts", null, "trname", "pfile", "tfile"); trse.BuildEventContext = buildEventContext; L.TargetStartedHandler(null, trse); TaskStartedEventArgs tase = new TaskStartedEventArgs("tks", null, "tname", "tfname", "tsname"); tase.BuildEventContext = buildEventContext; L.TaskStartedHandler(null, tase); BuildWarningEventArgs beea = new BuildWarningEventArgs("VBC", "31415", "file.vb", 42, 0, 0, 0, "Some long message", "help", "sender"); beea.BuildEventContext = buildEventContext; L.WarningHandler(null, beea); TaskFinishedEventArgs tafea = new TaskFinishedEventArgs("tkf", null, "fname", "tsname", "tfname", true); tafea.BuildEventContext = buildEventContext; L.TaskFinishedHandler(null, tafea); TargetFinishedEventArgs trfea = new TargetFinishedEventArgs("tf", null, "trname", "fname", "tfile", true); trfea.BuildEventContext = buildEventContext; L.TargetFinishedHandler(null, trfea); ProjectFinishedEventArgs pfea = new ProjectFinishedEventArgs("pf", null, "fname", true); pfea.BuildEventContext = buildEventContext; L.ProjectFinishedHandler(null, pfea); BuildFinishedEventArgs bfea = new BuildFinishedEventArgs("bf", null, true); bfea.BuildEventContext = buildEventContext; L.BuildFinishedHandler(null, bfea); Console.WriteLine("=="); Console.WriteLine(sc.ToString()); Console.WriteLine("=="); if (i == 1) { Assertion.AssertEquals( "<cyan>" + BaseConsoleLogger.projectSeparatorLine + Environment.NewLine + ResourceUtilities.FormatResourceString("ProjectStartedPrefixForTopLevelProjectWithDefaultTargets", "fname") + Environment.NewLine + Environment.NewLine + "<reset color><yellow>file.vb(42): VBC warning 31415: Some long message" + Environment.NewLine + "<reset color><cyan>pf" + Environment.NewLine + "<reset color>", sc.ToString()); } else { Assertion.AssertEquals( "<yellow>file.vb(42): VBC warning 31415: Some long message" + Environment.NewLine + "<reset color>", sc.ToString()); } } }
// engine should be invoked with path where binary files are // to find microsoft.build.tasks public Engine(string binPath) { this.binPath = binPath; this.buildEnabled = true; this.projects = new Dictionary <string, Project> (); this.eventSource = new EventSource (); this.loggers = new List <ILogger> (); this.buildStarted = false; this.global_properties = new BuildPropertyGroup (); this.builtTargetsOutputByName = new Dictionary<string, ITaskItem[]> (); this.currentlyBuildingProjectsStack = new Stack<Project> (); this.Toolsets = new ToolsetCollection (); LoadDefaultToolsets (); defaultTasksTableByToolsVersion = new Dictionary<string, TaskDatabase> (); }
/// <summary> /// Initializes the logger and adds it to the list of loggers maintained by the engine /// </summary> /// <exception cref="LoggerException">Logger indicating it failed in a controlled way</exception> /// <exception cref="InternalLoggerException">Logger threw arbitrary exception</exception> private void RegisterLoggerInternal(ILogger logger, EventSource sourceForLogger, bool forwardingLogger) { try { if (logger is INodeLogger) { ((INodeLogger)logger).Initialize(sourceForLogger, this.numberOfCpus); } else { logger.Initialize(sourceForLogger); } } // Polite logger failure catch (LoggerException) { throw; } catch (Exception e) { InternalLoggerException.Throw(e, null, "FatalErrorWhileInitializingLogger", false, logger.GetType().Name); } if (forwardingLogger) { if (forwardingLoggers == null) { forwardingLoggers = new ArrayList(); } forwardingLoggers.Add(logger); } else { if (loggers == null) { loggers = new ArrayList(); } loggers.Add(logger); } }