예제 #1
0
        public async Task CalculateSimilarity(DumpMetainfo dumpA, bool force, DateTime timeFrom)
        {
            try {
                var swTotal = new Stopwatch();
                swTotal.Start();
                var resultA = await dumpRepo.GetResult(dumpA.BundleId, dumpA.DumpId);

                if (resultA == null)
                {
                    return;                                  // no results found. do nothing.
                }
                var allDumps = dumpRepo.GetAll().Where(x => x.Created >= timeFrom).OrderBy(x => x.Created);
                Console.WriteLine($"starting CalculateSimilarity for {allDumps.Count()} dumps; {dumpA} (TID:{Thread.CurrentThread.ManagedThreadId})");

                int i  = allDumps.Count();
                var sw = new Stopwatch();
                foreach (var dumpB in allDumps)
                {
                    i--;
                    sw.Start();
                    if (!force)
                    {
                        if (await relationShipRepo.GetRelationShip(dumpA.Id, dumpB.Id) != 0)
                        {
                            continue;                                                                                          // relationship already exists. skip!
                        }
                    }

                    if (!PreSelectOnMetadata(dumpA, dumpB))
                    {
                        continue;
                    }
                    var resultB = await dumpRepo.GetResult(dumpB.BundleId, dumpB.DumpId);

                    if (resultB == null)
                    {
                        continue;
                    }
                    if (!PreSelectOnResults(resultA, resultB))
                    {
                        continue;
                    }

                    CrashSimilarity crashSimilarity = CrashSimilarity.Calculate(resultA, resultB);

                    // only store value if above a certain threshold to avoid unnecessary disk writes
                    if (crashSimilarity.OverallSimilarity > 0.2)
                    {
                        await relationShipRepo.UpdateSimilarity(dumpA.Id, dumpB.Id, crashSimilarity);
                    }
                    sw.Stop();
                    //Console.WriteLine($"CalculateSimilarity.Finished for {dumpA}/{dumpB} ({i} to go...); (elapsed: {sw.Elapsed}) (TID:{Thread.CurrentThread.ManagedThreadId})");
                    sw.Reset();
                }
                swTotal.Stop();
                Console.WriteLine($"CalculateSimilarity.Finished for all {allDumps.Count()} dumps (total elapsed: {swTotal.Elapsed}); {dumpA} (TID:{Thread.CurrentThread.ManagedThreadId})");
            } catch (Exception e) {
                Console.WriteLine(e.Message);
            }
        }
예제 #2
0
        public async Task <DumpMiniInfo> GetOrCreateMiniInfo(DumpIdentifier id)
        {
            if (dumpRepo.MiniInfoExists(id))
            {
                try {
                    var loadedMiniInfo = await dumpRepo.GetMiniInfo(id);

                    if (loadedMiniInfo.DumpSimilarityInfoVersion == CrashSimilarity.MiniInfoVersion)
                    {
                        return(loadedMiniInfo);
                    }
                } catch {
                    Console.WriteLine($"could not load miniinfo for {id}. will re-create it.");
                }
            }

            // no mini-info exists yet, or version is outdated. re-create.
            var result = await dumpRepo.GetResult(id);

            var miniInfo =
                (result == null)
                                ? new DumpMiniInfo() // just store an empty mini-info if result is null
                                : CrashSimilarity.SDResultToMiniInfo(result);
            await dumpRepo.StoreMiniInfo(id, miniInfo);

            return(miniInfo);
        }
예제 #3
0
        public async Task PublishFaultReport(DumpMetainfo dumpInfo)
        {
            var result = await dumpRepository.GetResult(dumpInfo.Id);

            var faultReport = FaultReportCreator.CreateFaultReport(result);
            var bundleInfo  = bundleRepository.Get(dumpInfo.BundleId);

            if (bundleInfo.CustomProperties.ContainsKey("sourceId"))
            {
                faultReport.SourceId = bundleRepository.Get(dumpInfo.BundleId).CustomProperties["sourceId"];
            }
            await faultReportSender.SendFaultReport(dumpInfo, faultReport);
        }
