Beispiel #1
0
        public static ElasticSDResult FromResult(SDResult result, BundleMetainfo bundleInfo, DumpMetainfo dumpInfo, PathHelper pathHelper)
        {
            if (result == null)
            {
                throw new ArgumentNullException("result");
            }
            var eResult = new ElasticSDResult()
            {
                BundleId                        = dumpInfo.BundleId,
                DumpId                          = dumpInfo.DumpId,
                Timestamp                       = dumpInfo.Created,
                Type                            = dumpInfo.DumpType.ToString(),
                Executable                      = (result.SystemContext as SDCDSystemContext)?.FileName ?? "",
                IsManaged                       = result.IsManagedProcess,
                ProcessArchitecture             = result.SystemContext?.ProcessArchitecture,
                SystemArchitecture              = result.SystemContext?.SystemArchitecture,
                NrThreads                       = result.ThreadInformation != null ? result.ThreadInformation.Count : 0,
                LastEventDescription            = result.LastEvent?.Description,
                LoadedModules                   = result.SystemContext?.DistinctModules().Select(m => m.FileName).Aggregate("", (m1, m2) => m1 + " " + m2),
                LoadedModulesVersioned          = result.SystemContext?.DistinctModules().Select(m => $"{m.FileName}:{m.Version ?? "-"}").Aggregate("", (m1, m2) => m1 + " " + m2),
                DynatraceLoadedModulesVersioned = result.SystemContext?.DistinctModules().Where(m => m.Tags.Contains(SDTag.DynatraceAgentTag)).Select(m => $"{m.FileName}:{m.Version ?? "-"}").Aggregate("", (m1, m2) => m1 + " " + m2),
                ExitType                        = result.LastEvent?.Type ?? ""
            };

            bundleInfo.CustomProperties.TryGetValue("ref", out string reference);
            eResult.Reference = reference;

            bundleInfo.CustomProperties.TryGetValue("tenantId", out string tenantId);
            eResult.TenantId = tenantId;

            eResult.FaultingStacktrace = result.GetErrorOrLastExecutingThread()?.ToText();
            eResult.Stacktraces        = "";      // TODO

            if (dumpInfo.Finished != null && dumpInfo.Started != null)
            {
                int durationSecs = (int)dumpInfo.Finished.Subtract(dumpInfo.Started).TotalSeconds;
                if (durationSecs > 0)
                {
                    // Only if a valid duration is present
                    eResult.AnalyzationDuration = durationSecs;
                }
            }

            long dumpSize = ComputeDumpFileSizeKb(bundleInfo, dumpInfo, pathHelper);

            if (dumpSize >= 0)
            {
                eResult.DumpSizeKb = dumpSize;
            }
            return(eResult);
        }
Beispiel #2
0
        private static double?CalculateStacktraceSimilarity(SDResult resultA, SDResult resultB)
        {
            var errorThreadA = resultA.GetErrorOrLastExecutingThread();
            var errorThreadB = resultB.GetErrorOrLastExecutingThread();

            if (errorThreadA == null && errorThreadB == null)
            {
                return(null);                                                          // no value in comparing if there are none
            }
            if (errorThreadA == null ^ errorThreadB == null)
            {
                return(0);                                                         // one result has an error thread, while the other one does not. inequal.
            }
            // approach 1: iterate over the top X stracktraces and compare each frame for similarity
            // CN -> not sure about this algorithm. there are cases where some frames differ while it's the same root cause.
            // maybe just generally looking how many frames appear in the other stack might be ok.
            //int take = 15;
            //int count = 0;
            //double methodsSimilarCount = 0;
            //double modulesSimilarCount = 0;
            //using (var iter1 = t1.StackTrace.GetEnumerator())
            //using (var iter2 = t2.StackTrace.GetEnumerator()) {
            //	// iterate while both stacktraces still have elements
            //	while (take-- > 0 && iter1.MoveNext() && iter2.MoveNext()) {
            //		count++;
            //		methodsSimilarCount += iter1.Current.MethodName.Equals(iter2.Current.MethodName, StringComparison.OrdinalIgnoreCase)
            //			? 1.0
            //			: 0.0;
            //		modulesSimilarCount += iter1.Current.ModuleName.Equals(iter2.Current.ModuleName, StringComparison.OrdinalIgnoreCase)
            //			? 1.0
            //			: 0.0;
            //	}
            //}

            // approach 2: apply "weight" to each stackframe. it should represent the relevance of the frame to the crash-reason.
            // treat all "error"-frames as 1.0. adjacent frames get linearly decreasing weight.
            // TBD


            // approach 3: let's start with a dead-simple alg. look how many frames of stack A appear in stack B and vice versa.
            int AinBCount = CountAinB(errorThreadA.StackTrace, errorThreadB.StackTrace, FrameEquals);
            int BinACount = CountAinB(errorThreadB.StackTrace, errorThreadA.StackTrace, FrameEquals);

            double ainb = AinBCount / (double)errorThreadA.StackTrace.Count;
            double bina = BinACount / (double)errorThreadB.StackTrace.Count;

            return(Math.Min(ainb, bina));
        }
