From 01473dd6d92c1c74e86df34187184cca549fecd7 Mon Sep 17 00:00:00 2001 From: Tomas Bartonek Date: Tue, 8 Oct 2024 11:46:37 +0200 Subject: [PATCH 1/4] replaced RaiseSomeEvent handlers by a generic one and lambdas --- .../Components/Logging/EventSourceSink.cs | 693 ++---------------- 1 file changed, 41 insertions(+), 652 deletions(-) diff --git a/src/Build/BackEnd/Components/Logging/EventSourceSink.cs b/src/Build/BackEnd/Components/Logging/EventSourceSink.cs index 8804918dbc0..0c4595aceea 100644 --- a/src/Build/BackEnd/Components/Logging/EventSourceSink.cs +++ b/src/Build/BackEnd/Components/Logging/EventSourceSink.cs @@ -8,6 +8,7 @@ using Microsoft.Build.Shared; using InternalLoggerException = Microsoft.Build.Exceptions.InternalLoggerException; +using static Microsoft.Build.BackEnd.Logging.EventSourceSink; #nullable disable @@ -224,57 +225,59 @@ public void Consume(BuildEventArgs buildEvent, int sinkId) /// public void Consume(BuildEventArgs buildEvent) { + switch (buildEvent) { case BuildMessageEventArgs buildMessageEvent: - RaiseMessageEvent(null, buildMessageEvent); + RaiseEvent(null, buildMessageEvent, (o, args) => MessageRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); break; case TaskStartedEventArgs taskStartedEvent: - RaiseTaskStartedEvent(null, taskStartedEvent); + RaiseEvent(null, taskStartedEvent, (o, args) => TaskStarted?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); break; case TaskFinishedEventArgs taskFinishedEvent: - RaiseTaskFinishedEvent(null, taskFinishedEvent); + RaiseEvent(null, taskFinishedEvent, (o, args) => TaskFinished?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); break; case TargetStartedEventArgs targetStartedEvent: - RaiseTargetStartedEvent(null, targetStartedEvent); + RaiseEvent(null, targetStartedEvent, (o, args) => TargetStarted?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); break; case TargetFinishedEventArgs targetFinishedEvent: - RaiseTargetFinishedEvent(null, targetFinishedEvent); + RaiseEvent(null, targetFinishedEvent, (o, args) => TargetFinished?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); break; case ProjectStartedEventArgs projectStartedEvent: - RaiseProjectStartedEvent(null, projectStartedEvent); + RaiseEvent(null, projectStartedEvent, (o, args) => ProjectStarted?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); break; case ProjectFinishedEventArgs projectFinishedEvent: - RaiseProjectFinishedEvent(null, projectFinishedEvent); + RaiseEvent(null, projectFinishedEvent, (o, args) => ProjectFinished?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); break; case BuildStartedEventArgs buildStartedEvent: HaveLoggedBuildStartedEvent = true; - RaiseBuildStartedEvent(null, buildStartedEvent); + RaiseEvent(null, buildStartedEvent, (o, args) => BuildStarted?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); break; case BuildFinishedEventArgs buildFinishedEvent: HaveLoggedBuildFinishedEvent = true; - RaiseBuildFinishedEvent(null, buildFinishedEvent); + RaiseEvent(null, buildFinishedEvent, (o, args) => BuildFinished?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); break; case BuildCanceledEventArgs buildCanceledEvent: - RaiseStatusEvent(null, buildCanceledEvent); + + RaiseEvent(null, buildCanceledEvent, (o, args) => StatusEventRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); break; case CustomBuildEventArgs customBuildEvent: - RaiseCustomEvent(null, customBuildEvent); + RaiseEvent(null, customBuildEvent, (o, args) => CustomEventRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); break; case BuildStatusEventArgs buildStatusEvent: - RaiseStatusEvent(null, buildStatusEvent); + RaiseEvent(null, buildStatusEvent, (o, args) => StatusEventRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); break; case BuildWarningEventArgs buildWarningEvent: - RaiseWarningEvent(null, buildWarningEvent); + RaiseEvent(null, buildWarningEvent, (o, args) => WarningRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); break; case BuildErrorEventArgs buildErrorEvent: - RaiseErrorEvent(null, buildErrorEvent); + RaiseEvent(null, buildErrorEvent, (o, args) => ErrorRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); break; case TelemetryEventArgs telemetryEvent: - RaiseTelemetryEvent(null, telemetryEvent); + RaiseEvent(null, telemetryEvent, (o, args) => TelemetryLogged?.Invoke(o, args), null); break; case BuildCheckEventArgs buildCheckEvent: - RaiseBuildCheckEvent(null, buildCheckEvent); + RaiseEvent(null, buildCheckEvent, (o, args) => BuildCheckEventRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); break; default: @@ -321,662 +324,48 @@ internal void UnregisterAllEventHandlers() #region Private Methods - /// - /// Raises a message event to all registered loggers. - /// - /// sender of the event - /// BuildMessageEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseMessageEvent(object sender, BuildMessageEventArgs buildEvent) - { - if (MessageRaised != null) - { - try - { - MessageRaised(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseAnyEvent(sender, buildEvent); - } - - /// - /// Raises an error event to all registered loggers. - /// - /// sender of the event - /// BuildErrorEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseErrorEvent(object sender, BuildErrorEventArgs buildEvent) - { - if (ErrorRaised != null) - { - try - { - ErrorRaised(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseAnyEvent(sender, buildEvent); - } - - /// - /// Raises a warning event to all registered loggers. - /// - /// sender of the event - /// BuildWarningEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseWarningEvent(object sender, BuildWarningEventArgs buildEvent) - { - if (WarningRaised != null) - { - try - { - WarningRaised(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseAnyEvent(sender, buildEvent); - } - - /// - /// Raises a "build started" event to all registered loggers. - /// - /// sender of the event - /// BuildStartedEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseBuildStartedEvent(object sender, BuildStartedEventArgs buildEvent) - { - if (BuildStarted != null) - { - try - { - BuildStarted(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseStatusEvent(sender, buildEvent); - } + public delegate void ArgsHandler(object sender, TArgs e) where TArgs : BuildEventArgs; /// - /// Raises a "build finished" event to all registered loggers. - /// - /// sender of the event - /// BuildFinishedEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseBuildFinishedEvent(object sender, BuildFinishedEventArgs buildEvent) - { - if (BuildFinished != null) - { - try - { - BuildFinished(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseStatusEvent(sender, buildEvent); - } - - /// - /// Raises a "project build started" event to all registered loggers. - /// - /// sender of the event - /// ProjectStartedEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseProjectStartedEvent(object sender, ProjectStartedEventArgs buildEvent) - { - if (ProjectStarted != null) - { - try - { - ProjectStarted(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseStatusEvent(sender, buildEvent); - } - - /// - /// Raises a "project build finished" event to all registered loggers. - /// - /// sender of the event - /// ProjectFinishedEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseProjectFinishedEvent(object sender, ProjectFinishedEventArgs buildEvent) - { - if (ProjectFinished != null) - { - try - { - ProjectFinished(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseStatusEvent(sender, buildEvent); - } - - /// - /// Raises a "target build started" event to all registered loggers. - /// - /// sender of the event - /// TargetStartedEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseTargetStartedEvent(object sender, TargetStartedEventArgs buildEvent) - { - if (TargetStarted != null) - { - try - { - TargetStarted(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseStatusEvent(sender, buildEvent); - } - - /// - /// Raises a "target build finished" event to all registered loggers. - /// - /// sender of the event - /// TargetFinishedEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseTargetFinishedEvent(object sender, TargetFinishedEventArgs buildEvent) - { - if (TargetFinished != null) - { - try - { - TargetFinished(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseStatusEvent(sender, buildEvent); - } - - /// - /// Raises a "task execution started" event to all registered loggers. - /// - /// sender of the event - /// TaskStartedEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseTaskStartedEvent(object sender, TaskStartedEventArgs buildEvent) - { - if (TaskStarted != null) - { - try - { - TaskStarted(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseStatusEvent(sender, buildEvent); - } - - /// - /// Raises a "task finished executing" event to all registered loggers. - /// - /// sender of the event - /// TaskFinishedEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseTaskFinishedEvent(object sender, TaskFinishedEventArgs buildEvent) - { - if (TaskFinished != null) - { - try - { - TaskFinished(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseStatusEvent(sender, buildEvent); - } - - /// - /// Raises a custom event to all registered loggers. + /// Raises a message event to all registered loggers. /// /// sender of the event - /// CustomBuildEventArgs + /// event args + /// argument handler that invokes the respective event + /// either anyEvent, customEvent or statusEvent /// When EventHandler raises an logger exception the LoggerException is rethrown /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseCustomEvent(object sender, CustomBuildEventArgs buildEvent) + private void RaiseEvent(object sender, TArgs buildEvent, ArgsHandler handler, ArgsHandler followUp) + where TArgs : BuildEventArgs { - if (CustomEventRaised != null) + try { - try - { - CustomEventRaised(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } + handler(sender, buildEvent); } - - RaiseAnyEvent(sender, buildEvent); - } - - /// - /// Raises a catch-all build status event to all registered loggers. - /// - /// sender of the event - /// BuildStatusEventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseStatusEvent(object sender, BuildStatusEventArgs buildEvent) - { - if (StatusEventRaised != null) + catch (LoggerException) { - try - { - StatusEventRaised(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } + // if a logger has failed politely, abort immediately + // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings + // if a fellow logger is throwing in an event handler. + UnregisterAllEventHandlers(); + throw; } - - RaiseAnyEvent(sender, buildEvent); - } - - private void RaiseBuildCheckEvent(object sender, BuildCheckEventArgs buildEvent) - { - if (BuildCheckEventRaised != null) + catch (Exception exception) { - try - { - BuildCheckEventRaised(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } - - RaiseAnyEvent(sender, buildEvent); - } + // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings + // if a fellow logger is throwing in an event handler. + UnregisterAllEventHandlers(); - /// - /// Raises a catch-all build event to all registered loggers. - /// - /// sender of the event - /// Build EventArgs - /// When EventHandler raises an logger exception the LoggerException is rethrown - /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException - /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseAnyEvent(object sender, BuildEventArgs buildEvent) - { - if (AnyEventRaised != null) - { - try - { - AnyEventRaised(sender, buildEvent); - } - catch (LoggerException exception) + if (ExceptionHandling.IsCriticalException(exception)) { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - UnregisterAllEventHandlers(); - - // We ought to dump this further up the stack, but if for example a task is logging an event within a - // catch(Exception) block and not rethrowing it, there's the possibility that this exception could - // just get silently eaten. So better to have duplicates than to not log the problem at all. :) - ExceptionHandling.DumpExceptionToFile(exception); - throw; } - catch (Exception exception) - { - // We ought to dump this further up the stack, but if for example a task is logging an event within a - // catch(Exception) block and not rethrowing it, there's the possibility that this exception could - // just get silently eaten. So better to have duplicates than to not log the problem at all. :) - ExceptionHandling.DumpExceptionToFile(exception); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } + InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); } - } - /// - /// Raises the a telemetry event to all registered loggers. - /// - private void RaiseTelemetryEvent(object sender, TelemetryEventArgs buildEvent) - { - if (TelemetryLogged != null) - { - try - { - TelemetryLogged(sender, buildEvent); - } - catch (LoggerException) - { - // if a logger has failed politely, abort immediately - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - throw; - } - catch (Exception exception) - { - // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings - // if a fellow logger is throwing in an event handler. - this.UnregisterAllEventHandlers(); - - if (ExceptionHandling.IsCriticalException(exception)) - { - throw; - } - - InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); - } - } + followUp?.Invoke(sender, buildEvent); } #endregion From 48fa78f8de58e139098cb78125b7e45ee0d97537 Mon Sep 17 00:00:00 2001 From: Tomas Bartonek Date: Tue, 8 Oct 2024 12:12:52 +0200 Subject: [PATCH 2/4] removing something that slipped in --- src/Build/BackEnd/Components/Logging/EventSourceSink.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Build/BackEnd/Components/Logging/EventSourceSink.cs b/src/Build/BackEnd/Components/Logging/EventSourceSink.cs index 0c4595aceea..d86379a2c91 100644 --- a/src/Build/BackEnd/Components/Logging/EventSourceSink.cs +++ b/src/Build/BackEnd/Components/Logging/EventSourceSink.cs @@ -8,7 +8,6 @@ using Microsoft.Build.Shared; using InternalLoggerException = Microsoft.Build.Exceptions.InternalLoggerException; -using static Microsoft.Build.BackEnd.Logging.EventSourceSink; #nullable disable From be1c09c8d27ae26dab8a57ba0708a959d065199b Mon Sep 17 00:00:00 2001 From: Tomas Bartonek Date: Tue, 8 Oct 2024 14:23:19 +0200 Subject: [PATCH 3/4] reintroducing skipped try catch. RaiseAnyEvent added since it is doing separate logging. removing null arguments, removing #nullable disable --- .../Components/Logging/EventSourceSink.cs | 136 ++++++++++++------ 1 file changed, 96 insertions(+), 40 deletions(-) diff --git a/src/Build/BackEnd/Components/Logging/EventSourceSink.cs b/src/Build/BackEnd/Components/Logging/EventSourceSink.cs index d86379a2c91..f0f7891ede4 100644 --- a/src/Build/BackEnd/Components/Logging/EventSourceSink.cs +++ b/src/Build/BackEnd/Components/Logging/EventSourceSink.cs @@ -9,8 +9,6 @@ using InternalLoggerException = Microsoft.Build.Exceptions.InternalLoggerException; -#nullable disable - namespace Microsoft.Build.BackEnd.Logging { /// @@ -27,84 +25,84 @@ internal sealed class EventSourceSink : /// /// This event is raised to log a message. /// - public event BuildMessageEventHandler MessageRaised; + public event BuildMessageEventHandler? MessageRaised; /// /// This event is raised to log an error. /// - public event BuildErrorEventHandler ErrorRaised; + public event BuildErrorEventHandler? ErrorRaised; /// /// This event is raised to log a warning. /// - public event BuildWarningEventHandler WarningRaised; + public event BuildWarningEventHandler? WarningRaised; /// /// this event is raised to log the start of a build /// - public event BuildStartedEventHandler BuildStarted; + public event BuildStartedEventHandler? BuildStarted; /// /// this event is raised to log the end of a build /// - public event BuildFinishedEventHandler BuildFinished; + public event BuildFinishedEventHandler? BuildFinished; /// /// this event is raised to log the start of a project build /// - public event ProjectStartedEventHandler ProjectStarted; + public event ProjectStartedEventHandler? ProjectStarted; /// /// this event is raised to log the end of a project build /// - public event ProjectFinishedEventHandler ProjectFinished; + public event ProjectFinishedEventHandler? ProjectFinished; /// /// this event is raised to log the start of a target build /// - public event TargetStartedEventHandler TargetStarted; + public event TargetStartedEventHandler? TargetStarted; /// /// this event is raised to log the end of a target build /// - public event TargetFinishedEventHandler TargetFinished; + public event TargetFinishedEventHandler? TargetFinished; /// /// this event is raised to log the start of task execution /// - public event TaskStartedEventHandler TaskStarted; + public event TaskStartedEventHandler? TaskStarted; /// /// this event is raised to log the end of task execution /// - public event TaskFinishedEventHandler TaskFinished; + public event TaskFinishedEventHandler? TaskFinished; /// /// this event is raised to log a custom event /// - public event CustomBuildEventHandler CustomEventRaised; + public event CustomBuildEventHandler? CustomEventRaised; /// /// this event is raised to log build status events, such as /// build/project/target/task started/stopped /// - public event BuildStatusEventHandler StatusEventRaised; + public event BuildStatusEventHandler? StatusEventRaised; /// /// This event is raised to log that some event has /// occurred. It is raised on every event. /// - public event AnyEventHandler AnyEventRaised; + public event AnyEventHandler? AnyEventRaised; /// /// This event is raised to log telemetry. /// - public event TelemetryEventHandler TelemetryLogged; + public event TelemetryEventHandler? TelemetryLogged; /// /// This event is raised to log BuildCheck events. /// - internal event BuildCheckEventHandler BuildCheckEventRaised; + internal event BuildCheckEventHandler? BuildCheckEventRaised; #endregion #region Properties @@ -228,55 +226,63 @@ public void Consume(BuildEventArgs buildEvent) switch (buildEvent) { case BuildMessageEventArgs buildMessageEvent: - RaiseEvent(null, buildMessageEvent, (o, args) => MessageRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); + RaiseEvent(buildMessageEvent, args => MessageRaised?.Invoke(null, args), RaiseAnyEvent); break; case TaskStartedEventArgs taskStartedEvent: - RaiseEvent(null, taskStartedEvent, (o, args) => TaskStarted?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); + ArgsHandler taskStartedFollowUp = args => RaiseEvent(args, args=> StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); + RaiseEvent(taskStartedEvent, args => TaskStarted?.Invoke(null, args), taskStartedFollowUp); break; case TaskFinishedEventArgs taskFinishedEvent: - RaiseEvent(null, taskFinishedEvent, (o, args) => TaskFinished?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); + ArgsHandler taskFinishedFollowUp = args => RaiseEvent(args, args => StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); + RaiseEvent(taskFinishedEvent, args => TaskFinished?.Invoke(null, args), taskFinishedFollowUp); break; case TargetStartedEventArgs targetStartedEvent: - RaiseEvent(null, targetStartedEvent, (o, args) => TargetStarted?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); + ArgsHandler targetStartedFollowUp = args => RaiseEvent(args, args => StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); + RaiseEvent(targetStartedEvent, args => TargetStarted?.Invoke(null, args), targetStartedFollowUp); break; case TargetFinishedEventArgs targetFinishedEvent: - RaiseEvent(null, targetFinishedEvent, (o, args) => TargetFinished?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); + ArgsHandler targetFinishedFollowUp = args => RaiseEvent(args, args => StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); + RaiseEvent(targetFinishedEvent, args => TargetFinished?.Invoke(null, args), targetFinishedFollowUp); break; case ProjectStartedEventArgs projectStartedEvent: - RaiseEvent(null, projectStartedEvent, (o, args) => ProjectStarted?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); + ArgsHandler projectStartedFollowUp = args => RaiseEvent(args, args => StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); + RaiseEvent(projectStartedEvent, args => ProjectStarted?.Invoke(null, args), projectStartedFollowUp); break; case ProjectFinishedEventArgs projectFinishedEvent: - RaiseEvent(null, projectFinishedEvent, (o, args) => ProjectFinished?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); + ArgsHandler projectFinishedFollowUp = args => RaiseEvent(args, args => StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); + RaiseEvent(projectFinishedEvent, args => ProjectFinished?.Invoke(null, args), projectFinishedFollowUp); break; case BuildStartedEventArgs buildStartedEvent: HaveLoggedBuildStartedEvent = true; - RaiseEvent(null, buildStartedEvent, (o, args) => BuildStarted?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); + ArgsHandler BuildStartedFollowUp = args => RaiseEvent(args, args => StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); + RaiseEvent(buildStartedEvent, args => BuildStarted?.Invoke(null, args), BuildStartedFollowUp); break; case BuildFinishedEventArgs buildFinishedEvent: HaveLoggedBuildFinishedEvent = true; - RaiseEvent(null, buildFinishedEvent, (o, args) => BuildFinished?.Invoke(o, args), (o, args) => StatusEventRaised?.Invoke(o, args)); + ArgsHandler BuildFinishedFollowUp = args => RaiseEvent(args, args => StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); + RaiseEvent(buildFinishedEvent, args => BuildFinished?.Invoke(null, args), BuildFinishedFollowUp); break; case BuildCanceledEventArgs buildCanceledEvent: - RaiseEvent(null, buildCanceledEvent, (o, args) => StatusEventRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); + RaiseEvent(buildCanceledEvent, args => StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); break; case CustomBuildEventArgs customBuildEvent: - RaiseEvent(null, customBuildEvent, (o, args) => CustomEventRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); + RaiseEvent(customBuildEvent, args => CustomEventRaised?.Invoke(null, args), RaiseAnyEvent); break; case BuildStatusEventArgs buildStatusEvent: - RaiseEvent(null, buildStatusEvent, (o, args) => StatusEventRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); + RaiseEvent(buildStatusEvent, args => StatusEventRaised?.Invoke(null, args), RaiseAnyEvent); break; case BuildWarningEventArgs buildWarningEvent: - RaiseEvent(null, buildWarningEvent, (o, args) => WarningRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); + RaiseEvent(buildWarningEvent, args => WarningRaised?.Invoke(null, args), RaiseAnyEvent); break; case BuildErrorEventArgs buildErrorEvent: - RaiseEvent(null, buildErrorEvent, (o, args) => ErrorRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); + RaiseEvent(buildErrorEvent, args => ErrorRaised?.Invoke(null, args), RaiseAnyEvent); break; case TelemetryEventArgs telemetryEvent: - RaiseEvent(null, telemetryEvent, (o, args) => TelemetryLogged?.Invoke(o, args), null); + RaiseEvent(telemetryEvent, args => TelemetryLogged?.Invoke(null, args), null); break; case BuildCheckEventArgs buildCheckEvent: - RaiseEvent(null, buildCheckEvent, (o, args) => BuildCheckEventRaised?.Invoke(o, args), (o, args) => AnyEventRaised?.Invoke(o, args)); + RaiseEvent(buildCheckEvent, args => BuildCheckEventRaised?.Invoke(null, args), RaiseAnyEvent); break; default: @@ -290,7 +296,7 @@ public void Consume(BuildEventArgs buildEvent) /// public void ShutDown() { - this.UnregisterAllEventHandlers(); + UnregisterAllEventHandlers(); } #endregion @@ -323,7 +329,7 @@ internal void UnregisterAllEventHandlers() #region Private Methods - public delegate void ArgsHandler(object sender, TArgs e) where TArgs : BuildEventArgs; + public delegate void ArgsHandler(TArgs e) where TArgs : BuildEventArgs; /// /// Raises a message event to all registered loggers. @@ -331,16 +337,16 @@ internal void UnregisterAllEventHandlers() /// sender of the event /// event args /// argument handler that invokes the respective event - /// either anyEvent, customEvent or statusEvent + /// either anyEvent or statusEvent, it is invoked after the Event has been processed /// When EventHandler raises an logger exception the LoggerException is rethrown /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException /// ExceptionHandling.IsCriticalException exceptions will not be wrapped - private void RaiseEvent(object sender, TArgs buildEvent, ArgsHandler handler, ArgsHandler followUp) + private void RaiseEvent(TArgs buildEvent, ArgsHandler handler, ArgsHandler? followUpHandler) where TArgs : BuildEventArgs { try { - handler(sender, buildEvent); + handler(buildEvent); } catch (LoggerException) { @@ -363,8 +369,58 @@ private void RaiseEvent(object sender, TArgs buildEvent, ArgsHandler + /// Raises a catch-all build event to all registered loggers. + /// Keeping it separate since it also dumps the Exception to file as opposed to all other events. + /// + /// sender of the event + /// Build EventArgs + /// When EventHandler raises an logger exception the LoggerException is rethrown + /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException + /// ExceptionHandling.IsCriticalException exceptions will not be wrapped + private void RaiseAnyEvent(BuildEventArgs buildEvent) + { + if (AnyEventRaised != null) + { + try + { + AnyEventRaised(null, buildEvent); + } + catch (LoggerException exception) + { + if (ExceptionHandling.IsCriticalException(exception)) + { + // if a logger has failed politely, abort immediately + // first unregister all loggers, since other loggers may receive remaining events in unexpected orderings + // if a fellow logger is throwing in an event handler. + UnregisterAllEventHandlers(); + + // We ought to dump this further up the stack, but if for example a task is logging an event within a + // catch(Exception) block and not rethrowing it, there's the possibility that this exception could + // just get silently eaten. So better to have duplicates than to not log the problem at all. :) + ExceptionHandling.DumpExceptionToFile(exception); + + throw; + } + } + catch (Exception exception) + { + // We ought to dump this further up the stack, but if for example a task is logging an event within a + // catch(Exception) block and not rethrowing it, there's the possibility that this exception could + // just get silently eaten. So better to have duplicates than to not log the problem at all. :) + ExceptionHandling.DumpExceptionToFile(exception); + + if (ExceptionHandling.IsCriticalException(exception)) + { + throw; + } + + InternalLoggerException.Throw(exception, buildEvent, "FatalErrorWhileLogging", false); + } + } } #endregion From 3ab782175917dce44faefddf60e43f959f7f34dc Mon Sep 17 00:00:00 2001 From: Tomas Bartonek Date: Tue, 8 Oct 2024 16:01:23 +0200 Subject: [PATCH 4/4] nullable fix, argument annotation fix --- src/Build/BackEnd/Components/Logging/EventSourceSink.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Build/BackEnd/Components/Logging/EventSourceSink.cs b/src/Build/BackEnd/Components/Logging/EventSourceSink.cs index f0f7891ede4..1d42c48cd14 100644 --- a/src/Build/BackEnd/Components/Logging/EventSourceSink.cs +++ b/src/Build/BackEnd/Components/Logging/EventSourceSink.cs @@ -110,7 +110,7 @@ internal sealed class EventSourceSink : /// Provide a friendly name for the sink to make it easier to differentiate during /// debugging and display /// - public string Name + public string? Name { get; set; @@ -334,7 +334,6 @@ internal void UnregisterAllEventHandlers() /// /// Raises a message event to all registered loggers. /// - /// sender of the event /// event args /// argument handler that invokes the respective event /// either anyEvent or statusEvent, it is invoked after the Event has been processed @@ -376,7 +375,6 @@ private void RaiseEvent(TArgs buildEvent, ArgsHandler handler, Arg /// Raises a catch-all build event to all registered loggers. /// Keeping it separate since it also dumps the Exception to file as opposed to all other events. /// - /// sender of the event /// Build EventArgs /// When EventHandler raises an logger exception the LoggerException is rethrown /// Any exceptions which are not LoggerExceptions are wrapped in an InternalLoggerException