예제 #4
0
        public async Task PushAllResultsAsync(bool clean)
        {
            if (elasticClient == null)
            {
                throw new InvalidOperationException("ElasticSearch has not been initialized! Please verify that the settings specify a correct elastic search host.");
            }

            if (clean)
            {
                DeleteIndex();
                CreateIndex();
            }
            IEnumerable <string> documentIds = GetAllDocumentIds();

            int nErrorsLogged = 0;
            var bundles       = bundleRepo.GetAll();

            if (bundles == null)
            {
                throw new InvalidOperationException("Bundle repository must be populated before pushing data into ES.");
            }
            // Note that this ES push can be improved significantly by using bulk operations to create the documents
            foreach (BundleMetainfo bundle in bundles)
            {
                var dumps = dumpRepo.Get(bundle.BundleId);
                if (dumps == null)
                {
                    continue;
                }
                foreach (DumpMetainfo dump in dumps)
                {
                    if (documentIds.Contains(bundle.BundleId + "/" + dump.DumpId))
                    {
                        continue;
                    }
                    SDResult result = await dumpRepo.GetResult(bundle.BundleId, dump.DumpId);

                    if (result != null)
                    {
                        bool success = await PushResultAsync(result, bundle, dump);

                        if (!success && nErrorsLogged < 20)
                        {
                            Console.WriteLine($"Failed to create document for {dump.BundleId}/{dump.DumpId}");
                            nErrorsLogged++;
                        }
                    }
                }
            }
        }
예제 #5
0
        public async Task Analyze(DumpMetainfo dumpInfo, string dumpFilePath, string analysisWorkingDir)
        {
            try {
                dumpRepo.SetDumpStatus(dumpInfo.BundleId, dumpInfo.DumpId, DumpStatus.Analyzing);

                if (dumpInfo.DumpType == DumpType.WindowsDump)
                {
                    await AnalyzeWindows(dumpInfo, new DirectoryInfo(analysisWorkingDir), dumpFilePath);
                }
                else if (dumpInfo.DumpType == DumpType.LinuxCoreDump)
                {
                    await LinuxAnalyzationAsync(dumpInfo, new DirectoryInfo(analysisWorkingDir), dumpFilePath);
                }
                else
                {
                    throw new Exception("unknown dumptype. here be dragons");
                }
                dumpRepo.SetDumpStatus(dumpInfo.BundleId, dumpInfo.DumpId, DumpStatus.Finished);

                // Re-fetch dump info as it was updated
                dumpInfo = dumpRepo.Get(dumpInfo.BundleId, dumpInfo.DumpId);

                SDResult result = await dumpRepo.GetResult(dumpInfo.BundleId, dumpInfo.DumpId);

                if (result != null)
                {
                    var bundle = bundleRepo.Get(dumpInfo.BundleId);
                    await elasticSearch.PushResultAsync(result, bundle, dumpInfo);
                }
            } catch (Exception e) {
                Console.WriteLine(e.Message);
                dumpRepo.SetDumpStatus(dumpInfo.BundleId, dumpInfo.DumpId, DumpStatus.Failed, e.ToString());
            } finally {
                if (settings.Value.DeleteDumpAfterAnalysis)
                {
                    dumpStorage.DeleteDumpFile(dumpInfo.BundleId, dumpInfo.DumpId);
                }
                await notifications.NotifyDumpAnalysisFinished(dumpInfo);

                similarityService.ScheduleSimilarityAnalysis(dumpInfo, false, DateTime.Now - TimeSpan.FromDays(90));                 // last 90 days.
            }
        }
