internal HealthCheckRuleResult createHealthCheckRuleResult( JobTarget jobTarget, string entityType, string entityName, long entityID, HealthCheckRuleDescription hcrd) { HealthCheckRuleResult healthCheckRuleResult = new HealthCheckRuleResult(); healthCheckRuleResult.Controller = jobTarget.Controller; healthCheckRuleResult.Application = jobTarget.Application; healthCheckRuleResult.ApplicationID = jobTarget.ApplicationID; healthCheckRuleResult.EntityType = entityType; healthCheckRuleResult.EntityName = entityName; healthCheckRuleResult.EntityID = entityID; healthCheckRuleResult.Category = hcrd.Category; healthCheckRuleResult.Code = hcrd.Code; healthCheckRuleResult.Name = hcrd.Name; healthCheckRuleResult.Grade = 0; healthCheckRuleResult.EvaluationTime = DateTime.Now; return(healthCheckRuleResult); }
private HealthCheckRuleResult evaluate_Controller_Setting_Performance_Profile( HealthCheckRuleDescription hcrd, JobTarget jobTarget, Dictionary <string, HealthCheckSettingMapping> healthCheckSettingsDictionary, List <ControllerSetting> controllerSettingsList) { logger.Trace("Evaluating {0}", hcrd); HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "Controller", jobTarget.Controller, 0, hcrd); healthCheckRuleResult.Application = "[ALL APPS]"; if (controllerSettingsList != null) { ControllerSetting controllerSettingProfile = controllerSettingsList.Where(s => s.Name == "performance.profile").FirstOrDefault(); if (controllerSettingProfile == null) { healthCheckRuleResult.Grade = 1; healthCheckRuleResult.Description = "Controller performance profile is unknown"; } else { healthCheckRuleResult.Description = String.Format("Controller performance profile is '{0}'", controllerSettingProfile.Value); // Defined in Enterprise Console via various // C:\AppDynamics\Platform\platform-admin\archives\controller\4.5.4.15417\playbooks\controller-<size>.groovy switch (controllerSettingProfile.Value.ToLower()) { case "internal": case "dev": case "demo": healthCheckRuleResult.Grade = 1; break; case "small": healthCheckRuleResult.Grade = 2; break; case "medium": healthCheckRuleResult.Grade = 3; break; case "large": healthCheckRuleResult.Grade = 4; break; case "extra-large": healthCheckRuleResult.Grade = 5; break; default: healthCheckRuleResult.Grade = 1; break; } } } return(healthCheckRuleResult); }
/// <summary> /// Version of Controller should be reasonably latest /// </summary> /// <param name="jobTarget"></param> /// <param name="healthCheckSettingsDictionary"></param> /// <param name="controllerSummariesList"></param> /// <returns></returns> private HealthCheckRuleResult evaluate_Controller_Version( HealthCheckRuleDescription hcrd, JobTarget jobTarget, Dictionary <string, HealthCheckSettingMapping> healthCheckSettingsDictionary, List <ControllerSummary> controllerSummariesList) { logger.Trace("Evaluating {0}", hcrd); HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "Controller", jobTarget.Controller, 0, hcrd); healthCheckRuleResult.Application = "[ALL APPS]"; if (controllerSummariesList != null && controllerSummariesList.Count > 0) { ControllerSummary controllerSummary = controllerSummariesList[0]; Version versionThisController = new Version(jobTarget.ControllerVersion); healthCheckRuleResult.Description = String.Format("The Controller version '{0}'", jobTarget.ControllerVersion, getVersionSetting(healthCheckSettingsDictionary, "ControllerVersionGrade5", "4.5")); if (versionThisController >= getVersionSetting(healthCheckSettingsDictionary, "ControllerVersionGrade5", "4.5")) { healthCheckRuleResult.Grade = 5; } else if (versionThisController >= getVersionSetting(healthCheckSettingsDictionary, "ControllerVersionGrade4", "4.4")) { healthCheckRuleResult.Grade = 4; } else if (versionThisController >= getVersionSetting(healthCheckSettingsDictionary, "ControllerVersionGrade3", "4.3")) { healthCheckRuleResult.Grade = 3; } else if (versionThisController >= getVersionSetting(healthCheckSettingsDictionary, "ControllerVersionGrade2", "4.2")) { healthCheckRuleResult.Grade = 2; } else { healthCheckRuleResult.Grade = 1; } } else { healthCheckRuleResult.Grade = 1; healthCheckRuleResult.Description = "No information about Controller version available"; } return(healthCheckRuleResult); }
/// <summary> /// We like SaaS controllers more than on premises /// </summary> /// <param name="jobTarget"></param> /// <param name="healthCheckSettingsDictionary"></param> /// <returns></returns> private HealthCheckRuleResult evaluate_Controller_SaaS_OnPrem( HealthCheckRuleDescription hcrd, JobTarget jobTarget, Dictionary <string, HealthCheckSettingMapping> healthCheckSettingsDictionary) { logger.Trace("Evaluating {0}", hcrd); HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "Controller", jobTarget.Controller, 0, hcrd); healthCheckRuleResult.Application = "[ALL APPS]"; if (jobTarget.Controller.ToLower().Contains("saas.appdynamics") == true) { healthCheckRuleResult.Grade = 5; healthCheckRuleResult.Description = "Controller is running in AppDynamics SaaS cloud"; } else { healthCheckRuleResult.Grade = 3; healthCheckRuleResult.Description = "Controller is running in OnPremises configuration"; } return(healthCheckRuleResult); }
public override bool Execute(ProgramOptions programOptions, JobConfiguration jobConfiguration) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); StepTiming stepTimingFunction = new StepTiming(); stepTimingFunction.JobFileName = programOptions.OutputJobFilePath; stepTimingFunction.StepName = jobConfiguration.Status.ToString(); stepTimingFunction.StepID = (int)jobConfiguration.Status; stepTimingFunction.StartTime = DateTime.Now; stepTimingFunction.NumEntities = jobConfiguration.Target.Count; this.DisplayJobStepStartingStatus(jobConfiguration); FilePathMap = new FilePathMap(programOptions, jobConfiguration); if (this.ShouldExecute(programOptions, jobConfiguration) == false) { return(true); } try { loggerConsole.Info("Prepare APM Health Check Report File"); #region Prepare the report package // Prepare package ExcelPackage excelReport = new ExcelPackage(); excelReport.Workbook.Properties.Author = String.Format("AppDynamics DEXTER {0}", Assembly.GetEntryAssembly().GetName().Version); excelReport.Workbook.Properties.Title = "AppDynamics DEXTER APM Health Check Report"; excelReport.Workbook.Properties.Subject = programOptions.JobName; excelReport.Workbook.Properties.Comments = String.Format("Targets={0}\nFrom={1:o}\nTo={2:o}", jobConfiguration.Target.Count, jobConfiguration.Input.TimeRange.From, jobConfiguration.Input.TimeRange.To); #endregion #region Parameters sheet // Parameters sheet ExcelWorksheet sheet = excelReport.Workbook.Worksheets.Add(SHEET_PARAMETERS); var hyperLinkStyle = sheet.Workbook.Styles.CreateNamedStyle("HyperLinkStyle"); hyperLinkStyle.Style.Font.UnderLineType = ExcelUnderLineType.Single; hyperLinkStyle.Style.Font.Color.SetColor(colorBlueForHyperlinks); var timelineStyle = sheet.Workbook.Styles.CreateNamedStyle("TimelineStyle"); timelineStyle.Style.Font.Name = "Consolas"; timelineStyle.Style.Font.Size = 8; fillReportParametersSheet(sheet, jobConfiguration, "AppDynamics DEXTER APM Health Check Report"); #endregion #region TOC sheet // Navigation sheet with link to other sheets sheet = excelReport.Workbook.Worksheets.Add(SHEET_TOC); #endregion #region Entity sheets and their associated pivot // Entity sheets sheet = excelReport.Workbook.Worksheets.Add(SHEET_CONTROLLERS_LIST); sheet.Cells[1, 1].Value = "Table of Contents"; sheet.Cells[1, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_TOC); sheet.Cells[1, 2].StyleName = "HyperLinkStyle"; sheet.View.FreezePanes(LIST_SHEET_START_TABLE_AT + 1, 1); sheet = excelReport.Workbook.Worksheets.Add(SHEET_APPLICATIONS_ALL_LIST); sheet.Cells[1, 1].Value = "Table of Contents"; sheet.Cells[1, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_TOC); sheet.Cells[1, 2].StyleName = "HyperLinkStyle"; sheet.View.FreezePanes(LIST_SHEET_START_TABLE_AT + 1, 1); sheet = excelReport.Workbook.Worksheets.Add(SHEET_HEALTH_CHECK_RULE_RESULTS); sheet.Cells[1, 1].Value = "Table of Contents"; sheet.Cells[1, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_TOC); sheet.Cells[1, 2].StyleName = "HyperLinkStyle"; sheet.Cells[2, 1].Value = "See Rating"; sheet.Cells[2, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_HEALTH_CHECK_RULE_RESULTS_DISPLAY); sheet.Cells[2, 2].StyleName = "HyperLinkStyle"; sheet.Cells[3, 1].Value = "See Summary"; sheet.Cells[3, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_HEALTH_CHECK_RULE_RESULTS_DISPLAY); sheet.Cells[3, 2].StyleName = "HyperLinkStyle"; sheet.View.FreezePanes(LIST_SHEET_START_TABLE_AT + 1, 1); sheet = excelReport.Workbook.Worksheets.Add(SHEET_HEALTH_CHECK_RULE_RESULTS_DESCRIPTION_PIVOT); sheet.Cells[1, 1].Value = "Table of Contents"; sheet.Cells[1, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_TOC); sheet.Cells[1, 2].StyleName = "HyperLinkStyle"; sheet.Cells[2, 1].Value = "See Table"; sheet.Cells[2, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_HEALTH_CHECK_RULE_RESULTS); sheet.Cells[2, 2].StyleName = "HyperLinkStyle"; sheet.View.FreezePanes(PIVOT_SHEET_START_PIVOT_AT - 4 + 2, 1); sheet = excelReport.Workbook.Worksheets.Add(SHEET_HEALTH_CHECK_RULE_RESULTS_DISPLAY); sheet.Cells[1, 1].Value = "Table of Contents"; sheet.Cells[1, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_TOC); sheet.Cells[1, 2].StyleName = "HyperLinkStyle"; sheet.Cells[2, 1].Value = "See Table"; sheet.Cells[2, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_HEALTH_CHECK_RULE_RESULTS); sheet.Cells[2, 2].StyleName = "HyperLinkStyle"; sheet.View.FreezePanes(LIST_SHEET_START_TABLE_AT + 1, 1); #endregion #region Report file variables ExcelRangeBase range = null; ExcelTable table = null; #endregion loggerConsole.Info("Fill APM Health Check Report File"); #region Controllers loggerConsole.Info("List of Controllers"); sheet = excelReport.Workbook.Worksheets[SHEET_CONTROLLERS_LIST]; EPPlusCSVHelper.ReadCSVFileIntoExcelRange(FilePathMap.ControllerSummaryReportFilePath(), 0, typeof(ControllerSummary), sheet, LIST_SHEET_START_TABLE_AT, 1); #endregion #region Applications loggerConsole.Info("List of Applications - All"); sheet = excelReport.Workbook.Worksheets[SHEET_APPLICATIONS_ALL_LIST]; EPPlusCSVHelper.ReadCSVFileIntoExcelRange(FilePathMap.ControllerApplicationsReportFilePath(), 0, typeof(ControllerApplication), sheet, LIST_SHEET_START_TABLE_AT, 1); #endregion #region Health Check Results loggerConsole.Info("List of Health Check Results"); sheet = excelReport.Workbook.Worksheets[SHEET_HEALTH_CHECK_RULE_RESULTS]; EPPlusCSVHelper.ReadCSVFileIntoExcelRange(FilePathMap.APMHealthCheckRuleResultsReportFilePath(), 0, typeof(HealthCheckRuleResult), sheet, LIST_SHEET_START_TABLE_AT, 1); if (sheet.Dimension.Rows > LIST_SHEET_START_TABLE_AT) { EPPlusCSVHelper.ReadCSVFileIntoExcelRange(FilePathMap.ControllerHealthCheckRuleResultsReportFilePath(), 1, typeof(HealthCheckRuleResult), sheet, sheet.Dimension.Rows + 1, 1); } else { EPPlusCSVHelper.ReadCSVFileIntoExcelRange(FilePathMap.ControllerHealthCheckRuleResultsReportFilePath(), 0, typeof(HealthCheckRuleResult), sheet, LIST_SHEET_START_TABLE_AT, 1); } #endregion loggerConsole.Info("Finalize APM Health Check Report File"); #region Controllers sheet // Make table sheet = excelReport.Workbook.Worksheets[SHEET_CONTROLLERS_LIST]; logger.Info("{0} Sheet ({1} rows)", sheet.Name, sheet.Dimension.Rows); loggerConsole.Info("{0} Sheet ({1} rows)", sheet.Name, sheet.Dimension.Rows); if (sheet.Dimension.Rows > LIST_SHEET_START_TABLE_AT) { range = sheet.Cells[LIST_SHEET_START_TABLE_AT, 1, sheet.Dimension.Rows, sheet.Dimension.Columns]; table = sheet.Tables.Add(range, TABLE_CONTROLLERS); table.ShowHeader = true; table.TableStyle = TableStyles.Medium2; table.ShowFilter = true; table.ShowTotal = false; sheet.Column(table.Columns["Controller"].Position + 1).Width = 25; sheet.Column(table.Columns["Version"].Position + 1).Width = 15; } #endregion #region Applications // Make table sheet = excelReport.Workbook.Worksheets[SHEET_APPLICATIONS_ALL_LIST]; logger.Info("{0} Sheet ({1} rows)", sheet.Name, sheet.Dimension.Rows); loggerConsole.Info("{0} Sheet ({1} rows)", sheet.Name, sheet.Dimension.Rows); if (sheet.Dimension.Rows > LIST_SHEET_START_TABLE_AT) { range = sheet.Cells[LIST_SHEET_START_TABLE_AT, 1, sheet.Dimension.Rows, sheet.Dimension.Columns]; table = sheet.Tables.Add(range, TABLE_APPLICATIONS_ALL); table.ShowHeader = true; table.TableStyle = TableStyles.Medium2; table.ShowFilter = true; table.ShowTotal = false; sheet.Column(table.Columns["Controller"].Position + 1).Width = 15; sheet.Column(table.Columns["ApplicationName"].Position + 1).Width = 20; sheet.Column(table.Columns["Description"].Position + 1).Width = 15; sheet.Column(table.Columns["CreatedBy"].Position + 1).Width = 15; sheet.Column(table.Columns["UpdatedBy"].Position + 1).Width = 15; sheet.Column(table.Columns["CreatedOn"].Position + 1).Width = 20; sheet.Column(table.Columns["UpdatedOn"].Position + 1).Width = 20; sheet.Column(table.Columns["CreatedOnUtc"].Position + 1).Width = 20; sheet.Column(table.Columns["UpdatedOnUtc"].Position + 1).Width = 20; } #endregion #region Health Check Results // Make table sheet = excelReport.Workbook.Worksheets[SHEET_HEALTH_CHECK_RULE_RESULTS]; logger.Info("{0} Sheet ({1} rows)", sheet.Name, sheet.Dimension.Rows); loggerConsole.Info("{0} Sheet ({1} rows)", sheet.Name, sheet.Dimension.Rows); if (sheet.Dimension.Rows > LIST_SHEET_START_TABLE_AT) { range = sheet.Cells[LIST_SHEET_START_TABLE_AT, 1, sheet.Dimension.Rows, sheet.Dimension.Columns]; table = sheet.Tables.Add(range, TABLE_HEALTH_CHECK_RULE_RESULTS); table.ShowHeader = true; table.TableStyle = TableStyles.Medium2; table.ShowFilter = true; table.ShowTotal = false; sheet.Column(table.Columns["Controller"].Position + 1).Width = 15; sheet.Column(table.Columns["Application"].Position + 1).Width = 20; sheet.Column(table.Columns["EntityName"].Position + 1).Width = 20; sheet.Column(table.Columns["Category"].Position + 1).Width = 30; sheet.Column(table.Columns["Code"].Position + 1).Width = 15; sheet.Column(table.Columns["Name"].Position + 1).Width = 50; sheet.Column(table.Columns["Description"].Position + 1).Width = 40; ExcelAddress cfAddressGrade = new ExcelAddress(LIST_SHEET_START_TABLE_AT + 1, table.Columns["Grade"].Position + 1, sheet.Dimension.Rows, table.Columns["Grade"].Position + 1); var cfGrade = sheet.ConditionalFormatting.AddThreeColorScale(cfAddressGrade); cfGrade.LowValue.Type = eExcelConditionalFormattingValueObjectType.Num; cfGrade.LowValue.Color = colorRedFor3ColorScales; cfGrade.LowValue.Value = 1; cfGrade.MiddleValue.Type = eExcelConditionalFormattingValueObjectType.Num; cfGrade.MiddleValue.Value = 3; cfGrade.MiddleValue.Color = colorYellowFor3ColorScales; cfGrade.HighValue.Type = eExcelConditionalFormattingValueObjectType.Num; cfGrade.HighValue.Color = colorGreenFor3ColorScales; cfGrade.HighValue.Value = 5; sheet = excelReport.Workbook.Worksheets[SHEET_HEALTH_CHECK_RULE_RESULTS_DESCRIPTION_PIVOT]; ExcelPivotTable pivot = sheet.PivotTables.Add(sheet.Cells[PIVOT_SHEET_START_PIVOT_AT - 4, 1], range, PIVOT_HEALTH_CHECK_RULE_RESULTS_DESCRIPTION_TYPE); setDefaultPivotTableSettings(pivot); addRowFieldToPivot(pivot, "Controller"); addRowFieldToPivot(pivot, "Application"); addRowFieldToPivot(pivot, "Category"); addRowFieldToPivot(pivot, "EntityType"); addRowFieldToPivot(pivot, "Name"); addRowFieldToPivot(pivot, "Description"); addColumnFieldToPivot(pivot, "Grade", eSortType.Ascending); addDataFieldToPivot(pivot, "Name", DataFieldFunctions.Count, "Rating"); sheet.Column(1).Width = 20; sheet.Column(2).Width = 20; sheet.Column(3).Width = 20; sheet.Column(4).Width = 20; sheet.Column(5).Width = 30; sheet.Column(6).Width = 30; } #endregion #region Health Check Results Display sheet = excelReport.Workbook.Worksheets[SHEET_HEALTH_CHECK_RULE_RESULTS_DISPLAY]; List <HealthCheckRuleResult> healthCheckRuleResults = new List <HealthCheckRuleResult>(); List <HealthCheckRuleResult> healthCheckRuleResultsController = FileIOHelper.ReadListFromCSVFile(FilePathMap.ControllerHealthCheckRuleResultsReportFilePath(), new HealthCheckRuleResultReportMap()); if (healthCheckRuleResultsController != null) { healthCheckRuleResults.AddRange(healthCheckRuleResultsController); } List <HealthCheckRuleResult> healthCheckRuleResultsAPM = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMHealthCheckRuleResultsReportFilePath(), new HealthCheckRuleResultReportMap()); if (healthCheckRuleResultsAPM != null) { healthCheckRuleResults.AddRange(healthCheckRuleResultsAPM); } if (healthCheckRuleResults != null) { #region Output summary of Applications by Category table // Make this following table out of the list of health rule evaluations // Controller | Application | Category1 | Category2 | Category 3 // ------------------------------------------------------------- // CntrVal | AppName | Avg(Grade)| Avg(Grade)| Avg(Grade) // To do this, we measure number of rows (Controller/Application pairs) and Columns (Category values), and build a table int numRows = healthCheckRuleResults.Select(h => String.Format("{0}/{1}", h.Controller, h.Application)).Distinct().Count(); int numColumns = healthCheckRuleResults.Select(h => h.Category).Distinct().Count(); Dictionary <string, int> categoryTableRowsLookup = new Dictionary <string, int>(numRows); Dictionary <string, int> categoryTableColumnsLookup = new Dictionary <string, int>(numColumns); List <HealthCheckRuleResult>[,] categoryTableValues = new List <HealthCheckRuleResult> [numRows, numColumns]; foreach (HealthCheckRuleResult healthCheckRuleResult in healthCheckRuleResults) { int rowIndex = 0; int columnIndex = 0; string rowIndexValue = String.Format("{0}/{1}", healthCheckRuleResult.Controller, healthCheckRuleResult.Application); string columnIndexValue = healthCheckRuleResult.Category; if (categoryTableRowsLookup.ContainsKey(rowIndexValue) == true) { rowIndex = categoryTableRowsLookup[rowIndexValue]; } else { rowIndex = categoryTableRowsLookup.Count; categoryTableRowsLookup.Add(rowIndexValue, rowIndex); } if (categoryTableColumnsLookup.ContainsKey(columnIndexValue) == true) { columnIndex = categoryTableColumnsLookup[columnIndexValue]; } else { columnIndex = categoryTableColumnsLookup.Count; categoryTableColumnsLookup.Add(columnIndexValue, columnIndex); } // Fill in the cell List <HealthCheckRuleResult> healthCheckRuleResultsInCell = categoryTableValues[rowIndex, columnIndex]; if (healthCheckRuleResultsInCell == null) { healthCheckRuleResultsInCell = new List <HealthCheckRuleResult>(); categoryTableValues[rowIndex, columnIndex] = healthCheckRuleResultsInCell; } healthCheckRuleResultsInCell.Add(healthCheckRuleResult); } // Output headers int rowTableStart = 4; int gradeColumnStart = 4; int fromRow = rowTableStart; int fromColumn = gradeColumnStart; sheet.Cells[fromRow, 1].Value = "Controller"; sheet.Cells[fromRow, 2].Value = "Application"; sheet.Cells[fromRow, 3].Value = "ApplicationID"; foreach (KeyValuePair <string, int> categoriesKVP in categoryTableColumnsLookup) { sheet.Cells[fromRow, fromColumn].Value = categoriesKVP.Key; sheet.Cells[fromRow - 1, fromColumn].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<See Details>"")", String.Format(SHEET_HEALTH_CHECK_RULE_CATEGORY_RESULTS_DISPLAY, categoriesKVP.Key)); sheet.Cells[fromRow - 1, fromColumn].StyleName = "HyperLinkStyle"; fromColumn++; } fromRow++; // Output table for (int rowIndex = 0; rowIndex < numRows; rowIndex++) { for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) { List <HealthCheckRuleResult> healthCheckRuleResultsInCell = categoryTableValues[rowIndex, columnIndex]; if (healthCheckRuleResultsInCell != null && healthCheckRuleResultsInCell.Count > 0) { double gradeAverage = Math.Round((double)healthCheckRuleResultsInCell.Sum(h => h.Grade) / healthCheckRuleResultsInCell.Count, 1); sheet.Cells[fromRow + rowIndex, gradeColumnStart + columnIndex].Value = gradeAverage; sheet.Cells[fromRow + rowIndex, 1].Value = healthCheckRuleResultsInCell[0].Controller; sheet.Cells[fromRow + rowIndex, 2].Value = healthCheckRuleResultsInCell[0].Application; sheet.Cells[fromRow + rowIndex, 3].Value = healthCheckRuleResultsInCell[0].ApplicationID; } else { sheet.Cells[fromRow + rowIndex, gradeColumnStart + columnIndex].Value = "-"; } } } fromRow = fromRow + numRows; // Insert the table range = sheet.Cells[4, 1, 4 + numRows, 3 + numColumns]; table = sheet.Tables.Add(range, TABLE_HEALTH_CHECK_RULE_APPLICATIONS); table.ShowHeader = true; table.TableStyle = TableStyles.None; table.TableStyle = TableStyles.Medium2; table.ShowFilter = true; table.ShowTotal = false; // Resize the columns sheet.Column(table.Columns["Controller"].Position + 1).Width = 20; sheet.Column(table.Columns["Application"].Position + 1).Width = 25; for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) { sheet.Column(gradeColumnStart + columnIndex).Width = 15; // Make the header column cells wrap text for Categories headings sheet.Cells[rowTableStart, gradeColumnStart + columnIndex].Style.WrapText = true; } // Make header row taller sheet.Row(rowTableStart).Height = 40; if (sheet.Dimension.Rows > rowTableStart) { // Color code it ExcelAddress cfGradeNum = new ExcelAddress(LIST_SHEET_START_TABLE_AT + 1, 4, sheet.Dimension.Rows, 4 + numColumns); var cfGrade = sheet.ConditionalFormatting.AddThreeColorScale(cfGradeNum); cfGrade.LowValue.Type = eExcelConditionalFormattingValueObjectType.Num; cfGrade.LowValue.Color = colorRedFor3ColorScales; cfGrade.LowValue.Value = 1; cfGrade.MiddleValue.Type = eExcelConditionalFormattingValueObjectType.Num; cfGrade.MiddleValue.Value = 3; cfGrade.MiddleValue.Color = colorYellowFor3ColorScales; cfGrade.HighValue.Type = eExcelConditionalFormattingValueObjectType.Num; cfGrade.HighValue.Color = colorGreenFor3ColorScales; cfGrade.HighValue.Value = 5; } #endregion #region Output individual categories on separate sheets // Get list of categories for which we'll be making things List <string> listOfCategories = healthCheckRuleResults.Select(h => h.Category).Distinct().ToList <string>(); foreach (string category in listOfCategories) { sheet = excelReport.Workbook.Worksheets.Add(String.Format(SHEET_HEALTH_CHECK_RULE_CATEGORY_RESULTS_DISPLAY, category)); sheet.Cells[1, 1].Value = "Table of Contents"; sheet.Cells[1, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_TOC); sheet.Cells[1, 2].StyleName = "HyperLinkStyle"; sheet.Cells[2, 1].Value = "See Table"; sheet.Cells[2, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_HEALTH_CHECK_RULE_RESULTS); sheet.Cells[2, 2].StyleName = "HyperLinkStyle"; sheet.Cells[3, 1].Value = "See Display"; sheet.Cells[3, 2].Formula = String.Format(@"=HYPERLINK(""#'{0}'!A1"", ""<Go>"")", SHEET_HEALTH_CHECK_RULE_RESULTS_DISPLAY); sheet.Cells[3, 2].StyleName = "HyperLinkStyle"; sheet.View.FreezePanes(LIST_SHEET_START_TABLE_AT + 1, 1); // Make this following table out of the list of health rule evaluations // Controller | Application | EntityType | EntityName | Rule 1 | Rule 2 | Rule 3 // ----------------------------------------------------------------------------- // CntrVal | AppName | APMApp | AppName | Grade | Grade | Grade (with comment of value) // To do this, we measure number of rows (Controller/Application/EntityType/EntityName quads) and Columns (Rules within Category), and build a table numRows = healthCheckRuleResults.Where(h => h.Category == category).Select(h => String.Format("{0}/{1}/{2}/{3}", h.Controller, h.Application, h.EntityType, h.EntityName)).Distinct().Count(); numColumns = healthCheckRuleResults.Where(h => h.Category == category).Select(h => h.Name).Distinct().Count(); Dictionary <string, int> nameTableRowsLookup = new Dictionary <string, int>(numRows); Dictionary <string, int> nameTableColumnsLookup = new Dictionary <string, int>(numColumns); List <HealthCheckRuleResult>[,] nameTableValues = new List <HealthCheckRuleResult> [numRows, numColumns]; foreach (HealthCheckRuleResult healthCheckRuleResult in healthCheckRuleResults) { // Only process the rules with the desired category if (healthCheckRuleResult.Category != category) { continue; } int rowIndex = 0; int columnIndex = 0; string rowIndexValue = String.Format("{0}/{1}/{2}/{3}", healthCheckRuleResult.Controller, healthCheckRuleResult.Application, healthCheckRuleResult.EntityType, healthCheckRuleResult.EntityName); string columnIndexValue = healthCheckRuleResult.Name; if (nameTableRowsLookup.ContainsKey(rowIndexValue) == true) { rowIndex = nameTableRowsLookup[rowIndexValue]; } else { rowIndex = nameTableRowsLookup.Count; nameTableRowsLookup.Add(rowIndexValue, rowIndex); } if (nameTableColumnsLookup.ContainsKey(columnIndexValue) == true) { columnIndex = nameTableColumnsLookup[columnIndexValue]; } else { columnIndex = nameTableColumnsLookup.Count; nameTableColumnsLookup.Add(columnIndexValue, columnIndex); } // Fill in the cell List <HealthCheckRuleResult> healthCheckRuleResultsInCell = nameTableValues[rowIndex, columnIndex]; if (healthCheckRuleResultsInCell == null) { healthCheckRuleResultsInCell = new List <HealthCheckRuleResult>(); nameTableValues[rowIndex, columnIndex] = healthCheckRuleResultsInCell; } healthCheckRuleResultsInCell.Add(healthCheckRuleResult); } // Output headers rowTableStart = 4; gradeColumnStart = 6; fromRow = rowTableStart; fromColumn = gradeColumnStart; sheet.Cells[fromRow, 1].Value = "Controller"; sheet.Cells[fromRow, 2].Value = "Application"; sheet.Cells[fromRow, 3].Value = "ApplicationID"; sheet.Cells[fromRow, 4].Value = "EntityType"; sheet.Cells[fromRow, 5].Value = "EntityName"; foreach (KeyValuePair <string, int> namesKVP in nameTableColumnsLookup) { sheet.Cells[fromRow, fromColumn].Value = namesKVP.Key; fromColumn++; } fromRow++; // Output table for (int rowIndex = 0; rowIndex < numRows; rowIndex++) { for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) { List <HealthCheckRuleResult> healthCheckRuleResultsInCell = nameTableValues[rowIndex, columnIndex]; if (healthCheckRuleResultsInCell != null && healthCheckRuleResultsInCell.Count > 0) { double gradeAverage = Math.Round((double)healthCheckRuleResultsInCell.Sum(h => h.Grade) / healthCheckRuleResultsInCell.Count, 1); sheet.Cells[fromRow + rowIndex, gradeColumnStart + columnIndex].Value = gradeAverage; sheet.Cells[fromRow + rowIndex, 1].Value = healthCheckRuleResultsInCell[0].Controller; sheet.Cells[fromRow + rowIndex, 2].Value = healthCheckRuleResultsInCell[0].Application; sheet.Cells[fromRow + rowIndex, 3].Value = healthCheckRuleResultsInCell[0].ApplicationID; sheet.Cells[fromRow + rowIndex, 4].Value = healthCheckRuleResultsInCell[0].EntityType; sheet.Cells[fromRow + rowIndex, 5].Value = healthCheckRuleResultsInCell[0].EntityName; StringBuilder sb = new StringBuilder(healthCheckRuleResultsInCell.Count * 128); for (int k = 0; k < healthCheckRuleResultsInCell.Count; k++) { HealthCheckRuleResult healthCheckRuleResult = healthCheckRuleResultsInCell[k]; sb.AppendFormat("{0}: {1}\n", k + 1, wordWrapString(healthCheckRuleResult.Description, 100)); } // Limit the size of the comment generated to ~2K of text because I think the Excel barfs when the comments are too long. if (sb.Length > 2500) { sb.Length = 2547; sb.Append("..."); } // Excessive comments in the workbook lead to poor use experience. Need to rethink and refactor this ExcelComment comment = sheet.Cells[fromRow + rowIndex, gradeColumnStart + columnIndex].AddComment(sb.ToString(), healthCheckRuleResultsInCell[0].Code); comment.AutoFit = true; } else { sheet.Cells[fromRow + rowIndex, gradeColumnStart + columnIndex].Value = "-"; } } } fromRow = fromRow + numRows; // Insert the table range = sheet.Cells[4, 1, 4 + numRows, 5 + numColumns]; table = sheet.Tables.Add(range, getExcelTableOrSheetSafeString(String.Format(TABLE_HEALTH_CHECK_RULE_CATEGORY_RESULTS, category))); table.ShowHeader = true; table.TableStyle = TableStyles.None; table.TableStyle = TableStyles.Medium2; table.ShowFilter = true; table.ShowTotal = false; // Resize the columns sheet.Column(table.Columns["Controller"].Position + 1).Width = 20; sheet.Column(table.Columns["Application"].Position + 1).Width = 25; sheet.Column(table.Columns["EntityName"].Position + 1).Width = 25; sheet.Column(table.Columns["EntityType"].Position + 1).Width = 25; for (int columnIndex = 0; columnIndex < numColumns; columnIndex++) { sheet.Column(gradeColumnStart + columnIndex).Width = 15; // Make the header column cells wrap text for Categories headings sheet.Cells[rowTableStart, gradeColumnStart + columnIndex].Style.WrapText = true; } // Make header row taller sheet.Row(rowTableStart).Height = 50; if (sheet.Dimension.Rows > rowTableStart) { // Color code it ExcelAddress cfGradeNum = new ExcelAddress(LIST_SHEET_START_TABLE_AT + 1, 5, sheet.Dimension.Rows, 5 + numColumns); var cfGrade = sheet.ConditionalFormatting.AddThreeColorScale(cfGradeNum); cfGrade.LowValue.Type = eExcelConditionalFormattingValueObjectType.Num; cfGrade.LowValue.Color = colorRedFor3ColorScales; cfGrade.LowValue.Value = 1; cfGrade.MiddleValue.Type = eExcelConditionalFormattingValueObjectType.Num; cfGrade.MiddleValue.Value = 3; cfGrade.MiddleValue.Color = colorYellowFor3ColorScales; cfGrade.HighValue.Type = eExcelConditionalFormattingValueObjectType.Num; cfGrade.HighValue.Color = colorGreenFor3ColorScales; cfGrade.HighValue.Value = 5; } } #endregion } #endregion #region TOC sheet // TOC sheet again sheet = excelReport.Workbook.Worksheets[SHEET_TOC]; fillTableOfContentsSheet(sheet, excelReport); #endregion #region Save file FileIOHelper.CreateFolder(FilePathMap.ReportFolderPath()); string reportFilePath = FilePathMap.HealthCheckResultsExcelReportFilePath(jobConfiguration.Input.TimeRange); logger.Info("Saving Excel report {0}", reportFilePath); loggerConsole.Info("Saving Excel report {0}", reportFilePath); try { // Save full report Excel files excelReport.SaveAs(new FileInfo(reportFilePath)); } catch (InvalidOperationException ex) { logger.Warn("Unable to save Excel file {0}", reportFilePath); logger.Warn(ex); loggerConsole.Warn("Unable to save Excel file {0}", reportFilePath); } #endregion return(true); } catch (Exception ex) { logger.Error(ex); loggerConsole.Error(ex); return(false); } finally { stopWatch.Stop(); this.DisplayJobStepEndedStatus(jobConfiguration, stopWatch); stepTimingFunction.EndTime = DateTime.Now; stepTimingFunction.Duration = stopWatch.Elapsed; stepTimingFunction.DurationMS = stopWatch.ElapsedMilliseconds; List <StepTiming> stepTimings = new List <StepTiming>(1); stepTimings.Add(stepTimingFunction); FileIOHelper.WriteListToCSVFile(stepTimings, new StepTimingReportMap(), FilePathMap.StepTimingReportFilePath(), true); } }
/// <summary> /// https://community.appdynamics.com/t5/Knowledge-Base/Controller-and-Agent-ADD-Limit-Notifications-Explanations/ta-p/23273#CONTROLLER_ASYNC_ADD_REG_LIMIT_REACHED /// </summary> /// <param name="hcrd"></param> /// <param name="jobTarget"></param> /// <param name="healthCheckSettingsDictionary"></param> /// <param name="controllerSettingsList"></param> /// <returns></returns> private List <HealthCheckRuleResult> evaluate_Controller_Setting_ADD_Limits( HealthCheckRuleDescription hcrd, JobTarget jobTarget, Dictionary <string, HealthCheckSettingMapping> healthCheckSettingsDictionary, List <ControllerSetting> controllerSettingsList) { logger.Trace("Evaluating {0}", hcrd); HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "Controller", jobTarget.Controller, 0, hcrd); healthCheckRuleResult.Application = "[ALL APPS]"; List <HealthCheckRuleResult> healthCheckRuleResults = new List <HealthCheckRuleResult>(); if (controllerSettingsList != null) { // Defined in Enterprise Console via various // C:\AppDynamics\Platform\platform-admin\archives\controller\4.5.4.15417\playbooks\controller-<size>.groovy ControllerSetting controllerSettingProfile = controllerSettingsList.Where(s => s.Name == "performance.profile").FirstOrDefault(); if (controllerSettingProfile != null) { List <ControllerSetting> controllerSettingsLimits = controllerSettingsList.Where(s => s.Name.Contains(".registration.limit")).ToList(); if (controllerSettingsLimits != null) { foreach (ControllerSetting controllerSetting in controllerSettingsLimits) { string lookupSettingName = String.Format("ControllerSetting.{0}.{1}", controllerSettingProfile.Value, controllerSetting.Name); int settingCurrentValue = -1; int settingDefaultValue = -1; int settingRecommendedValue = -1; if (Int32.TryParse(controllerSetting.Value, out settingCurrentValue) == true) { HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone(); healthCheckRuleResult1.Name = String.Format("{0} ({1})", healthCheckRuleResult.Name, controllerSetting.Name); healthCheckRuleResult1.Grade = -1; // All settings are taken // from C:\AppDynamics\Platform\platform-admin\archives\controller\4.5.4.15417\playbooks\controller-<size>.groovy in EC // And from careful review of significant number of controllers switch (controllerSetting.Name) { case "application.custom.metric.registration.limit": case "application.metric.registration.limit": case "async.thread.tracking.registration.limit": case "metric.registration.limit": case "sep.ADD.registration.limit": case "stacktrace.ADD.registration.limit": case "error.registration.limit": // maxStacktracePerAccountLimit = 4000 // maxSepPerAccountLimit = 4000 // maxErrorsPerAccountLimit = 4000 settingRecommendedValue = getIntegerSetting(healthCheckSettingsDictionary, lookupSettingName, -1); if (settingRecommendedValue != -1) { if (settingCurrentValue == settingRecommendedValue) { healthCheckRuleResult1.Grade = 5; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', at recommended value", controllerSetting.Name, settingCurrentValue); } else if (settingCurrentValue < settingRecommendedValue) { healthCheckRuleResult1.Grade = 3; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (<) less than recommended value '{2}'", controllerSetting.Name, settingCurrentValue, settingRecommendedValue); } else if (settingCurrentValue > settingRecommendedValue) { healthCheckRuleResult1.Grade = 5; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (>) greater than recommended value '{2}'", controllerSetting.Name, settingCurrentValue, settingRecommendedValue); } } break; case "collections.ADD.registration.limit": // maxCollectionsPerAccountLimit = 4000 settingDefaultValue = getIntegerSetting(healthCheckSettingsDictionary, lookupSettingName, 4000); if (settingCurrentValue == settingDefaultValue) { healthCheckRuleResult1.Grade = 3; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', at default value", controllerSetting.Name, settingCurrentValue); } else if (settingCurrentValue < settingDefaultValue) { healthCheckRuleResult1.Grade = 2; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (<) less than default value '{2}'", controllerSetting.Name, settingCurrentValue, settingDefaultValue); } else if (settingCurrentValue > settingDefaultValue) { healthCheckRuleResult1.Grade = 5; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (>) greater than default value '{2}'", controllerSetting.Name, settingCurrentValue, settingDefaultValue); } break; case "tracked.object.ADD.registration.limit": // maxTrackedObjectAccountLimit = 4000 settingDefaultValue = getIntegerSetting(healthCheckSettingsDictionary, lookupSettingName, 4000); if (settingCurrentValue == settingDefaultValue) { healthCheckRuleResult1.Grade = 3; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', at default value", controllerSetting.Name, settingCurrentValue); } else if (settingCurrentValue < settingDefaultValue) { healthCheckRuleResult1.Grade = 2; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (<) less than default value '{2}'", controllerSetting.Name, settingCurrentValue, settingDefaultValue); } else if (settingCurrentValue > settingDefaultValue) { healthCheckRuleResult1.Grade = 5; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (>) greater than default value '{2}'", controllerSetting.Name, settingCurrentValue, settingDefaultValue); } break; case "memory.ADD.registration.limit": // maxMemoryPointsPerAccountLimit = 4000 settingDefaultValue = getIntegerSetting(healthCheckSettingsDictionary, lookupSettingName, 4000); if (settingCurrentValue == settingDefaultValue) { healthCheckRuleResult1.Grade = 3; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', at default value", controllerSetting.Name, settingCurrentValue); } else if (settingCurrentValue < settingDefaultValue) { healthCheckRuleResult1.Grade = 2; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (<) less than default value '{2}'", controllerSetting.Name, settingCurrentValue, settingDefaultValue); } else if (settingCurrentValue > settingDefaultValue) { healthCheckRuleResult1.Grade = 5; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (>) greater than default value '{2}'", controllerSetting.Name, settingCurrentValue, settingDefaultValue); } break; case "backend.registration.limit": // maxBackendsPerAccountLimit = 100000 settingDefaultValue = getIntegerSetting(healthCheckSettingsDictionary, lookupSettingName, 10000); if (settingCurrentValue == settingDefaultValue) { healthCheckRuleResult1.Grade = 3; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', at default value", controllerSetting.Name, settingCurrentValue); } else if (settingCurrentValue < settingDefaultValue) { healthCheckRuleResult1.Grade = 2; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (<) less than default value '{2}'", controllerSetting.Name, settingCurrentValue, settingDefaultValue); } else if (settingCurrentValue > settingDefaultValue) { healthCheckRuleResult1.Grade = 5; healthCheckRuleResult1.Description = String.Format("Controller setting '{0}'='{1}', (>) greater than default value '{2}'", controllerSetting.Name, settingCurrentValue, settingDefaultValue); } break; case "controller.metric.registration.limit": // Don't know what this one means default: break; } if (healthCheckRuleResult1.Grade != -1) { healthCheckRuleResults.Add(healthCheckRuleResult1); } } } } } } return(healthCheckRuleResults); }
/// <summary> /// https://community.appdynamics.com/t5/Knowledge-Base/Why-am-I-receiving-the-error-quot-Controller-Metric-Data-Buffer/ta-p/14653 /// https://community.appdynamics.com/t5/Knowledge-Base/Why-are-snapshots-missing-in-the-Controller/ta-p/19047 /// </summary> /// <param name="hcrd"></param> /// <param name="jobTarget"></param> /// <param name="healthCheckSettingsDictionary"></param> /// <param name="controllerSettingsList"></param> /// <returns></returns> private List <HealthCheckRuleResult> evaluate_Controller_Setting_Buffer_Sizes( HealthCheckRuleDescription hcrd, JobTarget jobTarget, Dictionary <string, HealthCheckSettingMapping> healthCheckSettingsDictionary, List <ControllerSetting> controllerSettingsList) { logger.Trace("Evaluating {0}", hcrd); HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "Controller", jobTarget.Controller, 0, hcrd); healthCheckRuleResult.Application = "[ALL APPS]"; List <HealthCheckRuleResult> healthCheckRuleResults = new List <HealthCheckRuleResult>(); if (controllerSettingsList != null) { // Defined in Enterprise Console via various // C:\AppDynamics\Platform\platform-admin\archives\controller\4.5.4.15417\playbooks\controller-<size>.groovy ControllerSetting controllerSettingProfile = controllerSettingsList.Where(s => s.Name == "performance.profile").FirstOrDefault(); if (controllerSettingProfile != null) { List <ControllerSetting> controllerSettingsBuffers = controllerSettingsList.Where(s => s.Name.Contains(".buffer.size")).ToList(); if (controllerSettingsBuffers != null) { foreach (ControllerSetting controllerSetting in controllerSettingsBuffers) { // Dealing with only these: // events.buffer.size // metrics.buffer.size // process.snapshots.buffer.size // snapshots.buffer.size string lookupSettingName = String.Format("ControllerSetting.{0}.{1}", controllerSettingProfile.Value, controllerSetting.Name); int settingCurrentValue = -1; Int32.TryParse(controllerSetting.Value, out settingCurrentValue); int settingDefaultValue = getIntegerSetting(healthCheckSettingsDictionary, lookupSettingName, -1); if (settingDefaultValue != -1 && settingCurrentValue != -1) { HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone(); healthCheckRuleResult1.Name = String.Format("{0} ({1})", healthCheckRuleResult.Name, controllerSetting.Name); if (settingCurrentValue == settingDefaultValue) { healthCheckRuleResult1.Grade = 5; healthCheckRuleResult1.Description = String.Format("Controller performance profile is '{0}', setting '{1}'='{2}', at default value", controllerSettingProfile.Value, controllerSetting.Name, settingCurrentValue); } else if (settingCurrentValue < settingDefaultValue) { healthCheckRuleResult1.Grade = 3; healthCheckRuleResult1.Description = String.Format("Controller performance profile is '{0}', setting '{1}'='{2}', (<) less than default value '{3}'", controllerSettingProfile.Value, controllerSetting.Name, settingCurrentValue, settingDefaultValue); } else if (settingCurrentValue > settingDefaultValue) { healthCheckRuleResult1.Grade = 4; healthCheckRuleResult1.Description = String.Format("Controller performance profile is '{0}', setting '{1}'='{2}', (>) greater than default value '{3}'", controllerSettingProfile.Value, controllerSetting.Name, settingCurrentValue, settingDefaultValue); } healthCheckRuleResults.Add(healthCheckRuleResult1); } } } } } return(healthCheckRuleResults); }