[mono/monodevelop] [2 commits] 83c032bd: Reworking the logging services, using Raygun.io

"Cody Russell ([email protected])" <[email protected]>
Newsgroups gmane.comp.gnome.mono.patches
Message-ID <00000141a098cc1f-23652e54-e634-4519-b697-4a42dbe668c4-000000@email.amazonses.com>
   Branch: refs/heads/master
     Home: https://github.com/mono/monodevelop
  Compare: https://github.com/mono/monodevelop/compare/fd46981b2c3a...f2fb303446cf

   Commit: 83c032bdeb2beae7a30811087448144b95b25a25
   Author: Cody Russell <[email protected]> (bratsche)
     Date: 2013-10-10 04:17:01 GMT
      URL: https://github.com/mono/monodevelop/commit/83c032bdeb2beae7a30811087448144b95b25a25

Reworking the logging services, using Raygun.io

Changed paths:
  M .gitmodules
  M main/Main.sln
  M main/src/addins/AspNet/MonoDevelop.AspNet.Mvc/RazorEditorParserFixed/BackgroundParser.cs
  M main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/SubviewAttachmentHandler.cs
  M main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/TargetRuntime.cs
  M main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
  M main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs
  M main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs
  M main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateService.cs
  M main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/LogAgentOptionsPanel.cs
  M main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
  M main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/LogReportingStartup.cs
Added paths:
  A main/external/raygun4net
  A main/src/addins/AspNet/MonoDevelop.AspNet/MonoDevelop.AspNet/AspNetAppProject.cs
  A main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor.Gui/XmlSchemasPanel.cs
  A main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor/OpenStylesheetCommand.cs
Removed paths:
  D main/src/addins/AspNet/MonoDevelop.AspNet/MonoDevelop.AspNet/AspNetAppProject.cs
  D main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor.Gui/XmlSchemasPanel.cs
  D main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor/OpenStylesheetCommand.cs
  D main/src/core/MonoDevelop.Core/MonoDevelop.Core.LogReporting/LogReportingService.cs

Modified: .gitmodules
===================================================================
@@ -37,3 +37,6 @@
 [submodule "main/external/guiunit"]
 	path = main/external/guiunit
 	url = git://github.com/mono/guiunit.git
+[submodule "main/external/raygun4net"]
+	path = main/external/raygun4net
+	url = [email protected]:bratsche/raygun4net.git

Modified: main/Main.sln
===================================================================
@@ -237,6 +237,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.CSha
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GuiUnit_NET_4_0", "external\guiunit\src\framework\GuiUnit_NET_4_0.csproj", "{E13A0A7B-4DE6-43ED-A139-41052D065A9B}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mindscape.Raygun4Net", "external\raygun4net\Mindscape.Raygun4Net\Mindscape.Raygun4Net.csproj", "{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}"
+EndProject
 Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "po", "po\po.mdproj", "{AC7D119C-980B-4712-8811-5368C14412D7}"
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{5D3F7E65-E55B-45CA-A83B-D1E10040281E}"
@@ -468,6 +470,14 @@ Global
 		{459868D2-54DC-415B-B1AB-BE39BDBD352F}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
 		{459868D2-54DC-415B-B1AB-BE39BDBD352F}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
 		{459868D2-54DC-415B-B1AB-BE39BDBD352F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.DebugMac|Any CPU.Build.0 = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.Release|Any CPU.Build.0 = Release|Any CPU
 		{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
@@ -1059,6 +1069,7 @@ Global
 		{B8897B76-1A12-4DFA-8B60-7944CC4C9654} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
 		{2D711139-8765-4929-BC7A-AA2DEE6F615D} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
 		{E13A0A7B-4DE6-43ED-A139-41052D065A9B} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
 		{92494904-35FA-4DC9-BDE9-3A3E87AC49D3} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
 		{C3887A93-B2BD-4097-8E2F-3A063EFF32FD} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
 		{B7C1673E-5124-4BE5-8D21-EC8B12F85B6B} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}


Added: main/external/raygun4net
===================================================================
@@ -0,0 +1 @@
+Subproject commit f22449a80d87f34b1f1469171391b27bd627017d

Modified: main/src/addins/AspNet/MonoDevelop.AspNet.Mvc/RazorEditorParserFixed/BackgroundParser.cs
===================================================================
@@ -438,7 +438,7 @@ private void WorkerLoop()
                 catch (Exception ex)
                 {
                     MonoDevelop.Core.LoggingService.LogError ("Internal error in Razor parser", ex);
-                    MonoDevelop.Core.LogReporting.LogReportingService.ReportUnhandledException (ex, false);
+                    MonoDevelop.Core.LoggingService.ReportUnhandledException (ex, false);
                 }
                 finally
                 {

Added: main/src/addins/AspNet/MonoDevelop.AspNet/MonoDevelop.AspNet/AspNetAppProject.cs
===================================================================


Added: main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor.Gui/XmlSchemasPanel.cs
===================================================================


Added: main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor/OpenStylesheetCommand.cs
===================================================================


Modified: main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/SubviewAttachmentHandler.cs
===================================================================
@@ -29,7 +29,7 @@
 using Mono.Addins;
 using MonoDevelop.VersionControl;
 using MonoDevelop.Ide.Gui;
-using MonoDevelop.Core.LogReporting;
+using MonoDevelop.Core;
 using MonoDevelop.Projects;
 
 namespace MonoDevelop.VersionControl.Views
@@ -79,7 +79,7 @@ void HandleDocumentChanged (object sender, EventArgs e)
 				// If a user is hitting this, it will show a dialog box every time they
 				// switch to a document or open a document, so suppress the crash dialog
 				// This bug *should* be fixed already, but it's hard to tell.
-				LogReportingService.ReportUnhandledException (ex, false, true);
+				LoggingService.ReportUnhandledException (ex, false, true);
 			}
 		}
 		

