Skip to content

Commit 00d6cd6

Browse files
committed
transfer dev to fork
1 parent dbbde02 commit 00d6cd6

File tree

6 files changed

+129
-94
lines changed

6 files changed

+129
-94
lines changed

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ Options:
138138
-c, --concurrent-connections INTEGER
139139
-u, --username TEXT Adds the option to put username dynamically
140140
-p, --password TEXT Adds the option to put password dynamically
141-
--car Generate the configration analysis report as part of the output
142141
--help Show this help message and exit.
143142
```
144143

@@ -198,7 +197,6 @@ Options:
198197
-c, --concurrent-connections INTEGER
199198
-u, --username TEXT Adds the option to put username dynamically
200199
-p, --password TEXT Adds the option to put password dynamically
201-
--car Generate the configration analysis report as part of the output
202200
--help Show this help message and exit
203201
```
204202

@@ -326,3 +324,19 @@ Debug logs can be taken by either:
326324

327325
- checking the `debug` checkbox in the UI
328326
- running the backend with the `--debug` or `-d` flag
327+
328+
329+
330+
release notes:
331+
-CAR report generated automically now as part of the artifacts generated.
332+
- UI enhancements (#160):
333+
- UI now supports Dynamic Credentials for API client secret and token entries. Previously only basic auth was supported.
334+
- You can view job file/threshhold files in-line rather than popup OS editor
335+
- #157 - Archive function added to keep a copy of all generated reports, timestamped in the "output/archive" diretory
336+
- Makefile added to ease building artifacts, docker images, running CAT from source, bundling, etc.
337+
- bug fixes
338+
- #156
339+
340+
341+
342+

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v1.8
1+
v1.8.0

backend/api/appd/AppDService.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -561,12 +561,6 @@ async def getAnalyticsEnabledStatusForAllApplications(self) -> Result:
561561

562562
async def getDashboards(self) -> Result:
563563

564-
# self.controller.jsessionid = "c618719074f568d36fa97fca95c7"
565-
# self.controller.xcsrftoken= "8c6b20c6ee1128ae47b8c4c782a6a28b55b5dc3d"
566-
# self.controller.session.headers["X-CSRF-TOKEN"] = ( self.controller.xcsrftoken)
567-
# self.controller.session.headers["Set-Cookie"] = (f"JSESSIONID="
568-
# f"{self.controller.jsessionid};X-CSRF-TOKEN={self.controller.xcsrftoken};")
569-
570564
debugString = f"Gathering Dashboards"
571565
logging.debug(f"{self.host} - {debugString}")
572566
response = await self.controller.getAllDashboardsMetadata()

backend/extractionSteps/maturityAssessment/apm/AppAgentsAPM.py

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -180,71 +180,72 @@ def analyze(self, controllerData, thresholds):
180180
application["appAgentVersions"] = []
181181

182182
for node in application["nodes"]:
183-
if node["appAgentVersion"] in nodeVersionMap:
183+
app_agent_present = node.get("appAgentPresent") is True
184+
if app_agent_present and node["appAgentVersion"] in nodeVersionMap:
184185
nodeVersionMap[node["appAgentVersion"]] += 1
185-
else:
186+
elif app_agent_present:
186187
nodeVersionMap[node["appAgentVersion"]] = 1
187188

188189
# Calculate version age
189-
numberNodesWithAppAgentInstalled += 1
190-
if "" == node["appAgentVersion"]: # No agent installed
191-
continue
190+
numberNodesWithAppAgentInstalled += 1
191+
if not app_agent_present:
192+
continue
192193

193-
version = semanticVersionRegex.search(node["appAgentVersion"])[0].split(".") # e.g. 'Server Agent v21.6.1.2 GA ...'
194-
majorVersion = int(version[0])
195-
minorVersion = int(version[1])
194+
version = semanticVersionRegex.search(node["appAgentVersion"])[0].split(".") # e.g. 'Server Agent v21.6.1.2 GA ...'
195+
majorVersion = int(version[0])
196+
minorVersion = int(version[1])
196197

197198
hostInfo["appAgentVersions"].add((majorVersion, minorVersion, node["agentType"]))
198199
application["appAgentVersions"].append(f"{node['agentType']}:{version[0]}.{version[1]}")
199200

200-
if majorVersion == 4: # Agents with version 4 and below will always fail.
201-
node["appAgentAge"] = 3
202-
else:
203-
years = currYear - majorVersion
204-
if minorVersion < currMonth:
205-
years += 1
206-
node["appAgentAge"] = years
201+
if majorVersion == 4: # Agents with version 4 and below will always fail.
202+
node["appAgentAge"] = 3
203+
else:
204+
years = currYear - majorVersion
205+
if minorVersion < currMonth:
206+
years += 1
207+
node["appAgentAge"] = years
207208

208-
if years <= 2:
209-
numberAppAgentsLessThan2YearsOld += 1
210-
if years == 1:
211-
numberAppAgentsLessThan1YearOld += 1
209+
if years <= 2:
210+
numberAppAgentsLessThan2YearsOld += 1
211+
if years == 1:
212+
numberAppAgentsLessThan1YearOld += 1
212213

213-
# Determine application load
214-
if node["appAgentAvailability"] != 0:
215-
numberAppAgentsReportingData += 1
214+
# Determine application load
215+
if node["appAgentAvailability"] != 0:
216+
numberAppAgentsReportingData += 1
216217

217-
if node["nodeMetricsUploadRequestsExceedingLimit"] != 0:
218-
analysisDataEvaluatedMetrics["metricLimitNotHit"] = False
218+
if node["nodeMetricsUploadRequestsExceedingLimit"] != 0:
219+
analysisDataEvaluatedMetrics["metricLimitNotHit"] = False
219220

220-
# In the case of multiple versions, will return the largest common agent count regardless of version.
221-
try:
221+
# In the case of multiple versions, will return the largest common agent count regardless of version.
222+
try:
222223
numberAppAgentsRunningSameVersion = nodeVersionMap[max(nodeVersionMap, key=nodeVersionMap.get)]
223-
except ValueError:
224-
logging.debug(
225-
f'{hostInfo["controller"].host} - No app agents returned for application {application["name"]}, unable to parse agent versions.'
226-
)
224+
except ValueError:
225+
logging.debug(
226+
f'{hostInfo["controller"].host} - No app agents returned for application {application["name"]}, unable to parse agent versions.'
227+
)
227228

228-
# Calculate percents of compliant nodes.
229-
if numberNodesWithAppAgentInstalled != 0.0:
229+
# Calculate percents of compliant nodes.
230+
if numberNodesWithAppAgentInstalled != 0.0:
230231
analysisDataEvaluatedMetrics["percentAgentsLessThan1YearOld"] = (
231232
numberAppAgentsLessThan1YearOld / numberNodesWithAppAgentInstalled * 100
232-
)
233+
)
233234
analysisDataEvaluatedMetrics["percentAgentsLessThan2YearsOld"] = (
234235
numberAppAgentsLessThan2YearsOld / numberNodesWithAppAgentInstalled * 100
235-
)
236+
)
236237
analysisDataEvaluatedMetrics["percentAgentsReportingData"] = numberAppAgentsReportingData / numberNodesWithAppAgentInstalled * 100
237238
analysisDataEvaluatedMetrics["percentAgentsRunningSameVersion"] = (
238239
numberAppAgentsRunningSameVersion / numberNodesWithAppAgentInstalled * 100
239-
)
240-
else:
240+
)
241+
else:
241242
analysisDataEvaluatedMetrics["percentAgentsLessThan1YearOld"] = 0
242243
analysisDataEvaluatedMetrics["percentAgentsLessThan2YearsOld"] = 0
243-
analysisDataEvaluatedMetrics["percentAgentsReportingData"] = 0
244+
analysisDataEvaluatedMetrics["percentAgentsReportingData"] = 0
244245
analysisDataEvaluatedMetrics["percentAgentsRunningSameVersion"] = 0
245246

