Skip to content

Commit

Permalink
feat:export complex nested values as a metric (#266)
Browse files Browse the repository at this point in the history
* feat:export complex nested values as a metric

* one metric per vm

* remove condition

Co-authored-by: Tommy Sauer <[email protected]>

* remove assignment

Co-authored-by: Tommy Sauer <[email protected]>

* return value directly

Co-authored-by: Tommy Sauer <[email protected]>

* return value directly

Co-authored-by: Tommy Sauer <[email protected]>

* cleanup, move label extension to a dedicated function

* Update collectors/SDRSPropertiesCollector.py

Co-authored-by: Tommy Sauer <[email protected]>

* ensure json.loads()

---------

Co-authored-by: Tommy Sauer <[email protected]>
  • Loading branch information
richardtief and viennaa authored Feb 27, 2024
1 parent a841ebe commit b24acf1
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 5 deletions.
7 changes: 7 additions & 0 deletions BaseCollector.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def __init__(self):
self.label_names = []
self.project_ids = []
self.collect_running = False
self.nested_value_metric_keys = []

@abstractmethod
def collect(self):
Expand Down Expand Up @@ -373,6 +374,12 @@ def generate_alert_metrics(self, label_names: list) -> InfoMetricFamily:
labels=label_names)
return alert_metric

def add_metric_labels(self, metric_object: GaugeMetricFamily, labels):
if labels[0] not in metric_object._labelnames:
for label in labels:
metric_object._labelnames += (label,)
return

def describe(self):
collector_config = self.read_collector_config()
for metric in collector_config[self.name]:
Expand Down
27 changes: 23 additions & 4 deletions collectors/PropertiesCollector.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ class PropertiesCollector(BaseCollector):
def get_resource_uuids(self):
raise NotImplementedError("Please Implement this method")

def unlock_nested_values(self, s, m):
raise NotImplementedError("Please Implement this method")

def get_labels(self, resource_id: str, project_ids: list):
raise NotImplementedError("Please Implement this method")

def collect(self):
self.collect_running = True
logger.info(f'{self.name} starts with collecting the metrics')
if self.nested_value_metric_keys:
logger.info(f'Found nested metric values for: {self.name}, keys: {self.nested_value_metric_keys}')

token = self.get_target_tokens()
token = token.setdefault(self.target, '')
Expand Down Expand Up @@ -60,11 +65,26 @@ def collect(self):
metric_data = value_entry.get('data', [False])[0]
metric_value = value_entry.get('values', [False])[0]

if statkey in self.nested_value_metric_keys:

add_labels, add_label_value_list, add_value = self.unlock_nested_values(statkey, metric_value)

if not add_labels:
metric_suffix = metrics[statkey]['metric_suffix']
self.add_metric_labels(metrics[statkey]['gauge'], [metric_suffix])
metrics[statkey]['gauge'].add_metric(labels=labels+[metric_suffix], value=0)
continue

self.add_metric_labels(metrics[statkey]['gauge'], add_labels)

for add_label_value in add_label_value_list:
metrics[statkey]['gauge'].add_metric(labels=labels+add_label_value, value=add_value)
continue

if statkey in metrics:
# enum metrics
if metrics[statkey]['expected']:
if 'state' not in metrics[statkey]['gauge']._labelnames:
metrics[statkey]['gauge']._labelnames += ('state',)
self.add_metric_labels(metrics[statkey]['gauge'], ['state'])

state = metric_value if metric_value else 'n/a'
labels.append(state)
Expand All @@ -74,8 +94,7 @@ def collect(self):
# string values
elif metric_value:
metric_suffix = metrics[statkey]['metric_suffix']
if metric_suffix not in metrics[statkey]['gauge']._labelnames:
metrics[statkey]['gauge']._labelnames += (metric_suffix,)
self.add_metric_labels(metrics[statkey]['gauge'], [metric_suffix])