Modified: main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/TargetRuntime.cs
===================================================================
@@ -388,7 +388,7 @@ void BackgroundInitialize (object state)
 				try {
 					RunInitialization ();
 				} catch (Exception ex) {
-					LogReporting.LogReportingService.ReportUnhandledException (ex, false);
+					//LogReporting.LogReportingService.ReportUnhandledException (ex, false);
 					LoggingService.LogFatalError ("Unhandled exception in SystemAssemblyService background initialisation thread.", ex);
 				} finally {
 					lock (initEventLock) {

Removed: main/src/core/MonoDevelop.Core/MonoDevelop.Core.LogReporting/LogReportingService.cs
===================================================================
@@ -1,196 +0,0 @@
-// 
-// LogReportingService.cs
-//  
-// Author:
-//       Alan McGovern <[email protected]>
-// 
-// Copyright (c) 2011 Alan McGovern
-// 
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-// 
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.IO;
-using System.Threading;
-using System.Net;
-using System.Web;
-using System.IO.Compression;
-
-namespace MonoDevelop.Core.LogReporting
-{
-	public static class LogReportingService
-	{
-		const string ServiceVersion = "1";
-		public static readonly FilePath CrashLogDirectory = UserProfile.Current.LogDir.Combine ("LogAgent");
-		
-		const string ReportCrashesKey = "MonoDevelop.LogAgent.ReportCrashes";
-		const string ReportUsageKey = "MonoDevelop.LogAgent.ReportUsage";
-		
-		static int CrashId;
-		static int Processing;
-		
-		// Return value is the new value for 'ReportCrashes'
-		// First parameter is the current value of 'ReportCrashes
-		// Second parameter is the exception
-		// Thirdparameter shows if the exception is fatal or not
-		public static Func<bool?, Exception, bool, bool?> UnhandledErrorOccured;
-		
-		public static bool? ReportCrashes {
-			get { return PropertyService.Get<bool?> (ReportCrashesKey); }
-			set { PropertyService.Set (ReportCrashesKey, value); }
-		}
-			
-		public static bool? ReportUsage {
-			get { return PropertyService.Get<bool?> (ReportUsageKey); }
-			set { PropertyService.Set (ReportUsageKey, value); }
-		}
-		
-		public static void ReportUnhandledException (Exception ex, bool willShutDown)
-		{
-			ReportUnhandledException (ex, willShutDown, false);
-		}
-
-		static bool reporting;
-
-		public static void ReportUnhandledException (Exception ex, bool willShutDown, bool silently)
-		{
-			if (reporting)
-				return;
-			
-			reporting = true;
-			try {
-				var oldReportCrashes = ReportCrashes;
-				
-				if (UnhandledErrorOccured != null && !silently)
-					ReportCrashes = UnhandledErrorOccured (ReportCrashes, ex, willShutDown);
-				
-				// If crash reporting has been explicitly disabled, disregard this crash
-				if (ReportCrashes.HasValue && !ReportCrashes.Value)
-					return;
-				
-				byte[] data;
-				using (var stream = new MemoryStream ()) {
-					using (var writer = System.Xml.XmlWriter.Create (stream)) {
-							writer.WriteStartElement ("CrashLog");
-							writer.WriteAttributeString ("version", ServiceVersion);
-							
-							writer.WriteElementString ("SystemInformation", SystemInformation.GetTextDescription ());
-							writer.WriteElementString ("Exception", ex.ToString ());
-							
-							writer.WriteEndElement ();
-						}
-					data = stream.ToArray ();
-				}
-				
-				// Log to disk only if uploading fails.
-				var filename = string.Format ("{0}.{1}.{2}.crashlog", DateTime.UtcNow.ToString ("yyyy-MM-dd__HH-mm-ss"), SystemInformation.SessionUuid, Interlocked.Increment (ref CrashId));
-				ThreadPool.QueueUserWorkItem (delegate {
-					if (!TryUploadReport (filename, data)) {
-						if (!Directory.Exists (CrashLogDirectory))
-							Directory.CreateDirectory (CrashLogDirectory);
-
-						File.WriteAllBytes (CrashLogDirectory.Combine (filename), data);
-					}
-				});
-				
-				//ensure we don't lose the setting
-				if (ReportCrashes != oldReportCrashes) {
-					PropertyService.SaveProperties ();
-				}
-
-			} finally {
-				reporting = false;
-			}
-		}
-		
-		public static void ProcessCache ()
-		{
-			int origValue = -1;
-			try {
-				// Ensure only 1 thread at a time attempts to upload cached reports
-				origValue = Interlocked.CompareExchange (ref Processing, 1, 0);
-				if (origValue != 0)
-					return;
-				
-				// Uploading is not enabled, so bail out
-				if (!ReportCrashes.GetValueOrDefault ())
-					return;
-				
-				// Definitely no crash reports if this doesn't exist
-				if (!Directory.Exists (CrashLogDirectory))
-					return;
-				
-				foreach (var file in Directory.GetFiles (CrashLogDirectory)) {
-					if (TryUploadReport (file, File.ReadAllBytes (file)))
-						File.Delete (file);
-				}
-			} catch (Exception ex) {
-				LoggingService.LogError ("Exception processing cached crashes", ex);
-			} finally {
-				if (origValue == 0)
-					Interlocked.CompareExchange (ref Processing, 0, 1);
-			}
-		}
-
-		static bool TryUploadReport (string filename, byte[] data)
-		{
-			try {
-				// Empty files won't be accepted by the server as it thinks 'ContentLength' has not been set as it's
-				// zero. We don't need empty files anyway.
-				if (data.Length == 0)
-					return true;
-				
-				var server = Environment.GetEnvironmentVariable ("MONODEVELOP_CRASHREPORT_SERVER");
-				if (string.IsNullOrEmpty (server))
-					server = "monodevlog.xamarin.com:35162";
-
-				var request = (HttpWebRequest) WebRequest.Create (string.Format ("http://{0}/logagentreport/", server));
-				request.Headers.Add ("LogAgentVersion", ServiceVersion);
-				request.Headers.Add ("LogAgent_Filename", Path.GetFileName (filename));
-				request.Headers.Add ("Content-Encoding", "gzip");
-				request.Method = "POST";
-				
-				// Compress the data and then use the compressed length in ContentLength
-				var compressed = new MemoryStream ();
-				using (var zipper = new GZipStream (compressed, CompressionMode.Compress))
-					zipper.Write (data, 0, data.Length);
-				data = compressed.ToArray ();
-				
-				request.ContentLength = data.Length;
-				using (var requestStream = request.GetRequestStream ())
-					requestStream.Write (data, 0, data.Length);
-				
-				LoggingService.LogDebug ("CrashReport sent to server, awaiting response...");
-
-				// Ensure the server has correctly processed everything.
-				using (var response = (HttpWebResponse) request.GetResponse ()) {
-					if (response.StatusCode != HttpStatusCode.OK) {
-						LoggingService.LogError ("Server responded with status code {1} and error: {0}", response.StatusDescription, response.StatusCode);
-						return false;
-					}
-				}
-			} catch (Exception ex) {
-				LoggingService.LogError ("Failed to upload report to the server", ex);
-				return false;
-			}
-
-			LoggingService.LogDebug ("Successfully uploaded crash report");
-			return true;
-		}
-	}
-}
-

Modified: main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
===================================================================
@@ -82,6 +82,9 @@
     </Reference>
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Web" />
+    <Reference Include="Mindscape.Raygun4Net">
+      <HintPath>..\..\..\external\Mindscape.Raygun4Net\Mindscape.Raygun4Net.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="MonoDevelop.Core.Web\Utility.cs" />
@@ -427,7 +430,6 @@
     <Compile Include="MonoDevelop.Core\UnixSystemInformation.cs" />
     <Compile Include="MonoDevelop.Core\ISystemInformationProvider.cs" />
     <Compile Include="MonoDevelop.Core.FileSystem\UnixFileSystemExtension.cs" />
-    <Compile Include="MonoDevelop.Core.LogReporting\LogReportingService.cs" />
     <Compile Include="MonoDevelop.Core.LogReporting\CrashEventArgs.cs" />
     <Compile Include="MonoDevelop.Core.LogReporting\CrashMonitor.cs" />
     <Compile Include="MonoDevelop.Core.LogReporting\ICrashMonitor.cs" />

Modified: main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs
===================================================================
@@ -29,20 +29,42 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Net;
+using System.Web;
 using System.Linq;
+using System.Diagnostics;
+using System.Threading;
+using System.IO.Compression;
+using Mindscape.Raygun4Net;
+using Mindscape.Raygun4Net.Messages;
 
 using MonoDevelop.Core.Logging;
 
 namespace MonoDevelop.Core
 {
-	
 	public static class LoggingService
 	{
+		const string ServiceVersion = "1";
+		const string ReportCrashesKey = "MonoDevelop.LogAgent.ReportCrashes";
+		const string ReportUsageKey = "MonoDevelop.LogAgent.ReportUsage";
+
+		public static readonly FilePath CrashLogDirectory = UserProfile.Current.LogDir.Combine ("LogAgent");
+
+		static RaygunClient raygunClient;
 		static List<ILogger> loggers = new List<ILogger> ();
 		static RemoteLogger remoteLogger;
 		static DateTime timestamp;
 		static TextWriter defaultError;
 		static TextWriter defaultOut;
+		static bool reporting;
+		static int CrashId;
+		static int Processing;
+
+		// Return value is the new value for 'ReportCrashes'
+		// First parameter is the current value of 'ReportCrashes
+		// Second parameter is the exception
+		// Thirdparameter shows if the exception is fatal or not
+		public static Func<bool?, Exception, bool, bool?> UnhandledErrorOccured;
 
 		static LoggingService ()
 		{
@@ -78,6 +100,11 @@ static LoggingService ()
 
 			timestamp = DateTime.Now;
 
+			string raygunKey = Environment.GetEnvironmentVariable ("MONODEVELOP_RAYGUN_KEY");
+			if (raygunKey != null) {
+				raygunClient = new RaygunClient (raygunKey);
+			}
+
 			//remove the default trace listener on .NET, it throws up horrible dialog boxes for asserts
 			System.Diagnostics.Debug.Listeners.Clear ();
 
@@ -85,6 +112,16 @@ static LoggingService ()
 			System.Diagnostics.Debug.Listeners.Add (new AssertLoggingTraceListener ());
 		}
 
+		public static bool? ReportCrashes {
+			get { return PropertyService.Get<bool?> (ReportCrashesKey); }
+			set { PropertyService.Set (ReportCrashesKey, value); }
+		}
+
+		public static bool? ReportUsage {
+			get { return PropertyService.Get<bool?> (ReportUsageKey); }
+			set { PropertyService.Set (ReportUsageKey, value); }
+		}
+
 		static string GenericLogFile {
 			get { return "Ide.log"; }
 		}
@@ -113,6 +150,148 @@ public static void Shutdown ()
 			RestoreOutputRedirection ();
 		}
 
+		public static void ReportUnhandledException (Exception ex, bool willShutDown)
+		{
+			ReportUnhandledException (ex, willShutDown, false, null);
+		}
+
+		public static void ReportUnhandledException (Exception ex, bool willShutDown, bool silently)
+		{
+			ReportUnhandledException (ex, willShutDown, silently);
+		}
+
+		public static void ReportUnhandledException (Exception ex, bool willShutDown, bool silently, string tag)
+		{
+			var tags = new List<string> { tag };
+
+			if (reporting)
+				return;
+
+			reporting = true;
+			try {
+				var oldReportCrashes = ReportCrashes;
+
+				if (UnhandledErrorOccured != null && !silently)
+					ReportCrashes = UnhandledErrorOccured (ReportCrashes, ex, willShutDown);
+
+				// If crash reporting has been explicitly disabled, disregard this crash
+				if (ReportCrashes.HasValue && !ReportCrashes.Value)
+					return;
+
+				byte[] data;
+				using (var stream = new MemoryStream ()) {
+					using (var writer = System.Xml.XmlWriter.Create (stream)) {
+						writer.WriteStartElement ("CrashLog");
+						writer.WriteAttributeString ("version", ServiceVersion);
+
+						writer.WriteElementString ("SystemInformation", SystemInformation.GetTextDescription ());
+						writer.WriteElementString ("Exception", ex.ToString ());
+
+						writer.WriteEndElement ();
+					}
+					data = stream.ToArray ();
+				}
+
+				if (raygunClient != null) {
+					raygunClient.Send (ex, tags);
+				}
+
+				// Log to disk only if uploading fails.
+				var filename = string.Format ("{0}.{1}.{2}.crashlog", DateTime.UtcNow.ToString ("yyyy-MM-dd__HH-mm-ss"), SystemInformation.SessionUuid, Interlocked.Increment (ref CrashId));
+				ThreadPool.QueueUserWorkItem (delegate {
+					if (!TryUploadReport (filename, data)) {
+						if (!Directory.Exists (CrashLogDirectory))
+							Directory.CreateDirectory (CrashLogDirectory);
+
+						File.WriteAllBytes (CrashLogDirectory.Combine (filename), data);
+					}
+				});
+
+				//ensure we don't lose the setting
+				if (ReportCrashes != oldReportCrashes) {
+					PropertyService.SaveProperties ();
+				}
+
+			} finally {
+				reporting = false;
+			}
+		}
+
+		public static void ProcessCache ()
+		{
+			int origValue = -1;
+			try {
+				// Ensure only 1 thread at a time attempts to upload cached reports
+				origValue = Interlocked.CompareExchange (ref Processing, 1, 0);
+				if (origValue != 0)
+					return;
+
+				// Uploading is not enabled, so bail out
+				if (!ReportCrashes.GetValueOrDefault ())
+					return;
+
+				// Definitely no crash reports if this doesn't exist
+				if (!Directory.Exists (CrashLogDirectory))
+					return;
+
+				foreach (var file in Directory.GetFiles (CrashLogDirectory)) {
+					if (TryUploadReport (file, File.ReadAllBytes (file)))
+						File.Delete (file);
+				}
+			} catch (Exception ex) {
+				LoggingService.LogError ("Exception processing cached crashes", ex);
+			} finally {
+				if (origValue == 0)
+					Interlocked.CompareExchange (ref Processing, 0, 1);
+			}
+		}
+
+		static bool TryUploadReport (string filename, byte[] data)
+		{
+			try {
+				// Empty files won't be accepted by the server as it thinks 'ContentLength' has not been set as it's
+				// zero. We don't need empty files anyway.
+				if (data.Length == 0)
+					return true;
+
+				var server = Environment.GetEnvironmentVariable ("MONODEVELOP_CRASHREPORT_SERVER");
+				if (string.IsNullOrEmpty (server))
+					server = "monodevlog.xamarin.com:35162";
+
+				var request = (HttpWebRequest) WebRequest.Create (string.Format ("http://{0}/logagentreport/", server));
+				request.Headers.Add ("LogAgentVersion", ServiceVersion);
+				request.Headers.Add ("LogAgent_Filename", Path.GetFileName (filename));
+				request.Headers.Add ("Content-Encoding", "gzip");
+				request.Method = "POST";
+
+				// Compress the data and then use the compressed length in ContentLength
+				var compressed = new MemoryStream ();
+				using (var zipper = new GZipStream (compressed, CompressionMode.Compress))
+					zipper.Write (data, 0, data.Length);
+				data = compressed.ToArray ();
+
+				request.ContentLength = data.Length;
+				using (var requestStream = request.GetRequestStream ())
+					requestStream.Write (data, 0, data.Length);
+
+				LoggingService.LogDebug ("CrashReport sent to server, awaiting response...");
+
+				// Ensure the server has correctly processed everything.
+				using (var response = (HttpWebResponse) request.GetResponse ()) {
+					if (response.StatusCode != HttpStatusCode.OK) {
+						LoggingService.LogError ("Server responded with status code {1} and error: {0}", response.StatusDescription, response.StatusCode);
+						return false;
+					}
+				}
+			} catch (Exception ex) {
+				LoggingService.LogError ("Failed to upload report to the server", ex);
+				return false;
+			}
+
+			LoggingService.LogDebug ("Successfully uploaded crash report");
+			return true;
+		}
+
 		static void PurgeOldLogs ()
 		{
 			// Delete all logs older than a week
@@ -220,7 +399,7 @@ static void RestoreOutputRedirection ()
 				return remoteLogger;
 			}
 		}
-		
+
 #region the core service
 		
 		public static bool IsLevelEnabled (LogLevel level)
@@ -295,7 +474,7 @@ public static void LogFatalError (string message)
 		{
 			Log (LogLevel.Fatal, message);
 		}
-		
+
 #endregion
 		
 #region convenience methods (string messageFormat, params object[] args)
@@ -314,12 +493,17 @@ public static void LogWarning (string messageFormat, params object[] args)
 		{
 			Log (LogLevel.Warn, string.Format (messageFormat, args));
 		}
-		
-		public static void LogError (string messageFormat, params object[] args)
+
+		public static void LogUserError (string messageFormat, params object[] args)
 		{
 			Log (LogLevel.Error, string.Format (messageFormat, args));
 		}
 		
+		public static void LogError (string messageFormat, params object[] args)
+		{
+			LogUserError (messageFormat, args);
+		}
+
 		public static void LogFatalError (string messageFormat, params object[] args)
 		{
 			Log (LogLevel.Fatal, string.Format (messageFormat, args));
@@ -346,12 +530,29 @@ public static void LogWarning (string message, Exception ex)
 		
 		public static void LogError (string message, Exception ex)
 		{
+			LogUserError (message, ex);
+		}
+
+		public static void LogUserError (string message, Exception ex)
+		{
 			Log (LogLevel.Error, message + (ex != null? System.Environment.NewLine + ex.ToString () : string.Empty));
 		}
-		
+
+		public static void LogInternalError (Exception ex)
+		{
+			ReportUnhandledException (ex, false, false, "internal");
+		}
+
+		public static void LogCriticalError (string message, Exception ex)
+		{
+			ReportUnhandledException (ex, true, false, "critical");
+		}
+
 		public static void LogFatalError (string message, Exception ex)
 		{
 			Log (LogLevel.Fatal, message + (ex != null? System.Environment.NewLine + ex.ToString () : string.Empty));
+
+			ReportUnhandledException (ex, true, false, "fatal");
 		}
 
 #endregion

Modified: main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs
===================================================================
@@ -198,7 +198,7 @@ static void SetupInstrumentation ()
 		static void OnLoadError (object s, AddinErrorEventArgs args)
 		{
 			string msg = "Add-in error (" + args.AddinId + "): " + args.Message;
-			LogReporting.LogReportingService.ReportUnhandledException (args.Exception, false, true);
+			//LogReporting.LogReportingService.ReportUnhandledException (args.Exception, false, true);
 			LoggingService.LogError (msg, args.Exception);
 		}
 		

Modified: main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateService.cs
===================================================================
@@ -155,7 +155,7 @@ public static void SaveTemplates ()
 			}
 			foreach (CodeTemplate template in templates) {
 				if (string.IsNullOrEmpty (template.Shortcut)) {
-					LoggingService.LogError ("CodeTemplateService: Can't save unnamed template " + template);
+					LoggingService.LogUserError ("CodeTemplateService: Can't save unnamed template " + template);
 					continue;
 				}
 				SaveTemplate (template, Path.Combine (TemplatePath, template.Shortcut + ".template.xml"));

Modified: main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/LogAgentOptionsPanel.cs
===================================================================
@@ -60,13 +60,13 @@ public LogAgentPanelWidget ()
 		{
 			global::Stetic.BinContainer.Attach (this);
 			
-			var value = LogReportingService.ReportCrashes;
+			var value = LoggingService.ReportCrashes;
 			chkCrash = new CheckButton (GettextCatalog.GetString ("Automatically submit error diagnostic information"));
 			if (value.HasValue)
 				chkCrash.Active = value.Value;
 			chkCrash.Toggled += (sender, e) => reportCrash = chkCrash.Active;
 			
-			value = LogReportingService.ReportUsage;
+			value = LoggingService.ReportUsage;
 			chkUsage = new CheckButton (GettextCatalog.GetString ("Automatically submit usage information"));
 			if (value.HasValue)
 				chkUsage.Active = value.Value;
@@ -83,9 +83,9 @@ public LogAgentPanelWidget ()
 		public void Store ()
 		{
 			if (reportCrash.HasValue)
-				LogReportingService.ReportCrashes = reportCrash.Value;
+				LoggingService.ReportCrashes = reportCrash.Value;
 			if (reportUsage.HasValue)
-				LogReportingService.ReportUsage = reportUsage.Value;
+				LoggingService.ReportUsage = reportUsage.Value;
 		}
 	}
 }

Modified: main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
===================================================================
@@ -123,7 +123,7 @@ int Run (MonoDevelopOptions options)
 			EndPoint ep = null;
 			
 			DispatchService.Initialize ();
-			
+
 			// Set a synchronization context for the main gtk thread
 			SynchronizationContext.SetSynchronizationContext (new GtkSynchronizationContext ());
 			
@@ -505,7 +505,7 @@ void HandleException (Exception ex, bool willShutdown)
 			LoggingService.LogError (string.Format ("An unhandled exception has occured. Terminating MonoDevelop? {0}", willShutdown), ex);
 			
 			// Pass it off to the reporting service now.
-			LogReportingService.ReportUnhandledException (ex, willShutdown);
+			LoggingService.ReportUnhandledException (ex, willShutdown);
 		}
 		
 		/// <summary>SDBM-style hash, bounded to a range of 1000.</summary>

Modified: main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/LogReportingStartup.cs
===================================================================
@@ -43,11 +43,11 @@ protected override void Run ()
 		{
 			System.Threading.ThreadPool.QueueUserWorkItem (delegate {
 				// Process cached crash reports if there are any and uploading is enabled
-				LogReportingService.ProcessCache ();
+				LoggingService.ProcessCache ();
 			});
 			
 			// Attach a handler for when exceptions need to be processed
-			LogReportingService.UnhandledErrorOccured = (enabled, ex, willShutdown) => {
+			LoggingService.UnhandledErrorOccured = (enabled, ex, willShutdown) => {
 				var doNotSend = new AlertButton (GettextCatalog.GetString ("Do _Not Send"));
 				var sendOnce = new AlertButton (GettextCatalog.GetString ("_Send This Time"));
 				var alwaysSend = new AlertButton (GettextCatalog.GetString ("_Always Send"));

   Commit: f2fb303446cf2958ddd67f8ae133d52debf83f9c
   Author: Cody Russell <[email protected]> (bratsche)
     Date: 2013-10-10 04:19:05 GMT
      URL: https://github.com/mono/monodevelop/commit/f2fb303446cf2958ddd67f8ae133d52debf83f9c

Merge pull request #413 from bratsche/lumberjack

Reworking the logging services, using Raygun.io

Changed paths:
  M .gitmodules
  M main/Main.sln
  M main/src/addins/AspNet/MonoDevelop.AspNet.Mvc/RazorEditorParserFixed/BackgroundParser.cs
  M main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/SubviewAttachmentHandler.cs
  M main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/TargetRuntime.cs
  M main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
  M main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs
  M main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs
  M main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateService.cs
  M main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/LogAgentOptionsPanel.cs
  M main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
  M main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/LogReportingStartup.cs
Added paths:
  A main/external/raygun4net
  A main/src/addins/AspNet/MonoDevelop.AspNet/MonoDevelop.AspNet/AspNetAppProject.cs
  A main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor.Gui/XmlSchemasPanel.cs
  A main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor/OpenStylesheetCommand.cs
Removed paths:
  D main/src/addins/AspNet/MonoDevelop.AspNet/MonoDevelop.AspNet/AspNetAppProject.cs
  D main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor.Gui/XmlSchemasPanel.cs
  D main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor/OpenStylesheetCommand.cs
  D main/src/core/MonoDevelop.Core/MonoDevelop.Core.LogReporting/LogReportingService.cs

Modified: .gitmodules
===================================================================
@@ -37,3 +37,6 @@
 [submodule "main/external/guiunit"]
 	path = main/external/guiunit
 	url = git://github.com/mono/guiunit.git
+[submodule "main/external/raygun4net"]
+	path = main/external/raygun4net
+	url = [email protected]:bratsche/raygun4net.git

Modified: main/Main.sln
===================================================================
@@ -237,6 +237,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.CSha
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GuiUnit_NET_4_0", "external\guiunit\src\framework\GuiUnit_NET_4_0.csproj", "{E13A0A7B-4DE6-43ED-A139-41052D065A9B}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mindscape.Raygun4Net", "external\raygun4net\Mindscape.Raygun4Net\Mindscape.Raygun4Net.csproj", "{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}"
+EndProject
 Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "po", "po\po.mdproj", "{AC7D119C-980B-4712-8811-5368C14412D7}"
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{5D3F7E65-E55B-45CA-A83B-D1E10040281E}"
@@ -468,6 +470,14 @@ Global
 		{459868D2-54DC-415B-B1AB-BE39BDBD352F}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
 		{459868D2-54DC-415B-B1AB-BE39BDBD352F}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
 		{459868D2-54DC-415B-B1AB-BE39BDBD352F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.DebugMac|Any CPU.Build.0 = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9}.Release|Any CPU.Build.0 = Release|Any CPU
 		{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{4CB170EF-DFE6-4A56-9E1B-A85449E827A7}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
@@ -1059,6 +1069,7 @@ Global
 		{B8897B76-1A12-4DFA-8B60-7944CC4C9654} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
 		{2D711139-8765-4929-BC7A-AA2DEE6F615D} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
 		{E13A0A7B-4DE6-43ED-A139-41052D065A9B} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
+		{495E53B3-F3AF-4C4F-BAAF-865EFAA2F4A9} = {F12939F1-D55A-4CE9-9F33-8D959BFC7D6C}
 		{92494904-35FA-4DC9-BDE9-3A3E87AC49D3} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
 		{C3887A93-B2BD-4097-8E2F-3A063EFF32FD} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}
 		{B7C1673E-5124-4BE5-8D21-EC8B12F85B6B} = {67A32B53-F719-4ECB-B5E1-FD0B04FEE258}


Added: main/external/raygun4net
===================================================================
@@ -0,0 +1 @@
+Subproject commit f22449a80d87f34b1f1469171391b27bd627017d

Modified: main/src/addins/AspNet/MonoDevelop.AspNet.Mvc/RazorEditorParserFixed/BackgroundParser.cs
===================================================================
@@ -438,7 +438,7 @@ private void WorkerLoop()
                 catch (Exception ex)
                 {
                     MonoDevelop.Core.LoggingService.LogError ("Internal error in Razor parser", ex);
-                    MonoDevelop.Core.LogReporting.LogReportingService.ReportUnhandledException (ex, false);
+                    MonoDevelop.Core.LoggingService.ReportUnhandledException (ex, false);
                 }
                 finally
                 {

Added: main/src/addins/AspNet/MonoDevelop.AspNet/MonoDevelop.AspNet/AspNetAppProject.cs
===================================================================


Added: main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor.Gui/XmlSchemasPanel.cs
===================================================================


Added: main/src/addins/MonoDevelop.XmlEditor/MonoDevelop.XmlEditor/OpenStylesheetCommand.cs
===================================================================


Modified: main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/SubviewAttachmentHandler.cs
===================================================================
@@ -29,7 +29,7 @@
 using Mono.Addins;
 using MonoDevelop.VersionControl;
 using MonoDevelop.Ide.Gui;
-using MonoDevelop.Core.LogReporting;
+using MonoDevelop.Core;
 using MonoDevelop.Projects;
 
 namespace MonoDevelop.VersionControl.Views
@@ -79,7 +79,7 @@ void HandleDocumentChanged (object sender, EventArgs e)
 				// If a user is hitting this, it will show a dialog box every time they
 				// switch to a document or open a document, so suppress the crash dialog
 				// This bug *should* be fixed already, but it's hard to tell.
-				LogReportingService.ReportUnhandledException (ex, false, true);
+				LoggingService.ReportUnhandledException (ex, false, true);
 			}
 		}
 		

Modified: main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/TargetRuntime.cs
===================================================================
@@ -388,7 +388,7 @@ void BackgroundInitialize (object state)
 				try {
 					RunInitialization ();
 				} catch (Exception ex) {
-					LogReporting.LogReportingService.ReportUnhandledException (ex, false);
+					//LogReporting.LogReportingService.ReportUnhandledException (ex, false);
 					LoggingService.LogFatalError ("Unhandled exception in SystemAssemblyService background initialisation thread.", ex);
 				} finally {
 					lock (initEventLock) {

Removed: main/src/core/MonoDevelop.Core/MonoDevelop.Core.LogReporting/LogReportingService.cs
===================================================================
@@ -1,196 +0,0 @@
-// 
-// LogReportingService.cs
-//  
-// Author:
-//       Alan McGovern <[email protected]>
-// 
-// Copyright (c) 2011 Alan McGovern
-// 
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-// 
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-// 
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.IO;
-using System.Threading;
-using System.Net;
-using System.Web;
-using System.IO.Compression;
-
-namespace MonoDevelop.Core.LogReporting
-{
-	public static class LogReportingService
-	{
-		const string ServiceVersion = "1";
-		public static readonly FilePath CrashLogDirectory = UserProfile.Current.LogDir.Combine ("LogAgent");
-		
-		const string ReportCrashesKey = "MonoDevelop.LogAgent.ReportCrashes";
-		const string ReportUsageKey = "MonoDevelop.LogAgent.ReportUsage";
-		
-		static int CrashId;
-		static int Processing;
-		
-		// Return value is the new value for 'ReportCrashes'
-		// First parameter is the current value of 'ReportCrashes
-		// Second parameter is the exception
-		// Thirdparameter shows if the exception is fatal or not
-		public static Func<bool?, Exception, bool, bool?> UnhandledErrorOccured;
-		
-		public static bool? ReportCrashes {
-			get { return PropertyService.Get<bool?> (ReportCrashesKey); }
-			set { PropertyService.Set (ReportCrashesKey, value); }
-		}
-			
-		public static bool? ReportUsage {
-			get { return PropertyService.Get<bool?> (ReportUsageKey); }
-			set { PropertyService.Set (ReportUsageKey, value); }
-		}
-		
-		public static void ReportUnhandledException (Exception ex, bool willShutDown)
-		{
-			ReportUnhandledException (ex, willShutDown, false);
-		}
-
-		static bool reporting;
-
-		public static void ReportUnhandledException (Exception ex, bool willShutDown, bool silently)
-		{
-			if (reporting)
-				return;
-			
-			reporting = true;
-			try {
-				var oldReportCrashes = ReportCrashes;
-				
-				if (UnhandledErrorOccured != null && !silently)
-					ReportCrashes = UnhandledErrorOccured (ReportCrashes, ex, willShutDown);
-				
-				// If crash reporting has been explicitly disabled, disregard this crash
-				if (ReportCrashes.HasValue && !ReportCrashes.Value)
-					return;
-				
-				byte[] data;
-				using (var stream = new MemoryStream ()) {
-					using (var writer = System.Xml.XmlWriter.Create (stream)) {
-							writer.WriteStartElement ("CrashLog");
-							writer.WriteAttributeString ("version", ServiceVersion);
-							
-							writer.WriteElementString ("SystemInformation", SystemInformation.GetTextDescription ());
-							writer.WriteElementString ("Exception", ex.ToString ());
-							
-							writer.WriteEndElement ();
-						}
-					data = stream.ToArray ();
-				}
-				
-				// Log to disk only if uploading fails.
-				var filename = string.Format ("{0}.{1}.{2}.crashlog", DateTime.UtcNow.ToString ("yyyy-MM-dd__HH-mm-ss"), SystemInformation.SessionUuid, Interlocked.Increment (ref CrashId));
-				ThreadPool.QueueUserWorkItem (delegate {
-					if (!TryUploadReport (filename, data)) {
-						if (!Directory.Exists (CrashLogDirectory))
-							Directory.CreateDirectory (CrashLogDirectory);
-
-						File.WriteAllBytes (CrashLogDirectory.Combine (filename), data);
-					}
-				});
-				
-				//ensure we don't lose the setting
-				if (ReportCrashes != oldReportCrashes) {
-					PropertyService.SaveProperties ();
-				}
-
-			} finally {
-				reporting = false;
-			}
-		}
-		
-		public static void ProcessCache ()
-		{
-			int origValue = -1;
-			try {
-				// Ensure only 1 thread at a time attempts to upload cached reports
-				origValue = Interlocked.CompareExchange (ref Processing, 1, 0);
-				if (origValue != 0)
-					return;
-				
-				// Uploading is not enabled, so bail out
-				if (!ReportCrashes.GetValueOrDefault ())
-					return;
-				
-				// Definitely no crash reports if this doesn't exist
-				if (!Directory.Exists (CrashLogDirectory))
-					return;
-				
-				foreach (var file in Directory.GetFiles (CrashLogDirectory)) {
-					if (TryUploadReport (file, File.ReadAllBytes (file)))
-						File.Delete (file);
-				}
-			} catch (Exception ex) {
-				LoggingService.LogError ("Exception processing cached crashes", ex);
-			} finally {
-				if (origValue == 0)
-					Interlocked.CompareExchange (ref Processing, 0, 1);
-			}
-		}
-
-		static bool TryUploadReport (string filename, byte[] data)
-		{
-			try {
-				// Empty files won't be accepted by the server as it thinks 'ContentLength' has not been set as it's
-				// zero. We don't need empty files anyway.
-				if (data.Length == 0)
-					return true;
-				
-				var server = Environment.GetEnvironmentVariable ("MONODEVELOP_CRASHREPORT_SERVER");
-				if (string.IsNullOrEmpty (server))
-					server = "monodevlog.xamarin.com:35162";
-
-				var request = (HttpWebRequest) WebRequest.Create (string.Format ("http://{0}/logagentreport/", server));
-				request.Headers.Add ("LogAgentVersion", ServiceVersion);
-				request.Headers.Add ("LogAgent_Filename", Path.GetFileName (filename));
-				request.Headers.Add ("Content-Encoding", "gzip");
-				request.Method = "POST";
-				
-				// Compress the data and then use the compressed length in ContentLength
-				var compressed = new MemoryStream ();
-				using (var zipper = new GZipStream (compressed, CompressionMode.Compress))
-					zipper.Write (data, 0, data.Length);
-				data = compressed.ToArray ();
-				
-				request.ContentLength = data.Length;
-				using (var requestStream = request.GetRequestStream ())
-					requestStream.Write (data, 0, data.Length);
-				
-				LoggingService.LogDebug ("CrashReport sent to server, awaiting response...");
-
-				// Ensure the server has correctly processed everything.
-				using (var response = (HttpWebResponse) request.GetResponse ()) {
-					if (response.StatusCode != HttpStatusCode.OK) {
-						LoggingService.LogError ("Server responded with status code {1} and error: {0}", response.StatusDescription, response.StatusCode);
-						return false;
-					}
-				}
-			} catch (Exception ex) {
-				LoggingService.LogError ("Failed to upload report to the server", ex);
-				return false;
-			}
-
-			LoggingService.LogDebug ("Successfully uploaded crash report");
-			return true;
-		}
-	}
-}
-

Modified: main/src/core/MonoDevelop.Core/MonoDevelop.Core.csproj
===================================================================
@@ -82,6 +82,9 @@
     </Reference>
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Web" />
+    <Reference Include="Mindscape.Raygun4Net">
+      <HintPath>..\..\..\external\Mindscape.Raygun4Net\Mindscape.Raygun4Net.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="MonoDevelop.Core.Web\Utility.cs" />
@@ -427,7 +430,6 @@
     <Compile Include="MonoDevelop.Core\UnixSystemInformation.cs" />
     <Compile Include="MonoDevelop.Core\ISystemInformationProvider.cs" />
     <Compile Include="MonoDevelop.Core.FileSystem\UnixFileSystemExtension.cs" />
-    <Compile Include="MonoDevelop.Core.LogReporting\LogReportingService.cs" />
     <Compile Include="MonoDevelop.Core.LogReporting\CrashEventArgs.cs" />
     <Compile Include="MonoDevelop.Core.LogReporting\CrashMonitor.cs" />
     <Compile Include="MonoDevelop.Core.LogReporting\ICrashMonitor.cs" />

Modified: main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs
===================================================================
@@ -29,20 +29,42 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Net;
+using System.Web;
 using System.Linq;
+using System.Diagnostics;
+using System.Threading;
+using System.IO.Compression;
+using Mindscape.Raygun4Net;
+using Mindscape.Raygun4Net.Messages;
 
 using MonoDevelop.Core.Logging;
 
 namespace MonoDevelop.Core
 {
-	
 	public static class LoggingService
 	{
+		const string ServiceVersion = "1";
+		const string ReportCrashesKey = "MonoDevelop.LogAgent.ReportCrashes";
+		const string ReportUsageKey = "MonoDevelop.LogAgent.ReportUsage";
+
+		public static readonly FilePath CrashLogDirectory = UserProfile.Current.LogDir.Combine ("LogAgent");
+
+		static RaygunClient raygunClient;
 		static List<ILogger> loggers = new List<ILogger> ();
 		static RemoteLogger remoteLogger;
 		static DateTime timestamp;
 		static TextWriter defaultError;
 		static TextWriter defaultOut;
+		static bool reporting;
+		static int CrashId;
+		static int Processing;
+
+		// Return value is the new value for 'ReportCrashes'
+		// First parameter is the current value of 'ReportCrashes
+		// Second parameter is the exception
+		// Thirdparameter shows if the exception is fatal or not
+		public static Func<bool?, Exception, bool, bool?> UnhandledErrorOccured;
 
 		static LoggingService ()
 		{
@@ -78,6 +100,11 @@ static LoggingService ()
 
 			timestamp = DateTime.Now;
 
+			string raygunKey = Environment.GetEnvironmentVariable ("MONODEVELOP_RAYGUN_KEY");
+			if (raygunKey != null) {
+				raygunClient = new RaygunClient (raygunKey);
+			}
+
 			//remove the default trace listener on .NET, it throws up horrible dialog boxes for asserts
 			System.Diagnostics.Debug.Listeners.Clear ();
 
@@ -85,6 +112,16 @@ static LoggingService ()
 			System.Diagnostics.Debug.Listeners.Add (new AssertLoggingTraceListener ());
 		}
 
+		public static bool? ReportCrashes {
+			get { return PropertyService.Get<bool?> (ReportCrashesKey); }
+			set { PropertyService.Set (ReportCrashesKey, value); }
+		}
+
+		public static bool? ReportUsage {
+			get { return PropertyService.Get<bool?> (ReportUsageKey); }
+			set { PropertyService.Set (ReportUsageKey, value); }
+		}
+
 		static string GenericLogFile {
 			get { return "Ide.log"; }
 		}
@@ -113,6 +150,148 @@ public static void Shutdown ()
 			RestoreOutputRedirection ();
 		}
 
+		public static void ReportUnhandledException (Exception ex, bool willShutDown)
+		{
+			ReportUnhandledException (ex, willShutDown, false, null);
+		}
+
+		public static void ReportUnhandledException (Exception ex, bool willShutDown, bool silently)
+		{
+			ReportUnhandledException (ex, willShutDown, silently);
+		}
+
+		public static void ReportUnhandledException (Exception ex, bool willShutDown, bool silently, string tag)
+		{
+			var tags = new List<string> { tag };
+
+			if (reporting)
+				return;
+
+			reporting = true;
+			try {
+				var oldReportCrashes = ReportCrashes;
+
+				if (UnhandledErrorOccured != null && !silently)
+					ReportCrashes = UnhandledErrorOccured (ReportCrashes, ex, willShutDown);
+
+				// If crash reporting has been explicitly disabled, disregard this crash
+				if (ReportCrashes.HasValue && !ReportCrashes.Value)
+					return;
+
+				byte[] data;
+				using (var stream = new MemoryStream ()) {
+					using (var writer = System.Xml.XmlWriter.Create (stream)) {
+						writer.WriteStartElement ("CrashLog");
+						writer.WriteAttributeString ("version", ServiceVersion);
+
+						writer.WriteElementString ("SystemInformation", SystemInformation.GetTextDescription ());
+						writer.WriteElementString ("Exception", ex.ToString ());
+
+						writer.WriteEndElement ();
+					}
+					data = stream.ToArray ();
+				}
+
+				if (raygunClient != null) {
+					raygunClient.Send (ex, tags);
+				}
+
+				// Log to disk only if uploading fails.
+				var filename = string.Format ("{0}.{1}.{2}.crashlog", DateTime.UtcNow.ToString ("yyyy-MM-dd__HH-mm-ss"), SystemInformation.SessionUuid, Interlocked.Increment (ref CrashId));
+				ThreadPool.QueueUserWorkItem (delegate {
+					if (!TryUploadReport (filename, data)) {
+						if (!Directory.Exists (CrashLogDirectory))
+							Directory.CreateDirectory (CrashLogDirectory);
+
+						File.WriteAllBytes (CrashLogDirectory.Combine (filename), data);
+					}
+				});
+
+				//ensure we don't lose the setting
+				if (ReportCrashes != oldReportCrashes) {
+					PropertyService.SaveProperties ();
+				}
+
+			} finally {
+				reporting = false;
+			}
+		}
+
+		public static void ProcessCache ()
+		{
+			int origValue = -1;
+			try {
+				// Ensure only 1 thread at a time attempts to upload cached reports
+				origValue = Interlocked.CompareExchange (ref Processing, 1, 0);
+				if (origValue != 0)
+					return;
+
+				// Uploading is not enabled, so bail out
+				if (!ReportCrashes.GetValueOrDefault ())
+					return;
+
+				// Definitely no crash reports if this doesn't exist
+				if (!Directory.Exists (CrashLogDirectory))
+					return;
+
+				foreach (var file in Directory.GetFiles (CrashLogDirectory)) {
+					if (TryUploadReport (file, File.ReadAllBytes (file)))
+						File.Delete (file);
+				}
+			} catch (Exception ex) {
+				LoggingService.LogError ("Exception processing cached crashes", ex);
+			} finally {
+				if (origValue == 0)
+					Interlocked.CompareExchange (ref Processing, 0, 1);
+			}
+		}
+
+		static bool TryUploadReport (string filename, byte[] data)
+		{
+			try {
+				// Empty files won't be accepted by the server as it thinks 'ContentLength' has not been set as it's
+				// zero. We don't need empty files anyway.
+				if (data.Length == 0)
+					return true;
+
+				var server = Environment.GetEnvironmentVariable ("MONODEVELOP_CRASHREPORT_SERVER");
+				if (string.IsNullOrEmpty (server))
+					server = "monodevlog.xamarin.com:35162";
+
+				var request = (HttpWebRequest) WebRequest.Create (string.Format ("http://{0}/logagentreport/", server));
+				request.Headers.Add ("LogAgentVersion", ServiceVersion);
+				request.Headers.Add ("LogAgent_Filename", Path.GetFileName (filename));
+				request.Headers.Add ("Content-Encoding", "gzip");
+				request.Method = "POST";
+
+				// Compress the data and then use the compressed length in ContentLength
+				var compressed = new MemoryStream ();
+				using (var zipper = new GZipStream (compressed, CompressionMode.Compress))
+					zipper.Write (data, 0, data.Length);
+				data = compressed.ToArray ();
+
+				request.ContentLength = data.Length;
+				using (var requestStream = request.GetRequestStream ())
+					requestStream.Write (data, 0, data.Length);
+
+				LoggingService.LogDebug ("CrashReport sent to server, awaiting response...");
+
+				// Ensure the server has correctly processed everything.
+				using (var response = (HttpWebResponse) request.GetResponse ()) {
+					if (response.StatusCode != HttpStatusCode.OK) {
+						LoggingService.LogError ("Server responded with status code {1} and error: {0}", response.StatusDescription, response.StatusCode);
+						return false;
+					}
+				}
+			} catch (Exception ex) {
+				LoggingService.LogError ("Failed to upload report to the server", ex);
+				return false;
+			}
+
+			LoggingService.LogDebug ("Successfully uploaded crash report");
+			return true;
+		}
+
 		static void PurgeOldLogs ()
 		{
 			// Delete all logs older than a week
@@ -220,7 +399,7 @@ static void RestoreOutputRedirection ()
 				return remoteLogger;
 			}
 		}
-		
+
 #region the core service
 		
 		public static bool IsLevelEnabled (LogLevel level)
@@ -295,7 +474,7 @@ public static void LogFatalError (string message)
 		{
 			Log (LogLevel.Fatal, message);
 		}
-		
+
 #endregion
 		
 #region convenience methods (string messageFormat, params object[] args)
@@ -314,12 +493,17 @@ public static void LogWarning (string messageFormat, params object[] args)
 		{
 			Log (LogLevel.Warn, string.Format (messageFormat, args));
 		}
-		
-		public static void LogError (string messageFormat, params object[] args)
+
+		public static void LogUserError (string messageFormat, params object[] args)
 		{
 			Log (LogLevel.Error, string.Format (messageFormat, args));
 		}
 		
+		public static void LogError (string messageFormat, params object[] args)
+		{
+			LogUserError (messageFormat, args);
+		}
+
 		public static void LogFatalError (string messageFormat, params object[] args)
 		{
 			Log (LogLevel.Fatal, string.Format (messageFormat, args));
@@ -346,12 +530,29 @@ public static void LogWarning (string message, Exception ex)
 		
 		public static void LogError (string message, Exception ex)
 		{
+			LogUserError (message, ex);
+		}
+
+		public static void LogUserError (string message, Exception ex)
+		{
 			Log (LogLevel.Error, message + (ex != null? System.Environment.NewLine + ex.ToString () : string.Empty));
 		}
-		
+
+		public static void LogInternalError (Exception ex)
+		{
+			ReportUnhandledException (ex, false, false, "internal");
+		}
+
+		public static void LogCriticalError (string message, Exception ex)
+		{
+			ReportUnhandledException (ex, true, false, "critical");
+		}
+
 		public static void LogFatalError (string message, Exception ex)
 		{
 			Log (LogLevel.Fatal, message + (ex != null? System.Environment.NewLine + ex.ToString () : string.Empty));
+
+			ReportUnhandledException (ex, true, false, "fatal");
 		}
 
 #endregion

Modified: main/src/core/MonoDevelop.Core/MonoDevelop.Core/Runtime.cs
===================================================================
@@ -198,7 +198,7 @@ static void SetupInstrumentation ()
 		static void OnLoadError (object s, AddinErrorEventArgs args)
 		{
 			string msg = "Add-in error (" + args.AddinId + "): " + args.Message;
-			LogReporting.LogReportingService.ReportUnhandledException (args.Exception, false, true);
+			//LogReporting.LogReportingService.ReportUnhandledException (args.Exception, false, true);
 			LoggingService.LogError (msg, args.Exception);
 		}
 		

Modified: main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplateService.cs
===================================================================
@@ -155,7 +155,7 @@ public static void SaveTemplates ()
 			}
 			foreach (CodeTemplate template in templates) {
 				if (string.IsNullOrEmpty (template.Shortcut)) {
-					LoggingService.LogError ("CodeTemplateService: Can't save unnamed template " + template);
+					LoggingService.LogUserError ("CodeTemplateService: Can't save unnamed template " + template);
 					continue;
 				}
 				SaveTemplate (template, Path.Combine (TemplatePath, template.Shortcut + ".template.xml"));

Modified: main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/LogAgentOptionsPanel.cs
===================================================================
@@ -60,13 +60,13 @@ public LogAgentPanelWidget ()
 		{
 			global::Stetic.BinContainer.Attach (this);
 			
-			var value = LogReportingService.ReportCrashes;
+			var value = LoggingService.ReportCrashes;
 			chkCrash = new CheckButton (GettextCatalog.GetString ("Automatically submit error diagnostic information"));
 			if (value.HasValue)
 				chkCrash.Active = value.Value;
 			chkCrash.Toggled += (sender, e) => reportCrash = chkCrash.Active;
 			
-			value = LogReportingService.ReportUsage;
+			value = LoggingService.ReportUsage;
 			chkUsage = new CheckButton (GettextCatalog.GetString ("Automatically submit usage information"));
 			if (value.HasValue)
 				chkUsage.Active = value.Value;
@@ -83,9 +83,9 @@ public LogAgentPanelWidget ()
 		public void Store ()
 		{
 			if (reportCrash.HasValue)
-				LogReportingService.ReportCrashes = reportCrash.Value;
+				LoggingService.ReportCrashes = reportCrash.Value;
 			if (reportUsage.HasValue)
-				LogReportingService.ReportUsage = reportUsage.Value;
+				LoggingService.ReportUsage = reportUsage.Value;
 		}
 	}
 }

Modified: main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
===================================================================
@@ -123,7 +123,7 @@ int Run (MonoDevelopOptions options)
 			EndPoint ep = null;
 			
 			DispatchService.Initialize ();
-			
+
 			// Set a synchronization context for the main gtk thread
 			SynchronizationContext.SetSynchronizationContext (new GtkSynchronizationContext ());
 			
@@ -505,7 +505,7 @@ void HandleException (Exception ex, bool willShutdown)
 			LoggingService.LogError (string.Format ("An unhandled exception has occured. Terminating MonoDevelop? {0}", willShutdown), ex);
 			
 			// Pass it off to the reporting service now.
-			LogReportingService.ReportUnhandledException (ex, willShutdown);
+			LoggingService.ReportUnhandledException (ex, willShutdown);
 		}
 		
 		/// <summary>SDBM-style hash, bounded to a range of 1000.</summary>

Modified: main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/LogReportingStartup.cs
===================================================================
@@ -43,11 +43,11 @@ protected override void Run ()
 		{
 			System.Threading.ThreadPool.QueueUserWorkItem (delegate {
 				// Process cached crash reports if there are any and uploading is enabled
-				LogReportingService.ProcessCache ();
+				LoggingService.ProcessCache ();
 			});
 			
 			// Attach a handler for when exceptions need to be processed
-			LogReportingService.UnhandledErrorOccured = (enabled, ex, willShutdown) => {
+			LoggingService.UnhandledErrorOccured = (enabled, ex, willShutdown) => {
 				var doNotSend = new AlertButton (GettextCatalog.GetString ("Do _Not Send"));
 				var sendOnce = new AlertButton (GettextCatalog.GetString ("_Send This Time"));
 				var alwaysSend = new AlertButton (GettextCatalog.GetString ("_Always Send"));


_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.