246-
analysisDataRawMetrics["numberOfNodes"] = len(application["nodes"])
247-
analysisDataRawMetrics["numberOfTiers"] = len(application["tiers"])
247+
analysisDataRawMetrics["numberOfNodes"] = len(application["nodes"])
248+
analysisDataRawMetrics["numberOfTiers"] = len(application["tiers"])
248249
analysisDataRawMetrics["numberNodesWithAppAgentInstalled"] = numberNodesWithAppAgentInstalled
249250
analysisDataRawMetrics["numberAppAgentsLessThan1YearOld"] = numberAppAgentsLessThan1YearOld
250251
analysisDataRawMetrics["numberAppAgentsLessThan2YearsOld"] = numberAppAgentsLessThan2YearsOld

backend/extractionSteps/maturityAssessment/apm/MachineAgentsAPM.py

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -124,73 +124,99 @@ def analyze(self, controllerData, thresholds):
124124
application["machineAgentVersions"] = []
125125

126126
for node in application["nodes"]:
127-
if node["machineAgentVersion"] in nodeVersionMap:
128-
nodeVersionMap[node["machineAgentVersion"]] += 1
129-
else:
130-
nodeVersionMap[node["machineAgentVersion"]] = 1
131-
132-
if node["appAgentPresent"] and node["machineAgentPresent"]:
133-
numberMachineAgentsInstalledAlongsideAppAgents += 1
134-
135-
if node["machineAgentPresent"]:
127+
if node.get("machineAgentPresent", False):
136128
numberNodesWithMachineAgentInstalled += 1
137-
else:
138-
logging.info("machineAgentPresent NOT present!")
139-
continue
140-
141-
# Calculate version age
142-
version = semanticVersionRegex.search(node["machineAgentVersion"])[0].split(".") # e.g. 'Server Agent v21.6.1.2 GA ...'
143-
majorVersion = int(version[0])
144-
minorVersion = int(version[1])
145-
146-
logging.info(f'major version: {majorVersion}, minor version: {minorVersion}')
147129