예제 #6
0
        public async Task Analyze(DumpMetainfo dumpInfo, string dumpFilePath, string analysisWorkingDir)
        {
            try {
                dumpRepo.SetDumpStatus(dumpInfo.BundleId, dumpInfo.DumpId, DumpStatus.Analyzing);

                if (dumpInfo.DumpType == DumpType.WindowsDump)
                {
                    await AnalyzeWindows(dumpInfo, new DirectoryInfo(analysisWorkingDir), dumpFilePath);
                }
                else if (dumpInfo.DumpType == DumpType.LinuxCoreDump)
                {
                    await LinuxAnalyzationAsync(dumpInfo, new DirectoryInfo(analysisWorkingDir), dumpFilePath);
                }
                else
                {
                    throw new Exception("unknown dumptype. here be dragons");
                }
                dumpRepo.SetDumpStatus(dumpInfo.BundleId, dumpInfo.DumpId, DumpStatus.Finished);

                SDResult result = dumpRepo.GetResult(dumpInfo.BundleId, dumpInfo.DumpId, out string err);
                if (result != null)
                {
                    var bundle = bundleRepo.Get(dumpInfo.BundleId);
                    await elasticSearch.PushResultAsync(result, bundle, dumpInfo);
                }
            } catch (Exception e) {
                Console.WriteLine(e.Message);
                dumpRepo.SetDumpStatus(dumpInfo.BundleId, dumpInfo.DumpId, DumpStatus.Failed, e.ToString());
            } finally {
                if (settings.Value.DeleteDumpAfterAnalysis)
                {
                    dumpStorage.DeleteDumpFile(dumpInfo.BundleId, dumpInfo.DumpId);
                }
                await notifications.NotifyDumpAnalysisFinished(dumpInfo);
            }
        }
예제 #7
0
 public SDResult GetResult(string bundleId, string dumpId, out string error)
 {
     return(dumpRepo.GetResult(bundleId, dumpId, out error));
 }
예제 #8
0
        public async Task <string> GetMessage(DumpMetainfo dumpInfo)
        {
            var model = new SlackMessageViewModel();

            var res = dumpRepo.GetResult(dumpInfo.BundleId, dumpInfo.DumpId, out string error);

            var engine = new EngineFactory().ForEmbeddedResources(typeof(SlackMessageViewModel));

            model.TopProperties.Add(dumpInfo.DumpType == DumpType.WindowsDump ? "Windows" : "Linux");
            model.DumpFilename = Path.GetFileName(dumpInfo.DumpFileName);
            model.Url          = $"{superDumpUrl}/Home/Report?bundleId={dumpInfo.BundleId}&dumpId={dumpInfo.DumpId}";
            if (res != null)
            {
                model.TopProperties.Add(res.SystemContext.ProcessArchitecture);

                if (res.IsManagedProcess)
                {
                    model.TopProperties.Add(".NET");
                }
                if (res.SystemContext.Modules.Any(x => x.FileName.Contains("jvm.dll")))
                {
                    model.TopProperties.Add("Java");
                }
                if (res.SystemContext.Modules.Any(x => x.FileName.Contains("jvm.so")))
                {
                    model.TopProperties.Add("Java");
                }
                if (res.SystemContext.Modules.Any(x => x.FileName.Contains("iiscore.dll")))
                {
                    model.TopProperties.Add("IIS");
                }
                if (res.SystemContext.Modules.Any(x => x.FileName.Contains("nginx.so")))
                {
                    model.TopProperties.Add("NGINX");
                }
                if (res.SystemContext.Modules.Any(x => x.FileName.Contains("httpd/modules")))
                {
                    model.TopProperties.Add("Apache");
                }
                if (res.SystemContext.Modules.Any(x => x.FileName.Contains("node.exe")))
                {
                    model.TopProperties.Add("Node.js");
                }

                var agentModules = res.SystemContext.Modules.Where(x => x.Tags.Any(t => t.Equals(SDTag.DynatraceAgentTag))).Select(m => m.ToString());
                model.AgentModules = agentModules.ToList();

                model.NumManagedExceptions = res.ThreadInformation.Count(x => x.Value.Tags.Any(t => t.Equals(SDTag.ManagedExceptionTag)));
                model.NumNativeExceptions  = res.ThreadInformation.Count(x => x.Value.Tags.Any(t => t.Equals(SDTag.NativeExceptionTag)));
                model.NumAssertErrors      = res.ThreadInformation.Count(x => x.Value.Tags.Any(t => t.Equals(SDTag.AssertionErrorTag)));

                SDThread       managedExceptionThread = res.ThreadInformation.Values.FirstOrDefault(x => x.Tags.Any(t => t.Equals(SDTag.ManagedExceptionTag)));
                SDClrException clrException           = managedExceptionThread?.LastException;
                if (clrException != null)
                {
                    model.TopException = clrException.Type;
                    model.Stacktrace   = clrException.StackTrace.ToString();
                }

                if (res.LastEvent != null && !res.LastEvent.Description.Contains("Break instruction"))                   // break instruction events are useless
                {
                    model.LastEvent = $"{res.LastEvent.Type}: {res.LastEvent.Description}";
                }
            }

            return(await engine.CompileRenderAsync("SlackMessage", model));
        }
