Files
Disco/Disco.Client/ErrorReporting.cs
T
2025-07-20 15:20:22 +10:00

190 lines
6.1 KiB
C#

using Disco.Client.Extensions;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
namespace Disco.Client
{
public static class ErrorReporting
{
private const string ServicePathTemplate = "http://DISCO:9292/Services/Client/ClientError";
public static string DeviceIdentifier { get; set; }
public static string EnrolmentSessionId { get; set; }
public static void ReportError(Exception Ex, bool ReportToServer)
{
bool isClientServiceException = Ex is ClientServiceException;
ErrorReport report = new ErrorReport()
{
DeviceIdentifier = DeviceIdentifier,
SessionId = EnrolmentSessionId,
JsonException = Ex.IntenseExceptionSerialization()
};
try
{
LogToFile(report);
}
catch (Exception) { }
try
{
LogToEventLog(report);
}
catch (Exception) { }
// Don't log server errors back to the server
if (!isClientServiceException && ReportToServer)
{
try
{
LogToServer(report);
}
catch (Exception) { }
}
try
{
Presentation.WriteFatalError(Ex);
}
catch (Exception) { }
}
#region Log Actions
private static void LogToFile(ErrorReport report)
{
var logPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ErrorLog.csv");
using (var streamWriter = File.AppendText(logPath))
{
streamWriter.Write(DateTime.Now.ToString("s"));
streamWriter.Write(",");
streamWriter.Write(report.DeviceIdentifier);
streamWriter.Write(",\"");
streamWriter.Write(report.JsonException);
streamWriter.Write("\"");
streamWriter.Flush();
}
}
private static void LogToEventLog(ErrorReport report)
{
string eventSource = "Disco Client";
if (!EventLog.SourceExists(eventSource))
EventLog.CreateEventSource(eventSource, "Application");
EventLog.WriteEntry(eventSource, report.JsonException, EventLogEntryType.Error, 400);
}
private static void LogToServer(ErrorReport report)
{
string reportJson = JsonConvert.SerializeObject(report);
string reportResponse;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(ServicePathTemplate);
request.UserAgent = $"Disco-Client/{Assembly.GetExecutingAssembly().GetName().Version.ToString(3)}";
request.ContentType = "application/json";
request.Method = WebRequestMethods.Http.Post;
request.UseDefaultCredentials = true;
request.Timeout = 300000; // 5 Minutes
using (StreamWriter requestWriter = new StreamWriter(request.GetRequestStream()))
{
requestWriter.Write(reportJson);
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader responseReader = new StreamReader(response.GetResponseStream()))
{
reportResponse = responseReader.ReadToEnd();
}
}
Debug.WriteLine("Error Report Logged to Server; Response: {0}", reportResponse);
}
#endregion
public class ErrorReport
{
public string SessionId { get; set; }
public string DeviceIdentifier { get; set; }
public string JsonException { get; set; }
}
public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
{
ReportError(ex, true);
}
}
catch (Exception)
{
// Igore failure to Log Errors
}
}
#region Exception Serialization
private static string IntenseExceptionSerialization(this Exception Ex)
{
try
{
return JsonConvert.SerializeObject(Ex);
}
catch (Exception)
{
try
{
var encapsulatedEx = Ex.ToEncapsulatedException();
return JsonConvert.SerializeObject(encapsulatedEx);
}
catch (Exception)
{
try
{
var encapsulatedEx = Ex.ToEncapsulatedException(0);
return JsonConvert.SerializeObject(encapsulatedEx);
}
catch (Exception)
{
return JsonConvert.SerializeObject(Ex.Message);
}
}
}
}
private static EncapsulatedException ToEncapsulatedException(this Exception ex, int InnerRecursionDepth = 4)
{
EncapsulatedException inner = null;
if (InnerRecursionDepth > 0 && ex.InnerException != null)
inner = ex.InnerException.ToEncapsulatedException(--InnerRecursionDepth);
return new EncapsulatedException()
{
EncapsulatedType = ex.GetType().Name,
Message = ex.Message,
StackTrace = ex.StackTrace,
InnerException = inner
};
}
public class EncapsulatedException
{
public string Message { get; set; }
public string EncapsulatedType { get; set; }
public string StackTrace { get; set; }
public EncapsulatedException InnerException { get; set; }
}
#endregion
}
}