Home > database >  How to use local varaiable containing a string to reference the name of a Global Variable
How to use local varaiable containing a string to reference the name of a Global Variable

Time:03-27

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.

  • Related