Esempio n. 1
0
        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);
        }
        /// <summary>
        /// Adds an ASC Insight that will be rendered as a regular insight.
        /// It will flow automatically to Azure Support Center if your detector is enabled for a support topic.
        /// </summary>
        /// <param name="res">Response object for extension method</param>
        /// <param name="title">Title of insight. This should be a constant string, without any part of it changing depending on the resource.</param>
        /// <param name="status">Status of the insight. All insight status types are available, but None and Success with be changes to Info in Azure Support Center.</param>
        /// <param name="description">The description of the insight. This should not contain anything that is instructing the reader to do anything.
        /// It should only expand on any relevant information about the insight.</param>
        /// <param name="recommendedAction">Recommended action that is specifically addressing what steps thesupport engineer should take.
        /// If you only want to have the support engineer to send the customer ready content, then that is all you would have to include here.</param>
        /// <param name="customerReadyContent">This is a response that is meant for the support engineer to paste directly into an email to the customer.
        /// It is meant to completely solve the problem, and if that is not the case you may not want to use this field, by passing a null value.
        /// Other good information to have is additional resources for the customer so that they can solve the problem in the future.</param>
        /// <param name="context">Operation context which is passed into detector run method.</param>
        /// <param name="ascOnly">Only show the insight in Azure Support Center.</param>
        /// <param name="extraNameValuePairs">Additional name value pairs that you want to display in Applens/App Service Diagnostics. These will not be added in Azure Support Center.
        /// For markdown, wrap your text in markdown tags. HTML or plain text also allowed</param>
        /// <param name="isExpanded">Whether you want to Applens/App Service Diagnostics to expand the insight initially.</param>
        /// <returns>Azure Support Center Insight Object</returns>
        /// <example>
        /// This sample shows how to use the <see cref="AddAscInsight"/> method.
        /// <code>
        /// public async static Task<![CDATA[<Response>]]> Run(DataProviders dp, OperationContext cxt, Response res)
        /// {
        ///     var descriptionMarkdown =
        ///         @"###A scale operation failed because there was already a scale operation underway. Here is the error:
        ///
        ///           ```
        ///           Operation failed because a current scale operation is ongoing.
        ///           ```";
        ///
        ///     var recommendedActionPlainText = "Copy and paste the Customer Ready Content and send to the customer";
        ///
        ///     var customerReadyActionMarkdown =
        ///         @$"Your scale operation for site ***{cxt.Resource.Name}*** failed because there was a current scale operation underway.
        ///
        ///            Please wait for the current operation to finish and then try again to scale your app service plan. ";
        ///
        ///     res.AddAscInsight(
        ///         "Failed Scale Operation Detected",
        ///         InsightStatus.Critical,
        ///         new Text(descriptionMarkdown, true),
        ///         new Text(recommendedActionPlainText),
        ///         new Text(customerReadyActionMarkdown, true),
        ///         cxt);
        /// }
        /// </code>
        /// </example>
        public static AzureSupportCenterInsight AddAscInsight <TResource>(this Response res, string title,
                                                                          InsightStatus status, Text description, Text recommendedAction, Text customerReadyContent,
                                                                          OperationContext <TResource> context, Dictionary <string, string> extraNameValuePairs = null,
                                                                          bool ascOnly = false, bool isExpanded = false)
            where TResource : IResource
        {
            var insight = AzureSupportCenterInsightUtilites.CreateInsight(title, status, description, recommendedAction, customerReadyContent, res.Metadata, context);

            res.AscInsights.Add(insight);

            // If you designate an insight as ASC only, it will not show in applens
            // If this is an external call, it will not be added as an insight that renders in the UI
            if (ascOnly || !context.IsInternalCall)
            {
                return(insight);
            }

            var nameValuePairs = new Dictionary <string, string>();

            if (description != null)
            {
                nameValuePairs.Add("Description", GetContentStringForApplens(description));
            }

            // Recommended Action is only for internal
            if (context.IsInternalCall && recommendedAction != null)
            {
                nameValuePairs.Add("Recommended Action", GetContentStringForApplens(recommendedAction));
            }

            // For consistency with ASC, we will convert Customer Ready Content to HTML on the server side,
            // so that we ensure that it renders the same in both ASC and applens
            // For external requests, we will put this content as 'Recommended Action'
            if (customerReadyContent != null)
            {
                nameValuePairs.Add(context.IsInternalCall ? "Customer Ready Content" : "Recommended Action", CommonMark.CommonMarkConverter.Convert(customerReadyContent.Value));
            }

            if (extraNameValuePairs != null)
            {
                foreach (var key in extraNameValuePairs.Keys)
                {
                    nameValuePairs.Add(key, extraNameValuePairs[key]);
                }
            }

            res.AddInsight(new Insight(status, title, nameValuePairs, isExpanded));

            return(insight);
        }
