| 
					
				 | 
			
			
				@@ -25,8 +25,8 @@ uptime_attributes = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 time_attributes = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "Status_eDirectorySystemCurrTime", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "CheckPointThreadData_CheckPointThreadStartTime", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "Status_eDirectorySystemCurrTime", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 time_attributes_ignored = [ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -59,7 +59,6 @@ non_graphable_attributes = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "Scheduler_Id", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "Handler_lock", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "Handler_state", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "IDM jvm_stats", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "IDM job_stats", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "system_properties", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ] 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -90,40 +89,105 @@ idm_nongraphable_attributes = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 total_counter_attributes = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "TrafficVolume_inBytes", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "TrafficVolume_outBytes", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "Errors_securityErrors", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "Errors_errors", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "Bindings_simpleAuthBinds", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "Bindings_unAuthBinds", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "Bindings_bindSecurityErrors", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "Bindings_strongAuthBinds", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "IncomingOperations_extendedOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "CacheFaultLooks_BlockCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "CacheFaultLooks_EntryCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "CacheFaultLooks_Total", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "Errors_errors", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "Errors_securityErrors", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "Hits_BlockCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "Hits_EntryCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "Hits_Total", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "HitLooks_BlockCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "HitLooks_EntryCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "HitLooks_Total", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "IncomingOperations_abandonOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "IncomingOperations_addEntryOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "IncomingOperations_compareOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "IncomingOperations_extendedOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "IncomingOperations_inOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "IncomingOperations_listOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "IncomingOperations_wholeSubtreeSearchOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "IncomingOperations_oneLevelSearchOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "IncomingOperations_searchOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "IncomingOperations_listOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "IncomingOperations_modifyRDNOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "IncomingOperations_modifyEntryOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "IncomingOperations_removeEntryOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "IncomingOperations_addEntryOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "IncomingOperations_compareOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "IncomingOperations_readOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "IncomingOperations_inOps", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "OutgoingOperations_chainings", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "CacheFaultLooks_Total", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "CacheFaultLooks_BlockCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "CacheFaultLooks_EntryCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "Hits_Total", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "Hits_BlockCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "Hits_EntryCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "HitLooks_Total", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "HitLooks_BlockCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    "HitLooks_EntryCache", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "OutBoundContext_ActiveOutBoundContextCount", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "OutBoundContext_TotalOutBoundContextCount", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     "Thread_Stats_Total_Shared_Count", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "TrafficVolume_inBytes", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "TrafficVolume_outBytes", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def print_sections(raw_result): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    separator = 124 # '|'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lines = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def process_item(item): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        """Process an individual item in the raw result.""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if isinstance(item, list): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for sub_item in item: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                process_item(sub_item) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif isinstance(item, dict): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for key, value in item.items(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if isinstance(value, list): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    value_str = chr(separator).join(value)  # Preserve list information by joining elements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    value_str = value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lines.append(f"{key}={value_str}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if "BackGroundProcInterval" not in str(item):  # Skip irrelevant sections 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lines.append(str(item)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for each_item in raw_result: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if isinstance(each_item, list): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            print_sections(each_item)  # Recursive call for nested lists 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        elif isinstance(each_item, tuple) and len(each_item) == 2: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            dn, attributes = each_item 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if "BackGroundProcInterval" in dn: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                continue  # Skip irrelevant DNs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            lines.append(clean_key(dn)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for key, value in attributes.items(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if key == "objectclass": 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    continue  # Skip objectclass attribute 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if isinstance(value, list):  # Handle list values 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    for item in value: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            decoded_value = item.decode("utf-8") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if len(decoded_value) != 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                lines.append(f"{key}={clean_value(decoded_value)}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        except AttributeError: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if len(item) != 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                lines.append(f"{key}={clean_value(item)}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else:  # Handle scalar values 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        decoded_value = value.decode("utf-8") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if len(decoded_value) != 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            lines.append(f"{key}={clean_value(decoded_value)}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    except AttributeError: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if len(item) != 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            lines.append(f"{key}={clean_value(value)}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            process_item(each_item) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if lines: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        print(chr(separator).join(lines)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def clean_value(value): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Clean and format the values by removing unwanted parts.""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cleaned_value = re.sub(' Bytes| KB| MB| ms', '', value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return cleaned_value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+def clean_key(key): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    """Clean and format the key by removing unwanted parts.""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cleaned_key = ' '.join(key.split(',')[::-1]).replace('cn=Monitor', '').replace('cn=', '').strip() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return cleaned_key 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 def format_partition_agent(value): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     """strip unwanted data from Agent Partition data""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     formatted = re.sub('CN=|OU=|O=|T=', '', value).replace("=", " ").replace(" ", "").split("#") 
			 |