diff --git a/AppDynamics.Dexter.Core.csproj b/AppDynamics.Dexter.Core.csproj
index aaaa7d2..00fbd5f 100644
--- a/AppDynamics.Dexter.Core.csproj
+++ b/AppDynamics.Dexter.Core.csproj
@@ -52,18 +52,18 @@
-
+
-
-
-
-
+
+
+
+
-
+
@@ -72,6 +72,30 @@
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ Always
+
+
+ Always
+
Always
diff --git a/ChromeDriver/78/linux64/chromedriver b/ChromeDriver/78/linux64/chromedriver
index 95965a8..eeecd35 100644
Binary files a/ChromeDriver/78/linux64/chromedriver and b/ChromeDriver/78/linux64/chromedriver differ
diff --git a/ChromeDriver/78/mac64/chromedriver b/ChromeDriver/78/mac64/chromedriver
index 0840731..4ff3bcc 100644
Binary files a/ChromeDriver/78/mac64/chromedriver and b/ChromeDriver/78/mac64/chromedriver differ
diff --git a/ChromeDriver/78/win32/chromedriver.exe b/ChromeDriver/78/win32/chromedriver.exe
index 7b97f31..ec9ce29 100644
Binary files a/ChromeDriver/78/win32/chromedriver.exe and b/ChromeDriver/78/win32/chromedriver.exe differ
diff --git a/ChromeDriver/77/linux64/chromedriver b/ChromeDriver/79/linux64/chromedriver
similarity index 57%
rename from ChromeDriver/77/linux64/chromedriver
rename to ChromeDriver/79/linux64/chromedriver
index e21c03d..6942445 100644
Binary files a/ChromeDriver/77/linux64/chromedriver and b/ChromeDriver/79/linux64/chromedriver differ
diff --git a/ChromeDriver/77/mac64/chromedriver b/ChromeDriver/79/mac64/chromedriver
similarity index 64%
rename from ChromeDriver/77/mac64/chromedriver
rename to ChromeDriver/79/mac64/chromedriver
index 543ed9f..d9bff50 100644
Binary files a/ChromeDriver/77/mac64/chromedriver and b/ChromeDriver/79/mac64/chromedriver differ
diff --git a/ChromeDriver/76/win32/chromedriver.exe b/ChromeDriver/79/win32/chromedriver.exe
similarity index 53%
rename from ChromeDriver/76/win32/chromedriver.exe
rename to ChromeDriver/79/win32/chromedriver.exe
index 0eedbe0..244efd4 100644
Binary files a/ChromeDriver/76/win32/chromedriver.exe and b/ChromeDriver/79/win32/chromedriver.exe differ
diff --git a/ChromeDriver/76/linux64/chromedriver b/ChromeDriver/80/linux64/chromedriver
similarity index 57%
rename from ChromeDriver/76/linux64/chromedriver
rename to ChromeDriver/80/linux64/chromedriver
index a087573..b362f8f 100644
Binary files a/ChromeDriver/76/linux64/chromedriver and b/ChromeDriver/80/linux64/chromedriver differ
diff --git a/ChromeDriver/76/mac64/chromedriver b/ChromeDriver/80/mac64/chromedriver
similarity index 63%
rename from ChromeDriver/76/mac64/chromedriver
rename to ChromeDriver/80/mac64/chromedriver
index 135416c..df7565d 100644
Binary files a/ChromeDriver/76/mac64/chromedriver and b/ChromeDriver/80/mac64/chromedriver differ
diff --git a/ChromeDriver/77/win32/chromedriver.exe b/ChromeDriver/80/win32/chromedriver.exe
similarity index 54%
rename from ChromeDriver/77/win32/chromedriver.exe
rename to ChromeDriver/80/win32/chromedriver.exe
index ae80772..d419a51 100644
Binary files a/ChromeDriver/77/win32/chromedriver.exe and b/ChromeDriver/80/win32/chromedriver.exe differ
diff --git a/ControllerApi/ControllerApi.cs b/ControllerApi/ControllerApi.cs
index 7b307a9..9da64ad 100644
--- a/ControllerApi/ControllerApi.cs
+++ b/ControllerApi/ControllerApi.cs
@@ -222,9 +222,75 @@ public string GetAPMConfigurationExportXML(long applicationID)
return this.apiGET(String.Format("controller/ConfigObjectImportExportServlet?applicationId={0}", applicationID), "text/xml", false);
}
- public string GetAPMSEPConfiguration(long accountID, long applicationID)
+ public string GetAPMSEPAutodetectionConfiguration(long applicationID)
{
- return this.apiGET(String.Format("api/accounts/{0}/applications/{1}/sep", accountID, applicationID), "application/vnd.appd.cntrl+json", false);
+ string requestJSONTemplate =
+@"{{
+ ""agentType"": ""APP_AGENT"",
+ ""attachedEntity"": {{
+ ""entityId"": {0},
+ ""entityType"": ""APPLICATION""
+ }}
+}}";
+
+ string requestBody = String.Format(requestJSONTemplate,
+ applicationID);
+
+ return this.apiPOST("controller/restui/serviceEndpoint/getServiceEndpointMatchConfigs", "application/json", requestBody, "application/json", true);
+ }
+
+ public string GetAPMSEPTierConfigurationOverride(long tierID, string agentType)
+ {
+ string requestJSONTemplate =
+@"{{
+ ""agentType"": ""{1}"",
+ ""attachedEntity"": {{
+ ""entityId"": {0},
+ ""entityType"": ""APPLICATION_COMPONENT""
+ }}
+}}";
+
+ string requestBody = String.Format(requestJSONTemplate,
+ tierID,
+ agentType);
+
+ return this.apiPOST("controller/restui/serviceEndpoint/getServiceEndpointDefContainer", "application/json", requestBody, "application/json", true);
+ }
+
+ public string GetAPMSEPTierAutodetectionConfiguration(long tierID, string agentType)
+ {
+ string requestJSONTemplate =
+@"{{
+ ""agentType"": ""{1}"",
+ ""attachedEntity"": {{
+ ""entityId"": {0},
+ ""entityType"": ""APPLICATION_COMPONENT""
+ }}
+}}";
+
+ string requestBody = String.Format(requestJSONTemplate,
+ tierID,
+ agentType);
+
+ return this.apiPOST("controller/restui/serviceEndpoint/getServiceEndpointMatchConfigs", "application/json", requestBody, "application/json", true);
+ }
+
+ public string GetAPMSEPTierRules(long tierID, string agentType)
+ {
+ string requestJSONTemplate =
+@"{{
+ ""agentType"": ""{1}"",
+ ""attachedEntity"": {{
+ ""entityId"": {0},
+ ""entityType"": ""APPLICATION_COMPONENT""
+ }}
+}}";
+
+ string requestBody = String.Format(requestJSONTemplate,
+ tierID,
+ agentType);
+
+ return this.apiPOST("controller/restui/serviceEndpoint/getAll", "application/json", requestBody, "application/json", true);
}
public string GetAPMDeveloperModeConfiguration(long applicationID)
diff --git a/DataObjects/JobConfiguration/JobOutput.cs b/DataObjects/JobConfiguration/JobOutput.cs
index 0400c2b..da840f3 100644
--- a/DataObjects/JobConfiguration/JobOutput.cs
+++ b/DataObjects/JobConfiguration/JobOutput.cs
@@ -14,6 +14,7 @@ public class JobOutput
public bool UsersGroupsRolesPermissions { get; set; }
public bool Dashboards { get; set; }
public bool Licenses { get; set; }
+ public bool HealthCheck { get; set; }
public bool ApplicationSummary { get; set; }
}
}
diff --git a/DataObjects/JobConfiguration/JobStatus.cs b/DataObjects/JobConfiguration/JobStatus.cs
index a23c7ba..f8952a0 100644
--- a/DataObjects/JobConfiguration/JobStatus.cs
+++ b/DataObjects/JobConfiguration/JobStatus.cs
@@ -61,6 +61,8 @@ public enum JobStatus
IndexAPMMetrics = 80,
IndexAPMFlowmaps = 81,
IndexAPMSnapshots = 82,
+
+ IndexAPMHealthCheck = 90,
// Report steps
ReportControllerAndApplicationConfiguration = 100,
@@ -86,9 +88,11 @@ public enum JobStatus
ReportAPMFlameGraphs = 132,
ReportAPMEntityDetails = 133,
- ReportAPMApplicationSummary = 134,
+
+ ReportHealthCheck = 140,
+ ReportAPMApplicationSummary = 141,
- ReportAPMEntityDashboardScreenshots = 140,
+ ReportAPMEntityDashboardScreenshots = 150,
// The rest
Done = 500,
diff --git a/DefaultJob.json b/DefaultJob.json
index b88b147..b4ae939 100644
--- a/DefaultJob.json
+++ b/DefaultJob.json
@@ -51,8 +51,8 @@
],
"Input": {
"TimeRange": {
- "From": "2019-11-191T09:00:00",
- "To": "2019-11-19T10:00:00"
+ "From": "2019-12-17T09:00:00",
+ "To": "2019-12-17T10:00:00"
},
"UsersGroupsRolesPermissions": true,
"Dashboards": true,
@@ -72,99 +72,30 @@
"Tiers": [],
"TierType": {
"All": true,
- "APP_AGENT": false,
- "DOT_NET_APP_AGENT": false,
- "NATIVE_APP_AGENT": false,
- "NATIVE_DYNAMIC": false,
- "NATIVE_SDK": false,
- "NATIVE_WEB_SERVER": false,
- "NODEJS_APP_AGENT": false,
- "PHP_APP_AGENT": false,
- "PYTHON_APP_AGENT": false,
- "RUBY_APP_AGENT": false
+ "APP_AGENT": false, "DOT_NET_APP_AGENT": false, "NATIVE_APP_AGENT": false, "NATIVE_DYNAMIC": false, "NATIVE_SDK": false,
+ "NATIVE_WEB_SERVER": false, "NODEJS_APP_AGENT": false, "PHP_APP_AGENT": false, "PYTHON_APP_AGENT": false, "RUBY_APP_AGENT": false
},
"BusinessTransactions": [],
"BusinessTransactionType": {
"All": true,
- "SERVLET": false,
- "HTTP": false,
- "WEB_SERVICE": false,
- "POJO": false,
- "JMS": false,
- "EJB": false,
- "SPRING_BEAN": false,
- "STRUTS_ACTION": false,
- "ASP_DOTNET": false,
- "ASP_DOTNET_WEB_SERVICE": false,
- "DOTNET_REMOTING": false,
- "WCF": false,
- "DOTNET_JMS": false,
- "POCO": false,
- "PHP_WEB": false,
- "PHP_MVC": false,
- "PHP_DRUPAL": false,
- "PHP_WORDPRESS": false,
- "PHP_CLI": false,
- "PHP_WEB_SERVICE": false,
- "NODEJS_WEB": false,
- "NATIVE": false,
- "WEB": false,
- "PYTHON_WEB": false,
- "RUBY_WEB": false,
- "RUBY_RAILS": false,
- "BINARY_REMOTING": false
+ "SERVLET": false, "HTTP": false, "WEB_SERVICE": false, "POJO": false, "JMS": false, "EJB": false, "SPRING_BEAN": false, "STRUTS_ACTION": false,
+ "ASP_DOTNET": false, "ASP_DOTNET_WEB_SERVICE": false, "DOTNET_REMOTING": false, "WCF": false,
+ "DOTNET_JMS": false, "POCO": false, "PHP_WEB": false, "PHP_MVC": false, "PHP_DRUPAL": false,"PHP_WORDPRESS": false,
+ "PHP_CLI": false, "PHP_WEB_SERVICE": false, "NODEJS_WEB": false, "NATIVE": false, "WEB": false, "PYTHON_WEB": false, "RUBY_WEB": false, "RUBY_RAILS": false, "BINARY_REMOTING": false
},
"Nodes": [],
"NodeType": {
"All": true,
- "APP_AGENT": false,
- "DOT_NET_APP_AGENT": false,
- "NATIVE_APP_AGENT": false,
- "NATIVE_DYNAMIC": false,
- "NATIVE_SDK": false,
- "NATIVE_WEB_SERVER": false,
- "NODEJS_APP_AGENT": false,
- "PHP_APP_AGENT": false,
- "PYTHON_APP_AGENT": false,
- "RUBY_APP_AGENT": false
+ "APP_AGENT": false, "DOT_NET_APP_AGENT": false, "NATIVE_APP_AGENT": false, "NATIVE_DYNAMIC": false, "NATIVE_SDK": false,
+ "NATIVE_WEB_SERVER": false, "NODEJS_APP_AGENT": false, "PHP_APP_AGENT": false, "PYTHON_APP_AGENT": false, "RUBY_APP_AGENT": false
},
"Backends": [],
"BackendType": {
"All": true,
- "SOCKET": false,
- "HTTP": false,
- "CUSTOM": false,
- "CUSTOM_ASYNC": false,
- "FILE_SERVER": false,
- "MAIL_SERVER": false,
- "WEB_SERVICE": false,
- "ERP": false,
- "CACHE": false,
- "WEBSPHERE_MQ": false,
- "MAINFRAME": false,
- "TIBCO_ASYNC": false,
- "TIBCO": false,
- "ESB": false,
- "SAP": false,
- "AVRO": false,
- "THRIFT": false,
- "CASSANDRA": false,
- "MQ": false,
- "JMS": false,
- "WEBSOCKET": false,
- "JDBC": false,
- "RMI": false,
- "LDAP": false,
- "CORBA": false,
- "RABBITMQ": false,
- "ADODOTNET": false,
- "DOTNETDirectoryServices": false,
- "DOTNETRemoting": false,
- "DOTNETMessaging": false,
- "WCF": false,
- "MSMQ": false,
- "DB": false,
- "NETWORK": false
+ "SOCKET": false, "HTTP": false, "CUSTOM": false, "CUSTOM_ASYNC": false, "FILE_SERVER": false, "MAIL_SERVER": false, "WEB_SERVICE": false, "ERP": false,
+ "CACHE": false, "WEBSPHERE_MQ": false, "MAINFRAME": false, "TIBCO_ASYNC": false, "TIBCO": false, "ESB": false, "SAP": false, "AVRO": false,
+ "THRIFT": false, "CASSANDRA": false, "MQ": false, "JMS": false, "WEBSOCKET": false, "JDBC": false, "RMI": false, "LDAP": false, "CORBA": false,
+ "RABBITMQ": false, "ADODOTNET": false, "DOTNETDirectoryServices": false, "DOTNETRemoting": false, "DOTNETMessaging": false, "WCF": false, "MSMQ": false, "DB": false, "NETWORK": false
}
},
"Snapshots": true,
@@ -172,47 +103,16 @@
"Tiers": [],
"TierType": {
"All": true,
- "APP_AGENT": false,
- "DOT_NET_APP_AGENT": false,
- "NATIVE_APP_AGENT": false,
- "NATIVE_DYNAMIC": false,
- "NATIVE_SDK": false,
- "NATIVE_WEB_SERVER": false,
- "NODEJS_APP_AGENT": false,
- "PHP_APP_AGENT": false,
- "PYTHON_APP_AGENT": false,
- "RUBY_APP_AGENT": false
+ "APP_AGENT": false, "DOT_NET_APP_AGENT": false, "NATIVE_APP_AGENT": false, "NATIVE_DYNAMIC": false, "NATIVE_SDK": false,
+ "NATIVE_WEB_SERVER": false, "NODEJS_APP_AGENT": false, "PHP_APP_AGENT": false, "PYTHON_APP_AGENT": false, "RUBY_APP_AGENT": false
},
"BusinessTransactions": [],
"BusinessTransactionType": {
"All": true,
- "SERVLET": false,
- "HTTP": false,
- "WEB_SERVICE": false,
- "POJO": false,
- "JMS": false,
- "EJB": false,
- "SPRING_BEAN": false,
- "STRUTS_ACTION": false,
- "ASP_DOTNET": false,
- "ASP_DOTNET_WEB_SERVICE": false,
- "DOTNET_REMOTING": false,
- "WCF": false,
- "DOTNET_JMS": false,
- "POCO": false,
- "PHP_WEB": false,
- "PHP_MVC": false,
- "PHP_DRUPAL": false,
- "PHP_WORDPRESS": false,
- "PHP_CLI": false,
- "PHP_WEB_SERVICE": false,
- "NODEJS_WEB": false,
- "NATIVE": false,
- "WEB": false,
- "PYTHON_WEB": false,
- "RUBY_WEB": false,
- "RUBY_RAILS": false,
- "BINARY_REMOTING": false
+ "SERVLET": false, "HTTP": false, "WEB_SERVICE": false, "POJO": false, "JMS": false, "EJB": false, "SPRING_BEAN": false, "STRUTS_ACTION": false,
+ "ASP_DOTNET": false, "ASP_DOTNET_WEB_SERVICE": false, "DOTNET_REMOTING": false, "WCF": false,
+ "DOTNET_JMS": false, "POCO": false, "PHP_WEB": false, "PHP_MVC": false, "PHP_DRUPAL": false,"PHP_WORDPRESS": false,
+ "PHP_CLI": false, "PHP_WEB_SERVICE": false, "NODEJS_WEB": false, "NATIVE": false, "WEB": false, "PYTHON_WEB": false, "RUBY_WEB": false, "RUBY_RAILS": false, "BINARY_REMOTING": false
},
"UserExperience": {
"Normal": true,
@@ -240,6 +140,7 @@
"EntityDetails": true,
"Snapshots": true,
"FlameGraphs": true,
- "ApplicationSummary": true
+ "HealthCheck": false,
+ "ApplicationSummary": false
}
}
\ No newline at end of file
diff --git a/EmptyConfig/reference.controller/EmptyAPM.0/CFG/seps.detection.json b/EmptyConfig/reference.controller/EmptyAPM.0/CFG/seps.detection.json
new file mode 100644
index 0000000..ddf1ae5
--- /dev/null
+++ b/EmptyConfig/reference.controller/EmptyAPM.0/CFG/seps.detection.json
@@ -0,0 +1,158 @@
+[ {
+ "id" : 43,
+ "version" : 0,
+ "name" : "SERVLET",
+ "nameUnique" : true,
+ "applicationComponentId" : 0,
+ "enabled" : true,
+ "discoveryConfig" : {
+ "namingSchemeType" : "URI",
+ "properties" : [ {
+ "id" : 0,
+ "version" : 0,
+ "name" : "uri-length",
+ "value" : "first-n-segments"
+ }, {
+ "id" : 0,
+ "version" : 0,
+ "name" : "segment-length",
+ "value" : "2"
+ } ]
+ },
+ "entryPointType" : "SERVLET",
+ "entryPointTypeString" : "SERVLET",
+ "attachedEntity" : {
+ "id" : 0,
+ "version" : 0,
+ "entityType" : "APPLICATION",
+ "entityId" : 7,
+ "prettyToString" : null
+ },
+ "agentType" : "APP_AGENT"
+}, {
+ "id" : 44,
+ "version" : 0,
+ "name" : "STRUTS_ACTION",
+ "nameUnique" : true,
+ "applicationComponentId" : 0,
+ "enabled" : true,
+ "discoveryConfig" : {
+ "namingSchemeType" : "ACTION_NAME_AND_METHOD_NAME",
+ "properties" : [ ]
+ },
+ "entryPointType" : "STRUTS_ACTION",
+ "entryPointTypeString" : "STRUTS_ACTION",
+ "attachedEntity" : {
+ "id" : 0,
+ "version" : 0,
+ "entityType" : "APPLICATION",
+ "entityId" : 7,
+ "prettyToString" : null
+ },
+ "agentType" : "APP_AGENT"
+}, {
+ "id" : 46,
+ "version" : 0,
+ "name" : "WEB_SERVICE",
+ "nameUnique" : true,
+ "applicationComponentId" : 0,
+ "enabled" : true,
+ "discoveryConfig" : {
+ "namingSchemeType" : "SERVICE_NAME_AND_OPERATION_NAME",
+ "properties" : [ ]
+ },
+ "entryPointType" : "WEB_SERVICE",
+ "entryPointTypeString" : "WEB_SERVICE",
+ "attachedEntity" : {
+ "id" : 0,
+ "version" : 0,
+ "entityType" : "APPLICATION",
+ "entityId" : 7,
+ "prettyToString" : null
+ },
+ "agentType" : "APP_AGENT"
+}, {
+ "id" : 48,
+ "version" : 0,
+ "name" : "POJO",
+ "nameUnique" : true,
+ "applicationComponentId" : 0,
+ "enabled" : true,
+ "discoveryConfig" : {
+ "namingSchemeType" : "FULLY_QUALIFIED_CLASS_NAME",
+ "properties" : [ ]
+ },
+ "entryPointType" : "POJO",
+ "entryPointTypeString" : "POJO",
+ "attachedEntity" : {
+ "id" : 0,
+ "version" : 0,
+ "entityType" : "APPLICATION",
+ "entityId" : 7,
+ "prettyToString" : null
+ },
+ "agentType" : "APP_AGENT"
+}, {
+ "id" : 47,
+ "version" : 0,
+ "name" : "SPRING_BEAN",
+ "nameUnique" : true,
+ "applicationComponentId" : 0,
+ "enabled" : false,
+ "discoveryConfig" : {
+ "namingSchemeType" : "BEAN_ID_AND_METHOD_NAME",
+ "properties" : [ ]
+ },
+ "entryPointType" : "SPRING_BEAN",
+ "entryPointTypeString" : "SPRING_BEAN",
+ "attachedEntity" : {
+ "id" : 0,
+ "version" : 0,
+ "entityType" : "APPLICATION",
+ "entityId" : 7,
+ "prettyToString" : null
+ },
+ "agentType" : "APP_AGENT"
+}, {
+ "id" : 49,
+ "version" : 0,
+ "name" : "EJB",
+ "nameUnique" : true,
+ "applicationComponentId" : 0,
+ "enabled" : false,
+ "discoveryConfig" : {
+ "namingSchemeType" : "EJB_NAME_AND_METHOD_NAME",
+ "properties" : [ ]
+ },
+ "entryPointType" : "EJB",
+ "entryPointTypeString" : "EJB",
+ "attachedEntity" : {
+ "id" : 0,
+ "version" : 0,
+ "entityType" : "APPLICATION",
+ "entityId" : 7,
+ "prettyToString" : null
+ },
+ "agentType" : "APP_AGENT"
+}, {
+ "id" : 45,
+ "version" : 0,
+ "name" : "JMS",
+ "nameUnique" : true,
+ "applicationComponentId" : 0,
+ "enabled" : true,
+ "discoveryConfig" : {
+ "namingSchemeType" : "DESTINATION_NAME",
+ "properties" : [ ]
+ },
+ "entryPointType" : "JMS",
+ "entryPointTypeString" : "JMS",
+ "attachedEntity" : {
+ "id" : 0,
+ "version" : 0,
+ "entityType" : "APPLICATION",
+ "entityId" : 7,
+ "prettyToString" : null
+ },
+ "agentType" : "APP_AGENT"
+} ]
\ No newline at end of file
diff --git a/EmptyConfig/reference.controller/EmptyAPM.0/CFG/seps.json b/EmptyConfig/reference.controller/EmptyAPM.0/CFG/seps.json
deleted file mode 100644
index 2af631b..0000000
--- a/EmptyConfig/reference.controller/EmptyAPM.0/CFG/seps.json
+++ /dev/null
@@ -1 +0,0 @@
-{"applicationId": "1754","applicationName": "endor-app","sepContainer": [{"entityType": "APPLICATION","entityId": "1754","agentType": "DOT_NET_APP_AGENT","override": true},{"entityType": "APPLICATION","entityId": "1754","agentType": "NODEJS_APP_AGENT","override": true},{"entityType": "APPLICATION","entityId": "1754","agentType": "APP_AGENT","override": true,"sEPMatchPointConfigs": [{"id": "10492","name": "EJB","enabled": false,"entryPointType": "EJB","namingSchemeType": "EJB_NAME_AND_METHOD_NAME"},{"id": "10488","name": "JMS","enabled": true,"entryPointType": "JMS","namingSchemeType": "DESTINATION_NAME"},{"id": "10489","name": "POJO","enabled": true,"entryPointType": "POJO","namingSchemeType": "FULLY_QUALIFIED_CLASS_NAME"},{"id": "10491","name": "SERVLET","enabled": true,"entryPointType": "SERVLET","namingSchemeType": "URI","namingSchemeProperties": "uri-length;first-n-segments;segment-length;2;"},{"id": "10487","name": "SPRING_BEAN","enabled": false,"entryPointType": "SPRING_BEAN","namingSchemeType": "BEAN_ID_AND_METHOD_NAME"},{"id": "10490","name": "STRUTS_ACTION","enabled": true,"entryPointType": "STRUTS_ACTION","namingSchemeType": "ACTION_NAME_AND_METHOD_NAME"},{"id": "10493","name": "WEB_SERVICE","enabled": true,"entryPointType": "WEB_SERVICE","namingSchemeType": "SERVICE_NAME_AND_OPERATION_NAME"}]},{"entityType": "APPLICATION","entityId": "1754","agentType": "PHP_APP_AGENT","override": true}],"actions": [{"href": "http://arb.saas.appdynamics.com/api/accounts/105/applications/1754/sep","method": ["POST"],"name": "SEP_CREATE_UPDATE"}],"links": [{"href": "http://arb.saas.appdynamics.com/api/accounts/105/applications/1754/sep/{tier.id}","name": "sep"}]}
\ No newline at end of file
diff --git a/HealthCheckSettingMapping.csv b/HealthCheckSettingMapping.csv
new file mode 100644
index 0000000..6a4fde1
--- /dev/null
+++ b/HealthCheckSettingMapping.csv
@@ -0,0 +1,21 @@
+Name,Value,DataType
+LatestControllerVersion,4.5.16,Version
+LatestAppAgentVersion,4.5.10,Version
+LatestMachineAgentVersion,4.5.10,Version
+ApplicationErrorPercentageCritical,80,Decimal
+ApplicationErrorPercentageWarning,50,Decimal
+TierErrorPercentageCritical,80,Decimal
+TierErrorPercentageWarning,50,Decimal
+NodeErrorPercentageCritical,80,Decimal
+NodeErrorPercentageWarning,50,Decimal
+BusinessTransactionErrorPercentageCritical,80,Decimal
+BusinessTransactionErrorPercentageWarning,50,Decimal
+TierAvailabilityPercentageCritical,10,Decimal
+TierAvailabilityPercentageWarning,30,Decimal
+NodeAvailabilityPercentageCritical,25,Decimal
+NodeAvailabilityPercentageWarning,50,Decimal
+APMApplicationNameLengthGrade5,30,Integer
+APMApplicationNameLengthGrade4,40,Integer
+APMApplicationNameLengthGrade3,50,Integer
+APMApplicationNameLengthGrade2,60,Integer
+APMApplicationNameEnvironmentRegex,(production|prod|qa|test|tst|nonprod|perf|performance|sit|clt|dev|uat|poc|pov|demo|stage|stg),String
diff --git a/ProcessingSteps/Extract/ExtractAPMConfiguration.cs b/ProcessingSteps/Extract/ExtractAPMConfiguration.cs
index be70f4f..27a9e0f 100644
--- a/ProcessingSteps/Extract/ExtractAPMConfiguration.cs
+++ b/ProcessingSteps/Extract/ExtractAPMConfiguration.cs
@@ -1,5 +1,7 @@
-using AppDynamics.Dexter.ReportObjectMaps;
+using AppDynamics.Dexter.DataObjects;
+using AppDynamics.Dexter.ReportObjectMaps;
using AppDynamics.Dexter.ReportObjects;
+using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
@@ -93,26 +95,62 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
#region Service Endpoints
// SEPs are not included in the extracted XML
- // There is Flash/Flex API but I am not going to call it
- // Otherwise there is accounts API https://docs.appdynamics.com/display/PRO45/Access+Swagger+and+Accounts+API
- // This includes this one:
- // GET /accounts/{acctId}/applications/{appId}/sep Get all ServiceEndPointConfigs for application
- // It requires pretty high admin level access but hey, it's not Flash
-
- loggerConsole.Info("Service Endpoint Configuration");
+ // 2018:
+ // There is Flash/Flex API but I am not going to call it
+ // Otherwise there is accounts API https://docs.appdynamics.com/display/PRO45/Access+Swagger+and+Accounts+API
+ // This includes this one:
+ // GET /accounts/{acctId}/applications/{appId}/sep Get all ServiceEndPointConfigs for application
+ // It requires pretty high admin level access but hey, it's not Flash
+ // 12/19/2019:
+ // Previous API is removed, so we're going to call the RESTUI API
+
+ loggerConsole.Info("Service Endpoint Detection");
+
+ if (File.Exists(FilePathMap.APMApplicationConfigurationSEPDetectionRulesDataFilePath(jobTarget)) == false)
+ {
+ string applicationConfigSEPJSON = controllerApi.GetAPMSEPAutodetectionConfiguration(jobTarget.ApplicationID);
+ if (applicationConfigSEPJSON != String.Empty) FileIOHelper.SaveFileToPath(applicationConfigSEPJSON, FilePathMap.APMApplicationConfigurationSEPDetectionRulesDataFilePath(jobTarget));
+ }
- if (File.Exists(FilePathMap.APMApplicationConfigurationSEPDataFilePath(jobTarget)) == false)
+ string tiersJSON = controllerApi.GetAPMTiers(jobTarget.ApplicationID);
+ if (tiersJSON != String.Empty)
{
- string myAccountJSON = controllerApi.GetAccountsMyAccount();
- if (myAccountJSON != String.Empty)
+ List tiersRESTList = JsonConvert.DeserializeObject>(tiersJSON);
+ if (tiersRESTList != null)
{
- JObject myAccount = JObject.Parse(myAccountJSON);
- if (myAccount != null)
+ loggerConsole.Info("Service Endpoint Detection for Tiers");
+ foreach (AppDRESTTier tier in tiersRESTList)
+ {
+ string tierConfigOverrideJSON = controllerApi.GetAPMSEPTierConfigurationOverride(tier.id, tier.agentType);
+ if (tierConfigOverrideJSON != String.Empty)
+ {
+ JObject tierOverrideObject = JObject.Parse(tierConfigOverrideJSON);
+ if (tierOverrideObject != null)
+ {
+ if (getBoolValueFromJToken(tierOverrideObject, "override") == true)
+ {
+ loggerConsole.Info("Service Endpoint Detection for Tier {0}", tier.name);
+
+ string tierConfigSEPJSON = controllerApi.GetAPMSEPTierAutodetectionConfiguration(tier.id, tier.agentType);
+ if (tierConfigSEPJSON != String.Empty && tierConfigSEPJSON != "[]" && tierConfigSEPJSON != "[ ]")
+ {
+ FileIOHelper.SaveFileToPath(tierConfigSEPJSON, FilePathMap.APMApplicationConfigurationSEPTierDetectionRulesDataFilePath(jobTarget, tier));
+ }
+ }
+ }
+ }
+ }
+
+ loggerConsole.Info("Explicit Service Endpoint Rules for Tiers");
+ foreach (AppDRESTTier tier in tiersRESTList)
{
- long accountID = getLongValueFromJToken(myAccount, "id");
+ string tierConfigSEPJSON = controllerApi.GetAPMSEPTierRules(tier.id, tier.agentType);
+ if (tierConfigSEPJSON != String.Empty && tierConfigSEPJSON != "[]" && tierConfigSEPJSON != "[ ]")
+ {
+ loggerConsole.Info("Service Endpoint Rule for Tier {0}", tier.name);
- string applicationConfigSEPJSON = controllerApi.GetAPMSEPConfiguration(accountID, jobTarget.ApplicationID);
- if (applicationConfigSEPJSON != String.Empty) FileIOHelper.SaveFileToPath(applicationConfigSEPJSON, FilePathMap.APMApplicationConfigurationSEPDataFilePath(jobTarget));
+ FileIOHelper.SaveFileToPath(tierConfigSEPJSON, FilePathMap.APMApplicationConfigurationSEPTierExplicitRulesDataFilePath(jobTarget, tier));
+ }
}
}
}
diff --git a/ProcessingSteps/Extract/ExtractAPMEntityDashboardScreenshots.cs b/ProcessingSteps/Extract/ExtractAPMEntityDashboardScreenshots.cs
index 0559d7e..924e444 100644
--- a/ProcessingSteps/Extract/ExtractAPMEntityDashboardScreenshots.cs
+++ b/ProcessingSteps/Extract/ExtractAPMEntityDashboardScreenshots.cs
@@ -122,7 +122,7 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
ChromeOptions options = new ChromeOptions();
options.AcceptInsecureCertificates = true;
- //options.AddArgument("--headless");
+ options.AddArgument("--headless");
options.AddArgument("--guest");
options.AddArgument("--disable-extensions");
diff --git a/ProcessingSteps/Extract/ExtractAPMSnapshots.cs b/ProcessingSteps/Extract/ExtractAPMSnapshots.cs
index ef4e9fc..501ec22 100644
--- a/ProcessingSteps/Extract/ExtractAPMSnapshots.cs
+++ b/ProcessingSteps/Extract/ExtractAPMSnapshots.cs
@@ -215,7 +215,7 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
}
else
{
- logger.Warn("Snapshot list retrival call unexpectedly did not have any evidence of continuation CursorId");
+ logger.Warn("Snapshot list retrieval call unexpectedly did not have any evidence of continuation CursorId");
}
logger.Info("Retrieved snapshots from Controller {0}, Application {1}, From {2:o}, To {3:o}', number of snapshots {4}, continuation type {5}, continuation CursorId {6}", jobTarget.Controller, jobTarget.Application, jobTimeRange.From, jobTimeRange.To, retrievedSnapshotsArray.Count, serverCursorIdType, serverCursorId);
diff --git a/ProcessingSteps/FilePathMap.cs b/ProcessingSteps/FilePathMap.cs
index 3448461..4abc028 100644
--- a/ProcessingSteps/FilePathMap.cs
+++ b/ProcessingSteps/FilePathMap.cs
@@ -49,6 +49,9 @@ public class FilePathMap
private const string CONTROLLER_RBAC_FOLDER_NAME = "RBAC";
+ private const string HEALTHCHECK_FOLDER_NAME = "HEALTH";
+ private const string HEALTHCHECK_APM_FOLDER_NAME = "HEALTHAPM";
+
#endregion
#region Constants for the folder and file names of data extract
@@ -60,7 +63,9 @@ public class FilePathMap
// Controller wide settings file names
private const string EXTRACT_CONFIGURATION_APPLICATION_FILE_NAME = "configuration.xml";
private const string EXTRACT_CONFIGURATION_APPLICATION_DETAILS_FILE_NAME = "configuration.json";
- private const string EXTRACT_CONFIGURATION_APPLICATION_SEP_FILE_NAME = "seps.json";
+ private const string EXTRACT_CONFIGURATION_APPLICATION_SEP_DETECTION_FILE_NAME = "seps.detection.json";
+ private const string EXTRACT_CONFIGURATION_APPLICATION_TIER_SEP_DETECTION_FILE_NAME = "seps.detection.{0}.json";
+ private const string EXTRACT_CONFIGURATION_APPLICATION_TIER_SEP_EXPLICIT_FILE_NAME = "seps.rules.{0}.json";
private const string EXTRACT_CONTROLLER_VERSION_FILE_NAME = "controllerversion.xml";
private const string EXTRACT_HTTP_TEMPLATES_FILE_NAME = "templateshttp.json";
@@ -314,7 +319,8 @@ public class FilePathMap
private const string CONVERT_CONFIG_BUSINESS_TRANSACTION_ENTRY_RULES_FILE_NAME = "btentry.rules.csv";
private const string CONVERT_CONFIG_BUSINESS_TRANSACTION_ENTRY_RULES_2_0_FILE_NAME = "btentry.rules.2.0.csv";
private const string CONVERT_CONFIG_BUSINESS_TRANSACTION_ENTRY_SCOPES_FILE_NAME = "btentry.scopes.csv";
- private const string CONVERT_CONFIG_SERVICE_ENDPOINT_ENTRY_RULES_FILE_NAME = "sep.rules.csv";
+ private const string CONVERT_CONFIG_SERVICE_ENDPOINT_DISCOVERY_RULES_FILE_NAME = "sep.discovery.csv";
+ private const string CONVERT_CONFIG_SERVICE_ENDPOINT_ENTRY_RULES_FILE_NAME = "sep.entry.csv";
private const string CONVERT_CONFIG_BACKEND_DISCOVERY_RULES_FILE_NAME = "backend.rules.csv";
private const string CONVERT_CONFIG_CUSTOM_EXIT_RULES_FILE_NAME = "customexit.rules.csv";
private const string CONVERT_CONFIG_INFORMATION_POINT_RULES_FILE_NAME = "infopoints.csv";
@@ -415,6 +421,9 @@ public class FilePathMap
private const string CONVERT_ACTIVITY_GRIDS_PERMINUTE_FILE_NAME = "activitygrids.perminute.full.csv";
private const string CONVERT_ALL_ACTIVITY_GRIDS_PERMINUTE_FILE_NAME = "{0}.activitygrids.perminute.full.csv";
+ // Health check conversion file names
+ private const string CONVERT_HEALTH_CHECK_RULE_RESULTS_FILE_NAME = "healthcheck.rule.results.csv";
+
#endregion
#region Constants for the folder and file names of data reports
@@ -439,6 +448,7 @@ public class FilePathMap
private const string REPORT_LICENSES_FILE_NAME = "Licenses.{0}.{1:yyyyMMddHHmm}-{2:yyyyMMddHHmm}.xlsx";
private const string REPORT_APPLICATIONS_DASHBOARDS_FILE_NAME = "ApplicationsDashboards.{0}.{1:yyyyMMddHHmm}-{2:yyyyMMddHHmm}.html";
private const string REPORT_APPLICATION_DASHBOARDS_FILE_NAME = "ApplicationDashboards.html";
+ private const string REPORT_HEALTH_CHECK_RESULTS_APM_FILE_NAME = "HealthCheck.APM.{0}.{1:yyyyMMddHHmm}-{2:yyyyMMddHHmm}.xlsx";
// Per entity report names
private const string REPORT_ENTITY_DETAILS_APPLICATION_FILE_NAME = "EntityDetails.{0}.{1}.{2:yyyyMMddHHmm}-{3:yyyyMMddHHmm}.xlsx";
@@ -476,6 +486,9 @@ public class FilePathMap
// Settings for the metric extracts
private const string ENTITY_METRICS_EXTRACT_MAPPING_FILE_NAME = "EntityMetricsExtractMapping.csv";
+ // Settings for the metric extracts
+ private const string HEALTH_CHECK_SETTING_MAPPING_FILE_NAME = "HealthCheckSettingMapping.csv";
+
// Flame graph template SVG XML file
private const string FLAME_GRAPH_TEMPLATE_FILE_NAME = "FlameGraphTemplate.svg";
@@ -3723,15 +3736,75 @@ public string APMApplicationConfigurationDetailsDataFilePath(JobTarget jobTarget
}
- public string APMApplicationConfigurationSEPDataFilePath(JobTarget jobTarget)
+ public string APMApplicationConfigurationSEPDetectionRulesDataFilePath(JobTarget jobTarget)
+ {
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ DATA_FOLDER_NAME,
+ getFileSystemSafeString(getControllerNameForFileSystem(jobTarget.Controller)),
+ getShortenedEntityNameForFileSystem(jobTarget.Application, jobTarget.ApplicationID),
+ CONFIGURATION_FOLDER_NAME,
+ EXTRACT_CONFIGURATION_APPLICATION_SEP_DETECTION_FILE_NAME);
+ }
+
+ public string APMApplicationConfigurationSEPTierDetectionRulesDataFilePath(JobTarget jobTarget, AppDRESTTier tier)
+ {
+ string reportFileName = String.Format(
+ EXTRACT_CONFIGURATION_APPLICATION_TIER_SEP_DETECTION_FILE_NAME,
+ getShortenedEntityNameForFileSystem(tier.name, tier.id));
+
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ DATA_FOLDER_NAME,
+ getFileSystemSafeString(getControllerNameForFileSystem(jobTarget.Controller)),
+ getShortenedEntityNameForFileSystem(jobTarget.Application, jobTarget.ApplicationID),
+ CONFIGURATION_FOLDER_NAME,
+ reportFileName);
+ }
+
+ public string APMApplicationConfigurationSEPTierDetectionRulesDataFilePath(JobTarget jobTarget, APMTier tier)
+ {
+ string reportFileName = String.Format(
+ EXTRACT_CONFIGURATION_APPLICATION_TIER_SEP_DETECTION_FILE_NAME,
+ getShortenedEntityNameForFileSystem(tier.TierName, tier.TierID));
+
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ DATA_FOLDER_NAME,
+ getFileSystemSafeString(getControllerNameForFileSystem(jobTarget.Controller)),
+ getShortenedEntityNameForFileSystem(jobTarget.Application, jobTarget.ApplicationID),
+ CONFIGURATION_FOLDER_NAME,
+ reportFileName);
+ }
+
+ public string APMApplicationConfigurationSEPTierExplicitRulesDataFilePath(JobTarget jobTarget, AppDRESTTier tier)
+ {
+ string reportFileName = String.Format(
+ EXTRACT_CONFIGURATION_APPLICATION_TIER_SEP_EXPLICIT_FILE_NAME,
+ getShortenedEntityNameForFileSystem(tier.name, tier.id));
+
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ DATA_FOLDER_NAME,
+ getFileSystemSafeString(getControllerNameForFileSystem(jobTarget.Controller)),
+ getShortenedEntityNameForFileSystem(jobTarget.Application, jobTarget.ApplicationID),
+ CONFIGURATION_FOLDER_NAME,
+ reportFileName);
+ }
+
+ public string APMApplicationConfigurationSEPTierExplicitRulesDataFilePath(JobTarget jobTarget, APMTier tier)
{
+ string reportFileName = String.Format(
+ EXTRACT_CONFIGURATION_APPLICATION_TIER_SEP_EXPLICIT_FILE_NAME,
+ getShortenedEntityNameForFileSystem(tier.TierName, tier.TierID));
+
return Path.Combine(
this.ProgramOptions.OutputJobFolderPath,
DATA_FOLDER_NAME,
getFileSystemSafeString(getControllerNameForFileSystem(jobTarget.Controller)),
getShortenedEntityNameForFileSystem(jobTarget.Application, jobTarget.ApplicationID),
CONFIGURATION_FOLDER_NAME,
- EXTRACT_CONFIGURATION_APPLICATION_SEP_FILE_NAME);
+ reportFileName);
}
public string APMApplicationDeveloperModeNodesDataFilePath(JobTarget jobTarget)
@@ -3782,6 +3855,17 @@ public string APMBusinessTransactionEntryRulesIndexFilePath(JobTarget jobTarget)
CONVERT_CONFIG_BUSINESS_TRANSACTION_ENTRY_RULES_FILE_NAME);
}
+ public string APMServiceEndpointDiscoveryRulesIndexFilePath(JobTarget jobTarget)
+ {
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ INDEX_FOLDER_NAME,
+ getFileSystemSafeString(getControllerNameForFileSystem(jobTarget.Controller)),
+ getShortenedEntityNameForFileSystem(jobTarget.Application, jobTarget.ApplicationID),
+ CONFIGURATION_FOLDER_NAME,
+ CONVERT_CONFIG_SERVICE_ENDPOINT_DISCOVERY_RULES_FILE_NAME);
+ }
+
public string APMServiceEndpointEntryRulesIndexFilePath(JobTarget jobTarget)
{
return Path.Combine(
@@ -4041,6 +4125,15 @@ public string APMBusinessTransactionEntryRulesReportFilePath()
CONVERT_CONFIG_BUSINESS_TRANSACTION_ENTRY_RULES_FILE_NAME);
}
+ public string APMServiceEndpointDiscoveryRulesReportFilePath()
+ {
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ REPORT_FOLDER_NAME,
+ CONFIGURATION_APM_FOLDER_NAME,
+ CONVERT_CONFIG_SERVICE_ENDPOINT_DISCOVERY_RULES_FILE_NAME);
+ }
+
public string APMServiceEndpointEntryRulesReportFilePath()
{
return Path.Combine(
@@ -4305,6 +4398,63 @@ public string ConfigurationComparisonReportFilePath()
#endregion
+ #region APM Health Check Index
+
+ public string APMHealthCheckRuleResultsIndexFilePath(JobTarget jobTarget)
+ {
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ INDEX_FOLDER_NAME,
+ getFileSystemSafeString(getControllerNameForFileSystem(jobTarget.Controller)),
+ getShortenedEntityNameForFileSystem(jobTarget.Application, jobTarget.ApplicationID),
+ HEALTHCHECK_FOLDER_NAME,
+ CONVERT_HEALTH_CHECK_RULE_RESULTS_FILE_NAME);
+ }
+
+ #endregion
+
+ #region APM Health Check Report
+
+ public string HealthCheckSettingMappingFilePath()
+ {
+ return Path.Combine(
+ this.ProgramOptions.ProgramLocationFolderPath,
+ HEALTH_CHECK_SETTING_MAPPING_FILE_NAME);
+ }
+
+ public string APMHealthCheckReportFolderPath()
+ {
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ REPORT_FOLDER_NAME,
+ HEALTHCHECK_APM_FOLDER_NAME);
+ }
+
+ public string APMHealthCheckRuleResultsReportFilePath()
+ {
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ REPORT_FOLDER_NAME,
+ HEALTHCHECK_APM_FOLDER_NAME,
+ CONVERT_HEALTH_CHECK_RULE_RESULTS_FILE_NAME);
+ }
+
+ public string APMHealthCheckResultsExcelReportFilePath(JobTimeRange jobTimeRange)
+ {
+ string reportFileName = String.Format(
+ REPORT_HEALTH_CHECK_RESULTS_APM_FILE_NAME,
+ this.ProgramOptions.JobName,
+ jobTimeRange.From,
+ jobTimeRange.To);
+ return Path.Combine(
+ this.ProgramOptions.OutputJobFolderPath,
+ REPORT_FOLDER_NAME,
+ reportFileName);
+ }
+
+ #endregion
+
+
#region RBAC Data
public string UsersDataFilePath(JobTarget jobTarget)
@@ -6679,6 +6829,8 @@ public string ApplicationSummaryWordReportFilePath(JobTarget jobTarget, JobTimeR
public static string getFileSystemSafeString(string fileOrFolderNameToClear)
{
+ if (fileOrFolderNameToClear == null) fileOrFolderNameToClear = String.Empty;
+
foreach (var c in Path.GetInvalidFileNameChars())
{
fileOrFolderNameToClear = fileOrFolderNameToClear.Replace(c, '-');
diff --git a/ProcessingSteps/Index/IndexAPMConfiguration.cs b/ProcessingSteps/Index/IndexAPMConfiguration.cs
index 26e1b03..a3555fd 100644
--- a/ProcessingSteps/Index/IndexAPMConfiguration.cs
+++ b/ProcessingSteps/Index/IndexAPMConfiguration.cs
@@ -128,6 +128,7 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
if (configXml == null)
{
logger.Warn("No application configuration in {0} file", FilePathMap.APMApplicationConfigurationXMLDataFilePath(jobTarget));
+ loggerConsole.Warn("No application configuration in {0} file", FilePathMap.APMApplicationConfigurationXMLDataFilePath(jobTarget));
continue;
}
@@ -377,118 +378,69 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
#endregion
- #region Service Endpoint Rules
+ #region Service Endpoint Discovery and Entry Rules
- loggerConsole.Info("Service Endpoint Rules");
+ loggerConsole.Info("Service Endpoint Discovery Rules");
- List serviceEndpointEntryRulesList = new List();
+ List serviceEndpointDiscoveryRulesList = new List();
- JObject serviceEndpointsContainer = FileIOHelper.LoadJObjectFromFile(FilePathMap.APMApplicationConfigurationSEPDataFilePath(jobTarget));
- if (serviceEndpointsContainer != null && isTokenPropertyNull(serviceEndpointsContainer, "sepContainer") == false)
+ // SEP Autodetection Rules for App
+ JArray serviceEndpointsArray = FileIOHelper.LoadJArrayFromFile(FilePathMap.APMApplicationConfigurationSEPDetectionRulesDataFilePath(jobTarget));
+ if (serviceEndpointsArray != null)
{
- foreach (JObject serviceEndpointContainer in serviceEndpointsContainer["sepContainer"])
+ foreach (JObject serviceEndpointObject in serviceEndpointsArray)
{
- // SEP Autodetection Rules
- if (getStringValueFromJToken(serviceEndpointContainer, "entityType") == "APPLICATION")
+ ServiceEndpointDiscoveryRule serviceEndpointDiscoveryRule = fillServiceEnpointDiscoveryRule(serviceEndpointObject, null, applicationConfiguration);
+ serviceEndpointDiscoveryRulesList.Add(serviceEndpointDiscoveryRule);
+ }
+ }
+
+ // SEP Autodetection Rules for Tiers overrides
+ if (tiersThisAppList != null)
+ {
+ foreach (APMTier tier in tiersThisAppList)
+ {
+ JArray serviceEndpointsTierArray = FileIOHelper.LoadJArrayFromFile(FilePathMap.APMApplicationConfigurationSEPTierDetectionRulesDataFilePath(jobTarget, tier));
+ if (serviceEndpointsTierArray != null)
{
- if (isTokenPropertyNull(serviceEndpointContainer, "sEPMatchPointConfigs") == false)
+ foreach (JObject serviceEndpointRuleObject in serviceEndpointsTierArray)
{
- foreach (JObject serviceEndpoint in serviceEndpointContainer["sEPMatchPointConfigs"])
- {
- ServiceEndpointEntryRule serviceEndpointEntryRule = new ServiceEndpointEntryRule();
+ ServiceEndpointDiscoveryRule serviceEndpointDiscoveryRule = fillServiceEnpointDiscoveryRule(serviceEndpointRuleObject, tier, applicationConfiguration);
+ serviceEndpointDiscoveryRulesList.Add(serviceEndpointDiscoveryRule);
+ }
+ }
+ }
+ }
- serviceEndpointEntryRule.Controller = applicationConfiguration.Controller;
- serviceEndpointEntryRule.ControllerLink = applicationConfiguration.ControllerLink;
- serviceEndpointEntryRule.ApplicationName = applicationConfiguration.ApplicationName;
- serviceEndpointEntryRule.ApplicationID = applicationConfiguration.ApplicationID;
- serviceEndpointEntryRule.ApplicationLink = applicationConfiguration.ApplicationLink;
+ applicationConfiguration.NumSEPDiscoveryRules = serviceEndpointDiscoveryRulesList.Count;
- serviceEndpointEntryRule.AgentType = getStringValueFromJToken(serviceEndpointContainer, "agentType");
- serviceEndpointEntryRule.RuleName = getStringValueFromJToken(serviceEndpoint, "name");
- serviceEndpointEntryRule.EntryPointType = getStringValueFromJToken(serviceEndpoint, "entryPointType");
- serviceEndpointEntryRule.IsOverride = getBoolValueFromJToken(serviceEndpointContainer, "override");
- serviceEndpointEntryRule.IsMonitoringEnabled = getBoolValueFromJToken(serviceEndpoint, "enabled");
- serviceEndpointEntryRule.NamingConfigType = getStringValueFromJToken(serviceEndpoint, "namingSchemeType");
+ serviceEndpointDiscoveryRulesList = serviceEndpointDiscoveryRulesList.OrderBy(b => b.TierName).ThenBy(b => b.AgentType).ThenBy(b => b.EntryPointType).ToList();
+ FileIOHelper.WriteListToCSVFile(serviceEndpointDiscoveryRulesList, new ServiceEndpointDiscoveryRuleReportMap(), FilePathMap.APMServiceEndpointDiscoveryRulesIndexFilePath(jobTarget));
- serviceEndpointEntryRule.DiscoveryType = getStringValueFromJToken(serviceEndpoint, "namingSchemeProperties");
+ stepTimingTarget.NumEntities = stepTimingTarget.NumEntities + serviceEndpointDiscoveryRulesList.Count;
- serviceEndpointEntryRulesList.Add(serviceEndpointEntryRule);
- }
- }
- }
- }
- foreach (JObject serviceEndpointContainer in serviceEndpointsContainer["sepContainer"])
+ loggerConsole.Info("Custom Service Endpoint Entry Rules");
+
+ List serviceEndpointEntryRulesList = new List();
+
+ if (tiersThisAppList != null)
+ {
+ foreach (APMTier tier in tiersThisAppList)
{
- // Explicit SEP rule
- if (getStringValueFromJToken(serviceEndpointContainer, "entityType") == "APPLICATION_COMPONENT")
+ JArray serviceEndpointRulesInTierArray = FileIOHelper.LoadJArrayFromFile(FilePathMap.APMApplicationConfigurationSEPTierExplicitRulesDataFilePath(jobTarget, tier));
+ if (serviceEndpointRulesInTierArray != null)
{
- if (isTokenPropertyNull(serviceEndpointContainer, "sEPDefinitions") == false)
+ foreach (JObject serviceEndpointRuleObject in serviceEndpointRulesInTierArray)
{
- foreach (JObject serviceEndpointObject in serviceEndpointContainer["sEPDefinitions"])
- {
- ServiceEndpointEntryRule serviceEndpointEntryRule = new ServiceEndpointEntryRule();
-
- serviceEndpointEntryRule.Controller = applicationConfiguration.Controller;
- serviceEndpointEntryRule.ControllerLink = applicationConfiguration.ControllerLink;
- serviceEndpointEntryRule.ApplicationName = applicationConfiguration.ApplicationName;
- serviceEndpointEntryRule.ApplicationID = applicationConfiguration.ApplicationID;
- serviceEndpointEntryRule.ApplicationLink = applicationConfiguration.ApplicationLink;
-
- if (tiersThisAppList != null)
- {
- APMTier tier = tiersThisAppList.Where(t => t.EntityID == getLongValueFromJToken(serviceEndpointContainer, "entityId")).FirstOrDefault();
- if (tier != null)
- {
- serviceEndpointEntryRule.TierName = tier.TierName;
- }
- }
-
- serviceEndpointEntryRule.AgentType = getStringValueFromJToken(serviceEndpointContainer, "agentType");
- serviceEndpointEntryRule.RuleName = getStringValueFromJToken(serviceEndpointObject, "definitionName");
- serviceEndpointEntryRule.EntryPointType = getStringValueFromJToken(serviceEndpointObject, "entryPointType");
- serviceEndpointEntryRule.IsOverride = getBoolValueFromJToken(serviceEndpointContainer, "override");
- serviceEndpointEntryRule.IsMonitoringEnabled = true;
-
- serviceEndpointEntryRule.RuleRawValue = makeXMLFormattedAndIndented(serviceEndpointObject["MatchPointRuleXml"].ToString());
-
- if (serviceEndpointsThisAppList != null)
- {
- List serviceEndpointsForThisRule = new List();
-
- serviceEndpointsForThisRule.AddRange(serviceEndpointsThisAppList.Where(s => s.SEPName == serviceEndpointEntryRule.RuleName).ToList());
- serviceEndpointsForThisRule.AddRange(serviceEndpointsThisAppList.Where(s => s.SEPName.StartsWith(String.Format("{0}.", serviceEndpointEntryRule.RuleName))).ToList());
- serviceEndpointsForThisRule = serviceEndpointsForThisRule.Distinct().ToList();
- serviceEndpointEntryRule.NumDetectedSEPs = serviceEndpointsForThisRule.Count;
- if (serviceEndpointsForThisRule.Count > 0)
- {
- StringBuilder sb = new StringBuilder(32 * serviceEndpointsForThisRule.Count);
- foreach (APMServiceEndpoint sep in serviceEndpointsForThisRule)
- {
- sb.AppendFormat("{0}/{1};\n", sep.TierName, sep.SEPName);
- }
- sb.Remove(sb.Length - 1, 1);
-
- serviceEndpointEntryRule.DetectedSEPs = sb.ToString();
-
- // Now update the list of Entities to map which rule we are in
- foreach (APMServiceEndpoint serviceEndpoint in serviceEndpointsForThisRule)
- {
- serviceEndpoint.IsExplicitRule = true;
- serviceEndpoint.RuleName = String.Format("{0}/{1} [{2}]", serviceEndpointEntryRule.TierName, serviceEndpointEntryRule.RuleName, serviceEndpointEntryRule.EntryPointType);
- serviceEndpoint.RuleName = serviceEndpoint.RuleName.TrimStart('/');
- }
- }
- }
-
- serviceEndpointEntryRulesList.Add(serviceEndpointEntryRule);
- }
+ ServiceEndpointEntryRule serviceEndpointEntryRule = fillServiceEnpointEntryRule(serviceEndpointRuleObject, tier, applicationConfiguration, serviceEndpointsThisAppList);
+ serviceEndpointEntryRulesList.Add(serviceEndpointEntryRule);
}
}
}
}
- applicationConfiguration.NumSEPRules = serviceEndpointEntryRulesList.Count;
+ applicationConfiguration.NumSEPEntryRules = serviceEndpointEntryRulesList.Count;
serviceEndpointEntryRulesList = serviceEndpointEntryRulesList.OrderBy(b => b.TierName).ThenBy(b => b.AgentType).ThenBy(b => b.EntryPointType).ToList();
FileIOHelper.WriteListToCSVFile(serviceEndpointEntryRulesList, new ServiceEndpointEntryRuleReportMap(), FilePathMap.APMServiceEndpointEntryRulesIndexFilePath(jobTarget));
@@ -1386,8 +1338,11 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
#region Save the updated Backends, Business Transactions and Service Endpoints
FileIOHelper.WriteListToCSVFile(backendsList, new APMBackendReportMap(), FilePathMap.APMBackendsReportFilePath());
+ FileIOHelper.WriteListToCSVFile(backendsThisAppList, new APMBackendReportMap(), FilePathMap.APMBackendsIndexFilePath(jobTarget));
FileIOHelper.WriteListToCSVFile(businessTransactionsList, new APMBusinessTransactionReportMap(), FilePathMap.APMBusinessTransactionsReportFilePath());
+ FileIOHelper.WriteListToCSVFile(businessTransactionsThisAppList, new APMBusinessTransactionReportMap(), FilePathMap.APMBusinessTransactionsIndexFilePath(jobTarget));
FileIOHelper.WriteListToCSVFile(serviceEndpointsList, new APMServiceEndpointReportMap(), FilePathMap.APMServiceEndpointsReportFilePath());
+ FileIOHelper.WriteListToCSVFile(serviceEndpointsThisAppList, new APMServiceEndpointReportMap(), FilePathMap.APMServiceEndpointsIndexFilePath(jobTarget));
#endregion
@@ -1415,6 +1370,10 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
{
FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMBusinessTransactionEntryRulesReportFilePath(), FilePathMap.APMBusinessTransactionEntryRulesIndexFilePath(jobTarget));
}
+ if (File.Exists(FilePathMap.APMServiceEndpointDiscoveryRulesIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMServiceEndpointDiscoveryRulesIndexFilePath(jobTarget)).Length > 0)
+ {
+ FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMServiceEndpointDiscoveryRulesReportFilePath(), FilePathMap.APMServiceEndpointDiscoveryRulesIndexFilePath(jobTarget));
+ }
if (File.Exists(FilePathMap.APMServiceEndpointEntryRulesIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMServiceEndpointEntryRulesIndexFilePath(jobTarget)).Length > 0)
{
FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMServiceEndpointEntryRulesReportFilePath(), FilePathMap.APMServiceEndpointEntryRulesIndexFilePath(jobTarget));
@@ -2022,6 +1981,105 @@ private static BackendDiscoveryRule fillBackendDiscoveryRule(XmlNode backendDisc
return backendDiscoveryRule;
}
+ private static ServiceEndpointDiscoveryRule fillServiceEnpointDiscoveryRule(JObject serviceEndpointRuleObject, APMTier tier, APMApplicationConfiguration applicationConfiguration)
+ {
+ ServiceEndpointDiscoveryRule serviceEndpointDiscoveryRule = new ServiceEndpointDiscoveryRule();
+
+ serviceEndpointDiscoveryRule.Controller = applicationConfiguration.Controller;
+ serviceEndpointDiscoveryRule.ControllerLink = applicationConfiguration.ControllerLink;
+ serviceEndpointDiscoveryRule.ApplicationName = applicationConfiguration.ApplicationName;
+ serviceEndpointDiscoveryRule.ApplicationID = applicationConfiguration.ApplicationID;
+ serviceEndpointDiscoveryRule.ApplicationLink = applicationConfiguration.ApplicationLink;
+
+ serviceEndpointDiscoveryRule.AgentType = getStringValueFromJToken(serviceEndpointRuleObject, "agentType");
+ serviceEndpointDiscoveryRule.RuleName = getStringValueFromJToken(serviceEndpointRuleObject, "name");
+ serviceEndpointDiscoveryRule.EntryPointType = getStringValueFromJToken(serviceEndpointRuleObject, "entryPointType");
+ serviceEndpointDiscoveryRule.Version = getIntValueFromJToken(serviceEndpointRuleObject, "version");
+ serviceEndpointDiscoveryRule.IsEnabled = getBoolValueFromJToken(serviceEndpointRuleObject, "enabled");
+ if (isTokenPropertyNull(serviceEndpointRuleObject, "discoveryConfig") == false)
+ {
+ JObject discoveryConfigObject = (JObject)serviceEndpointRuleObject["discoveryConfig"];
+ serviceEndpointDiscoveryRule.NamingConfigType = getStringValueFromJToken(discoveryConfigObject, "namingSchemeType");
+
+ if (isTokenPropertyNull(discoveryConfigObject, "properties") == false)
+ {
+ string[] nameValues = discoveryConfigObject["properties"].Select(s => String.Format("{0}={1}", getStringValueFromJToken(s, "name"), getStringValueFromJToken(s, "value"))).ToArray();
+ serviceEndpointDiscoveryRule.DiscoveryType = String.Join(";", nameValues);
+ }
+ }
+
+ if (tier != null) serviceEndpointDiscoveryRule.TierName = tier.TierName;
+
+ return serviceEndpointDiscoveryRule;
+ }
+
+ private static ServiceEndpointEntryRule fillServiceEnpointEntryRule(JObject serviceEndpointRuleObject, APMTier tier, APMApplicationConfiguration applicationConfiguration, List serviceEndpointsList)
+ {
+ ServiceEndpointEntryRule serviceEndpointEntryRule = new ServiceEndpointEntryRule();
+
+ serviceEndpointEntryRule.Controller = applicationConfiguration.Controller;
+ serviceEndpointEntryRule.ControllerLink = applicationConfiguration.ControllerLink;
+ serviceEndpointEntryRule.ApplicationName = applicationConfiguration.ApplicationName;
+ serviceEndpointEntryRule.ApplicationID = applicationConfiguration.ApplicationID;
+ serviceEndpointEntryRule.ApplicationLink = applicationConfiguration.ApplicationLink;
+
+ serviceEndpointEntryRule.AgentType = getStringValueFromJToken(serviceEndpointRuleObject, "agentType");
+ serviceEndpointEntryRule.RuleName = getStringValueFromJToken(serviceEndpointRuleObject, "name");
+ serviceEndpointEntryRule.EntryPointType = getStringValueFromJToken(serviceEndpointRuleObject, "entryPointType");
+ serviceEndpointEntryRule.Version = getIntValueFromJToken(serviceEndpointRuleObject, "version");
+ if (isTokenPropertyNull(serviceEndpointRuleObject, "matchPointRule") == false)
+ {
+ JObject discoveryConfigObject = (JObject)serviceEndpointRuleObject["matchPointRule"];
+
+ serviceEndpointEntryRule.Priority = getIntValueFromJToken(discoveryConfigObject, "priority");
+ serviceEndpointEntryRule.IsEnabled = getBoolValueFromJToken(discoveryConfigObject, "enabled");
+ serviceEndpointEntryRule.IsExclusion = getBoolValueFromJToken(discoveryConfigObject, "excluded");
+
+ serviceEndpointEntryRule.MatchConditions = getStringValueOfObjectFromJToken(serviceEndpointRuleObject, "matchPointRule", false);
+
+ // This is for POCO/POJOs
+ serviceEndpointEntryRule.Actions = getStringValueOfObjectFromJToken(discoveryConfigObject, "splitConfig", false);
+
+ // This is for ASP.NET/Servlet
+ if (serviceEndpointEntryRule.Actions.Length == 0)
+ {
+ serviceEndpointEntryRule.Actions = getStringValueOfObjectFromJToken(discoveryConfigObject, "ruleProperties", false);
+ }
+ }
+
+ serviceEndpointEntryRule.TierName = tier.TierName;
+
+ if (serviceEndpointsList != null)
+ {
+ List serviceEndpointsForThisRule = new List();
+
+ serviceEndpointsForThisRule.AddRange(serviceEndpointsList.Where(s => s.SEPName == serviceEndpointEntryRule.RuleName).ToList());
+ serviceEndpointsForThisRule.AddRange(serviceEndpointsList.Where(s => s.SEPName.StartsWith(String.Format("{0}.", serviceEndpointEntryRule.RuleName))).ToList());
+ serviceEndpointsForThisRule = serviceEndpointsForThisRule.Distinct().ToList();
+ serviceEndpointEntryRule.NumDetectedSEPs = serviceEndpointsForThisRule.Count;
+ if (serviceEndpointsForThisRule.Count > 0)
+ {
+ StringBuilder sb = new StringBuilder(32 * serviceEndpointsForThisRule.Count);
+ foreach (APMServiceEndpoint sep in serviceEndpointsForThisRule)
+ {
+ sb.AppendFormat("{0}/{1};\n", sep.TierName, sep.SEPName);
+ }
+ sb.Remove(sb.Length - 1, 1);
+
+ serviceEndpointEntryRule.DetectedSEPs = sb.ToString();
+
+ // Now update the list of Entities to map which rule we are in
+ foreach (APMServiceEndpoint serviceEndpoint in serviceEndpointsForThisRule)
+ {
+ serviceEndpoint.IsExplicitRule = true;
+ serviceEndpoint.RuleName = String.Format("{0}/{1} [{2}]", serviceEndpointEntryRule.TierName, serviceEndpointEntryRule.RuleName, serviceEndpointEntryRule.EntryPointType);
+ serviceEndpoint.RuleName = serviceEndpoint.RuleName.TrimStart('/');
+ }
+ }
+ }
+ return serviceEndpointEntryRule;
+ }
+
private static CustomExitRule fillCustomExitRule(XmlNode backendDiscoveryMatchPointConfigurationNode, XmlNode customExitConfigurationNode, APMApplicationConfiguration applicationConfiguration, XmlNode applicationComponentNode, List backendsList)
{
CustomExitRule customExitRule = new CustomExitRule();
@@ -2173,6 +2231,8 @@ private static AgentConfigurationProperty fillAgentConfigurationProperty(XmlNode
agentConfigurationProperty.TierName = getStringValueFromXmlNode(applicationComponentNode.SelectSingleNode("name"));
}
+ agentConfigurationProperty.IsBuiltIn = AGENT_PROPERTIES_BUILTIN.Contains(agentConfigurationProperty.PropertyName);
+
return agentConfigurationProperty;
}
diff --git a/ProcessingSteps/Index/IndexAPMEntities.cs b/ProcessingSteps/Index/IndexAPMEntities.cs
index d4f1126..cb02e1e 100644
--- a/ProcessingSteps/Index/IndexAPMEntities.cs
+++ b/ProcessingSteps/Index/IndexAPMEntities.cs
@@ -770,7 +770,6 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
{
loggerConsole.Info("Index List of Tiers ({0} entities)", tiersRESTList.Count);
-
tiersList = new List(tiersRESTList.Count);
resolvedBackendsList = new List(tiersRESTList.Count * 10);
diff --git a/ProcessingSteps/Index/IndexAPMHealthCheck.cs b/ProcessingSteps/Index/IndexAPMHealthCheck.cs
new file mode 100644
index 0000000..2bf9bf7
--- /dev/null
+++ b/ProcessingSteps/Index/IndexAPMHealthCheck.cs
@@ -0,0 +1,1197 @@
+using AppDynamics.Dexter.DataObjects;
+using AppDynamics.Dexter.ReportObjectMaps;
+using AppDynamics.Dexter.ReportObjects;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Threading;
+
+namespace AppDynamics.Dexter.ProcessingSteps
+{
+ public class IndexAPMHealthCheck : JobStepIndexBase
+ {
+ 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);
+
+ try
+ {
+ if (this.ShouldExecute(jobConfiguration) == false)
+ {
+ return true;
+ }
+
+ if (jobConfiguration.Target.Count(t => t.Type == APPLICATION_TYPE_APM) == 0)
+ {
+ return true;
+ }
+
+ bool reportFolderCleaned = false;
+
+ // Process each target
+ for (int i = 0; i < jobConfiguration.Target.Count; i++)
+ {
+ Stopwatch stopWatchTarget = new Stopwatch();
+ stopWatchTarget.Start();
+
+ JobTarget jobTarget = jobConfiguration.Target[i];
+
+ if (jobTarget.Type != null && jobTarget.Type.Length > 0 && jobTarget.Type != APPLICATION_TYPE_APM) continue;
+
+ StepTiming stepTimingTarget = new StepTiming();
+ stepTimingTarget.Controller = jobTarget.Controller;
+ stepTimingTarget.ApplicationName = jobTarget.Application;
+ stepTimingTarget.ApplicationID = jobTarget.ApplicationID;
+ stepTimingTarget.JobFileName = programOptions.OutputJobFilePath;
+ stepTimingTarget.StepName = jobConfiguration.Status.ToString();
+ stepTimingTarget.StepID = (int)jobConfiguration.Status;
+ stepTimingTarget.StartTime = DateTime.Now;
+
+ try
+ {
+ this.DisplayJobTargetStartingStatus(jobConfiguration, jobTarget, i + 1);
+
+ #region Target step variables
+
+ List healthCheckRuleResults = new List();
+
+ #endregion
+
+ #region Preload all the reports that will be filtered by the subsequent entities
+
+ loggerConsole.Info("Entity Details Data Preloading");
+
+ // This file will always be there?
+ List healthCheckSettingsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.HealthCheckSettingMappingFilePath(), new HealthCheckSettingMappingMap());
+ if (healthCheckSettingsList == null || healthCheckSettingsList.Count == 0)
+ {
+ loggerConsole.Warn("Health check settings file did not load. Exiting the health checks");
+
+ return false;
+ }
+ Dictionary healthCheckSettingsDictionary = healthCheckSettingsList.ToDictionary(h => h.Name, h => h);
+
+ List controllerSummariesList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ControllerSummaryIndexFilePath(jobTarget), new ControllerSummaryReportMap());
+ List applicationsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMApplicationsIndexFilePath(jobTarget), new APMApplicationReportMap());
+ List applicationsMetricsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.EntitiesFullIndexFilePath(jobTarget, APMApplication.ENTITY_FOLDER), new ApplicationMetricReportMap());
+
+ List tiersList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMTiersIndexFilePath(jobTarget), new APMTierReportMap());
+ List tiersMetricsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.EntitiesFullIndexFilePath(jobTarget, APMTier.ENTITY_FOLDER), new TierMetricReportMap());
+
+ List nodesList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMNodesIndexFilePath(jobTarget), new APMNodeReportMap());
+ List nodesMetricsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.EntitiesFullIndexFilePath(jobTarget, APMNode.ENTITY_FOLDER), new NodeMetricReportMap());
+
+ List businessTransactionsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMBusinessTransactionsIndexFilePath(jobTarget), new APMBusinessTransactionReportMap());
+ List businessTransactionsMetricsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.EntitiesFullIndexFilePath(jobTarget, APMBusinessTransaction.ENTITY_FOLDER), new BusinessTransactionMetricReportMap());
+
+ List backendsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMBackendsIndexFilePath(jobTarget), new APMBackendReportMap());
+ List backendsMetricsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.EntitiesFullIndexFilePath(jobTarget, APMBackend.ENTITY_FOLDER), new BackendMetricReportMap());
+
+ List serviceEndpointsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMServiceEndpointsIndexFilePath(jobTarget), new APMServiceEndpointReportMap());
+ List serviceEndpointsMetricsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.EntitiesFullIndexFilePath(jobTarget, APMServiceEndpoint.ENTITY_FOLDER), new ServiceEndpointMetricReportMap());
+
+ List errorsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMErrorsIndexFilePath(jobTarget), new APMErrorReportMap());
+ List errorsMetricsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.EntitiesFullIndexFilePath(jobTarget, APMError.ENTITY_FOLDER), new ErrorMetricReportMap());
+
+ List informationPointsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMInformationPointsIndexFilePath(jobTarget), new APMInformationPointReportMap());
+ List informationPointsMetricsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.EntitiesFullIndexFilePath(jobTarget, APMInformationPoint.ENTITY_FOLDER), new InformationPointMetricReportMap());
+
+ List resolvedBackendsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMMappedBackendsIndexFilePath(jobTarget), new APMResolvedBackendReportMap());
+
+ //List eventsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationEventsIndexFilePath(jobTarget), new EventReportMap());
+ //List healthRuleViolationEventsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationHealthRuleViolationsIndexFilePath(jobTarget), new HealthRuleViolationEventReportMap());
+ //List snapshotsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsIndexFilePath(jobTarget), new SnapshotReportMap());
+ //List segmentsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsSegmentsIndexFilePath(jobTarget), new SegmentReportMap());
+ //List exitCallsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsExitCallsIndexFilePath(jobTarget), new ExitCallReportMap());
+ //List serviceEndpointCallsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsServiceEndpointCallsIndexFilePath(jobTarget), new ServiceEndpointCallReportMap());
+ //List detectedErrorsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsDetectedErrorsIndexFilePath(jobTarget), new DetectedErrorReportMap());
+ //List businessDataAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsBusinessDataIndexFilePath(jobTarget), new BusinessDataReportMap());
+
+ List agentPropertiesList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMAgentConfigurationPropertiesIndexFilePath(jobTarget), new AgentConfigurationPropertyReportMap());
+
+ #endregion
+
+ #region Controller
+
+ healthCheckRuleResults.Add(
+ evaluate_Controller_Version(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ controllerSummariesList));
+
+ healthCheckRuleResults.Add(
+ evaluate_Controller_SaaS_OnPrem(
+ jobTarget,
+ healthCheckSettingsDictionary));
+
+ #endregion
+
+ #region Application Naming
+
+ healthCheckRuleResults.Add(
+ evaluate_APMApplication_Name_Length(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ jobConfiguration));
+
+ healthCheckRuleResults.Add(
+ evaluate_APMApplication_Name_Environment(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ jobConfiguration));
+
+ #endregion
+
+ #region Application Agent Properties
+
+ healthCheckRuleResults.AddRange(
+ evaluate_APMApplication_Properties_BuiltIn_Modified(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ jobConfiguration,
+ agentPropertiesList));
+
+ healthCheckRuleResults.AddRange(
+ evaluate_APMApplication_Properties_New_Added(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ jobConfiguration,
+ agentPropertiesList));
+
+ healthCheckRuleResults.AddRange(
+ evaluate_APMApplication_Properties_WellKnown_analytics_dynamic_service_enabled(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ jobConfiguration,
+ agentPropertiesList));
+
+ healthCheckRuleResults.AddRange(
+ evaluate_APMApplication_Properties_WellKnown_find_entry_points(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ jobConfiguration,
+ agentPropertiesList));
+
+ healthCheckRuleResults.AddRange(
+ evaluate_APMApplication_Properties_WellKnown_use_old_servlet_split_for_get_parm_value_rule(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ jobConfiguration,
+ agentPropertiesList));
+
+ healthCheckRuleResults.AddRange(
+ evaluate_APMApplication_Properties_WellKnown_use_max_business_transactions(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ jobConfiguration,
+ agentPropertiesList));
+
+ #endregion
+
+ #region Tier Agent Property Overrides
+
+ healthCheckRuleResults.AddRange(
+ evaluate_APMApplication_Tier_Properties_Overriden(
+ jobTarget,
+ healthCheckSettingsDictionary,
+ jobConfiguration,
+ agentPropertiesList,
+ tiersList));
+
+ //#region Tier Property Overrides on
+
+ //healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMTier", "Tier1", -123, "Agent Property Configuration", "APM-005-TIER-PROPERTIES-OVERRIDE", "Tier Agent Properties Override");
+ //healthCheckRuleResult.Grade = 3;
+ //healthCheckRuleResult.Description = "Tiers {0} in Application {1} overridden App-level Agent Properties";
+ //healthCheckRuleResult.Code = "APM-0005";
+ //healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application_Properties"));
+ //healthCheckRuleResults.Add(healthCheckRuleResult);
+
+ //#endregion
+
+ //#region Built-in properties modified from their default values
+
+ //healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMTier", "Tier1", -123, "Agent Property Configuration", "APM-006-TIER-PROPERTIES-MODIFIED", "Tier Agent Properties Modified");
+ //healthCheckRuleResult.Grade = 3;
+ //healthCheckRuleResult.Description = "Built-in Agent Properties {0} modified from their default values in Application {1} Tier {2}";
+ //healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application_Properties"));
+ //healthCheckRuleResults.Add(healthCheckRuleResult);
+
+ //#endregion
+
+ //#region New properties added
+
+ //healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMTier", "Tier1", -123, "Agent Property Configuration", "APM-007-TIER-PROPERTIES-ADDED", "Tier Agent Properties Added");
+ //healthCheckRuleResult.Grade = 3;
+ //healthCheckRuleResult.Description = "Non-default Agent Properties {0} added to Application {1} Tier {2}";
+ //healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application_Properties"));
+ //healthCheckRuleResults.Add(healthCheckRuleResult);
+
+ //#endregion
+
+ #endregion
+
+ // Sort them
+ healthCheckRuleResults = healthCheckRuleResults.OrderBy(h => h.EntityType).ThenBy(h => h.EntityName).ThenBy(h => h.Category).ThenBy(h => h.Name).ToList();
+
+ // Set version
+ string versionOfDEXTER = Assembly.GetEntryAssembly().GetName().Version.ToString();
+ foreach (HealthCheckRuleResult healthCheckRuleResult in healthCheckRuleResults)
+ {
+ healthCheckRuleResult.Version = versionOfDEXTER;
+ }
+
+ FileIOHelper.WriteListToCSVFile(healthCheckRuleResults, new HealthCheckRuleResultReportMap(), FilePathMap.APMHealthCheckRuleResultsIndexFilePath(jobTarget));
+
+ stepTimingTarget.NumEntities = healthCheckRuleResults.Count;
+
+ #region Combine All for Report CSV
+
+ // If it is the first one, clear out the combined folder
+ if (reportFolderCleaned == false)
+ {
+ FileIOHelper.DeleteFolder(FilePathMap.APMHealthCheckReportFolderPath());
+ Thread.Sleep(1000);
+ FileIOHelper.CreateFolder(FilePathMap.APMHealthCheckReportFolderPath());
+ reportFolderCleaned = true;
+ }
+
+ // Append all the individual report files into one
+ if (File.Exists(FilePathMap.APMHealthCheckRuleResultsIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMHealthCheckRuleResultsIndexFilePath(jobTarget)).Length > 0)
+ {
+ FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMHealthCheckRuleResultsReportFilePath(), FilePathMap.APMHealthCheckRuleResultsIndexFilePath(jobTarget));
+ }
+ //if (File.Exists(FilePathMap.APMTiersIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMTiersIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMTiersReportFilePath(), FilePathMap.APMTiersIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMNodesIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMNodesIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMNodesReportFilePath(), FilePathMap.APMNodesIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMNodeStartupOptionsIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMNodeStartupOptionsIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMNodeStartupOptionsReportFilePath(), FilePathMap.APMNodeStartupOptionsIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMNodePropertiesIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMNodePropertiesIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMNodePropertiesReportFilePath(), FilePathMap.APMNodePropertiesIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMNodeEnvironmentVariablesIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMNodeEnvironmentVariablesIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMNodeEnvironmentVariablesReportFilePath(), FilePathMap.APMNodeEnvironmentVariablesIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMBackendsIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMBackendsIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMBackendsReportFilePath(), FilePathMap.APMBackendsIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMMappedBackendsIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMMappedBackendsIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMMappedBackendsReportFilePath(), FilePathMap.APMMappedBackendsIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMBusinessTransactionsIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMBusinessTransactionsIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMBusinessTransactionsReportFilePath(), FilePathMap.APMBusinessTransactionsIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMOverflowBusinessTransactionsIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMOverflowBusinessTransactionsIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMOverflowBusinessTransactionsReportFilePath(), FilePathMap.APMOverflowBusinessTransactionsIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMServiceEndpointsIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMServiceEndpointsIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMServiceEndpointsReportFilePath(), FilePathMap.APMServiceEndpointsIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMErrorsIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMErrorsIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMErrorsReportFilePath(), FilePathMap.APMErrorsIndexFilePath(jobTarget));
+ //}
+ //if (File.Exists(FilePathMap.APMInformationPointsIndexFilePath(jobTarget)) == true && new FileInfo(FilePathMap.APMInformationPointsIndexFilePath(jobTarget)).Length > 0)
+ //{
+ // FileIOHelper.AppendTwoCSVFiles(FilePathMap.APMInformationPointsReportFilePath(), FilePathMap.APMInformationPointsIndexFilePath(jobTarget));
+ //}
+
+ #endregion
+ }
+ catch (Exception ex)
+ {
+ logger.Warn(ex);
+ loggerConsole.Warn(ex);
+
+ return false;
+ }
+ finally
+ {
+ stopWatchTarget.Stop();
+
+ this.DisplayJobTargetEndedStatus(jobConfiguration, jobTarget, i + 1, stopWatchTarget);
+
+ stepTimingTarget.EndTime = DateTime.Now;
+ stepTimingTarget.Duration = stopWatchTarget.Elapsed;
+ stepTimingTarget.DurationMS = stopWatchTarget.ElapsedMilliseconds;
+
+ List stepTimings = new List(1);
+ stepTimings.Add(stepTimingTarget);
+ FileIOHelper.WriteListToCSVFile(stepTimings, new StepTimingReportMap(), FilePathMap.StepTimingReportFilePath(), true);
+ }
+ }
+
+ 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 stepTimings = new List(1);
+ stepTimings.Add(stepTimingFunction);
+ FileIOHelper.WriteListToCSVFile(stepTimings, new StepTimingReportMap(), FilePathMap.StepTimingReportFilePath(), true);
+ }
+ }
+
+ public override bool ShouldExecute(JobConfiguration jobConfiguration)
+ {
+ logger.Trace("Output.HealthCheck={0}", jobConfiguration.Output.HealthCheck);
+ loggerConsole.Trace("Output.HealthCheck={0}", jobConfiguration.Output.HealthCheck);
+ if (jobConfiguration.Output.HealthCheck == false)
+ {
+ loggerConsole.Trace("Skipping index of health check");
+ }
+ return (jobConfiguration.Output.HealthCheck == true);
+ }
+
+ #region Settings helper methods
+
+ private Version getVersionSetting(Dictionary healthCheckSettingsDictionary, string settingName, string valueIfNotThere)
+ {
+ if (healthCheckSettingsDictionary.ContainsKey(settingName) == true)
+ {
+ string versionString = healthCheckSettingsDictionary[settingName].Value;
+ Version version = new Version();
+ if (Version.TryParse(versionString, out version) == true)
+ {
+ return version;
+ }
+ else
+ {
+ return new Version(valueIfNotThere);
+ }
+ }
+ else
+ {
+ return new Version(valueIfNotThere);
+ }
+ }
+
+ private int getIntegerSetting(Dictionary healthCheckSettingsDictionary, string settingName, int valueIfNotThere)
+ {
+ if (healthCheckSettingsDictionary.ContainsKey(settingName) == true)
+ {
+ string numberString = healthCheckSettingsDictionary[settingName].Value;
+ int number = 0;
+ if (Int32.TryParse(numberString, out number) == true)
+ {
+ return number;
+ }
+ else
+ {
+ return valueIfNotThere;
+ }
+ }
+ else
+ {
+ return valueIfNotThere;
+ }
+ }
+
+ private string getStringSetting(Dictionary healthCheckSettingsDictionary, string settingName, string valueIfNotThere)
+ {
+ if (healthCheckSettingsDictionary.ContainsKey(settingName) == true)
+ {
+ return healthCheckSettingsDictionary[settingName].Value;
+ }
+ else
+ {
+ return valueIfNotThere;
+ }
+ }
+
+ #endregion
+
+ private HealthCheckRuleResult createHealthCheckRuleResult(
+ JobTarget jobTarget,
+ string entityType,
+ string entityName,
+ long entityID,
+ string ruleCategory,
+ string ruleCode,
+ string ruleName)
+ {
+ 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 = ruleCategory;
+ healthCheckRuleResult.Code = ruleCode;
+ healthCheckRuleResult.Name = ruleName;
+ healthCheckRuleResult.Grade = 0;
+
+ healthCheckRuleResult.EvaluationTime = DateTime.Now;
+
+ return healthCheckRuleResult;
+ }
+
+ #region Controller
+
+ ///
+ /// Version of Controller should be reasonably latest
+ ///
+ ///
+ ///
+ ///
+ ///
+ private HealthCheckRuleResult evaluate_Controller_Version(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ List controllerSummariesList)
+ {
+ string thisHealthRuleCode = "PLAT-001-PLATFORM-VERSION";
+ loggerConsole.Info("Evaluating Controller Version ({0})", thisHealthRuleCode);
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "Controller", jobTarget.Controller, 0, "Platform", thisHealthRuleCode, "Controller Version");
+ if (controllerSummariesList != null && controllerSummariesList.Count > 0)
+ {
+ ControllerSummary controllerSummary = controllerSummariesList[0];
+ Version versionThisController = new Version(jobTarget.ControllerVersion);
+
+ Version versionLatest = getVersionSetting(healthCheckSettingsDictionary, "LatestControllerVersion", "4.5.13");
+ Version versionLatestFirstRelease = new Version(versionLatest.Major, versionLatest.Minor);
+ Version versionLatestMinus1 = new Version(versionLatest.Major, versionLatest.Minor - 1);
+ Version versionLatestMinus2 = new Version(versionLatest.Major, versionLatest.Minor - 2);
+ Version versionLatestMinus3 = new Version(versionLatest.Major, versionLatest.Minor - 3);
+ Version versionLatestMinus4 = new Version(versionLatest.Major, versionLatest.Minor - 4);
+ Version versionLatestMinus5 = new Version(versionLatest.Major, versionLatest.Minor - 5);
+ if (versionThisController >= versionLatest)
+ {
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = String.Format("The Controller version '{0}' is greater or equal to latest '{1}'", jobTarget.ControllerVersion, versionLatest);
+ }
+ else if (versionThisController >= versionLatestFirstRelease)
+ {
+ healthCheckRuleResult.Grade = 4;
+ healthCheckRuleResult.Description = String.Format("The Controller version '{0}' is in '{1}' branch, old", jobTarget.ControllerVersion, versionLatestFirstRelease);
+ }
+ else if (versionThisController >= versionLatestMinus1)
+ {
+ healthCheckRuleResult.Grade = 4;
+ healthCheckRuleResult.Description = String.Format("The Controller version '{0}' is in '{1}' branch, really old", jobTarget.ControllerVersion, versionLatestMinus1);
+ }
+ else if (versionThisController >= versionLatestMinus2)
+ {
+ healthCheckRuleResult.Grade = 3;
+ healthCheckRuleResult.Description = String.Format("The Controller version '{0}' is in '{1}' branch, really, really old", jobTarget.ControllerVersion, versionLatestMinus2);
+ }
+ else if (versionThisController >= versionLatestMinus3)
+ {
+ healthCheckRuleResult.Grade = 3;
+ healthCheckRuleResult.Description = String.Format("The Controller version '{0}' is in '{1}' branch, really, really, really old", jobTarget.ControllerVersion, versionLatestMinus3);
+ }
+ else if (versionThisController >= versionLatestMinus4)
+ {
+ healthCheckRuleResult.Grade = 2;
+ healthCheckRuleResult.Description = String.Format("The Controller version '{0}' is in '{1}' branch, really, really, really, really old", jobTarget.ControllerVersion, versionLatestMinus4);
+ }
+ else if (versionThisController >= versionLatestMinus5)
+ {
+ healthCheckRuleResult.Grade = 2;
+ healthCheckRuleResult.Description = String.Format("The Controller version '{0}' is in '{1}' branch, really, really, really, really, really old", jobTarget.ControllerVersion, versionLatestMinus5);
+ }
+ else
+ {
+ healthCheckRuleResult.Grade = 1;
+ healthCheckRuleResult.Description = String.Format("The Controller version '{0}' is < '{1}' branch. Ancient", jobTarget.ControllerVersion, versionLatestMinus5);
+ }
+ }
+ else
+ {
+ healthCheckRuleResult.Grade = 1;
+ healthCheckRuleResult.Description = "No information about Controller version available";
+ }
+
+ return healthCheckRuleResult;
+ }
+
+ ///
+ /// We like SaaS controllers more than on premises
+ ///
+ ///
+ ///
+ ///
+ private HealthCheckRuleResult evaluate_Controller_SaaS_OnPrem(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary)
+ {
+ string thisHealthRuleCode = "PLAT-002-PLATFORM-SAAS";
+ loggerConsole.Info("Evaluating Controller SaaS or OnPremises ({0})", thisHealthRuleCode);
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "Controller", jobTarget.Controller, 0, "Platform", thisHealthRuleCode, "Controller SaaS or OnPrem");
+ 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;
+ }
+
+ #endregion
+
+ #region APM Application Naming
+
+ ///
+ /// Length of the APM Application Name
+ ///
+ ///
+ ///
+ ///
+ private HealthCheckRuleResult evaluate_APMApplication_Name_Length(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration)
+ {
+ string thisHealthRuleCode = "APM-001-APP-NAME-LENGTH";
+ loggerConsole.Info("Evaluating Application name length ({0})", thisHealthRuleCode);
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Logical Model Naming", thisHealthRuleCode, "App Name Length");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application"));
+
+ if (jobTarget.Application.Length > getIntegerSetting(healthCheckSettingsDictionary, "APMApplicationNameLengthGrade2", 60))
+ {
+ healthCheckRuleResult.Grade = 1;
+ healthCheckRuleResult.Description = String.Format("The Application Name '{0}' is very, very, very long (>{1} characters)", jobTarget.Application, getIntegerSetting(healthCheckSettingsDictionary, "APMApplicationNameLengthGrade2", 60));
+ }
+ else if (jobTarget.Application.Length > getIntegerSetting(healthCheckSettingsDictionary, "APMApplicationNameLengthGrade3", 50))
+ {
+ healthCheckRuleResult.Grade = 2;
+ healthCheckRuleResult.Description = String.Format("The Application Name '{0}' is very, very long (>{1} characters)", jobTarget.Application, getIntegerSetting(healthCheckSettingsDictionary, "APMApplicationNameLengthGrade3", 50));
+ }
+ else if (jobTarget.Application.Length > getIntegerSetting(healthCheckSettingsDictionary, "APMApplicationNameLengthGrade4", 40))
+ {
+ healthCheckRuleResult.Grade = 3;
+ healthCheckRuleResult.Description = String.Format("The Application Name '{0}' is very long (>{1} characters)", jobTarget.Application, getIntegerSetting(healthCheckSettingsDictionary, "APMApplicationNameLengthGrade2", 40));
+ }
+ else if (jobTarget.Application.Length > getIntegerSetting(healthCheckSettingsDictionary, "APMApplicationNameLengthGrade5", 30))
+ {
+ healthCheckRuleResult.Grade = 4;
+ healthCheckRuleResult.Description = String.Format("The Application Name '{0}' is long (>{1} characters)", jobTarget.Application, getIntegerSetting(healthCheckSettingsDictionary, "APMApplicationNameLengthGrade5", 30));
+ }
+ else
+ {
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = String.Format("The Application Name '{0}' is within recommended length (<={1} characters)", jobTarget.Application, getIntegerSetting(healthCheckSettingsDictionary, "APMApplicationNameLengthGrade5", 30));
+ }
+
+ return healthCheckRuleResult;
+ }
+
+ ///
+ /// APM Application name should contain environment designation
+ ///
+ ///
+ ///
+ ///
+ private HealthCheckRuleResult evaluate_APMApplication_Name_Environment(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration)
+ {
+ string thisHealthRuleCode = "APM-002-APP-NAME-INC-ENV-DESIGNATION";
+ loggerConsole.Info(thisHealthRuleCode);
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Logical Model Naming", thisHealthRuleCode, "App Name Includes Environment Designation");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application"));
+
+ Regex regexQuery = new Regex(getStringSetting(healthCheckSettingsDictionary, "APMApplicationNameEnvironmentRegex", "(production|prod|qa|test|tst|nonprod|perf|performance|sit|clt|dev|uat|poc|pov|demo|stage|stg)"), RegexOptions.IgnoreCase);
+ Match regexMatch = regexQuery.Match(jobTarget.Application);
+ if (regexMatch.Success == true && regexMatch.Groups.Count == 2)
+ {
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = String.Format("The Application Name '{0}' contains environment designation '{1}'", jobTarget.Application, regexMatch.Groups[1].Value);
+ }
+ else
+ {
+ healthCheckRuleResult.Grade = 3;
+ healthCheckRuleResult.Description = String.Format("The Application Name '{0}' does not contains environment designation", jobTarget.Application);
+ }
+
+ return healthCheckRuleResult;
+ }
+
+ #endregion
+
+ #region Application Agent Properties
+
+ ///
+ /// Built-in properties modified from their default values
+ /// Any change is graded 3
+ ///
+ ///
+ ///
+ ///
+ ///
+ private List evaluate_APMApplication_Properties_BuiltIn_Modified(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration,
+ List agentPropertiesList)
+ {
+ string thisHealthRuleCode = "APM-003-APP-DEFAULT-PROPERTY-MODIFIED";
+ loggerConsole.Info("Evaluating default Agent Properties modified ({0})", thisHealthRuleCode);
+
+ List healthCheckRuleResults = new List();
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Agent Property Configuration", thisHealthRuleCode, "App Agent Property Modified");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application_Properties"));
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = "None of the built-in Agent Properties are modified from their default values";
+
+ if (agentPropertiesList != null && agentPropertiesList.Count > 0)
+ {
+ List agentPropertiesBuiltInList = agentPropertiesList.Where(p => AGENT_PROPERTIES_BUILTIN.Contains(p.PropertyName) == true && p.IsDefault == false && p.TierName.Length == 0).ToList();
+ if (agentPropertiesBuiltInList != null && agentPropertiesBuiltInList.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesBuiltInList)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 3;
+
+ switch (agentProperty.PropertyType)
+ {
+ case "BOOLEAN":
+ healthCheckRuleResult1.Description = String.Format("Built-in Agent Property '{0}/{1} [{2}]' value is '{3}' and modified from its default value '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.BooleanValue, agentProperty.BooleanDefaultValue);
+ break;
+
+ case "INTEGER":
+ healthCheckRuleResult1.Description = String.Format("Built-in Agent Property '{0}/{1} [{2}]' value is '{3}' and modified from its default value '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.IntegerValue, agentProperty.IntegerDefaultValue);
+ break;
+
+ case "STRING":
+ healthCheckRuleResult1.Description = String.Format("Built-in Agent Property '{0}/{1} [{2}]' value is '{3}' and modified from its default value '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.StringValue, agentProperty.StringDefaultValue);
+ break;
+
+ default:
+ break;
+ }
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+ }
+
+ if (healthCheckRuleResults.Count == 0)
+ {
+ healthCheckRuleResults.Add(healthCheckRuleResult);
+ }
+
+ return healthCheckRuleResults;
+ }
+
+ ///
+ /// Non-built in properties added
+ /// Any change is graded 3
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private List evaluate_APMApplication_Properties_New_Added(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration,
+ List agentPropertiesList)
+ {
+ string thisHealthRuleCode = "APM-004-APP-PROPERTY-ADDED";
+ loggerConsole.Info("Evaluating non-default Agent Properties added ({0})", thisHealthRuleCode);
+
+ List healthCheckRuleResults = new List();
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Agent Property Configuration", thisHealthRuleCode, "App Agent Property Added");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application_Properties"));
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = "No additional non-default Agent Properties are added to application configuration";
+
+ if (agentPropertiesList != null && agentPropertiesList.Count > 0)
+ {
+ List agentPropertiesNonBuiltIntList = agentPropertiesList.Where(p => AGENT_PROPERTIES_BUILTIN.Contains(p.PropertyName) == false && p.TierName.Length == 0).ToList();
+ if (agentPropertiesNonBuiltIntList != null && agentPropertiesNonBuiltIntList.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesNonBuiltIntList)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 3;
+
+ switch (agentProperty.PropertyType)
+ {
+ case "BOOLEAN":
+ healthCheckRuleResult1.Description = String.Format("Non-default Agent Property '{0}/{1} [{2}]' value is '{3}' and its default value is '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.BooleanValue, agentProperty.BooleanDefaultValue);
+ break;
+
+ case "INTEGER":
+ healthCheckRuleResult1.Description = String.Format("Non-default Agent Property '{0}/{1} [{2}]' value is '{3}' and its default value is '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.IntegerValue, agentProperty.IntegerDefaultValue);
+ break;
+
+ case "STRING":
+ healthCheckRuleResult1.Description = String.Format("Non-default Agent Property '{0}/{1} [{2}]' value is '{3}' and its default value is '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.StringValue, agentProperty.StringDefaultValue);
+ break;
+
+ default:
+ break;
+ }
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+ }
+
+ if (healthCheckRuleResults.Count == 0)
+ {
+ healthCheckRuleResults.Add(healthCheckRuleResult);
+ }
+
+ return healthCheckRuleResults;
+ }
+
+ ///
+ /// Well-known properties - analytics-dynamic-service-enabled
+ /// if it is not set at all , grade 5
+ /// if it is set, grade 5
+ /// if it is set for some but not others, grade 1
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private List evaluate_APMApplication_Properties_WellKnown_analytics_dynamic_service_enabled(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration,
+ List agentPropertiesList)
+ {
+ string thisHealthRuleCode = "APM-005-APP-SIGNIFICANT-PROPERTY-SET";
+ loggerConsole.Info("Evaluating significat Agent Property analytics-dynamic-service-enabled ({0})", thisHealthRuleCode);
+
+ List healthCheckRuleResults = new List();
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Agent Property Configuration", thisHealthRuleCode, "App Agent Property Set (analytics-dynamic-service-enabled)");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application_Properties"));
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = "BIQ/Analytics is not enabled via 'analytics-dynamic-service-enabled' Agent Property for any agent types";
+
+ if (agentPropertiesList != null && agentPropertiesList.Count > 0)
+ {
+ List agentPropertiesAnalyticsEnabledList = agentPropertiesList.Where(p => p.PropertyName == "analytics-dynamic-service-enabled" && p.BooleanValue == true && p.TierName.Length == 0).ToList();
+ if (agentPropertiesAnalyticsEnabledList != null && agentPropertiesAnalyticsEnabledList.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesAnalyticsEnabledList)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 5;
+ healthCheckRuleResult1.Description = String.Format("BIQ/Analytics is enabled via '{0}/{1} [{2}]' Agent Property set to '{3}' for agent type '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.BooleanValue, agentProperty.AgentType);
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+
+ List agentPropertiesAnalyticsDisabledList = agentPropertiesList.Where(p => p.PropertyName == "analytics-dynamic-service-enabled" && p.BooleanValue == false && p.TierName.Length == 0).ToList();
+ if (agentPropertiesAnalyticsDisabledList != null && agentPropertiesAnalyticsDisabledList.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesAnalyticsDisabledList)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 1;
+ healthCheckRuleResult1.Description = String.Format("BIQ/Analytics is disabled via '{0}/{1} [{2}]' Agent Property set to '{3}' for agent type '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.BooleanValue, agentProperty.AgentType);
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+ }
+
+ if (healthCheckRuleResults.Count == 0)
+ {
+ healthCheckRuleResults.Add(healthCheckRuleResult);
+ }
+
+ return healthCheckRuleResults;
+ }
+
+ ///
+ /// Well-known properties - find-entry-points
+ /// If it is set at all, grade 2
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private List evaluate_APMApplication_Properties_WellKnown_find_entry_points(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration,
+ List agentPropertiesList)
+ {
+ string thisHealthRuleCode = "APM-005-APP-SIGNIFICANT-PROPERTY-SET";
+ loggerConsole.Info("Evaluating significat Agent Property find-entry-points ({0})", thisHealthRuleCode);
+
+ List healthCheckRuleResults = new List();
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Agent Property Configuration", thisHealthRuleCode, "App Agent Property Set (find-entry-points)");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application_Properties"));
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = "Business Transaction discovery stack logging is disabled via 'find-entry-points' Agent Property for all agent types";
+
+ if (agentPropertiesList != null && agentPropertiesList.Count > 0)
+ {
+ List agentPropertiesFindEntryPointsDisabledList = agentPropertiesList.Where(p => p.PropertyName == "find-entry-points" && p.BooleanValue == false && p.TierName.Length == 0).ToList();
+ if (agentPropertiesFindEntryPointsDisabledList != null && agentPropertiesFindEntryPointsDisabledList.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesFindEntryPointsDisabledList)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 5;
+ healthCheckRuleResult1.Description = String.Format("Business Transaction discovery stack logging is disabled via '{0}/{1} [{2}]' Agent Property set to '{3}' for agent type '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.BooleanValue, agentProperty.AgentType);
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+
+ List agentPropertiesFindEntryPointsEnabledList = agentPropertiesList.Where(p => p.PropertyName == "find-entry-points" && p.BooleanValue == true && p.TierName.Length == 0).ToList();
+ if (agentPropertiesFindEntryPointsEnabledList != null && agentPropertiesFindEntryPointsEnabledList.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesFindEntryPointsEnabledList)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 2;
+ healthCheckRuleResult1.Description = String.Format("Business Transaction discovery stack logging is enabled via '{0}/{1} [{2}]' Agent Property set to '{3}' for agent type '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.BooleanValue, agentProperty.AgentType);
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+ }
+
+ if (healthCheckRuleResults.Count == 0)
+ {
+ healthCheckRuleResults.Add(healthCheckRuleResult);
+
+ }
+ return healthCheckRuleResults;
+ }
+
+ ///
+ /// Well-known properties - use-old-servlet-split-for-get-parm-value-rule
+ /// You set it, you get graded lowest
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private List evaluate_APMApplication_Properties_WellKnown_use_old_servlet_split_for_get_parm_value_rule(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration,
+ List agentPropertiesList)
+ {
+ string thisHealthRuleCode = "APM-005-APP-SIGNIFICANT-PROPERTY-SET";
+ loggerConsole.Info("Evaluating significat Agent Property use-old-servlet-split-for-get-parm-value-rule ({0})", thisHealthRuleCode);
+
+ List healthCheckRuleResults = new List();
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Agent Property Configuration", thisHealthRuleCode, "App Agent Property Set (use-old-servlet-split-for-get-parm-value-rule)");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application_Properties"));
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = "Dangerous Servlet parameter parsing option is disabled via 'use-old-servlet-split-for-get-parm-value-rule' Agent Property for all agent types";
+
+ if (agentPropertiesList != null && agentPropertiesList.Count > 0)
+ {
+ List agentPropertiesEvilOldServletSplitEnabledList = agentPropertiesList.Where(p => p.PropertyName == "use-old-servlet-split-for-get-parm-value-rule" && p.BooleanValue == true && p.TierName.Length == 0).ToList();
+ if (agentPropertiesEvilOldServletSplitEnabledList != null && agentPropertiesEvilOldServletSplitEnabledList.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesEvilOldServletSplitEnabledList)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 1;
+ healthCheckRuleResult1.Description = String.Format("Dangerous Servlet parameter parsing option is enabled via '{0}/{1} [{2}]' Agent Property set to '{3}' for agent type '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.BooleanValue, agentProperty.AgentType);
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+ }
+
+ if (healthCheckRuleResults.Count == 0)
+ {
+ healthCheckRuleResults.Add(healthCheckRuleResult);
+ }
+
+ return healthCheckRuleResults;
+ }
+
+ ///
+ /// Well-known properties - max-business-transactions
+ /// Set higher than standard - grade 2
+ /// Set lower than standard, grade 3
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private List evaluate_APMApplication_Properties_WellKnown_use_max_business_transactions(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration,
+ List agentPropertiesList)
+ {
+ string thisHealthRuleCode = "APM-005-APP-SIGNIFICANT-PROPERTY-SET";
+ loggerConsole.Info("Evaluating significat Agent Property max-business-transactions ({0})", thisHealthRuleCode);
+
+ List healthCheckRuleResults = new List();
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Agent Property Configuration", thisHealthRuleCode, "App Agent Property Set (max-business-transactions)");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "Application_Properties"));
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = "Maximum Business Transaction slot registration are at default value via 'max-business-transactions' Agent Property for all agent types";
+
+ if (agentPropertiesList != null && agentPropertiesList.Count > 0)
+ {
+ List agentPropertiesMaxBTGreaterThanDefault = agentPropertiesList.Where(p => p.PropertyName == "max-business-transactions" && p.IntegerValue > 50 && p.TierName.Length == 0).ToList();
+ if (agentPropertiesMaxBTGreaterThanDefault != null && agentPropertiesMaxBTGreaterThanDefault.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesMaxBTGreaterThanDefault)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 2;
+ healthCheckRuleResult1.Description = String.Format("Higher than standard Business Transaction slot registration value is set via '{0}/{1} [{2}]' Agent Property set to '{3}' for agent type '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.IntegerValue, agentProperty.AgentType);
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+
+ List agentPropertiesMaxBTLessThanDefault = agentPropertiesList.Where(p => p.PropertyName == "max-business-transactions" && p.IntegerValue < 50 && p.TierName.Length == 0).ToList();
+ if (agentPropertiesMaxBTLessThanDefault != null && agentPropertiesMaxBTLessThanDefault.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesMaxBTLessThanDefault)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 3;
+ healthCheckRuleResult1.Description = String.Format("Lower than standard Business Transaction slot registration value is set via '{0}/{1} [{2}]' Agent Property set to '{3}' for agent type '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.IntegerValue, agentProperty.AgentType);
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+ }
+
+ if (healthCheckRuleResults.Count == 0)
+ {
+ healthCheckRuleResults.Add(healthCheckRuleResult);
+ }
+
+ return healthCheckRuleResults;
+ }
+
+ #endregion
+
+ #region Tier Agent Property evaluations
+
+ ///
+ /// Tier override has properties?
+ /// Any change is graded 3
+ ///
+ ///
+ ///
+ ///
+ ///
+ private List evaluate_APMApplication_Tier_Properties_Overriden(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration,
+ List agentPropertiesList,
+ List tiersList)
+ {
+ string thisHealthRuleCode = "APM-006-APP-TIER-PROPERTIES-OVERRIDEN";
+ loggerConsole.Info("Evaluating Tier Agent Properties override ({0})", thisHealthRuleCode);
+
+ List healthCheckRuleResults = new List();
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Agent Property Configuration", thisHealthRuleCode, "App Tier Agent Property Override");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "TODO"));
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = "None of the Application Tiers have Agent Properties override";
+
+ if (agentPropertiesList != null && agentPropertiesList.Count > 0)
+ {
+ List agentPropertiesTierOverridePropertiesList = agentPropertiesList.Where(p => p.TierName.Length > 0).ToList();
+ if (agentPropertiesTierOverridePropertiesList != null && agentPropertiesTierOverridePropertiesList.Count > 0)
+ {
+ var agentPropertiesTierOverridePropertiesListUniqueTiers = agentPropertiesTierOverridePropertiesList.GroupBy(p => p.TierName);
+ foreach (var uniqueTier in agentPropertiesTierOverridePropertiesListUniqueTiers)
+ {
+ List agentPropertiesInTier = uniqueTier.ToList();
+ AgentConfigurationProperty agentProperty = agentPropertiesInTier[0];
+
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+
+ healthCheckRuleResult1.EntityType = "APMTier";
+ healthCheckRuleResult1.EntityName = agentProperty.TierName;
+ if (tiersList != null)
+ {
+ APMTier tier = tiersList.Where(t => t.TierName == agentProperty.TierName).FirstOrDefault();
+ if (tier != null)
+ {
+ healthCheckRuleResult1.EntityID = tier.TierID;
+ }
+ else
+ {
+ healthCheckRuleResult1.EntityID = 0;
+ }
+ }
+
+ healthCheckRuleResult1.Grade = 3;
+ healthCheckRuleResult1.Description = String.Format("Tier '{0} [{1}]' has Agent Property override flag on, overriding '{2}' properties", agentProperty.TierName, agentProperty.AgentType, agentPropertiesInTier.Count);
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+ }
+
+ if (healthCheckRuleResults.Count == 0)
+ {
+ healthCheckRuleResults.Add(healthCheckRuleResult);
+ }
+
+ return healthCheckRuleResults;
+ }
+
+ ///
+ /// Tier override has things changed from defaults
+ /// Any change is graded 3
+ ///
+ ///
+ ///
+ ///
+ ///
+ private List evaluate_APMApplication_Tier_Properties_Overriden_BuiltIn_Modified(
+ JobTarget jobTarget,
+ Dictionary healthCheckSettingsDictionary,
+ JobConfiguration jobConfiguration,
+ List agentPropertiesList,
+ List tiersList)
+ {
+ string thisHealthRuleCode = "APM-006-APP-TIER-DEFAULT-PROPERTY-MODIFIED";
+ loggerConsole.Info("Evaluating default properties in Tier Agent Properties override ({0})", thisHealthRuleCode);
+
+ List healthCheckRuleResults = new List();
+
+ HealthCheckRuleResult healthCheckRuleResult = createHealthCheckRuleResult(jobTarget, "APMApp", jobTarget.Application, jobTarget.ApplicationID, "Agent Property Configuration", thisHealthRuleCode, "App Tier Agent Property Modified");
+ healthCheckRuleResult.RuleLink = String.Format(@"=HYPERLINK(""{0}"", """")", String.Format("{0}#{1}", FilePathMap.ApplicationSummaryWordReportFilePath(jobTarget, jobConfiguration.Input.TimeRange, false), "TODO"));
+ healthCheckRuleResult.Grade = 5;
+ healthCheckRuleResult.Description = "None of the Application Tiers with Agent Properties override on have modified built-in properties";
+
+ if (agentPropertiesList != null && agentPropertiesList.Count > 0)
+ {
+ List agentPropertiesBuiltInList = agentPropertiesList.Where(p => AGENT_PROPERTIES_BUILTIN.Contains(p.PropertyName) == true && p.IsDefault == false && p.TierName.Length > 0).ToList();
+ if (agentPropertiesBuiltInList != null && agentPropertiesBuiltInList.Count > 0)
+ {
+ foreach (AgentConfigurationProperty agentProperty in agentPropertiesBuiltInList)
+ {
+ HealthCheckRuleResult healthCheckRuleResult1 = healthCheckRuleResult.Clone();
+ healthCheckRuleResult1.Grade = 3;
+
+ healthCheckRuleResult1.EntityType = "APMTier";
+ healthCheckRuleResult1.EntityName = agentProperty.TierName;
+ if (tiersList != null)
+ {
+ APMTier tier = tiersList.Where(t => t.TierName == agentProperty.TierName).FirstOrDefault();
+ if (tier != null)
+ {
+ healthCheckRuleResult1.EntityID = tier.TierID;
+ }
+ else
+ {
+ healthCheckRuleResult1.EntityID = 0;
+ }
+ }
+
+ switch (agentProperty.PropertyType)
+ {
+ case "BOOLEAN":
+ healthCheckRuleResult1.Description = String.Format("Built-in Agent Property '{0}/{1} [{2}]' value is '{3}' and modified from its default value '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.BooleanValue, agentProperty.BooleanDefaultValue);
+ break;
+
+ case "INTEGER":
+ healthCheckRuleResult1.Description = String.Format("Built-in Agent Property '{0}/{1} [{2}]' value is '{3}' and modified from its default value '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.IntegerValue, agentProperty.IntegerDefaultValue);
+ break;
+
+ case "STRING":
+ healthCheckRuleResult1.Description = String.Format("Built-in Agent Property '{0}/{1} [{2}]' value is '{3}' and modified from its default value '{4}'", agentProperty.AgentType, agentProperty.PropertyName, agentProperty.PropertyType, agentProperty.StringValue, agentProperty.StringDefaultValue);
+ break;
+
+ default:
+ break;
+ }
+
+ healthCheckRuleResults.Add(healthCheckRuleResult1);
+ }
+ }
+ }
+
+ if (healthCheckRuleResults.Count == 0)
+ {
+ healthCheckRuleResults.Add(healthCheckRuleResult);
+ }
+
+ return healthCheckRuleResults;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ProcessingSteps/Index/IndexApplicationConfigurationDifferences.cs b/ProcessingSteps/Index/IndexApplicationConfigurationDifferences.cs
index 6c57292..0d2cb86 100644
--- a/ProcessingSteps/Index/IndexApplicationConfigurationDifferences.cs
+++ b/ProcessingSteps/Index/IndexApplicationConfigurationDifferences.cs
@@ -259,7 +259,18 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
#endregion
- #region Service Endpoint Rules
+ #region Service Endpoint Discovery Rules
+
+ loggerConsole.Info("Service Endpoint Discovery Rules");
+
+ List serviceEndpointDiscoveryRulesListReference = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMServiceEndpointDiscoveryRulesIndexFilePath(referenceTarget), new ServiceEndpointDiscoveryRuleReportMap());
+ List serviceEndpointDiscoveryRulesListDifference = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMServiceEndpointDiscoveryRulesIndexFilePath(jobTarget), new ServiceEndpointDiscoveryRuleReportMap());
+
+ configurationDifferencesList.AddRange(compareListOfEntities(referenceTarget, jobTarget, serviceEndpointDiscoveryRulesListReference, serviceEndpointDiscoveryRulesListDifference));
+
+ #endregion
+
+ #region Service Endpoint Entry Rules
loggerConsole.Info("Service Endpoint Entry Rules");
diff --git a/ProcessingSteps/JobStepBase.cs b/ProcessingSteps/JobStepBase.cs
index d49aaa3..244f0d3 100644
--- a/ProcessingSteps/JobStepBase.cs
+++ b/ProcessingSteps/JobStepBase.cs
@@ -24,6 +24,60 @@ public class JobStepBase
#endregion
+ #region Agent Properties
+
+ internal static List AGENT_PROPERTIES_BUILTIN = new List
+ {
+ { "adaptive-callgraph-granularity" },
+ { "api-thread-activity-timeout-in-seconds" },
+ { "api-transaction-timeout-in-seconds" },
+ { "async-transaction-demarcator" },
+ { "callgraph-granularity-in-ms" },
+ { "capture-error-urls" },
+ { "capture-raw-sql" },
+ { "collection-capture-period-in-minutes" },
+ { "collect-user-data-sync" },
+ { "disable-custom-exit-points-for" },
+ { "disable-exit-call-correlation-for" },
+ { "disable-exit-call-metrics-for" },
+ { "dont-show-packages" },
+ { "downstream-tx-detection-enabled" },
+ { "enable-collection-monitoring" },
+ { "enable-default-http-error-code-reporter" },
+ { "enable-instance-monitoring" },
+ { "enable-json-bci-rules" },
+ { "enable-object-size-monitoring" },
+ { "enable-soap-header-correlation" },
+ { "enable-startup-snapshot-policy" },
+ { "enable-transaction-correlation" },
+ { "enable-xml-bci-rules" },
+ { "end-to-end-message-latency-threshold-millis" },
+ { "find-entry-points" },
+ { "jdbc-callable-statements" },
+ { "jdbc-connections" },
+ { "jdbc-prepared-statements" },
+ { "jdbc-statements" },
+ { "leak-diagnostic-interval-in-minutes" },
+ { "log-request-payload" },
+ { "max-business-transactions" },
+ { "max-jdbc-calls-per-callgraph" },
+ { "max-jdbc-calls-per-snapshot" },
+ { "min-duration-for-jdbc-call-in-ms" },
+ { "minimum-age-for-evaluation-in-minutes" },
+ { "minimum-size-for-evaluation-in-mb" },
+ { "min-load-per-minute-diagnostic-session-trigger" },
+ { "on-demand-snapshots" },
+ { "rest-num-segments" },
+ { "rest-transaction-naming" },
+ { "rest-uri-segment-scheme" },
+ { "show-packages" },
+ { "slow-request-deviation" },
+ { "slow-request-monitor-interval" },
+ { "slow-request-threshold" }
+ };
+
+ #endregion
+
#region Event types
// There are a bazillion types of events
@@ -116,9 +170,9 @@ public class JobStepBase
{ "HTTP_REQUEST_ACTION_STARTED" },
{ "HTTP_REQUEST_ACTION_FAILED" },
{ "HTTP_REQUEST_ACTION_END" },
- { "RUNBOOK_DIAGNOSTIC SESSION_STARTED" },
- { "RUNBOOK_DIAGNOSTIC SESSION_FAILED" },
- { "RUNBOOK_DIAGNOSTIC SESSION_END" },
+ { "RUNBOOK_DIAGNOSTIC_SESSION_STARTED" },
+ { "RUNBOOK_DIAGNOSTIC_SESSION_FAILED" },
+ { "RUNBOOK_DIAGNOSTIC_SESSION_END" },
{ "RUN_LOCAL_SCRIPT_ACTION_STARTED" },
{ "RUN_LOCAL_SCRIPT_ACTION_FAILED" },
{ "RUN_LOCAL_SCRIPT_ACTION_END" },
diff --git a/ProcessingSteps/JobStepRouter.cs b/ProcessingSteps/JobStepRouter.cs
index 468453a..ac4c62f 100644
--- a/ProcessingSteps/JobStepRouter.cs
+++ b/ProcessingSteps/JobStepRouter.cs
@@ -75,6 +75,8 @@ public class JobStepRouter
JobStatus.IndexAPMFlowmaps,
JobStatus.IndexAPMSnapshots,
+ JobStatus.IndexAPMHealthCheck,
+
// Report data
JobStatus.ReportControllerAndApplicationConfiguration,
JobStatus.ReportControllerUsersGroupsRolesAndPermissions,
@@ -99,6 +101,8 @@ public class JobStepRouter
JobStatus.ReportAPMFlameGraphs,
JobStatus.ReportAPMEntityDetails,
+
+ JobStatus.ReportHealthCheck,
JobStatus.ReportAPMApplicationSummary,
JobStatus.ReportAPMEntityDashboardScreenshots,
@@ -324,6 +328,8 @@ private static JobStepBase getJobStepFromFactory(JobStatus jobStatus)
case JobStatus.IndexAPMSnapshots:
return new IndexAPMSnapshots();
+ case JobStatus.IndexAPMHealthCheck:
+ return new IndexAPMHealthCheck();
// Report data
case JobStatus.ReportControllerAndApplicationConfiguration:
@@ -367,6 +373,8 @@ private static JobStepBase getJobStepFromFactory(JobStatus jobStatus)
case JobStatus.ReportAPMEntityDetails:
return new ReportAPMEntityDetails();
+ case JobStatus.ReportHealthCheck:
+ return new ReportHealthCheck();
case JobStatus.ReportAPMApplicationSummary:
return new ReportAPMApplicationSummary();
diff --git a/ProcessingSteps/Report/JobStepReportBase.cs b/ProcessingSteps/Report/JobStepReportBase.cs
index d144c64..fec17de 100644
--- a/ProcessingSteps/Report/JobStepReportBase.cs
+++ b/ProcessingSteps/Report/JobStepReportBase.cs
@@ -337,7 +337,7 @@ internal static string getExcelTableOrSheetSafeString(string stringToClear)
char[] excelTableInvalidChars = { ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '=', ',', '/', '\\', '[', ']', ':', '?', '|', '"', '<', '>' };
foreach (var c in excelTableInvalidChars)
{
- stringToClear = stringToClear.Replace(c, '-');
+ stringToClear = stringToClear.Replace(c, '_');
}
// Apparently it is possible to have a NUL character as a BT name courtesy of penetration testing somehow
stringToClear = stringToClear.Replace("\u0000", "NULL");
diff --git a/ProcessingSteps/Report/ReportAPMApplicationSummary.cs b/ProcessingSteps/Report/ReportAPMApplicationSummary.cs
index e58cdd7..94ed15d 100644
--- a/ProcessingSteps/Report/ReportAPMApplicationSummary.cs
+++ b/ProcessingSteps/Report/ReportAPMApplicationSummary.cs
@@ -1,6 +1,8 @@
using AppDynamics.Dexter.ReportObjectMaps;
using AppDynamics.Dexter.ReportObjects;
using Aspose.Words;
+using Aspose.Words.Drawing;
+using Aspose.Words.Drawing.Charts;
using Aspose.Words.Lists;
using Aspose.Words.Saving;
using Aspose.Words.Tables;
@@ -23,7 +25,6 @@ public class ReportAPMApplicationSummary : JobStepReportBase
#endregion
-
public override bool Execute(ProgramOptions programOptions, JobConfiguration jobConfiguration)
{
Stopwatch stopWatch = new Stopwatch();
@@ -50,9 +51,20 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
return true;
}
- logger.Info("Setting Aspose License");
- Aspose.Words.License license = new Aspose.Words.License();
- license.SetLicense("Aspose.Words.lic");
+ try
+ {
+ logger.Info("Setting Aspose License");
+ Aspose.Words.License license = new Aspose.Words.License();
+ license.SetLicense("Aspose.Words.lic");
+ }
+ catch (Exception ex)
+ {
+ logger.Error("No Aspose license");
+ logger.Error(ex);
+ loggerConsole.Warn("No Aspose license, will not generate document");
+
+ return true;
+ }
try
{
@@ -116,8 +128,11 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
List resolvedBackendsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMMappedBackendsIndexFilePath(jobTarget), new APMResolvedBackendReportMap());
- //List eventsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationEventsIndexFilePath(jobTarget), new EventReportMap());
- //List healthRuleViolationEventsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationHealthRuleViolationsIndexFilePath(jobTarget), new HealthRuleViolationEventReportMap());
+ List businessTransactionsOverflowList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMOverflowBusinessTransactionsIndexFilePath(jobTarget), new APMOverflowBusinessTransactionReportMap());
+
+ //List eventsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationEventsIndexFilePath(jobTarget), new EventReportMap());
+ //List healthRuleViolationEventsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationHealthRuleViolationsIndexFilePath(jobTarget), new HealthRuleViolationEventReportMap());
+
//List snapshotsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsIndexFilePath(jobTarget), new SnapshotReportMap());
//List segmentsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsSegmentsIndexFilePath(jobTarget), new SegmentReportMap());
//List exitCallsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsExitCallsIndexFilePath(jobTarget), new ExitCallReportMap());
@@ -125,6 +140,18 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
//List detectedErrorsAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsDetectedErrorsIndexFilePath(jobTarget), new DetectedErrorReportMap());
//List businessDataAllList = FileIOHelper.ReadListFromCSVFile(FilePathMap.SnapshotsBusinessDataIndexFilePath(jobTarget), new BusinessDataReportMap());
+ List applicationActivityFlowsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationFlowmapIndexFilePath(jobTarget), new ApplicationActivityFlowReportMap());
+ List tiersActivityFlowsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.TiersFlowmapIndexFilePath(jobTarget), new TierActivityFlowReportMap());
+ List nodesActivityFlowsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.NodesFlowmapIndexFilePath(jobTarget), new NodeActivityFlowReportMap());
+ List businessTransactionsActivityFlowsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.BusinessTransactionsFlowmapIndexFilePath(jobTarget), new BusinessTransactionActivityFlowReportMap());
+ List backendsActivityFlowsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.BackendsFlowmapIndexFilePath(jobTarget), new BackendActivityFlowReportMap());
+
+ List healthRulesList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationHealthRulesIndexFilePath(jobTarget), new HealthRuleReportMap());
+ List policiesList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationPoliciesIndexFilePath(jobTarget), new PolicyReportMap());
+ List actionsList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationActionsIndexFilePath(jobTarget), new ActionReportMap());
+ List policyActionMappingList = FileIOHelper.ReadListFromCSVFile(FilePathMap.ApplicationPolicyActionMappingsIndexFilePath(jobTarget), new PolicyActionMappingReportMap());
+
+ List agentPropertiesList = FileIOHelper.ReadListFromCSVFile(FilePathMap.APMAgentConfigurationPropertiesIndexFilePath(jobTarget), new AgentConfigurationPropertyReportMap());
#endregion
@@ -158,185 +185,495 @@ public override bool Execute(ProgramOptions programOptions, JobConfiguration job
APMApplication application = applicationsList[0];
ControllerSummary controllerSummary = controllerSummariesList[0];
- Table table = insertNameValueTable(builder);
-
- insertNameValueRow(builder, table, "Controller", String.Format("{0}, Version {1} ({2})", application.Controller, controllerSummary.Version, controllerSummary.VersionDetail));
- insertNameValueRow(builder, table, "Saas or OnPrem", application.Controller.ToLower().Contains("saas.appdynamics") ? "SaaS" : "OnPrem");
- insertNameValueRow(builder, table, "Application", String.Format("{0} ({1}) {2}", application.ApplicationName, application.ApplicationID, application.Description));
-
- StringBuilder sb = new StringBuilder(200);
- sb.AppendFormat("{0} total ", application.NumTiers);
+
+ Table tableApplicationSummary = insertTableApplicationSummary(builder);
+
+ insertCellStringValue(builder, "Controller");
+ insertCellStringValue(builder, application.Controller);
+ insertCellStringValue(builder, application.Controller.ToLower().Contains("saas.appdynamics") ? "SaaS" : "On Premises");
+ builder.EndRow();
+
+ insertCellStringValue(builder, "Version");
+ insertCellStringValue(builder, controllerSummary.Version);
+ insertCellStringValue(builder, controllerSummary.VersionDetail);
+ builder.EndRow();
+
+ insertCellStringValue(builder, "Application");
+ insertCellStringValue(builder, String.Format("{0} ({1}) {2} [{3}]", application.ApplicationName, application.ApplicationID, application.Description, jobTarget.Type));
+ insertCellNoValue(builder);
+ builder.Write("Navigate to: ");
+ if (applicationsMetricsList != null && applicationsMetricsList.Count > 0)
+ {
+ APMApplication applicationWithMetrics = applicationsMetricsList[0];
+ insertLinkToURL(builder, hyperLinkStyle, "Controller", applicationWithMetrics.ControllerLink);
+ builder.Write(", ");
+ insertLinkToURL(builder, hyperLinkStyle, "Application", applicationWithMetrics.ApplicationLink);
+ }
+ else
+ {
+ insertLinkToURL(builder, hyperLinkStyle, "Controller", application.ControllerLink);
+ builder.Write(", ");
+ insertLinkToURL(builder, hyperLinkStyle, "Application", application.ApplicationLink);
+ }
+ builder.EndRow();
+
+ finalizeTableApplicationSummary(builder, tableApplicationSummary);
+
+ #endregion
+
+ #region Entity Types Table
+
+ insertHeading(builder, StyleIdentifier.Heading2, "Entity Types and Activity", String.Empty, listHeadingsOutline, 1);
+
+ builder.ParagraphFormat.StyleIdentifier = StyleIdentifier.Normal;
+
+ Table tableApplicationEntitySummary = insertTableApplicationEntityTypes(builder);
+
+ #region Tiers
+
+ insertCellNoValue(builder); insertLinkToBookmark(builder, hyperLinkStyle, "Tiers", "Tiers");
if (tiersList != null && tiersList.Count > 0)
{
+ List tierTypesList = new List(100);
+ List tierTypesCountsList = new List(100);
+ List tierTypeAndCountsList = new List(100);
+
var groupTypes = tiersList.GroupBy(t => t.AgentType);
- sb.Append("(");
- foreach (var groupType in groupTypes)
- {
- sb.AppendFormat("{0} {1}", groupType.Count(), groupType.Key);
- sb.Append(", ");
- }
- if (sb.Length > 2) sb.Remove(sb.Length - 2, 2);
- sb.Append("), ");
+ measureTypesOfItemsInGroupBy(groupTypes, tierTypeAndCountsList, tierTypesList, tierTypesCountsList);
+
+ insertCellStringValue(builder, String.Format("{0} total\n{1}", tiersList.Count, String.Join("\n", tierTypeAndCountsList.ToArray())));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Tier Types", tierTypesList.ToArray(), tierTypesCountsList.ToArray());
}
- if (tiersMetricsList != null)
+ else
{
- sb.AppendFormat("{0} active/{1} inactive", tiersMetricsList.Count(t => t.HasActivity == true), tiersMetricsList.Count(t => t.HasActivity == false));
+ insertCellStringValue(builder, "No tier list available");
+ insertCellStringValue(builder, String.Empty);
}
- insertNameValueRow(builder, table, "Tiers", sb.ToString());
- sb = new StringBuilder(200);
- sb.AppendFormat("{0} total ", application.NumNodes);
+ if (tiersMetricsList != null && tiersMetricsList.Count > 0)
+ {
+ string[] tierActivityArray = new string[2];
+ tierActivityArray[0] = "Has Activity";
+ tierActivityArray[1] = "No Activity";
+ double[] tierActivityCountsArray = new double[2];
+
+ tierActivityCountsArray[0] = tiersMetricsList.Count(t => t.HasActivity == true);
+ tierActivityCountsArray[1] = tiersMetricsList.Count(t => t.HasActivity == false);
+
+ insertCellStringValue(builder, String.Format("{0} active\n{1} inactive", tierActivityCountsArray[0], tierActivityCountsArray[1]));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Tier Activity", tierActivityArray, tierActivityCountsArray);
+ }
+ else
+ {
+ insertCellStringValue(builder, "No metrics available");
+ insertCellStringValue(builder, String.Empty);
+ }
+ builder.EndRow();
+
+ #endregion
+
+ #region Nodes
+
+ insertCellNoValue(builder); insertLinkToBookmark(builder, hyperLinkStyle, "Nodes", "Nodes");
if (nodesList != null && nodesList.Count > 0)
{
- var groupTypes = nodesList.GroupBy(n => n.AgentType);
- sb.Append("(");
- foreach (var groupType in groupTypes)
- {
- sb.AppendFormat("{0} {1}", groupType.Count(), groupType.Key);
- sb.Append(", ");
- }
- if (sb.Length > 2) sb.Remove(sb.Length - 2, 2);
- sb.Append("), ");
+ List nodeTypesList = new List(100);
+ List nodeTypesCountsList = new List(100);
+ List nodeTypeAndCountsList = new List(100);
+
+ var groupTypes = nodesList.GroupBy(t => t.AgentType);
+ measureTypesOfItemsInGroupBy(groupTypes, nodeTypeAndCountsList, nodeTypesList, nodeTypesCountsList);
+
+ insertCellStringValue(builder, String.Format("{0} total\n{1}", nodesList.Count, String.Join("\n", nodeTypeAndCountsList.ToArray())));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Node Types", nodeTypesList.ToArray(), nodeTypesCountsList.ToArray());
}
- if (nodesMetricsList != null)
+ else
+ {
+ insertCellStringValue(builder, "No node list available");
+ insertCellStringValue(builder, String.Empty);
+ }
+
+ if (nodesMetricsList != null && nodesMetricsList.Count > 0)
+ {
+ string[] nodeActivityArray = new string[2];
+ nodeActivityArray[0] = "Has Activity";
+ nodeActivityArray[1] = "No Activity";
+ double[] nodeActivityCountsArray = new double[2];
+
+ nodeActivityCountsArray[0] = nodesMetricsList.Count(t => t.HasActivity == true);
+ nodeActivityCountsArray[1] = nodesMetricsList.Count(t => t.HasActivity == false);
+
+ insertCellStringValue(builder, String.Format("{0} active\n{1} inactive", nodeActivityCountsArray[0], nodeActivityCountsArray[1]));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Node Activity", nodeActivityArray, nodeActivityCountsArray);
+ }
+ else
{
- sb.AppendFormat("{0} active/{1} inactive", nodesMetricsList.Count(t => t.HasActivity == true), nodesMetricsList.Count(t => t.HasActivity == false));
+ insertCellStringValue(builder, "No metrics available");
+ insertCellStringValue(builder, String.Empty);
}
- insertNameValueRow(builder, table, "Nodes", sb.ToString());
+ builder.EndRow();
+
+ #endregion
- sb = new StringBuilder(200);
- sb.AppendFormat("{0} total ", application.NumBTs);
+ #region Business Transactions
+
+ insertCellNoValue(builder); insertLinkToBookmark(builder, hyperLinkStyle, "Business Transactions", "Business_Transactions");
if (businessTransactionsList != null && businessTransactionsList.Count > 0)
{
- var groupTypes = businessTransactionsList.GroupBy(b => b.BTType);
- sb.Append("(");
- foreach (var groupType in groupTypes)
- {
- sb.AppendFormat("{0} {1}", groupType.Count(), groupType.Key);
- sb.Append(", ");
- }
- if (sb.Length > 2) sb.Remove(sb.Length - 2, 2);
- sb.Append("), ");
+ List businessTransactionTypesList = new List(100);
+ List businessTransactionTypesCountsList = new List(100);
+ List businessTransactionTypeAndCountsList = new List(100);
+
+ var groupTypes = businessTransactionsList.GroupBy(t => t.BTType);
+ measureTypesOfItemsInGroupBy(groupTypes, businessTransactionTypeAndCountsList, businessTransactionTypesList, businessTransactionTypesCountsList);
+
+ insertCellStringValue(builder, String.Format("{0} total\n{1}", businessTransactionsList.Count, String.Join("\n", businessTransactionTypeAndCountsList.ToArray())));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Business Transaction Types", businessTransactionTypesList.ToArray(), businessTransactionTypesCountsList.ToArray());
+ }
+ else
+ {
+ insertCellStringValue(builder, "No business transaction list available");
+ insertCellStringValue(builder, String.Empty);
+ }
+
+ if (businessTransactionsMetricsList != null && businessTransactionsMetricsList.Count > 0)
+ {
+ string[] businessTransactionActivityArray = new string[2];
+ businessTransactionActivityArray[0] = "Has Activity";
+ businessTransactionActivityArray[1] = "No Activity";
+ double[] businessTransactionActivityCountsArray = new double[2];
+
+ businessTransactionActivityCountsArray[0] = businessTransactionsMetricsList.Count(t => t.HasActivity == true);
+ businessTransactionActivityCountsArray[1] = businessTransactionsMetricsList.Count(t => t.HasActivity == false);
+
+ insertCellStringValue(builder, String.Format("{0} active\n{1} inactive", businessTransactionActivityCountsArray[0], businessTransactionActivityCountsArray[1]));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Business Transaction Activity", businessTransactionActivityArray, businessTransactionActivityCountsArray);
+ }
+ else
+ {
+ insertCellStringValue(builder, "No metrics available");
+ insertCellStringValue(builder, String.Empty);
+ }
+ builder.EndRow();
+
+ #endregion
+
+ #region Business Transactions - Overflow
+
+ insertCellStringValue(builder, "Overflow Business Transactions");
+ if (businessTransactionsList != null && businessTransactionsList.Count > 0 &&
+ businessTransactionsOverflowList != null && businessTransactionsOverflowList.Count > 0)
+ {
+ List businessTransactionTypesList = new List(100);
+ List businessTransactionTypesCountsList = new List(100);
+ List businessTransactionTypeAndCountsList = new List(100);
+
+ var groupTypes = businessTransactionsOverflowList.GroupBy(t => t.BTType);
+ measureTypesOfItemsInGroupBy(groupTypes, businessTransactionTypeAndCountsList, businessTransactionTypesList, businessTransactionTypesCountsList);
+
+ insertCellStringValue(builder, String.Format("{0} total\n{1} unregistered\n{2}", businessTransactionsList.Where(b => b.BTType == "OVERFLOW").Count(), businessTransactionsOverflowList.Count, String.Join("\n", businessTransactionTypeAndCountsList.ToArray())));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Overflow Business Transaction Types", businessTransactionTypesList.ToArray(), businessTransactionTypesCountsList.ToArray());
}
- if (businessTransactionsMetricsList != null)
+ else
{
- sb.AppendFormat("{0} active/{1} inactive", businessTransactionsMetricsList.Count(t => t.HasActivity == true), businessTransactionsMetricsList.Count(t => t.HasActivity == false));
+ insertCellStringValue(builder, "No business transaction list available");
+ insertCellStringValue(builder, String.Empty);
}
- insertNameValueRow(builder, table, "Business Transactions", sb.ToString());
- sb = new StringBuilder(200);
if (businessTransactionsMetricsList != null && businessTransactionsMetricsList.Count > 0)
{
- sb.AppendFormat("{0} active/{1} inactive", businessTransactionsMetricsList.Count(t => t.BTType == "OVERFLOW" && t.HasActivity == true), businessTransactionsMetricsList.Count(t => t.BTType == "OVERFLOW" && t.HasActivity == false));
+ string[] businessTransactionActivityArray = new string[2];
+ businessTransactionActivityArray[0] = "Has Activity";
+ businessTransactionActivityArray[1] = "No Activity";
+ double[] businessTransactionActivityCountsArray = new double[2];
+
+ businessTransactionActivityCountsArray[0] = businessTransactionsMetricsList.Where(b => b.BTType == "OVERFLOW").Count(t => t.HasActivity == true);
+ businessTransactionActivityCountsArray[1] = businessTransactionsMetricsList.Where(b => b.BTType == "OVERFLOW").Count(t => t.HasActivity == false);
+
+ insertCellStringValue(builder, String.Format("{0} active\n{1} inactive", businessTransactionActivityCountsArray[0], businessTransactionActivityCountsArray[1]));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Business Transaction Activity", businessTransactionActivityArray, businessTransactionActivityCountsArray);
+ }
+ else
+ {
+ insertCellStringValue(builder, "No metrics available");
+ insertCellStringValue(builder, String.Empty);
}
- insertNameValueRow(builder, table, "Overflow BTs", sb.ToString());
+ builder.EndRow();
+ #endregion
+
+ #region Backends
- sb = new StringBuilder(200);
- sb.AppendFormat("{0} total ", application.NumBackends);
+ insertCellNoValue(builder); insertLinkToBookmark(builder, hyperLinkStyle, "Backends", "Backends");
if (backendsList != null && backendsList.Count > 0)
{
- var groupTypes = backendsList.GroupBy(b => b.BackendType);
- sb.Append("(");
- foreach (var groupType in groupTypes)
- {
- sb.AppendFormat("{0} {1}", groupType.Count(), groupType.Key);
- sb.Append(", ");
- }
- if (sb.Length > 2) sb.Remove(sb.Length - 2, 2);
- sb.Append("), ");
+ List backendTypesList = new List(100);
+ List backendTypesCountsList = new List(100);
+ List backendTypeAndCountsList = new List(100);
+
+ var groupTypes = backendsList.GroupBy(t => t.BackendType);
+ measureTypesOfItemsInGroupBy(groupTypes, backendTypeAndCountsList, backendTypesList, backendTypesCountsList);
+
+ insertCellStringValue(builder, String.Format("{0} total\n{1}", backendsList.Count, String.Join("\n", backendTypeAndCountsList.ToArray())));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Backend Types", backendTypesList.ToArray(), backendTypesCountsList.ToArray());
}
- if (backendsMetricsList != null)
+ else
{
- sb.AppendFormat("{0} active/{1} inactive", backendsMetricsList.Count(t => t.HasActivity == true), backendsMetricsList.Count(t => t.HasActivity == false));
+ insertCellStringValue(builder, "No backend list available");
+ insertCellStringValue(builder, String.Empty);
}
- insertNameValueRow(builder, table, "Backends", sb.ToString());
- sb = new StringBuilder(200);
- sb.AppendFormat("{0} total ", application.NumSEPs);
+ if (backendsMetricsList != null && backendsMetricsList.Count > 0)
+ {
+ string[] backendActivityArray = new string[2];
+ backendActivityArray[0] = "Has Activity";
+ backendActivityArray[1] = "No Activity";
+ double[] backendActivityCountsArray = new double[2];
+
+ backendActivityCountsArray[0] = backendsMetricsList.Count(t => t.HasActivity == true);
+ backendActivityCountsArray[1] = backendsMetricsList.Count(t => t.HasActivity == false);
+
+ insertCellStringValue(builder, String.Format("{0} active\n{1} inactive", backendActivityCountsArray[0], backendActivityCountsArray[1]));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Backend Activity", backendActivityArray, backendActivityCountsArray);
+ }
+ else
+ {
+ insertCellStringValue(builder, "No metrics available");
+ insertCellStringValue(builder, String.Empty);
+ }
+ builder.EndRow();
+
+ #endregion
+
+ #region Service Endpoints
+
+ insertCellNoValue(builder); insertLinkToBookmark(builder, hyperLinkStyle, "Service Endpoints", "Service_Endpoints");
if (serviceEndpointsList != null && serviceEndpointsList.Count > 0)
{
- var groupTypes = serviceEndpointsList.GroupBy(b => b.SEPType);
- sb.Append("(");
- foreach (var groupType in groupTypes)
- {
- sb.AppendFormat("{0} {1}", groupType.Count(), groupType.Key);
- sb.Append(", ");
- }
- if (sb.Length > 2) sb.Remove(sb.Length - 2, 2);
- sb.Append("), ");
+ List serviceEndpointTypesList = new List(100);
+ List serviceEndpointTypesCountsList = new List(100);
+ List serviceEndpointTypeAndCountsList = new List(100);
+
+ var groupTypes = serviceEndpointsList.GroupBy(t => t.SEPType);
+ measureTypesOfItemsInGroupBy(groupTypes, serviceEndpointTypeAndCountsList, serviceEndpointTypesList, serviceEndpointTypesCountsList);
+
+ insertCellStringValue(builder, String.Format("{0} total\n{1}", serviceEndpointsList.Count, String.Join("\n", serviceEndpointTypeAndCountsList.ToArray())));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Service Endpoint Types", serviceEndpointTypesList.ToArray(), serviceEndpointTypesCountsList.ToArray());
}
- if (serviceEndpointsMetricsList != null)
+ else
{
- sb.AppendFormat("{0} active/{1} inactive", serviceEndpointsMetricsList.Count(t => t.HasActivity == true), serviceEndpointsMetricsList.Count(t => t.HasActivity == false));
+ insertCellStringValue(builder, "No service endpoint list available");
+ insertCellStringValue(builder, String.Empty);
}
- insertNameValueRow(builder, table, "Service Endpoints", sb.ToString());
- sb = new StringBuilder(200);
- sb.AppendFormat("{0} total ", application.NumErrors);
+ if (serviceEndpointsMetricsList != null && serviceEndpointsMetricsList.Count > 0)
+ {
+ string[] serviceEndpointActivityArray = new string[2];
+ serviceEndpointActivityArray[0] = "Has Activity";
+ serviceEndpointActivityArray[1] = "No Activity";
+ double[] serviceEndpointActivityCountsArray = new double[2];
+
+ serviceEndpointActivityCountsArray[0] = serviceEndpointsMetricsList.Count(t => t.HasActivity == true);
+ serviceEndpointActivityCountsArray[1] = serviceEndpointsMetricsList.Count(t => t.HasActivity == false);
+
+ insertCellStringValue(builder, String.Format("{0} active\n{1} inactive", serviceEndpointActivityCountsArray[0], serviceEndpointActivityCountsArray[1]));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Service Endpoint Activity", serviceEndpointActivityArray, serviceEndpointActivityCountsArray);
+ }
+ else
+ {
+ insertCellStringValue(builder, "No metrics available");
+ insertCellStringValue(builder, String.Empty);
+ }
+ builder.EndRow();
+
+ #endregion
+
+ #region Errors
+
+ insertCellNoValue(builder); insertLinkToBookmark(builder, hyperLinkStyle, "Errors", "Errors");
if (errorsList != null && errorsList.Count > 0)
{
- var groupTypes = errorsList.GroupBy(e => e.ErrorType);
- sb.Append("(");
- foreach (var groupType in groupTypes)
- {
- sb.AppendFormat("{0} {1}", groupType.Count(), groupType.Key);
- sb.Append(", ");
- }
- if (sb.Length > 2) sb.Remove(sb.Length - 2, 2);
- sb.Append("), ");
+ List errorTypesList = new List(100);
+ List errorTypesCountsList = new List(100);
+ List errorTypeAndCountsList = new List(100);
+
+ var groupTypes = errorsList.GroupBy(t => t.ErrorType);
+ measureTypesOfItemsInGroupBy(groupTypes, errorTypeAndCountsList, errorTypesList, errorTypesCountsList);
+
+ insertCellStringValue(builder, String.Format("{0} total\n{1}", errorsList.Count, String.Join("\n", errorTypeAndCountsList.ToArray())));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Error Types", errorTypesList.ToArray(), errorTypesCountsList.ToArray());
}
- if (errorsMetricsList != null)
+ else
{
- sb.AppendFormat("{0} active/{1} inactive", errorsMetricsList.Count(t => t.HasActivity == true), errorsMetricsList.Count(t => t.HasActivity == false));
+ insertCellStringValue(builder, "No error list available");
+ insertCellStringValue(builder, String.Empty);
}
- insertNameValueRow(builder, table, "Errors", sb.ToString());
- sb = new StringBuilder(200);
- sb.AppendFormat("{0} total ", application.NumIPs);
+ if (errorsMetricsList != null && errorsMetricsList.Count > 0)
+ {
+ string[] errorActivityArray = new string[2];
+ errorActivityArray[0] = "Has Activity";
+ errorActivityArray[1] = "No Activity";
+ double[] errorActivityCountsArray = new double[2];
+
+ errorActivityCountsArray[0] = errorsMetricsList.Count(t => t.HasActivity == true);
+ errorActivityCountsArray[1] = errorsMetricsList.Count(t => t.HasActivity == false);
+
+ insertCellStringValue(builder, String.Format("{0} active\n{1} inactive", errorActivityCountsArray[0], errorActivityCountsArray[1]));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Error Activity", errorActivityArray, errorActivityCountsArray);
+ }
+ else
+ {
+ insertCellStringValue(builder, "No metrics available");
+ insertCellStringValue(builder, String.Empty);
+ }
+ builder.EndRow();
+
+ #endregion
+
+ #region Information Points
+
+ insertCellNoValue(builder); insertLinkToBookmark(builder, hyperLinkStyle, "Information Points", "Information_Points");
if (informationPointsList != null && informationPointsList.Count > 0)
{
- var groupTypes = informationPointsList.GroupBy(p => p.IPType);
- sb.Append("(");
- foreach (var groupType in groupTypes)
- {
- sb.AppendFormat("{0} {1}", groupType.Count(), groupType.Key);
- sb.Append(", ");
- }
- if (sb.Length > 2) sb.Remove(sb.Length - 2, 2);
- sb.Append("), ");
+ List informationPointTypesList = new List(100);
+ List informationPointTypesCountsList = new List(100);
+ List informationPointTypeAndCountsList = new List(100);
+
+ var groupTypes = informationPointsList.GroupBy(t => t.IPType);
+ measureTypesOfItemsInGroupBy(groupTypes, informationPointTypeAndCountsList, informationPointTypesList, informationPointTypesCountsList);
+
+ insertCellStringValue(builder, String.Format("{0} total\n{1}", informationPointsList.Count, String.Join("\n", informationPointTypeAndCountsList.ToArray())));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Information Point Types", informationPointTypesList.ToArray(), informationPointTypesCountsList.ToArray());
}
- if (informationPointsMetricsList != null)
+ else
{
- sb.AppendFormat("{0} active/{1} inactive", informationPointsMetricsList.Count(t => t.HasActivity == true), informationPointsMetricsList.Count(t => t.HasActivity == false));
+ insertCellStringValue(builder, "No information point list available");
+ insertCellStringValue(builder, String.Empty);
}
- insertNameValueRow(builder, table, "Information Points", sb.ToString());
- sb = new StringBuilder(200);
+ if (informationPointsMetricsList != null && informationPointsMetricsList.Count > 0)
+ {
+ string[] informationPointActivityArray = new string[2];
+ informationPointActivityArray[0] = "Has Activity";
+ informationPointActivityArray[1] = "No Activity";
+ double[] informationPointActivityCountsArray = new double[2];
+
+ informationPointActivityCountsArray[0] = informationPointsMetricsList.Count(t => t.HasActivity == true);
+ informationPointActivityCountsArray[1] = informationPointsMetricsList.Count(t => t.HasActivity == false);
+
+ insertCellStringValue(builder, String.Format("{0} active\n{1} inactive", informationPointActivityCountsArray[0], informationPointActivityCountsArray[1]));
+ insertCellNoValue(builder);
+ insertPieChart(builder, "Information Point Activity", informationPointActivityArray, informationPointActivityCountsArray);
+ }
+ else
+ {
+ insertCellStringValue(builder, "No metrics available");
+ insertCellStringValue(builder, String.Empty);
+ }
+ builder.EndRow();
+
+ #endregion
+
+ finalizeTableApplicationEntityTypes(builder, tableApplicationEntitySummary);
+
+ #endregion
+
+ #region Detected Entity Dependencies
+
+ insertHeading(builder, StyleIdentifier.Heading2, "Detected Entity Dependencies", String.Empty, listHeadingsOutline, 1);
+
+ builder.ParagraphFormat.StyleIdentifier = StyleIdentifier.Normal;
+
+ Table tableApplicationEntityMapped = insertTableApplicationEntityMapped(builder);
+
+ #region Explicitly Registered Business Transactions
+
+ insertCellStringValue(builder, "Business Transaction Source");
+ if (businessTransactionsList != null && businessTransactionsList.Count > 0)
+ {
+ List businessTransactionTypesList = new List(100);
+ List businessTransactionTypesCountsList = new List