Esempio n. 3
0
        protected async Task <IActionResult> GetInsights(TResource resource, string supportTopicId, string minimumSeverity, string startTime, string endTime, string timeGrain)
        {
            if (!DateTimeHelper.PrepareStartEndTimeWithTimeGrain(startTime, endTime, timeGrain, out DateTime startTimeUtc, out DateTime endTimeUtc, out TimeSpan timeGrainTimeSpan, out string errorMessage))
            {
                return(BadRequest(errorMessage));
            }

            OperationContext <TResource> cxt = PrepareContext(resource, startTimeUtc, endTimeUtc, forceInternal: true);

            List <AzureSupportCenterInsight> insights = null;
            string            error        = null;
            List <Definition> detectorsRun = new List <Definition>();

            try
            {
                supportTopicId = ParseCorrectSupportTopicId(supportTopicId);
                var allDetectors = (await ListDetectorsInternal(cxt)).Select(detectorResponse => detectorResponse.Metadata);

                var applicableDetectors = allDetectors
                                          .Where(detector => string.IsNullOrWhiteSpace(supportTopicId) || detector.SupportTopicList.FirstOrDefault(supportTopic => supportTopic.Id == supportTopicId) != null);

                var insightGroups = await Task.WhenAll(applicableDetectors.Select(detector => GetInsightsFromDetector(cxt, detector, detectorsRun)));

                insights = insightGroups.Where(group => group != null).SelectMany(group => group).ToList();
            }
            catch (Exception ex)
            {
                error = ex.GetType().ToString();
                DiagnosticsETWProvider.Instance.LogRuntimeHostHandledException(cxt.RequestId, "GetInsights", cxt.Resource.SubscriptionId, cxt.Resource.ResourceGroup,
                                                                               cxt.Resource.Name, ex.GetType().ToString(), ex.ToString());
            }


            var correlationId = Guid.NewGuid();
            var insightInfo   = new
            {
                Total    = insights.Count,
                Critical = insights.Count(insight => insight.ImportanceLevel == ImportanceLevel.Critical),
                Warning  = insights.Count(insight => insight.ImportanceLevel == ImportanceLevel.Warning),
                Info     = insights.Count(insight => insight.ImportanceLevel == ImportanceLevel.Info),
                Default  = detectorsRun.Any() && !insights.Any() ? 1 : 0
            };

            DiagnosticsETWProvider.Instance.LogRuntimeHostInsightCorrelation(cxt.RequestId, "ControllerBase.GetInsights", cxt.Resource.SubscriptionId,
                                                                             cxt.Resource.ResourceGroup, cxt.Resource.Name, correlationId.ToString(), JsonConvert.SerializeObject(insightInfo));

            if (!insights.Any() && detectorsRun.Any())
            {
                insights.Add(AzureSupportCenterInsightUtilites.CreateDefaultInsight(cxt, detectorsRun));
            }

            var response = new AzureSupportCenterInsightEnvelope()
            {
                CorrelationId      = correlationId,
                ErrorMessage       = error,
                TotalInsightsFound = insights != null?insights.Count() : 0,
                                         Insights = insights
            };

            return(Ok(response));
        }
        private async Task <IEnumerable <AzureSupportCenterInsight> > GetInsightsFromDetector(RuntimeContext <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.OperationContext.RequestId, "GetInsightsFromDetector", context.OperationContext.Resource.SubscriptionId,
                                                                               context.OperationContext.Resource.ResourceGroup, context.OperationContext.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>();

            if (response.AscInsights.Any())
            {
                foreach (var ascInsight in response.AscInsights)
                {
                    logAscInsight(context, detector, ascInsight);
                    supportCenterInsights.Add(ascInsight);
                }
            }
            else
            {
                var regularToAscInsights = response.Insights.Select(insight => {
                    var ascInsight = AzureSupportCenterInsightUtilites.CreateInsight(insight, context.OperationContext, detector);
                    logAscInsight(context, detector, ascInsight);
                    return(ascInsight);
                });
                supportCenterInsights.AddRange(regularToAscInsights);
            }

            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);
        }