private async Task <IEnumerable <AzureSupportCenterInsight> > GetInsightsFromDetector(OperationContext <TResource> context, Definition detector, List <Definition> detectorsRun) { Response response = null; detectorsRun.Add(detector); try { var fullResponse = await GetDetectorInternal(detector.Id, context); if (fullResponse != null) { response = fullResponse.Item1; } } catch (Exception ex) { DiagnosticsETWProvider.Instance.LogRuntimeHostHandledException(context.RequestId, "GetInsightsFromDetector", context.Resource.SubscriptionId, context.Resource.ResourceGroup, context.Resource.Name, ex.GetType().ToString(), ex.ToString()); } // Handle Exception or Not Found // Not found can occur if invalid detector is put in detector list if (response == null) { return(null); } List <AzureSupportCenterInsight> supportCenterInsights = new List <AzureSupportCenterInsight>(); // Take max one insight per detector, only critical or warning, pick the most critical var mostCriticalInsight = response.Insights.OrderBy(insight => insight.Status).FirstOrDefault(); //TODO: Add Logging Per Detector Here AzureSupportCenterInsight ascInsight = null; if (mostCriticalInsight != null) { ascInsight = AzureSupportCenterInsightUtilites.CreateInsight(mostCriticalInsight, context, detector); supportCenterInsights.Add(ascInsight); } DiagnosticsETWProvider.Instance.LogRuntimeHostDetectorAscInsight(context.RequestId, detector.Id, ascInsight?.ImportanceLevel.ToString()); var detectorLists = response.Dataset .Where(diagnosicData => diagnosicData.RenderingProperties.Type == RenderingType.Detector) .SelectMany(diagnosticData => ((DetectorCollectionRendering)diagnosticData.RenderingProperties).DetectorIds) .Distinct(); if (detectorLists.Any()) { var applicableDetectorMetaData = (await this.ListDetectorsInternal(context)).Where(detectorResponse => detectorLists.Contains(detectorResponse.Metadata.Id)); var detectorListResponses = await Task.WhenAll(applicableDetectorMetaData.Select(detectorResponse => GetInsightsFromDetector(context, detectorResponse.Metadata, detectorsRun))); supportCenterInsights.AddRange(detectorListResponses.Where(detectorInsights => detectorInsights != null).SelectMany(detectorInsights => detectorInsights)); } return(supportCenterInsights); }
internal static AzureSupportCenterInsight CreateInsight <TResource>(Insight insight, OperationContext <TResource> context, Definition detector) where TResource : IResource { // Logic in line before would have to be updated if we added more resource types. // TODO: May make sense to have resource type enums contain the resource type string var resourceTypeString = context.Resource.ResourceType == ResourceType.App ? "sites" : "hostingEnvironments"; var issueCategory = context.Resource.ResourceType == ResourceType.App ? "Web App" : "App Service Environment"; var applensPath = $"subscriptions/{context.Resource.SubscriptionId}/resourceGroups/{context.Resource.ResourceGroup}/providers/Microsoft.Web/{resourceTypeString}/{context.Resource.Name}/detectors/{detector.Id}?startTime={context.StartTime}&endTime={context.EndTime}"; var description = GetTextObjectFromData("description", insight.Body) ?? new Text() { IsMarkdown = false, Value = string.Format(DefaultDescription, detector.Name) }; var recommendedAction = GetTextObjectFromData("recommended action", insight.Body) ?? DefaultRecommendedAction; var customerReadyContent = GetTextObjectFromData("customer ready content", insight.Body); if (insight.Status == InsightStatus.Success || insight.Status == InsightStatus.None) { insight.Status = InsightStatus.Info; } var supportCenterInsight = new AzureSupportCenterInsight() { Id = GetDetectorGuid(detector.Id), Title = insight.Message, ImportanceLevel = (ImportanceLevel)Enum.Parse(typeof(ImportanceLevel), ((int)insight.Status).ToString()), InsightFriendlyName = insight.Message, IssueCategory = issueCategory.ToUpper(), IssueSubCategory = issueCategory, Description = description, RecommendedAction = new RecommendedAction() { Id = Guid.NewGuid(), Text = recommendedAction }, CustomerReadyContent = customerReadyContent == null ? null : new CustomerReadyContent() { ArticleId = Guid.NewGuid(), ArticleContent = customerReadyContent.Value }, AdditionalDetails = GetExtraNameValuePairs(insight.Body), ConfidenceLevel = InsightConfidenceLevel.High, Scope = InsightScope.ResourceLevel, Links = new List <Link>() { new Link() { Type = 2, Text = "Applens Link", Uri = $"https://applens.azurewebsites.net/{applensPath}" } } }; return(supportCenterInsight); }
internal static AzureSupportCenterInsight CreateDefaultInsight <TResource>(OperationContext <TResource> context, List <Definition> detectorsRun) where TResource : IResource { var description = new StringBuilder(); description.AppendLine("The following detector(s) were run but no insights were found:"); description.AppendLine(); foreach (var detector in detectorsRun) { description.AppendLine($"* {detector.Name}"); } description.AppendLine(); // TODO: Handle other resource types var resourceTypeString = context.Resource.ResourceType == ResourceType.App ? "sites" : "hostingEnvironments"; var applensPath = $"subscriptions/{context.Resource.SubscriptionId}/resourceGroups/{context.Resource.ResourceGroup}/{resourceTypeString}/{context.Resource.Name}/detectors/{detectorsRun.FirstOrDefault().Id}"; var supportCenterInsight = new AzureSupportCenterInsight() { Id = Guid.Parse(DefaultInsightGuid), Title = "No issues found in relevant detector(s) in applens", ImportanceLevel = ImportanceLevel.Info, InsightFriendlyName = "No Issue", IssueCategory = "NOISSUE", IssueSubCategory = "noissue", Description = new Text() { IsMarkdown = true, Value = description.ToString() }, RecommendedAction = new RecommendedAction() { Id = Guid.NewGuid(), Text = new Text() { IsMarkdown = false, Value = "Follow the applens link to see any other information these detectors have." } }, ConfidenceLevel = InsightConfidenceLevel.High, Scope = InsightScope.ResourceLevel, Links = new List <Link>() { new Link() { Type = 2, Text = "Applens Link", Uri = $"https://applens.azurewebsites.net/{applensPath}" } } }; return(supportCenterInsight); }
internal static AzureSupportCenterInsight CreateInsight <TResource>(string title, InsightStatus status, Text description, Text recommendedAction, Text customerReadyContent, Definition detector, OperationContext <TResource> context) where TResource : IResource { var category = detector.Name; var applensPath = $"subscriptions/{context.Resource.SubscriptionId}/resourceGroups/{context.Resource.ResourceGroup}/providers/{context.Resource.Provider}/{context.Resource.ResourceTypeName}/{context.Resource.Name}/detectors/{detector.Id}?startTime={context.StartTime}&endTime={context.EndTime}"; string customerReadyContentText = customerReadyContent?.Value; if (customerReadyContent != null && customerReadyContent.IsMarkdown) { // Turn the customer ready content into HTML since that is what is supported by ASC as of now customerReadyContentText = CommonMark.CommonMarkConverter.Convert(customerReadyContent.Value); } if (status == InsightStatus.Success || status == InsightStatus.None) { status = InsightStatus.Info; } var supportCenterInsight = new AzureSupportCenterInsight() { Id = GetDetectorGuid(title), Title = title, ImportanceLevel = (ImportanceLevel)Enum.Parse(typeof(ImportanceLevel), ((int)status).ToString()), InsightFriendlyName = category, IssueCategory = category, IssueSubCategory = category, Description = description, RecommendedAction = new RecommendedAction() { Id = Guid.NewGuid(), Text = recommendedAction }, CustomerReadyContent = customerReadyContent == null ? null : new CustomerReadyContent() { ArticleId = Guid.NewGuid(), ArticleContent = customerReadyContentText }, ConfidenceLevel = InsightConfidenceLevel.High, Scope = InsightScope.ResourceLevel, Links = new List <Link>() { new Link() { Type = 2, Text = "Applens Link", Uri = $"https://applens.azurewebsites.net/{applensPath}" } } }; return(supportCenterInsight); }
private void logAscInsight(RuntimeContext <TResource> context, Definition detector, AzureSupportCenterInsight ascInsight) { var loggingContent = new { supportTopicId = context.OperationContext.SupportTopic.Id, pesId = context.OperationContext.SupportTopic.PesId, insight = ascInsight }; DiagnosticsETWProvider.Instance.LogFullAscInsight(context.OperationContext.RequestId, detector.Id, ascInsight?.ImportanceLevel.ToString(), JsonConvert.SerializeObject(loggingContent)); }