public static void LogAndReportCrash( [CanBeNull] string message, [CanBeNull] string assembly,
[CanBeNull] Exception exception, bool shutdownImminent )
{
if ( message == null )
message = "(null)";
if ( assembly == null )
assembly = "(null)";
if ( exception == null )
exception = new Exception( "(null)" );
Log( LogType.SeriousError, "{0}: {1}", message, exception );
bool submitCrashReport = ConfigKey.SubmitCrashReports.Enabled();
bool isCommon = CheckForCommonErrors( exception );
// ReSharper disable EmptyGeneralCatchClause
try {
var eventArgs = new CrashedEventArgs( message,
assembly,
exception,
submitCrashReport && !isCommon,
isCommon,
shutdownImminent );
RaiseCrashedEvent( eventArgs );
isCommon = eventArgs.IsCommonProblem;
} catch { }
// ReSharper restore EmptyGeneralCatchClause
if ( !submitCrashReport || isCommon ) {
return;
}
lock ( CrashReportLock ) {
if ( DateTime.UtcNow.Subtract( lastCrashReport ).TotalSeconds < MinCrashReportInterval ) {
Log( LogType.Warning, "Logger.SubmitCrashReport: Could not submit crash report, reports too frequent." );
return;
}
lastCrashReport = DateTime.UtcNow;
try {
StringBuilder sb = new StringBuilder();
sb.Append( "version=" ).Append( Uri.EscapeDataString( Updater.CurrentRelease.VersionString ) );
sb.Append( "&message=" ).Append( Uri.EscapeDataString( message ) );
sb.Append( "&assembly=" ).Append( Uri.EscapeDataString( assembly ) );
sb.Append( "&runtime=" );
if ( MonoCompat.IsMono ) {
sb.Append( Uri.EscapeDataString( "Mono " + MonoCompat.MonoVersionString ) );
} else {
sb.Append( Uri.EscapeDataString( "CLR " + Environment.Version ) );
}
sb.Append( "&os=" ).Append( Environment.OSVersion.Platform + " / " + Environment.OSVersion.VersionString );
sb.Append( "&exceptiontype=" ).Append( Uri.EscapeDataString( exception.GetType().ToString() ) );
sb.Append( "&exceptionmessage=" ).Append( Uri.EscapeDataString( exception.Message ) );
sb.Append( "&exceptionstacktrace=" );
if ( exception.StackTrace != null ) {
sb.Append( Uri.EscapeDataString( exception.StackTrace ) );
} else {
sb.Append( "(none)" );
}
sb.Append( "&config=" );
if ( File.Exists( Paths.ConfigFileName ) ) {
sb.Append( Uri.EscapeDataString( File.ReadAllText( Paths.ConfigFileName ) ) );
}
string assemblies = AppDomain.CurrentDomain
.GetAssemblies()
.JoinToString( Environment.NewLine, asm => asm.FullName );
sb.Append( "&asm=" ).Append( Uri.EscapeDataString( assemblies ) );
string[] lastFewLines;
lock ( LogLock ) {
lastFewLines = RecentMessages.ToArray();
}
sb.Append( "&log=" ).Append( Uri.EscapeDataString( String.Join( Environment.NewLine, lastFewLines ) ) );
byte[] formData = Encoding.UTF8.GetBytes( sb.ToString() );
HttpWebRequest request = ( HttpWebRequest )WebRequest.Create( CrashReportUri );
request.Method = "POST";
request.Timeout = 15000; // 15s timeout
request.ContentType = "application/x-www-form-urlencoded";
request.CachePolicy = new RequestCachePolicy( RequestCacheLevel.NoCacheNoStore );
request.ContentLength = formData.Length;
request.UserAgent = Updater.UserAgent;
using ( Stream requestStream = request.GetRequestStream() ) {
requestStream.Write( formData, 0, formData.Length );
requestStream.Flush();
}
string responseString;
using ( HttpWebResponse response = ( HttpWebResponse )request.GetResponse() ) {
using ( Stream responseStream = response.GetResponseStream() ) {
// ReSharper disable AssignNullToNotNullAttribute
using ( StreamReader reader = new StreamReader( responseStream ) ) {
// ReSharper restore AssignNullToNotNullAttribute
responseString = reader.ReadLine();
}
}
}
request.Abort();
if ( responseString != null && responseString.StartsWith( "ERROR" ) ) {
Log( LogType.Error, "Crash report could not be processed by 800Craft.net." );
} else {
int referenceNumber;
if ( responseString != null && Int32.TryParse( responseString, out referenceNumber ) ) {
Log( LogType.SystemActivity, "Crash report submitted (Reference #{0})", referenceNumber );
} else {
Log( LogType.SystemActivity, "Crash report submitted." );
}
}
} catch ( Exception ex ) {
Log( LogType.Warning, "Logger.SubmitCrashReport: {0}", ex );
}
}
}