Beispiel #3
0
        private static double?CalculateExceptionMessageSimilarity(SDResult resultA, SDResult resultB)
        {
            var exceptionA = resultA.GetErrorOrLastExecutingThread()?.LastException;
            var exceptionB = resultB.GetErrorOrLastExecutingThread()?.LastException;

            if (exceptionA == null && exceptionB == null)
            {
                return(null);                                                      // no value in comparing if there are none
            }
            if (exceptionA == null ^ exceptionB == null)
            {
                return(0);                                                     // one result has an error thread, while the other one does not. inequal.
            }
            return(EqualsIgnoreNonAscii(exceptionA.Type, exceptionB.Type) &&
                   EqualsIgnoreNonAscii(exceptionA.Message, exceptionB.Message)
                                ? 1.0
                                : 0.0);
            // omit comparison of StackTrace for now. maybe implement at later point if it makes sense.
        }
Beispiel #4
0
        /// <summary>
        /// Find the number of modules are the same in both stacks.
        ///
        /// returns a number between 0.0 and 1.0, where 1.0 is full similarity, and 0.0 is no similarity
        /// </summary>
        private static double?CalculateModulesInStacktraceSimilarity(SDResult resultA, SDResult resultB)
        {
            var errorThreadA = resultA.GetErrorOrLastExecutingThread();
            var errorThreadB = resultB.GetErrorOrLastExecutingThread();

            if (errorThreadA == null && errorThreadB == null)
            {
                return(null);                                                          // no value in comparing if there are none
            }
            if (errorThreadA == null ^ errorThreadB == null)
            {
                return(0);                                                         // one result has an error thread, while the other one does not. inequal.
            }
            var modulesA = errorThreadA.StackTrace.Select(x => x.ModuleName).Distinct();
            var modulesB = errorThreadB.StackTrace.Select(x => x.ModuleName).Distinct();

            int AinBCount = CountAinB(modulesA, modulesB, (a, b) => EqualsIgnoreNonAscii(a, b));
            int BinACount = CountAinB(modulesB, modulesA, (a, b) => EqualsIgnoreNonAscii(a, b));

            double ainb = AinBCount / (double)modulesA.Count();
            double bina = BinACount / (double)modulesB.Count();

            return(Math.Min(ainb, bina));
        }
        public static FaultReport CreateFaultReport(SDResult result, int maxFrames = 80)
        {
            var faultReport = new FaultReport();

            // modules & stackframes
            var faultingThread = result.GetErrorOrLastExecutingThread();

            if (faultingThread != null)
            {
                faultReport.FaultingFrames = new List <string>();

                if (faultingThread.StackTrace.Count <= maxFrames)
                {
                    foreach (var frame in faultingThread.StackTrace)
                    {
                        faultReport.FaultingFrames.Add(frame.ToString());
                    }
                }
                else
                {
                    // makes ure extra long stacktraces (stack overflows) are serialized in a human readable way
                    // add only the first X, then "...", then the last X
                    foreach (var frame in faultingThread.StackTrace.Take(maxFrames / 2))
                    {
                        faultReport.FaultingFrames.Add(frame.ToString());
                    }
                    faultReport.FaultingFrames.Add("...");
                    foreach (var frame in faultingThread.StackTrace.TakeLast(maxFrames / 2))
                    {
                        faultReport.FaultingFrames.Add(frame.ToString());
                    }
                }
            }

            var faultReasonSb = new StringBuilder();

            // lastevent
            if (result.LastEvent != null)
            {
                if (result.LastEvent.Description.StartsWith("Break instruction exception"))
                {
                    // "break instruction" as a lastevent is so generic, it's practically useless. treat it as if there was no information at all.
                }
                else
                {
                    if (!string.IsNullOrEmpty(result.LastEvent.Type))
                    {
                        faultReasonSb.Append(result.LastEvent.Type);
                    }
                    if (!string.IsNullOrEmpty(result.LastEvent.Description))
                    {
                        if (faultReasonSb.Length > 0)
                        {
                            faultReasonSb.Append(", ");
                        }
                        faultReasonSb.Append(result.LastEvent.Description);
                    }
                }
            }

            // exception
            var exception = result.GetErrorOrLastExecutingThread()?.LastException;

            if (exception != null)
            {
                if (!string.IsNullOrEmpty(exception.Type))
                {
                    if (faultReasonSb.Length > 0)
                    {
                        faultReasonSb.Append(", ");
                    }
                    faultReasonSb.Append(exception.Type);
                }
                if (!string.IsNullOrEmpty(exception.Message))
                {
                    if (faultReasonSb.Length > 0)
                    {
                        faultReasonSb.Append(", ");
                    }
                    faultReasonSb.Append(exception.Message);
                }
            }
            faultReport.FaultReason = faultReasonSb.ToString();

            return(faultReport);
        }