labels.append(metric_value)
metrics[statkey]['gauge'].add_metric(labels=labels, value=1)
Expand Down
65 changes: 65 additions & 0 deletions collectors/SDRSPropertiesCollector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from collectors.PropertiesCollector import PropertiesCollector
import json
import logging

logger = logging.getLogger('vrops-exporter')

class SDRSPropertiesCollector(PropertiesCollector):

def __init__(self):
super().__init__()
self.vrops_entity_name = 'storagepod'
self.label_names = [self.vrops_entity_name, 'vcenter', 'datacenter']
self.nested_value_metric_keys = [
"config|sdrsconfig|vmStorageAntiAffinityRules"
]

def get_resource_uuids(self):
return self.get_SDRS_clusters_by_target()

def get_labels(self, resource_id, project_ids):
return [self.sdrs_clusters[resource_id]['name'],
self.sdrs_clusters[resource_id]['vcenter'],
self.sdrs_clusters[resource_id]['parent_dc_name'].lower()] if resource_id in self.sdrs_clusters else []

def unlock_nested_values(self, statkey, metric_value):

match statkey:
case "config|sdrsconfig|vmStorageAntiAffinityRules":
return self.config_sdrsconfig_vmStorageAntiAffinityRules(metric_value)

def config_sdrsconfig_vmStorageAntiAffinityRules(self, metric_value):

try:
metric_value = json.loads(metric_value)

except (TypeError, json.decoder.JSONDecodeError) as e:
logger.warning(f'metric_value is not a valid json: {e.args}, {metric_value}')
return [], [], 0

rules = metric_value.get("rules") or []
amount_rules = len(rules)

rule_labels = ['rule', 'rule_name', 'rule_type', 'valid', 'virtualmachine']
rule_label_values = []

for i, rule in enumerate(rules):
mapped_vms = self.vm_mapping_helper(rule.get('virtualMachines', []))
for vm in mapped_vms:
rule_label_values.append([
f'{i+1}/{amount_rules}',
rule.get('name'),
rule.get('type'),
str(rule.get('valid')).lower(),
vm
])
return rule_labels, rule_label_values, 1

def vm_mapping_helper(self, vm_list):
mapped_vms = []
vms = self.get_vms(self.target)
for rule_vm in vm_list:
for vm in vms:
if rule_vm == vms[vm].get('internal_name'):
mapped_vms.append(vms[vm].get('name'))
return mapped_vms
2 changes: 1 addition & 1 deletion collectors/SDRSStatsCollector.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ def get_resource_uuids(self):
def get_labels(self, resource_id, project_ids):
return [self.sdrs_clusters[resource_id]['name'],
self.sdrs_clusters[resource_id]['vcenter'],
self.sdrs_clusters[resource_id]['parent_dc_name'].lower()] if resource_id in self.sdrs_clusters else []
self.sdrs_clusters[resource_id]['parent_dc_name'].lower()] if resource_id in self.sdrs_clusters else []
5 changes: 5 additions & 0 deletions tests/collector_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ default_collectors:
- 'DistributedvSwitchPropertiesCollector'
- 'DatastoreStatsCollector'
- 'SDRSStatsCollector'
- 'SDRSPropertiesCollector'
- 'DatastorePropertiesCollector'
- 'HostSystemStatsCollector'
- 'HostSystemPropertiesCollector'
Expand Down Expand Up @@ -102,6 +103,10 @@ SDRSStatsCollector:
- metric_suffix: "capacity_remaining_percentage"
key: "OnlineCapacityAnalytics|capacityRemainingPercentage"

SDRSPropertiesCollector:
- metric_suffix: "config_sdrsconfig_vmStorageAntiAffinityRules"
key: "config|sdrsconfig|vmStorageAntiAffinityRules"

DatastorePropertiesCollector:
- metric_suffix: "summary_datastore_accessible"
expected: "PoweredOn"
Expand Down

0 comments on commit b24acf1

Please sign in to comment.