Using Exists() function with nested if/else statements

This article applies to:

  • Querying
  • Product edition: N/A
  • Feature Category: N/A

Overview

When crafting Tanzu Observability query's using the exists() function with nested if/else conditional statements, new users can sometimes get results that were not what they expected. Should a query use exists() with nested if/else statements, and both expressions return data, series matching occurs. This article demonstrates an approach that allows for results without series matching.  

 

Use Case 

In order to demonstrate the nested if/else series matching in action, the sample metric data, "~sample.cpu.usage.percentage" and "~sample.cpu.usage.user.percentage" will be used.

For example see screenshot below which uses the two sample metrics coming from two sources, app-1 and app-12. Both metrics values are multiplied by 100 for demonstration purposes.

mceclip1.png

For the purpose of demonstration, a user wants to display the "~sample.cpu.usage.percentage" metric from app-1 multiplied by 100, if the metric exists. Else if the metric does not exist, display the metric "~sample.cpu.usage.user.percentage" from app-12 multiplied by 100, if that metric exists. If neither metric exists display -1.

The expression would take the following format: 

if(exists(ts(~sample.cpu.usage.percentage, source=app-1)), ts(~sample.cpu.usage.percentage, source=app-1) * 100,
if(exists(ts(~sample.cpu.usage.user.percentage, source=app-12)), ts(~sample.cpu.usage.user.percentage, source=app-12) * 100, -1))

To test the query output, lets use the same expression but with the 1st exist in the if/else statement being false by using a source that doesn't exist, app-01.

if(exists(ts(~sample.cpu.usage.percentage, source=app-01)), ts(~sample.cpu.usage.percentage, source=app-1) * 100,
if(exists(ts(~sample.cpu.usage.user.percentage, source=app-12)), ts(~sample.cpu.usage.user.percentage, source=app-12) * 100,-1))

As app-01 doesn't exist the expression displays the output as expected.

mceclip2.png

To test with both expressions using a source that doesn't exist, a -1 should be displayed:

if(exists(ts(~sample.cpu.usage.percentage, source=app-01)), ts(~sample.cpu.usage.percentage, source=app-1) * 100,
if(exists(ts(~sample.cpu.usage.user.percentage, source=app-012)), ts(~sample.cpu.usage.user.percentage, source=app-012) * 100,-1))

mceclip5.png

So the nested if/else statements work as expected when one or more of the metrics does not exist. When both metrics exist in a nested if/else expression the results displayed can lead to confusion due to series matching occurring. See below, the if/else query is showing value of app-1 but source name app-12 due to series matching:

mceclip6.png

 

Workaround:

One way to workaround the exists() and nested if/else series matching problem, would be to use a combination of the retainSeries() and collect() functions to ensure the displayed output follows a traditional nested if/else logical output.

Using the same metrics as used above, the expression would take the following format: 

retainSeries(collect(if(exists(ts(~sample.cpu.usage.percentage, source=app-1) as var1), $var1 * 100 ),if(exists(ts(~sample.cpu.usage.user.percentage, source=app-12) as var2), $var2 * 100),-1), collect_0="0")

This expression ensures that the nested if/else works for all scenarios.   

mceclip7.png

 

For further details and information please see:

Series matching and IF
Pairing Up Matching Series

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

Comments

Powered by Zendesk