148-
149-
hostInfo["machineAgentVersions"].add((majorVersion, minorVersion))
150-
application["machineAgentVersions"].append(f"{version[0]}.{version[1]}")
151-
152-
if majorVersion == 4: # Agents with version 4 and below will always fail.
153-
node["machineAgentAge"] = 3
130+
# Check if an App Agent is also present to count agents installed alongside each other.
131+
# Assuming 'appAgentPresent' is always a key if 'node' is well-formed.
132+
if node["appAgentPresent"]:
133+
numberMachineAgentsInstalledAlongsideAppAgents += 1
134+
135+
# Safely retrieve the machine agent version string from the nested metadata.
136+
# Using .get() with default empty dictionaries to prevent KeyError if intermediate keys are missing.
137+
machine_agent_version_str = node.get('metadata', {}).get('applicationComponentNode', {}).get('machineAgentVersion')
138+
139+
if machine_agent_version_str: # Only proceed if the version string is not None or empty
140+
# Update nodeVersionMap with the retrieved version string
141+
if machine_agent_version_str in nodeVersionMap:
142+
nodeVersionMap[machine_agent_version_str] += 1
143+
else:
144+
nodeVersionMap[machine_agent_version_str] = 1
145+
146+
logging.info(f'application {application["name"]} node data: {node}')
147+
148+
# Calculate version age
149+
match = semanticVersionRegex.search(machine_agent_version_str)
150+
if match:
151+
version = match[0].split(".")
152+
majorVersion = int(version[0])
153+
minorVersion = int(version[1])
154+
155+
logging.info(f'major version: {majorVersion}, minor version: {minorVersion}')
156+
157+
hostInfo["machineAgentVersions"].add((majorVersion, minorVersion))
158+
application["machineAgentVersions"].append(f"{version[0]}.{version[1]}")
159+
160+
if majorVersion == 4: # Agents with version 4 and below will always fail.
161+
node["machineAgentAge"] = 3
162+
else:
163+
years = currYear - majorVersion
164+
if minorVersion < currMonth:
165+
years += 1
166+
node["machineAgentAge"] = years
167+
168+
if years <= 2:
169+
numberMachineAgentsLessThan2YearsOld += 1
170+
if years == 1:
171+
numberMachineAgentsLessThan1YearOld += 1
172+
else:
173+
logging.warning(f"Could not parse machine agent version from '{machine_agent_version_str}' for node {node.get('name', 'unknown')}. Skipping age calculation.")
174+
node["machineAgentAge"] = None # Indicate that age couldn't be determined
175+
else:
176+
logging.warning(f"Machine agent present for node {node.get('name', 'unknown')}, but 'machineAgentVersion' is None or empty in metadata. Skipping version-dependent analysis.")
177+
node["machineAgentAge"] = None # Indicate that age couldn't be determined
178+
179+
# Determine application load - this uses 'machineAgentAvailability' which is at the top level of 'node'
180+
if node.get("machineAgentAvailability", 0) != 0:
181+
numberMachineAgentsReportingData += 1
154182
else:
155-
years = currYear - majorVersion
156-
if minorVersion < currMonth:
157-
years += 1
158-
node["machineAgentAge"] = years
159-
160-
if years <= 2:
161-
numberMachineAgentsLessThan2YearsOld += 1
162-
if years == 1:
163-
numberMachineAgentsLessThan1YearOld += 1
164-
165-
# Determine application load
166-
if node["machineAgentAvailability"] != 0:
167-
numberMachineAgentsReportingData += 1
183+
logging.info(f"No machine agent present for node {node.get('name', 'unknown')}. Skipping machine agent specific analysis for this node.")
184+
# The original code had a 'continue' here to skip the rest of the loop for this node
185+
# if 'machineAgentPresent' was False. We maintain that behavior.
186+
continue # Skip to the next node if no machine agent is present.
168187

