Nested template variable evalutation

  • What Grafana version and what operating system are you using?

Grafana v7.3.7 (1e261642f4)
Ubuntu 20.04

MySQL datasource

  • What are you trying to achieve?

Evaluate nested template variable.

  • How are you trying to achieve it?

Trying to do something like
${${client}_numbers}

where, for example, inner_var is some “client” and the outer_var is “${client}_numbers”

I have also experimented with key-value pairs in the custom variable type, but I can’t figure out how to access JUST the key or the value from each. Ideally I would just do {inner_var: outervar} and be able to access the key:value pair but I don’t think you can do that.

  • What happened?

Query evaluates ${inner_var} but not the outer var.

  • What did you expect to happen?

Inner_var is evaluated, then outer_var is evaluated

  • Can you copy/paste the configuration(s) that you are having problems with?

WHERE
caller regexp ${${client}_numbers}

  • Did you receive any errors in the Grafana UI or in related logs? If so, please tell us exactly what they were.

Just failure from MySQL as the variable is not fully evaluated.

As you’ve discovered, this kind of syntax is not supported. To be honest I’m not sure there are many contexts (in computing generally) where recursive evaluation of variable names is carried out in this way.

My hunch is that Grafana should nonetheless be able to support your use case via chained variables, but it would help to have some more details on what you’re trying to achieve.

You mention that you want to substitute ${${client}_numbers}. Does that mean that for example if $client can have value A, B, or C, you have a set of other template variables called $A_numbers, $B_numbers, and $C_numbers which have values that you’d like to substitute into the query? Where do the values of those other template variables come from?

I understand you’re trying to work around something, but if the data you’re pulling is a SQL database I feel like this is quite an awkward setup.

You’ve probably tried this already, but a more conventional approach would be to have two chained variables like $client and $client_numbers. The former could correspond to a query like SELECT client_name FROM client_list that gets you all clients. And the latter might be something like SELECT number FROM client_number WHERE client_name=‘$client’ that selects all numbers for the client selected in the other variable. This is obviously a contrived example and probably nothing like what you actually need, but I figured it might be helpful to put out there.

Could you share a bit more about your use case and the data schema you’re pulling from? Would be keen to help work out a solution!

1 Like

You mention that you want to substitute ${${client}_numbers} . Does that mean that for example if $client can have value A, B, or C, you have a set of other template variables called $A_numbers , $B_numbers , and $C_numbers which have values that you’d like to substitute into the query? Where do the values of those other template variables come from?

Yes, you have it correct. I am working with call detail records, where I have a number of clients and a series of numbers associated with each client. Within the database, the numbers for each client are stored however the database has not been properly normalized for storing this data. The data cannot be drawn from the database in any intuitive way, using joins or the like. I am hard-coding the numbers as template variables instead.

I am already using the $client variable throughout the dashboard which is a Prometheus query; label_values(client), and all of the panels update depending on it. All existing panels are using a Prometheus datasource which is managed by myself, however I am now working with a MySQL datasource which I cannot make many changes to, if any. Note that the values for $client do not actually appear in the MySQL database.

You’ve probably tried this already, but a more conventional approach would be to have two chained variables like $client and $client_numbers . The former could correspond to a query like SELECT client_name FROM client_list that gets you all clients. And the latter might be something like SELECT number FROM client_number WHERE client_name=‘$client’ that selects all numbers for the client selected in the other variable. This is obviously a contrived example and probably nothing like what you actually need, but I figured it might be helpful to put out there.

Unfortunately I do not think this is a viable option, as I do not have access to the actual client numbers from within the database. As stated above, I am left to hard-code these values into variables.

I was experimenting with a custom variable type using key:value pairs, client being key and list of numbers being value, but I could not figure out if there was a way to access just the key or the value for each selected item. This method would have worked out perfectly if not for that issue.

Thanks @crockk for the detailed explanation. It does sound like a complex setup you’re trying to work with!

To your last point regarding controlling what you get from a key-value variable, maybe check out https://github.com/grafana/grafana/pull/27829#issuecomment-731483712 and related comments/links in that thread. You should in principle be able to get back just the key or the value.

1 Like

Oh, nice, this worked actually. I just missed the fact that you have to include a space in between the key : value when defining the custom variable. Once I did that I could reference the key with ${var:text} and the value with ${var}. Thanks a lot!

1 Like