I have a script in which I'm trying to iterate through a list of strings, then take the value of the current variable, convert it to upper-case, then use use the result as a variable name. The end result will be to set the value of a prometheus metric, which is a global variable.
from prometheus_client import start_http_server, Gauge
# List of strings (global variables will be equal but upper-case)
MEASUREMENTS = ['x', 'y', 'z']
# Prometheus Metrics set as global variables
X = Gauge('some_value', 'some_description', ['label1', 'label2']
Y = Gauge('some_value', 'some_description', ['label1', 'label2']
Z = Gauge('some_value', 'some_description', ['label1', 'label2']
...
# Iterate through list of strings
for measurement in MEASUREMENTS:
metric = getattr(some_status, measurement) # Will be an integer
upper_measurement = measurement.upper() # Will equal the global variable name
[?UPPER_MEASUREMENT?].labels(label1=value_P1, label_2=value).set(metric) # This is where I need to reference the global variable name
Effectively this:
[?UPPER_MEASUREMENT?].labels(label1=value_P1, label_2=value).set(metric)
Needs to be:
X.labels(label1=value_P1, label_2=value).set(metric)
I tried:
upper_measurement.labels(label1=value_P1, label_2=value).set(metric)
But of course that will result in an error since it's a string:
Error: 'str' object has no attribute 'labels'
Not quite sure where to go from here. I could just write a big ugly block setting each metric, but I'd rather avoid that if possible.
CodePudding user response:
Define your metrics in a dictionary:
METRICS = {
key: Gauge('some_value', 'some_description', ['label1', 'label2'])
for key in ['x', 'y', 'z']
}
and then you can easily update all the metrics by iterating over the dictionary:
for key, metric in METRICS.items():
metric.labels(label1=value_P1, label_2=value).set(getattr(some_status, key))
CodePudding user response:
Even though I think the correct way of doing this should be using a Dictionary as other answers have pointed out, but if you still want to know, you could do this with eval()
. So, with just changing
[?UPPER_MEASUREMENT?].labels(label1=value_P1, label_2=value).set(metric)
with
eval(upper_measurement).labels(label1=value_P1, label_2=value).set(metric)
it should work. Beware if you're getting the elements of the MEASUREMENTS
list from some input that you can't sanitize before using eval()
, because it can potentially run dangerous code.