169188
# In the case of multiple versions, will return the largest common agent count regardless of version.
170189
try:
171-
numberMachineAgentsRunningSameVersion = nodeVersionMap[max(nodeVersionMap, key=nodeVersionMap.get)]
190+
# Only attempt to find the max if nodeVersionMap is not empty
191+
if nodeVersionMap:
192+
numberMachineAgentsRunningSameVersion = nodeVersionMap[max(nodeVersionMap, key=nodeVersionMap.get)]
193+
else:
194+
numberMachineAgentsRunningSameVersion = 0 # No machine agents, so 0 running same version
172195
except ValueError:
196+
# This ValueError typically happens if max() is called on an empty sequence,
197+
# which is now explicitly handled by 'if nodeVersionMap:'. This block might be redundant but harmless.
173198
logging.debug(
174199
f'{hostInfo["controller"].host} - No machine agents returned for application {application["name"]}, unable to parse agent versions.'
175200
)
201+
numberMachineAgentsRunningSameVersion = 0 # Ensure it's initialized even on error
176202

177203
# Calculate percentage of compliant nodes.
178204
# Default all to bronze. Will be modified in call to 'applyThresholds'.
179205
if numberNodesWithMachineAgentInstalled != 0.0:
180206
analysisDataEvaluatedMetrics["percentAgentsLessThan1YearOld"] = (
181-
numberMachineAgentsLessThan1YearOld / numberNodesWithMachineAgentInstalled * 100
207+
numberMachineAgentsLessThan1YearOld / numberNodesWithMachineAgentInstalled * 100
182208
)
183209
analysisDataEvaluatedMetrics["percentAgentsLessThan2YearsOld"] = (
184-
numberMachineAgentsLessThan2YearsOld / numberNodesWithMachineAgentInstalled * 100
210+
numberMachineAgentsLessThan2YearsOld / numberNodesWithMachineAgentInstalled * 100
185211
)
186212
analysisDataEvaluatedMetrics["percentAgentsReportingData"] = (
187-
numberMachineAgentsReportingData / numberNodesWithMachineAgentInstalled * 100
213+
numberMachineAgentsReportingData / numberNodesWithMachineAgentInstalled * 100
188214
)
189215
analysisDataEvaluatedMetrics["percentAgentsRunningSameVersion"] = (
190-
numberMachineAgentsRunningSameVersion / numberNodesWithMachineAgentInstalled * 100
216+
numberMachineAgentsRunningSameVersion / numberNodesWithMachineAgentInstalled * 100
191217
)
192218
analysisDataEvaluatedMetrics["percentAgentsInstalledAlongsideAppAgents"] = (
193-
numberMachineAgentsInstalledAlongsideAppAgents / numberNodesWithMachineAgentInstalled * 100
219+
numberMachineAgentsInstalledAlongsideAppAgents / numberNodesWithMachineAgentInstalled * 100
194220
)
195221
else:
196222
analysisDataEvaluatedMetrics["percentAgentsLessThan1YearOld"] = 0
@@ -205,4 +231,4 @@ def analyze(self, controllerData, thresholds):
205231
analysisDataRawMetrics["numberMachineAgentsLessThan1YearOld"] = numberMachineAgentsLessThan1YearOld
206232
analysisDataRawMetrics["numberMachineAgentsLessThan2YearsOld"] = numberMachineAgentsLessThan2YearsOld
207233

208-
self.applyThresholds(analysisDataEvaluatedMetrics, analysisDataRoot, jobStepThresholds)
234+
self.applyThresholds(analysisDataEvaluatedMetrics, analysisDataRoot, jobStepThresholds)

backend/output/presentations/cxPptFsoUseCases.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ def createCxHamUseCasePpt(folder: str):
544544
f"{file_prefix}-Synthetics.xlsx"
545545
))
546546

547-
assert len(excels.getWorkBooks()) >= 9
547+
assert len(excels.getWorkBooks()) >= 10
548548

549549
# currently only 1st controller in the job file is examined.
550550
controller = getValuesInColumn(apm_wb["Analysis"], "controller")[0]

0 commit comments

Comments
 (0)