public static void ReportNonFatal(Exception exception) { if (exception is OutOfMemoryException) { FailFast.OnFatalException(exception); } if (!s_report) { return; } var emptyCallstack = exception.SetCallstackIfEmpty(); var currentProcess = Process.GetCurrentProcess(); // write the exception to a log file: s_logger?.TraceEvent(TraceEventType.Error, 1, $"[{currentProcess.ProcessName}:{currentProcess.Id}] Unexpected exception: {exception}"); var session = s_telemetrySession; if (session == null) { return; } var logFilePaths = CaptureLogFiles(); var faultEvent = new FaultEvent( eventName: FunctionId.NonFatalWatson.GetEventName(), description: "Roslyn NonFatal Watson", FaultSeverity.Diagnostic, exceptionObject: exception, gatherEventDetails: faultUtility => { // add current process dump faultUtility.AddProcessDump(currentProcess.Id); // add ServiceHub log files: foreach (var path in logFilePaths) { faultUtility.AddFile(path); } // Returning "0" signals that we should send data to Watson; any other value will cancel the Watson report. return(0); }); // add extra bucket parameters to bucket better in NFW // we do it here so that it gets bucketted better in both // watson and telemetry. faultEvent.SetExtraParameters(exception, emptyCallstack); session.PostEvent(faultEvent); }
/// <summary> /// Report Non-Fatal Watson /// </summary> /// <param name="description">any description you want to save with this watson report</param> /// <param name="exception">Exception that triggered this non-fatal error</param> /// <param name="callback">Callback to include extra data with the NFW. Note that we always collect /// a dump of the current process, but this can be used to add further information or files to the /// CAB.</param> /// <param name="severity">indicate <see cref="WatsonSeverity"/> of NFW</param> public static void Report(string description, Exception exception, Func <IFaultUtility, int> callback, WatsonSeverity severity = WatsonSeverity.Default) { var critical = severity == WatsonSeverity.Critical; var emptyCallstack = exception.SetCallstackIfEmpty(); // if given exception is non recoverable exception, // crash instead of NFW if (IsNonRecoverableException(exception)) { CodeAnalysis.FailFast.OnFatalException(exception); } if (!exception.ShouldReport()) { return; } if (RoslynServices.SessionOpt == null) { return; } // in OOP, we don't fire Critical NFW, rather we fire General which is 1 level higher than Diagnostic // and we keep fire NFW even after critical report. // critical NFW regarding OOP from VS side will let us to prioritize NFW to fix, and NFW from here should provide // extra dump/info to take a look. // whenever there is an exception in OOP, we fire NFW in both VS and OOP side. VS will report it as critical NFW // and OOP will fire normal NFW. we only mark VS side critical since we don't want to double report same issue // and don't want to shutdown NFW in OOP // one can correlate NFW from VS and OOP through remote callstack in VS NFW var faultEvent = new FaultEvent( eventName: FunctionId.NonFatalWatson.GetEventName(), description: description, critical ? FaultSeverity.General : FaultSeverity.Diagnostic, exceptionObject: exception, gatherEventDetails: arg => { // always add current processes dump arg.AddProcessDump(System.Diagnostics.Process.GetCurrentProcess().Id); return(callback(arg)); }); // add extra bucket parameters to bucket better in NFW // we do it here so that it gets bucketted better in both // watson and telemetry. faultEvent.SetExtraParameters(exception, emptyCallstack); RoslynServices.SessionOpt.PostEvent(faultEvent); }
/// <summary> /// Report Non-Fatal Watson /// </summary> /// <param name="description">any description you want to save with this watson report</param> /// <param name="exception">Exception that triggered this non-fatal error</param> /// <param name="callback">Callback to include extra data with the NFW. Note that we always collect /// a dump of the current process, but this can be used to add further information or files to the /// CAB.</param> /// <param name="severity">indicate <see cref="WatsonSeverity"/> of NFW</param> public static void Report(string description, Exception exception, Func <IFaultUtility, int> callback, WatsonSeverity severity = WatsonSeverity.Default) { var critical = severity == WatsonSeverity.Critical; var emptyCallstack = exception.SetCallstackIfEmpty(); if (!WatsonDisabled.s_reportWatson || !exception.ShouldReport()) { return; } var faultEvent = new FaultEvent( eventName: FunctionId.NonFatalWatson.GetEventName(), description: description, critical ? FaultSeverity.Critical : FaultSeverity.Diagnostic, exceptionObject: exception, gatherEventDetails: arg => { // always add current processes dump arg.AddProcessDump(System.Diagnostics.Process.GetCurrentProcess().Id); return(callback(arg)); }); // add extra bucket parameters to bucket better in NFW // we do it here so that it gets bucketted better in both // watson and telemetry. faultEvent.SetExtraParameters(exception, emptyCallstack); TelemetryService.DefaultSession.PostEvent(faultEvent); if (exception is OutOfMemoryException || critical) { // Once we've encountered one OOM or Critial NFW, // we're likely to see more. There will probably be other // failures as a direct result of the OOM or critical NFW, as well. // These aren't helpful so we should just stop reporting failures. WatsonDisabled.s_reportWatson = false; } }
/// <summary> /// Report Non-Fatal Watson /// </summary> /// <param name="description">any description you want to save with this watson report</param> /// <param name="exception">Exception that triggered this non-fatal error</param> /// <param name="callback">Callback to include extra data with the NFW. Note that we always collect /// a dump of the current process, but this can be used to add further information or files to the /// CAB.</param> public static void Report(string description, Exception exception, Func <IFaultUtility, int> callback) { var emptyCallstack = exception.SetCallstackIfEmpty(); // if given exception is non recoverable exception, // crash instead of NFW if (IsNonRecoverableException(exception)) { CodeAnalysis.FailFast.OnFatalException(exception); } if (!exception.ShouldReport()) { return; } if (SessionOpt == null) { return; } var faultEvent = new FaultEvent( eventName: FunctionId.NonFatalWatson.GetEventName(), description: description, exceptionObject: exception, gatherEventDetails: arg => { // always add current processes dump arg.AddProcessDump(System.Diagnostics.Process.GetCurrentProcess().Id); return(callback(arg)); }); // add extra bucket parameters to bucket better in NFW // we do it here so that it gets bucketted better in both // watson and telemetry. faultEvent.SetExtraParameters(exception, emptyCallstack); SessionOpt.PostEvent(faultEvent); }