private static void SerializeTelemetryItem(ITelemetry telemetryItem, JsonWriter jsonWriter) { if (telemetryItem is EventTelemetry) { EventTelemetry eventTelemetry = telemetryItem as EventTelemetry; SerializeEventTelemetry(eventTelemetry, jsonWriter); } else if (telemetryItem is ExceptionTelemetry) { ExceptionTelemetry exceptionTelemetry = telemetryItem as ExceptionTelemetry; SerializeExceptionTelemetry(exceptionTelemetry, jsonWriter); } else if (telemetryItem is MetricTelemetry) { MetricTelemetry metricTelemetry = telemetryItem as MetricTelemetry; SerializeMetricTelemetry(metricTelemetry, jsonWriter); } else if (telemetryItem is PageViewTelemetry) { PageViewTelemetry pageViewTelemetry = telemetryItem as PageViewTelemetry; SerializePageViewTelemetry(pageViewTelemetry, jsonWriter); } else if (telemetryItem is DependencyTelemetry) { DependencyTelemetry remoteDependencyTelemetry = telemetryItem as DependencyTelemetry; SerializeDependencyTelemetry(remoteDependencyTelemetry, jsonWriter); } else if (telemetryItem is RequestTelemetry) { RequestTelemetry requestTelemetry = telemetryItem as RequestTelemetry; SerializeRequestTelemetry(requestTelemetry, jsonWriter); } else if (telemetryItem is SessionStateTelemetry) { SessionStateTelemetry sessionStateTelemetry = telemetryItem as SessionStateTelemetry; SerializeSessionStateTelemetry(sessionStateTelemetry, jsonWriter); } else if (telemetryItem is TraceTelemetry) { TraceTelemetry traceTelemetry = telemetryItem as TraceTelemetry; SerializeTraceTelemetry(traceTelemetry, jsonWriter); } else if (telemetryItem is PerformanceCounterTelemetry) { PerformanceCounterTelemetry performanceCounterTelemetry = telemetryItem as PerformanceCounterTelemetry; SerializePerformanceCounter(performanceCounterTelemetry, jsonWriter); } else if (telemetryItem is CrashTelemetry) { CrashTelemetry crashTelemetry = telemetryItem as CrashTelemetry; SerializeCrash(crashTelemetry, jsonWriter); } else { string msg = string.Format(CultureInfo.InvariantCulture, "Unknown telemtry type: {0}", telemetryItem.GetType()); CoreEventSource.Log.LogVerbose(msg); } }
/// <summary> /// Creates <see cref="CrashTelemetry"/> instance. /// </summary> /// <param name="exception">The exception to initialize the class with.</param> /// <param name="handledAt">Determines whether exception is handled or unhandled.</param> public ITelemetry CreateCrashTelemetry(Exception exception, ExceptionHandledAt handledAt) { CrashTelemetry result = new CrashTelemetry(); result.HandledAt = handledAt; result.Headers.Id = Guid.NewGuid().ToString("D"); result.Headers.CrashThreadId = Environment.CurrentManagedThreadId; result.Headers.ExceptionType = exception.GetType().FullName; result.Headers.ExceptionReason = exception.Message; CrashTelemetryThread thread = new CrashTelemetryThread { Id = Environment.CurrentManagedThreadId }; result.Threads.Add(thread); HashSet <long> seenBinaries = new HashSet <long>(); StringBuilder exceptionMessagesBuilder = new StringBuilder(); AddExceptionInformation(exception, result, seenBinaries, exceptionMessagesBuilder); bool hasNativeFrames = result.Threads != null && result.Threads.Count > 0 && result.Threads[0].Frames != null && result.Threads[0].Frames.Count > 0; if (HockeyClient.Current.AsInternal().DescriptionLoader != null) { try { result.Attachments.Description = HockeyClient.Current.AsInternal().DescriptionLoader(exception); } catch (Exception ex) { CoreEventSource.Log.LogError("An exception occured in TelemetryConfiguration.Active.DescriptionLoader callback : " + ex); } } else if (hasNativeFrames) { // If the user doesn't have a description loader, add info on all the inner exceptions. result.Attachments.Description = exceptionMessagesBuilder.ToString(); } result.StackTrace = GetStrackTrace(exception); return(result); }
/// <summary> /// Serializes the crash. /// </summary> /// <param name="telemetry">The telemetry.</param> /// <param name="writer">The writer.</param> private static void SerializeCrash(CrashTelemetry telemetry, JsonWriter writer) { writer.WriteStartObject(); telemetry.WriteTelemetryName(writer, CrashTelemetry.TelemetryName); telemetry.WriteEnvelopeProperties(writer); writer.WritePropertyName("data"); { writer.WriteStartObject(); writer.WriteProperty("baseType", telemetry.BaseType); writer.WritePropertyName("baseData"); { writer.WriteStartObject(); writer.WriteProperty("ver", telemetry.Data.ver); writer.WriteProperty("handledAt", Utils.PopulateRequiredStringValue(telemetry.Data.handledAt, "handledAt", typeof(ExceptionTelemetry).FullName)); writer.WriteProperty("stackTrace", telemetry.StackTrace); // write headers writer.WritePropertyName("headers"); { writer.WriteStartObject(); writer.WriteProperty("id", telemetry.Headers.Id); writer.WriteProperty("process", telemetry.Headers.Process); writer.WriteProperty("processId", telemetry.Headers.ProcessId); writer.WriteProperty("parentProcess", telemetry.Headers.ParentProcess); writer.WriteProperty("parentProcessId", telemetry.Headers.ParentProcessId); writer.WriteProperty("crashThread", telemetry.Headers.CrashThreadId); writer.WriteProperty("applicationPath", telemetry.Headers.ApplicationPath); writer.WriteProperty("applicationIdentifier", telemetry.Headers.ApplicationId); writer.WriteProperty("exceptionType", telemetry.Headers.ExceptionType); writer.WriteProperty("exceptionCode", telemetry.Headers.ExceptionCode); writer.WriteProperty("exceptionAddress", telemetry.Headers.ExceptionAddress); writer.WriteProperty("exceptionReason", telemetry.Headers.ExceptionReason); writer.WriteEndObject(); } // write threads writer.WritePropertyName("threads"); { writer.WriteStartArray(); JsonSerializer.SerializeCrashThreads(telemetry.Threads, writer); writer.WriteEndArray(); } // write threads writer.WritePropertyName("binaries"); { writer.WriteStartArray(); JsonSerializer.SerializeCrashBinaries(telemetry.Binaries, writer); writer.WriteEndArray(); } // write threads writer.WritePropertyName("attachments"); { writer.WriteStartObject(); writer.WriteProperty("description", telemetry.Attachments.Description); writer.WriteProperty("userName", HockeyClient.Current.AsInternal().UserID); writer.WriteProperty("userEmail", HockeyClient.Current.AsInternal().ContactInformation); writer.WriteEndObject(); } writer.WriteEndObject(); } writer.WriteEndObject(); } writer.WriteEndObject(); }
/// <summary> /// Adds frames and binaries from this exception and all inner exceptions to the given telemetry result. /// </summary> /// <param name="exception">The exception to examine.</param> /// <param name="telemetry">The telemetry object to add the frames to.</param> /// <param name="seenBinaries">The set of binaries we have already added to the frame list.</param> /// <param name="exceptionMessages">The list of exception types and messages seen.</param> /// <remarks>This will produce a flat list with no indication of which frame belongs to which exception. This is a workaround /// for the fact that the server side only knows how to process a flat list.</remarks> private static void AddExceptionInformation(Exception exception, CrashTelemetry telemetry, HashSet <long> seenBinaries, StringBuilder exceptionMessages) { if (exception.InnerException != null) { var aggregateException = exception as AggregateException; if (aggregateException != null) { foreach (Exception innerException in aggregateException.InnerExceptions) { AddExceptionInformation(innerException, telemetry, seenBinaries, exceptionMessages); } } else { AddExceptionInformation(exception.InnerException, telemetry, seenBinaries, exceptionMessages); } } exceptionMessages.AppendLine(string.Format(CultureInfo.CurrentCulture, "{0}: {1}", exception.GetType().FullName, exception.Message)); StackTrace stackTrace = new StackTrace(exception, true); var frames = stackTrace.GetFrames(); // stackTrace.GetFrames may return null (happened on Outlook Groups application). // HasNativeImage() method invoke on first frame is required to understand whether an application is compiled in native tool chain // and we can extract the frame addresses or not. if (frames != null && frames.Length > 0 && frames[0].HasNativeImage()) { foreach (StackFrame frame in stackTrace.GetFrames()) { CrashTelemetryThreadFrame crashFrame = new CrashTelemetryThreadFrame { Address = string.Format(CultureInfo.InvariantCulture, "0x{0:x16}", frame.GetNativeIP().ToInt64()) }; telemetry.Threads[0].Frames.Add(crashFrame); long nativeImageBase = frame.GetNativeImageBase().ToInt64(); if (seenBinaries.Contains(nativeImageBase) || nativeImageBase == 0) { continue; } PEImageReader reader = new PEImageReader(frame.GetNativeImageBase()); PEImageReader.CodeViewDebugData codeView = reader.Parse(); if (codeView == null) { continue; } CrashTelemetryBinary crashBinary = new CrashTelemetryBinary { StartAddress = string.Format(CultureInfo.InvariantCulture, "0x{0:x16}", nativeImageBase), EndAddress = string.Format(CultureInfo.InvariantCulture, "0x{0:x16}", codeView.EndAddress.ToInt64()), Uuid = string.Format(CultureInfo.InvariantCulture, "{0:N}-{1}", codeView.Signature, codeView.Age), Path = codeView.PdbPath, Name = string.IsNullOrEmpty(codeView.PdbPath) == false?Path.GetFileNameWithoutExtension(codeView.PdbPath) : null, CpuType = GetProcessorArchitecture() }; telemetry.Binaries.Add(crashBinary); seenBinaries.Add(nativeImageBase); } } }
/// <summary> /// Creates <see cref="CrashTelemetry"/> instance. /// </summary> /// <param name="exception">The exception to initialize the class with.</param> /// <param name="handledAt">Determines whether exception is handled or unhandled.</param> public ITelemetry CreateCrashTelemetry(Exception exception, ExceptionHandledAt handledAt) { CrashTelemetry result = new CrashTelemetry(); result.HandledAt = handledAt; result.Headers.Id = Guid.NewGuid().ToString("D"); result.Headers.CrashThreadId = Environment.CurrentManagedThreadId; result.Headers.ExceptionType = exception.GetType().FullName; result.Headers.ExceptionReason = exception.Message; var description = string.Empty; if (HockeyClient.Current.AsInternal().DescriptionLoader != null) { try { result.Attachments.Description = HockeyClient.Current.AsInternal().DescriptionLoader(exception); } catch (Exception ex) { CoreEventSource.Log.LogError("An exception occured in TelemetryConfiguration.Active.DescriptionLoader callback : " + ex); } } CrashTelemetryThread thread = new CrashTelemetryThread { Id = Environment.CurrentManagedThreadId }; result.Threads.Add(thread); HashSet <long> seenBinaries = new HashSet <long>(); StackTrace stackTrace = new StackTrace(exception, true); var frames = stackTrace.GetFrames(); // stackTrace.GetFrames may return null (happened on Outlook Groups application). // HasNativeImage() method invoke on first frame is required to understand whether an application is compiled in native tool chain // and we can extract the frame addresses or not. if (frames != null && frames.Length > 0 && frames[0].HasNativeImage()) { foreach (StackFrame frame in stackTrace.GetFrames()) { CrashTelemetryThreadFrame crashFrame = new CrashTelemetryThreadFrame { Address = string.Format(CultureInfo.InvariantCulture, "0x{0:x16}", frame.GetNativeIP().ToInt64()) }; thread.Frames.Add(crashFrame); long nativeImageBase = frame.GetNativeImageBase().ToInt64(); if (seenBinaries.Contains(nativeImageBase) == true) { continue; } PEImageReader reader = new PEImageReader(frame.GetNativeImageBase()); PEImageReader.CodeViewDebugData codeView = reader.Parse(); if (codeView == null) { continue; } CrashTelemetryBinary crashBinary = new CrashTelemetryBinary { StartAddress = string.Format(CultureInfo.InvariantCulture, "0x{0:x16}", nativeImageBase), EndAddress = string.Format(CultureInfo.InvariantCulture, "0x{0:x16}", codeView.EndAddress.ToInt64()), Uuid = string.Format(CultureInfo.InvariantCulture, "{0:N}-{1}", codeView.Signature, codeView.Age), Path = codeView.PdbPath, Name = string.IsNullOrEmpty(codeView.PdbPath) == false?Path.GetFileNameWithoutExtension(codeView.PdbPath) : null, CpuType = GetProcessorArchitecture() }; result.Binaries.Add(crashBinary); seenBinaries.Add(nativeImageBase); } } result.StackTrace = GetStrackTrace(exception); return(result); }
/// <summary> /// Creates <see cref="CrashTelemetry"/> instance. /// </summary> /// <param name="exception">The exception to initialize the class with.</param> /// <param name="handledAt">Determines whether exception is handled or unhandled.</param> public ITelemetry CreateCrashTelemetry(Exception exception, ExceptionHandledAt handledAt) { CrashTelemetry result = new CrashTelemetry(); result.HandledAt = handledAt; result.Headers.Id = Guid.NewGuid().ToString("D"); result.Headers.CrashThreadId = Environment.CurrentManagedThreadId; result.Headers.ExceptionType = exception.GetType().FullName; result.Headers.ExceptionReason = exception.Message; var description = string.Empty; if (HockeyClient.Current.AsInternal().DescriptionLoader != null) { try { result.Attachments.Description = HockeyClient.Current.AsInternal().DescriptionLoader(exception); } catch (Exception ex) { CoreEventSource.Log.LogError("An exception occured in TelemetryConfiguration.Active.DescriptionLoader callback : " + ex); } } CrashTelemetryThread thread = new CrashTelemetryThread { Id = Environment.CurrentManagedThreadId }; result.Threads.Add(thread); HashSet<long> seenBinaries = new HashSet<long>(); StackTrace stackTrace = new StackTrace(exception, true); var frames = stackTrace.GetFrames(); // stackTrace.GetFrames may return null (happened on Outlook Groups application). // HasNativeImage() method invoke on first frame is required to understand whether an application is compiled in native tool chain // and we can extract the frame addresses or not. if (frames != null && frames.Length > 0 && frames[0].HasNativeImage()) { foreach (StackFrame frame in stackTrace.GetFrames()) { CrashTelemetryThreadFrame crashFrame = new CrashTelemetryThreadFrame { Address = string.Format(CultureInfo.InvariantCulture, "0x{0:x16}", frame.GetNativeIP().ToInt64()) }; thread.Frames.Add(crashFrame); long nativeImageBase = frame.GetNativeImageBase().ToInt64(); if (seenBinaries.Contains(nativeImageBase) == true) { continue; } PEImageReader reader = new PEImageReader(frame.GetNativeImageBase()); PEImageReader.CodeViewDebugData codeView = reader.Parse(); if (codeView == null) { continue; } CrashTelemetryBinary crashBinary = new CrashTelemetryBinary { StartAddress = string.Format(CultureInfo.InvariantCulture, "0x{0:x16}", nativeImageBase), EndAddress = string.Format(CultureInfo.InvariantCulture, "0x{0:x16}", codeView.EndAddress.ToInt64()), Uuid = string.Format(CultureInfo.InvariantCulture, "{0:N}-{1}", codeView.Signature, codeView.Age), Path = codeView.PdbPath, Name = string.IsNullOrEmpty(codeView.PdbPath) == false ? Path.GetFileNameWithoutExtension(codeView.PdbPath) : null, CpuType = GetProcessorArchitecture() }; result.Binaries.Add(crashBinary); seenBinaries.Add(nativeImageBase); } } result.StackTrace = GetStrackTrace(exception); return result; }