예제 #9
0
 public SDResult GetResult(string bundleId, string dumpId)
 {
     return(dumpRepo.GetResult(bundleId, dumpId));
 }
예제 #10
0
 public async Task <SDResult> GetResult(DumpIdentifier id)
 {
     return(await dumpRepo.GetResult(id));
 }
예제 #11
0
 public async Task <SDResult> GetResult(string bundleId, string dumpId)
 {
     return(await dumpRepo.GetResult(bundleId, dumpId));
 }
예제 #12
0
        public async Task PushAllResultsAsync(bool clean)
        {
            if (elasticClient == null)
            {
                throw new InvalidOperationException("ElasticSearch has not been initialized! Please verify that the settings specify a correct elastic search host.");
            }

            await BlockIfBundleRepoNotReady("ElasticSearchService.PushAllResultsAsync");

            if (clean)
            {
                DeleteIndex();
                CreateIndex();

                // since we are clean, we can do everything in one bulk
                var dumps = dumpRepo.GetAll().OrderByDescending(x => x.Created);
                foreach (var dumpsBatch in dumps.Batch(100))
                {
                    var tasks   = dumpsBatch.Select(x => Task.Run(async() => new { res = await dumpRepo.GetResult(x.Id), bundleInfo = bundleRepo.Get(x.BundleId), dumpInfo = x }));
                    var results = (await Task.WhenAll(tasks)).Where(x => x.res != null);

                    Console.WriteLine($"pushing {results.Count()} results into elasticsearch");
                    var sdResults = results.Select(x => ElasticSDResult.FromResultOrDefault(x.res, x.bundleInfo, x.dumpInfo, pathHelper)).Where(x => x != null);
                    await PushBulk(sdResults);
                }
                return;
            }

            IEnumerable <string> documentIds = GetAllDocumentIds();

            int nErrorsLogged = 0;
            var bundles       = bundleRepo.GetAll();

            if (bundles == null)
            {
                throw new InvalidOperationException("Bundle repository must be populated before pushing data into ES.");
            }

            // In order to check if a dump has already been added, we go through them all and add one at the time
            // There is potential to optimize this and still do a bulk add.
            foreach (BundleMetainfo bundle in bundles)
            {
                var dumps = dumpRepo.Get(bundle.BundleId);
                if (dumps == null)
                {
                    continue;
                }
                foreach (DumpMetainfo dump in dumps)
                {
                    if (documentIds.Contains(bundle.BundleId + "/" + dump.DumpId))
                    {
                        continue;
                    }
                    SDResult result = await dumpRepo.GetResult(dump.Id);

                    if (result != null)
                    {
                        bool success = await PushResultAsync(result, bundle, dump);

                        if (!success && nErrorsLogged < 20)
                        {
                            Console.WriteLine($"Failed to create document for {dump.BundleId}/{dump.DumpId}");
                            nErrorsLogged++;
                        }
                    }
                }
            }
        }