AQL Standard Library

Functions

General functions

now

Added in revision 1

Function now returns the current time. Time is constant across all the script, so that all operations and queries have the same reference time.

>>> now()
2019-09-01T14:05:10Z

length

Added in revision 1

Function length returns the number of elements in a str, a timeseries or a dict.

>>> length(`analytics:/path/to/data`[0])
1

merge

Added in revision 1

Function merge returns a union of all the dicts contained in a timeseries. In case of key collision, the latest entry is kept.

>>> `analytics:/path/to/data`[1]
timeseries{
        tstamp1: dict{key1: val1, key2: val2, key3: val3}
        tstamp2: dict{key1: val4, key2: val5}
}
>>> merge(_)
dict{key1: val4, key2: val5, key: val3}

deletes

Added in revision 1

Function deletes returns a timeseries of dicts used as sets of the delete keys from the input timeseries. Only works with unfiltered timeseries, as most filters remove the deletes entries. An empty dict as value means the update is a DeleteAll

  • The first and only parameter is the timeseries

>>> deletes(`analytics:/path/to/data`[200])
timeseries{
        tstamp1: dict{key1: nil, key2: nil}
        tstamp2: dict{} # this deletes all keys
}

equal

Added in revision 1

Function equal performs a cross-type equality check on the given arguments using type coercions.

  • The first argument is a value of any type

  • The second argument is a value of any type

>>> equal("1", 1)
true
>>> equal(1, true)
true
>>> equal(0, true)
false

complexKey

Added in revision 1

Function complexKey parses a string containing a literal or json object. Numerical values without floating-point will produce an integer. Numerical values with a floating point will produce a float64 (num). Boolean literals will produce a boolean (bool). Values surrounded with {} or [] will be parsed as JSON. For all cases except float64 (num) and bool, the returned value will be of type unknown (internal interpreter type), but can be used to access complex keys in dicts.

  • The first and only parameter is the str to parse

>>> complexKey("1")
int(1) # AQL type is unknown
>>> complexKey("1.2")
float64(1.2) # AQL type is num
>>> complexKey("{\"key1\": 1, \"key2\": true}")
{"key1":1,"key2":true}# AQL type is unknown
>>> complexKey("[1, 2, true]")
[1,2,true] # AQL type is unknown

Dicts functions

newDict

Added in revision 1

Function newDict returns a new empty dict.

>>> newDict()
dict{}

dictRemove

Added in revision 1

Function dictRemove removes a given key from a dict.

  • The first argument is the dict

  • The second argument is the key to remove

>>> let d = newDict()
>>> d["key"] = 1
>>> d["key2"] = 2
>>> d
dict{"key": 1, "key2": 2}
>>> dictRemove(d, "key")
>>> d
dict{"key2": 2}

dictHasKey

Added in revision 1

Function dictHasKey returns true if a dict contains the specified key, false if it doesn’t.

  • The first parameter is the dict

  • The second parameter is the key

>>> let d = newDict()
>>> d["key"] = 1
>>> d["key2"] = 2
>>> d
dict{"key": 1, "key2": 2}
>>> dictHasKey(d, "key")
true
>>> dictHasKey(d, "key3")
false

dictKeys

Added in revision 1

Function dictKeys returns a timeseries with the list of keys in a dict.

  • The first and only parameter is the dict

>>> let d = newDict()
>>> d["key"] = 1
>>> d["key2"] = 2
>>> d
dict{"key": 1, "key2": 2}
>>> dictKeys(d)
timeseries{
        0000-00-00 00:00:00.000000001: "key"
        0000-00-00 00:00:00.000000002: "key2"
}

unnestTimeseries

Added in revision 4

Function unnestTimeseries merges multiple timeseries nested in dicts, pushes them to the top level, and returns a single flattened timeseries where the former top-level dicts are now nested within the timeseries’ values. The input data is typically what a query using * wildcards would return.

  • The first and only parameter is a dict that contains timeseries, either directly in the value, or nested in more levels of dict.

Example
>>> let ts = `analytics:/Devices/*/versioned-data/interfaces/data/*/aggregate/hardware/xcvr/1m`[1m] | recmap(2, _value | field("temperature") | field("avg"))
>>> let d = newDict() | setFields("AA", ts)
>>> d
dict{AA: dict{
                HSH14280171: dict{
                        Ethernet50: timeseries{
                                start: 2022-08-16 17:10:21.217673 +0200 CEST
                                end: 2022-08-16 17:11:21.217673 +0200 CEST
                                2022-08-16 17:10:00 +0200 CEST: 34.184087816704434
                                2022-08-16 17:11:00 +0200 CEST: 34.18519049983288
                        }
                        Ethernet51: timeseries{
                                start: 2022-08-16 17:10:21.217673 +0200 CEST
                                end: 2022-08-16 17:11:21.217673 +0200 CEST
                                2022-08-16 17:10:00 +0200 CEST: 34.84759166533158
                                2022-08-16 17:11:00 +0200 CEST: 34.84247911778802
                        }
                }
                JAS17070003: dict{
                        Ethernet50: timeseries{
                                start: 2022-08-16 17:10:21.217673 +0200 CEST
                                end: 2022-08-16 17:11:21.217673 +0200 CEST
                                2022-08-16 17:10:00 +0200 CEST: 30.65325390983907
                                2022-08-16 17:11:00 +0200 CEST: 30.65664047328105
                        }
                        Ethernet51: timeseries{
                                start: 2022-08-16 17:10:21.217673 +0200 CEST
                                end: 2022-08-16 17:11:21.217673 +0200 CEST
                                2022-08-16 17:10:00 +0200 CEST: 27.58473123455124
                                2022-08-16 17:11:00 +0200 CEST: 27.597529745280074
                        }
                }
        }}
>>> unnestTimeseries(d)
timeseries{
        start: 2022-08-16 17:10:21.217673 +0200 CEST
        end: 2022-08-16 17:11:21.217673 +0200 CEST
        2022-08-16 17:10:00 +0200 CEST: dict{AA: dict{
                        HSH14280171: dict{
                                Ethernet50: 34.184087816704434
                                Ethernet51: 34.84759166533158
                        }
                        JAS17070003: dict{
                                Ethernet50: 30.65325390983907
                                Ethernet51: 27.58473123455124
                        }
                }}
        2022-08-16 17:11:00 +0200 CEST: dict{AA: dict{
                        HSH14280171: dict{
                                Ethernet50: 34.18519049983288
                                Ethernet51: 34.84247911778802
                        }
                        JAS17070003: dict{
                                Ethernet50: 30.65664047328105
                                Ethernet51: 27.597529745280074
                        }
                }}
}
>>> let b = `analytics:/Devices/JPE17191574/versioned-data/interfaces/data/Ethernet50/aggregate/hardware/xcvr/1m`[2m] | field("voltage") | field("max")
>>> let dd = newDict() | setFields("BB", b)
>>> let ddd = newDict() | setFields("DD", ts, "EE", dd)
>>> d["FF"]=ddd
>>> d
dict{
        AA: dict{
                HSH14280171: dict{
                        Ethernet50: timeseries{
                                start: 2022-08-16 17:10:21.217673 +0200 CEST
                                end: 2022-08-16 17:11:21.217673 +0200 CEST
                                2022-08-16 17:10:00 +0200 CEST: 34.184087816704434
                                2022-08-16 17:11:00 +0200 CEST: 34.18519049983288
                        }
                        Ethernet51: timeseries{
                                start: 2022-08-16 17:10:21.217673 +0200 CEST
                                end: 2022-08-16 17:11:21.217673 +0200 CEST
                                2022-08-16 17:10:00 +0200 CEST: 34.84759166533158
                                2022-08-16 17:11:00 +0200 CEST: 34.84247911778802
                        }
                }
                JAS17070003: dict{
                        Ethernet50: timeseries{
                                start: 2022-08-16 17:10:21.217673 +0200 CEST
                                end: 2022-08-16 17:11:21.217673 +0200 CEST
                                2022-08-16 17:10:00 +0200 CEST: 30.65325390983907
                                2022-08-16 17:11:00 +0200 CEST: 30.65664047328105
                        }
                        Ethernet51: timeseries{
                                start: 2022-08-16 17:10:21.217673 +0200 CEST
                                end: 2022-08-16 17:11:21.217673 +0200 CEST
                                2022-08-16 17:10:00 +0200 CEST: 27.58473123455124
                                2022-08-16 17:11:00 +0200 CEST: 27.597529745280074
                        }
                }
        }
        FF: dict{
                DD: dict{
                        HSH14280171: dict{
                                Ethernet50: timeseries{
                                        start: 2022-08-16 17:10:21.217673 +0200 CEST
                                        end: 2022-08-16 17:11:21.217673 +0200 CEST
                                        2022-08-16 17:10:00 +0200 CEST: 34.184087816704434
                                        2022-08-16 17:11:00 +0200 CEST: 34.18519049983288
                                }
                                Ethernet51: timeseries{
                                        start: 2022-08-16 17:10:21.217673 +0200 CEST
                                        end: 2022-08-16 17:11:21.217673 +0200 CEST
                                        2022-08-16 17:10:00 +0200 CEST: 34.84759166533158
                                        2022-08-16 17:11:00 +0200 CEST: 34.84247911778802
                                }
                        }
                        JAS17070003: dict{
                                Ethernet50: timeseries{
                                        start: 2022-08-16 17:10:21.217673 +0200 CEST
                                        end: 2022-08-16 17:11:21.217673 +0200 CEST
                                        2022-08-16 17:10:00 +0200 CEST: 30.65325390983907
                                        2022-08-16 17:11:00 +0200 CEST: 30.65664047328105
                                }
                                Ethernet51: timeseries{
                                        start: 2022-08-16 17:10:21.217673 +0200 CEST
                                        end: 2022-08-16 17:11:21.217673 +0200 CEST
                                        2022-08-16 17:10:00 +0200 CEST: 27.58473123455124
                                        2022-08-16 17:11:00 +0200 CEST: 27.597529745280074
                                }
                        }
                }
                EE: dict{BB: timeseries{
                                start: 2022-08-16 17:14:06.794969 +0200 CEST
                                end: 2022-08-16 17:16:06.794969 +0200 CEST
                                2022-08-16 17:14:00 +0200 CEST: 3.2909
                                2022-08-16 17:15:00 +0200 CEST: 3.2909
                                2022-08-16 17:16:00 +0200 CEST: 3.2909
                        }}
        }
}
>>> unnestTimeseries(d)
timeseries{
        start: 2022-08-16 17:10:21.217673 +0200 CEST
        end: 2022-08-16 17:16:06.794969 +0200 CEST
        2022-08-16 17:10:00 +0200 CEST: dict{
                AA: dict{
                        HSH14280171: dict{
                                Ethernet50: 34.184087816704434
                                Ethernet51: 34.84759166533158
                        }
                        JAS17070003: dict{
                                Ethernet50: 30.65325390983907
                                Ethernet51: 27.58473123455124
                        }
                }
                FF: dict{DD: dict{
                                HSH14280171: dict{
                                        Ethernet50: 34.184087816704434
                                        Ethernet51: 34.84759166533158
                                }
                                JAS17070003: dict{
                                        Ethernet50: 30.65325390983907
                                        Ethernet51: 27.58473123455124
                                }
                        }}
        }
        2022-08-16 17:11:00 +0200 CEST: dict{
                AA: dict{
                        HSH14280171: dict{
                                Ethernet50: 34.18519049983288
                                Ethernet51: 34.84247911778802
                        }
                        JAS17070003: dict{
                                Ethernet50: 30.65664047328105
                                Ethernet51: 27.597529745280074
                        }
                }
                FF: dict{DD: dict{
                                HSH14280171: dict{
                                        Ethernet50: 34.18519049983288
                                        Ethernet51: 34.84247911778802
                                }
                                JAS17070003: dict{
                                        Ethernet50: 30.65664047328105
                                        Ethernet51: 27.597529745280074
                                }
                        }}
        }
        2022-08-16 17:14:00 +0200 CEST: dict{FF: dict{EE: dict{BB: 3.2909}}}
        2022-08-16 17:15:00 +0200 CEST: dict{FF: dict{EE: dict{BB: 3.2909}}}
        2022-08-16 17:16:00 +0200 CEST: dict{FF: dict{EE: dict{BB: 3.2909}}}
}

Data Analysis Functions

groupby

Added in revision 1

Function groupby, applied to a timeseries, returns a dict with keys corresponding to the ‘group by field’ parameter, and values corresponding to the associate method and field.

The function takes 4 parameters:

  • A timeseries of dicts to apply this function to

  • The name of the ‘group by field’ (a str)

  • The name of one of the supported associative methods (a str)

  • The name of the field whose values will be operated on by the associative method (a str)

The entries in the timeseries are grouped by the values of the field from parameter 1. For each entry, the value corresponding to the associative field of parameter 4 is obtained. This results in a map with entries of the following format:

  • key: values of the ‘group by field’

  • value: lists of values of the ‘associative field’

On each of these lists, the following associative methods can be applied:

  • count: returns the length of the list (i.e. the item count)

  • max: returns the max entry in the list

  • mean: returns the mean of the values in the list

  • min: returns the min entry in the list

  • sum: returns the sum of the entries in the list

>>> `analytics:/path/to/data`[3]
timeseries{
        tstamp1: dict{"name": "name1", "value": 1}
        tstamp2: dict{"name": "name2", "value": 10}
        tstamp3: dict{"name": "name1", "value": 2}
        tstamp4: dict{"name": "name2", "value": 11}
}
>>> let ts = _
>>> groupby(ts, "name", "mean", "value")
dict{
        "name1": 1.5
        "name2": 10.5
}
>>> groupby(ts, "name", "count", "value")
dict{
        "name1": 2
        "name2": 2
}
>>> groupby(ts, "name", "sum", "value")
dict{
        "name1": 3
        "name2": 21
}

histogram

Added in revision 1

Function histogram, for a given timeseries of non-dict values, returns a dict with entries of the following format:

  • key: value in the timeseries (range if a timeseries of num values)

  • value: time-weighted frequency in the timeseries

Arguments:

  • A timeseries of non-dict values is the only argument to this function

>>> `analytics:/path/to/data`[3] | field("strfield")
timeseries{
        start: 2019-08-31 00:00:00
        end: 2019-08-31 00:12:00
        2019-08-31 00:00:00: "string1"
        2019-08-31 00:01:00: "string2"
        2019-08-31 00:10:00: "string1"
        2019-08-31 00:11:00: "string1"
}
>>> histogram(_)
dict{
        "string1": 0.25
        "string2": 0.75
} # the count is weighted accordingly to the intervals
>>> `analytics:/path/to/data`[5] | field("numfield")
timeseries{
        start: 2019-08-31 00:00:00
        end: 2019-08-31 01:00:00
        2019-08-31 00:00:00: 1
        2019-08-31 00:01:00: 1.01
        2019-08-31 00:10:00: 1.011
        2019-08-31 00:30:00: 5.2
        2019-08-31 00:44:00: 5.22
        2019-08-31 00:56:00: 5.23
}
>>> histogram(_)
dict{
        "1.0-1.011": 0.5
        "5.2-5.23": 0.5
} # the count is weighted accordingly to the intervals

dhistogram

Added in revision 1

Function dhistogram, has a similar behaviour as histogram but its result is not time-weighted. For a given timeseries of non-dict values, returns a dict with entries of the following format:

Arguments:

A timeseries of non-dict values is the only argument to this function

>>> `analytics:/path/to/data`[3] | field("strfield")
timeseries{
        start: 2019-08-31 00:00:00
        end: 2019-08-31 00:05:00
        2019-08-31 00:00:00: "string1"
        2019-08-31 00:01:00: "string2"
        2019-08-31 00:10:00: "string1"
        2019-08-31 00:11:00: "string1"
} # the count does not depend of the time intervals between the updates
>>> dhistogram(_)
dict{
        "string1": 3
        "string2": 1
} # the count does not depend of the time intervals between the updates
>>> `analytics:/path/to/data`[5] | field("numfield")
timeseries{
        2019-08-31 00:00:00: 1
        2019-08-31 00:01:00: 1.01
        2019-08-31 00:10:00: 1.011
        2019-08-31 00:30:00: 5.2
        2019-08-31 00:44:12: 5.22
        2019-08-31 02:01:34: 5.23
}
>>> dhistogram(_)
dict{
        "1.0-1.011": 3
        "5.2-5.23": 3
} # the count does not depend of the time intervals between the updates

aggregate

Added in revision 4

Function aggregate merges multiple timeseries contained in a dict (like the result of a wildcarded query) using the associative method specified in the second parameter. The dict must contain timeseries, all of which must contain identical timestamps.

If one of the timeseries is empty, it will be ignored.

If some values’ timestamps are not matched in all the other non-empty timeseries of the dict, these timestamp-value pairs will not be present in the output timeseries.

aggregate returns a simple timeseries with the aggregated data of all the input timeseries.

  • The first argument is the dict containing timeseries to aggregate

  • The second argument is the name of the associative method to apply

Like with groupby, the following associative methods can be applied:

  • count: returns the length of the list (i.e. the item count)

  • max: returns the max entry in the list (requires the timeseries to be numerical)

  • mean: returns the mean of the values in the list (requires the timeseries to be numerical)

  • min: returns the min entry in the list (requires the timeseries to be numerical)

  • sum: returns the sum of the entries in the list (requires the timeseries to be numerical)

>>> let data = `analytics:/Devices/*/versioned-data/interfaces/data/*/aggregate/hardware/xcvr/15m`[1h]
>>> let avg = data | recmap(2, _value | field("temperature") | field("avg"))
>>> avg
        JPE123456: dict{
                Ethernet1: timeseries{
                        start: 2021-11-09 13:02:18.923904 +0000 GMT
                        end: 2021-11-09 13:32:18.923904 +0000 GMT
                        2021-11-09 13:00:00 +0000 GMT: 28.64315689104305
                        2021-11-09 13:15:00 +0000 GMT: 28.64771549594622
                        2021-11-09 13:30:00 +0000 GMT: 28.647003241959368
                }
                Ethernet2: timeseries{
                        start: 2021-11-09 13:02:18.923904 +0000 GMT
                        end: 2021-11-09 13:32:18.923904 +0000 GMT
                        2021-11-09 13:00:00 +0000 GMT: 26.52073192182222
                        2021-11-09 13:15:00 +0000 GMT: 26.57132998707
                        2021-11-09 13:30:00 +0000 GMT: 26.562415784963335
                }
                [...]
        }
        JPE654321: dict{
                Ethernet1: timeseries{
                        start: 2021-11-09 13:02:18.923904 +0000 GMT
                        end: 2021-11-09 13:32:18.923904 +0000 GMT
                        2021-11-09 13:00:00 +0000 GMT: 27.872056741171672
                        2021-11-09 13:15:00 +0000 GMT: 26.422506200403397
                        2021-11-09 13:30:00 +0000 GMT: 27.889330661612725
                }
                Ethernet2: timeseries{
                        start: 2021-11-09 13:02:18.923904 +0000 GMT
                        end: 2021-11-09 13:32:18.923904 +0000 GMT
                        2021-11-09 13:00:00 +0000 GMT: 25.501376131906685
                        2021-11-09 13:15:00 +0000 GMT: 24.06172043150084
                        2021-11-09 13:30:00 +0000 GMT: 25.520567819910998
                }
                [...]
        }
        [...]
>>> let deviceAvg = avg | map(aggregate(_value, "mean"))
>>> deviceAvg
        JPE123456: timeseries{
                start: 2021-11-09 13:02:18.923904 +0000 GMT
                end: 2021-11-09 13:32:18.923904 +0000 GMT
                2021-11-09 13:00:00 +0000 GMT: 29.46781924765547
                2021-11-09 13:15:00 +0000 GMT: 28.739134103556832
                2021-11-09 13:30:00 +0000 GMT: 29.756429823529587
        }
        JPE654321: timeseries{
                start: 2021-11-09 13:02:18.923904 +0000 GMT
                end: 2021-11-09 13:32:18.923904 +0000 GMT
                2021-11-09 13:00:00 +0000 GMT: 27.581944406432633
                2021-11-09 13:15:00 +0000 GMT: 27.60952274150811
                2021-11-09 13:30:00 +0000 GMT: 27.60470951346135
        }
        [...]
>>> aggregate(deviceAvg, "mean") # average temp accross all interfaces of all devices
timeseries{
        start: 2021-11-09 13:02:18.923904 +0000 GMT
        end: 2021-11-09 13:32:18.923904 +0000 GMT
        2021-11-09 13:00:00 +0000 GMT: 33.261383897237806
        2021-11-09 13:15:00 +0000 GMT: 33.16722874112898
        2021-11-09 13:30:00 +0000 GMT: 33.37487749955894
}

Math functions

abs

Added in revision 1

Function abs returns the absolute value (num) of the given value.

  • The first and only argument \(x\) is the value (num) of which the absolute value \(\lvert x \lvert\) is wanted

>>> abs(-11)
11
>>> abs(200)
200

ceil

Added in revision 1

Function ceil returns the closest integer (num) succeeding the given value.

  • The first and only argument \(x\) is the value (num) of which the ceil \(\lceil x \rceil\) is wanted

>>> ceil(12)
12
>>> ceil(12.1)
13
>>> ceil(-12.1)
-12

floor

Added in revision 1

Function floor returns the closest integer (num) preceding the given value.

  • The first and only argument \(x\) is the value (num) of which the floor \(\lfloor x \rfloor\) is wanted

>>> floor(3)
3
>>> floor(3.2)
3
>>> floor(-3.2)
-4

trunc

Added in revision 1

Function trunc returns the truncated (num) given value.

  • The first and only argument is the value (num) to be truncated

>>> trunc(2.6)
2
>>> trunc(-2.49)
-2

exp

Added in revision 1

Function exp returns the exponential (num) of the given value.

  • The first and only argument \(x\) is the value (num) of which the exp \(e^x\) is wanted

>>> exp(0)
1
>>> exp(12.1)
179871.86225375105

factorial

Added in revision 1

Function factorial returns the factorial (num) of the given value.

  • The first and only argument \(x\) is the value (num) of which the factorial \(x!\) is wanted

>>> factorial(3)
6

gcd

Added in revision 1

Function gcd returns the greatest common divisor (num) of two given integers.

  • The first two arguments are the integers (num) of which the GCD is wanted

>>> gcd(25, 30)
5

log

Added in revision 1

Function log returns the natural log (num) of the given value.

  • The first and only argument \(x\) is the value (num) of which the natural log \(log_e x\) is wanted

>>> log(10)
2.302585092994046

log10

Added in revision 1

Function log10 returns the decimal log (num) of the given value.

  • The first and only argument \(x\) is the value (num) of which the decimal log \(log_{10} x\) is wanted

>>> log10(10)
1

pow

Added in revision 1

Function pow returns the first given value (num) to the power of the second given value.

  • The two arguments are the values \(x\) (num), \(y\) (num) used to compute \(x^y\)

>>> pow(3, 2)
9
>>> pow(9, 1/2)
3

round

Added in revision 1

Function round returns the rounded (num) given value.

  • The first and only argument \(x\) is the value used to compute \(\lfloor x\rceil\) i.e. the rounded value (num)

>>> round(2.5)
3
>>> round(2.49)
2

sqrt

Added in revision 1

Function sqrt returns the square root (num) of the given value.

  • The first and only argument \(x\) is the value (num) of which the square root \(\sqrt{x}\) is wanted

>>> sqrt(9)
3

max

Added in revision 1

Function max returns the max value (num) in a timeseries or a dict.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> max(_)
200

min

Added in revision 1

Function min returns the min value (num) in a timeseries or a dict.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> min(_)
1

formatInt

Added in revision 4

Function formatInt formats a num into a str using the specified base. The num will be treated as an integer and any decimal part will be truncated.

  • The first argument is the num to convert

  • The second argument is the base (num)

>>> formatInt(4, 2)
100
>>> formatInt(4.5, 2)
100
>>> formatInt(33, 2)
100001
>>> formatInt(15, 16)
f
>>> formatInt(29, 16)
1d
>>> type(_)
str

formatFloat

Added in revision 4

Function formatFloat formats a num (float64) into a str, according to the specified format and precision.

  • The first argument is the num to convert

  • The second argument is a str of one letter describing the format:

    • 'b': binary exponent

    • 'e': decimal exponent

    • 'f': no exponent

    • 'x': hexadecimal fraction and binary exponent

  • The third argument is :ref:a num specifying the precision, i.e. the number of digits after the decimal point

>>> formatFloat(15682.8729, "e", 10)
1.5682872900e+04
>>> formatFloat(15682.8729, "f", 10)
15682.8729000000
>>> formatFloat(15, "x", 3)
0x1.e00p+03
>>> formatFloat(15, "b", 3)
8444249301319680p-49
>>> type(_)
str

Stats functions

dsum

Added in revision 1

Function dsum returns the non-weighted sum of values (num) in a timeseries.

  • The first and only argument is a timeseries containing plain num values

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> dsum(_)
216

dmean

Added in revision 1

Function dmean returns the non-weighted mean value (num) of a timeseries.

  • The first and only argument is a timeseries containing plain num values

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> dmean(_)
54

dmedian

Added in revision 1

Function dmedian returns the non-weighted median (num) of a timeseries.

  • The first and only argument is a timeseries containing plain num values

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> dmedian(_)
2

dpercentile

Added in revision 1

Function dpercentile returns the non-weighted nth percentile (num) of a timeseries.

  • The first argument is a timeseries containing plain num values

  • The second argument is a num specifying the percentile. If it is greater than 100 or lower than 0, the return value will be 0.

>>> let a = `analytics:/path/to/data`[3] | field("numfield")
>>> a
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> dpercentile(a, 50)
2
>>> dpercentile(a, 90)
200

dvariance

Added in revision 1

Function dvariance returns the non-weighted statistical variance (num) of a timeseries.

  • The first and only argument is a timeseries containing plain num values

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> dvariance(_)
9503.333333333334

dstddev

Added in revision 1

Function dstddev returns the non-weighted standard deviation (num) of a timeseries.

  • The first and only argument is a timeseries containing plain num values

>>> let a = `analytics:/path/to/data`[3] | field("numfield")
>>> a
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> dstddev(a)
97.48504158758581
>>> sqrt(dvariance(a))
97.48504158758581

dskew

Added in revision 1

Function dskew returns the non-weighted skewness of distribution (num) for data in a timeseries.

  • The first and only argument is a timeseries containing plain num values

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> dskew(_)
0.7431002727844832

dkurtosis

Added in revision 1

Function dkurtosis returns the non-weighted kurtosis of distribution (num) for data in a timeseries.

  • The first and only argument is a timeseries containing plain num values

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> dkurtosis(_)
-1.6923313578244437

sum

Added in revision 1

Function sum returns the sum of the num values in a timeseries or a dict. If applied to a timeseries, the result is time-weighted.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> sum(_)
216
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["key3"] = 2
>>> d["key4"] = 200
>>> sum(d)
216

mean

Added in revision 1

Function mean returns the mean of the num values in a timeseries or a dict. If applied to a timeseries, the result is time-weighted.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> mean(_)
54 # will be different from dmean if space between the timestamps (weight) is not constant
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["key3"] = 2
>>> d["key4"] = 200
>>> mean(d)
54

median

Added in revision 1

Function median returns the median of the num values in a timeseries or a dict. If applied to a timeseries, the result is time-weighted.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> median(_)
2 # will be different from dmedian if space between the timestamps (weight) is not constant
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["key3"] = 2
>>> d["key4"] = 200
>>> median(d)
2

percentile

Added in revision 1

Function percentile returns the time-weighted nth percentile (num) of a timeseries or a dict. If applied to a timeseries, the result is time-weighted.

  • The first argument is a timeseries or a dict containing plain num values

  • The second argument is a num specifying the percentile. If it is greater than \(100\) or lower than \(0\), the return value will be \(0\).

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> percentile(_, 90)
200 # will be different from dpercentile if space between the timestamps (weight) is not constant
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["key3"] = 2
>>> d["key4"] = 200
>>> percentile(d, 90)
200

variance

Added in revision 1

Function variance returns the statistical variance of the num values in a timeseries or a dict. If applied to a timeseries, the result is time-weighted.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> variance(_)
9503.333333333334 # will be different from dvariance if space between the timestamps (weight) is not constant
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["key3"] = 2
>>> d["key4"] = 200
>>> variance(d, 90)
9503.33333333

stddev

Added in revision 1

Function stddev returns the standard deviation of the num values in a timeseries or a dict. If applied to a timeseries, the result is time-weighted.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> stddev(_)
97.485041588 # will be different from dstddev if space between the timestamps (weight) is not constant
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["key3"] = 2
>>> d["key4"] = 200
>>> stddev(d, 90)
97.485041588

skew

Added in revision 1

Function skew returns the skewness of dist.n of the num values in a timeseries or a dict. If applied to a timeseries, the result is time-weighted. If the timeseries has exactly one element, \(0\) is returned.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> skew(_)
0.7431002727844832 # will be different from dskew if space between the timestamps (weight) is not constant
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["key3"] = 2
>>> d["key4"] = 200
>>> skew(d, 90)
0.7431002727844832

kurtosis

Added in revision 1

Function kurtosis returns the kurtosis of dist.n of the num values in a timeseries or a dict. If applied to a timeseries, the result is time-weighted. If the timeseries has exactly one element, \(0\) is returned.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        tstamp1: 13
        tstamp2: 1
        tstamp3: 2
        tstamp4: 200
}
>>> skew(_)
0.7431002727844832 # will be different from dskew if space between the timestamps (weight) is not constant
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["key3"] = 2
>>> d["key4"] = 200
>>> skew(d, 90)
0.7431002727844832

rate

Added in revision 1

Function rate returns a timeseries of rates computed from the initial timeseriesnum values.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
        2019-08-31 00:00:00: 1
        2019-08-31 00:01:00: 10
        2019-08-31 00:02:00: 50
        2019-08-31 00:03:00: 110
        2019-08-31 00:04:00: 230
}
>>> rate(_)
timeseries{
        2019-08-31 00:00:00: 0.016666666666666666
        2019-08-31 00:01:00: 0.15
        2019-08-31 00:02:00: 0.6666666666666666
        2019-08-31 00:03:00: 1
        2019-08-31 00:04:00: 2
}

linregression

Added in revision 3

Function linregression produces a linear fit of a timeseries of num.

It returns a dict with 4 entries slope, intercept, R2 and fit. The fit entry is a timeseries with num values corresponding to the fitted line on the input timeseries’ timestamps. The slope and intercept are in seconds.

>>> `analytics:/path/to/data`[5m] | field("numfield")
timeseries{
        start: 2021-10-14 13:57:55.000545 +0100 IST
        end: 2021-10-14 14:02:55.000545 +0100 IST
        2021-10-14 13:57:00 +0100 IST: 3.801633107494212e-05
        2021-10-14 13:58:00 +0100 IST: 7.653320559746086e-05
        2021-10-14 13:59:00 +0100 IST: 3.971200542852744e-05
        2021-10-14 14:00:00 +0100 IST: 3.981215360110563e-05
        2021-10-14 14:01:00 +0100 IST: 5.2121957107961934e-05
        2021-10-14 14:02:00 +0100 IST: 3.838672949594982e-05
}
>>> linregression(_)
dict{
        R2: 0.06273653863866613
        fit: timeseries{
                start: 2021-10-14 13:57:00 +0100 IST
                end: 2021-10-14 14:02:00 +0100 IST
                2021-10-14 13:57:00 +0100 IST: 5.252194027605128e-05
                2021-10-14 13:58:00 +0100 IST: 5.0485322987015024e-05
                2021-10-14 13:59:00 +0100 IST: 4.844870569797877e-05
                2021-10-14 14:00:00 +0100 IST: 4.641208840183708e-05
                2021-10-14 14:01:00 +0100 IST: 4.4375471112800824e-05
                2021-10-14 14:02:00 +0100 IST: 4.2338853823764566e-05
        }
        intercept: 55.47126937459381
        slope: -3.39436215194667e-08
}

ewlinregression

Added in revision 3

Function ewlinregression produces a linear fit of a timeseries of num using exponentially decaying weights. The older the value in the timeseries the smaller the weight. The latest value is always given a weight of \(1\).

  • The first argument is the input timeseries of num

  • The second argument is the desired weight that a point with time x seconds in the past would have

  • the third argument is how long ago that time \(x\) is, in seconds

It returns a dict with 4 entries slope, intercept, R2 and fit. The fit entry is a timeseries with num values corresponding to the fitted line on the input timeseries’ timestamps. The slope and intercept are in seconds.

>>> `analytics:/path/to/data`[5m] | field("numfield")
timeseries{
        start: 2021-10-14 13:57:55.000545 +0100 IST
        end: 2021-10-14 14:02:55.000545 +0100 IST
        2021-10-14 13:57:00 +0100 IST: 3.801633107494212e-05
        2021-10-14 13:58:00 +0100 IST: 7.653320559746086e-05
        2021-10-14 13:59:00 +0100 IST: 3.971200542852744e-05
        2021-10-14 14:00:00 +0100 IST: 3.981215360110563e-05
        2021-10-14 14:01:00 +0100 IST: 5.2121957107961934e-05
        2021-10-14 14:02:00 +0100 IST: 3.838672949594982e-05
}
>>> ewlinregression(_, 0.01, 100.0)
dict{
        R2: 0.34201204121343765
        fit: timeseries{
                start: 2021-10-14 14:03:00 +0100 IST
                end: 2021-10-14 14:08:00 +0100 IST
                2021-10-14 14:03:00 +0100 IST: 4.5425229615148055e-05
                2021-10-14 14:04:00 +0100 IST: 4.4509288322558405e-05
                2021-10-14 14:05:00 +0100 IST: 4.359334702641604e-05
                2021-10-14 14:06:00 +0100 IST: 4.267740573382639e-05
                2021-10-14 14:07:00 +0100 IST: 4.176146444123674e-05
                2021-10-14 14:08:00 +0100 IST: 4.0845523145094376e-05
        }
        intercept: 24.94748623552414
        slope: -1.526568822982724e-08
}

String manipulation

strToUpper

Added in revision 1

Function strToUpper returns uppercase version of given str.

  • The first and only parameter is a str to convert to uppercase

>>> strToUpper("ToUpper")
"TOUPPER"

strToLower

Added in revision 1

Function strToLower returns lowercase version of given str.

  • The first and only parameter is a str to convert to lowercase

>>> strToLower("ToLower")
"TOLOWER"

strContains

Added in revision 1

Function strContains returns whether the first str contains the second str.

  • Both arguments to the function are str

>>> strContains("thatistext", "is")
true

strCount

Added in revision 1

Function strCount returns the number of occurrences of the second str in the first str.

  • Both arguments to the function are str

>>> strCount("tertarter", "te")
2

strIndex

Added in revision 1

Function strIndex returns the index of the first occurrence of the second str in the first str, and -1 if it is not present.

  • Both arguments to the function are str

>>> strIndex("thatistext", "is")
4

strReplace

Added in revision 1

Function strReplace returns a copy of the first str, where occurrences of the second str are replaced by the third str.

  • The three arguments to the function are str

>>> strReplace("thatistext", "is", "was")
"thatwastext"

strHasPrefix

Added in revision 1

Function strHasPrefix returns whether the first str starts with the second str.

  • Both arguments to the function are str

>>> strHasPrefix("thatistext", "is")
false
>>> strHasPrefix("thatistext", "that")
true

strHasSuffix

Added in revision 1

Function strHasSuffix returns whether the first str ends with the second str.

  • Both arguments to the function are str

>>> strHasSuffix("thatistext", "xt")
true

strSplit

Added in revision 1

Function strSplit returns a timeseries of str. The function splits the first str into substrings, separated by the second str.

  • Both arguments to the function are str

>>> strSplit("that./is.text", "./")
timeseries{
        0000-00-00 00:00:00.000000001: "that"
        0000-00-00 00:00:00.000000002: "is.text"
}

strCut

Added in revision 4

Function strCut returns the portion of a str between two indexes (excluding ending index).

Negative indexes start from the end of the input str.

  • The first argument (str) is the string from which the portion is returned

  • The second argument (num) is the starting index

  • The third argument (num) is the ending index

>>> strCut("0123456789", 1, 4)
123
>>> strCut("0123456789", -8, -2)
234567
>>> strCut("abcd", 1, 3)
bc

reFindAll

Added in revision 1

Function reFindAll returns a timeseries of str which contains matches of the second str (regex) in the first str.

  • Both arguments to the function are str

>>> reFindAll("i am a string with text", "i[a-z]+")
timeseries{
        0000-00-00 00:00:00.000000001: "ing"
        0000-00-00 00:00:00.000000002: "ith"
}

reMatch

Added in revision 1

Function reMatch returns whether the first str contains matches of the second str (regex).

  • Both arguments to the function are str

>>> reMatch("i am a string with text", "i[a-z]+")
true

reFindCaptures

Added in revision 1

Function reFindCaptures returns a timeseries of str lists. Each list contains the full match followed by each capture

  • Both arguments to the function are str. The first one is the str to match, and the second is the regular expression

>>> reFindCaptures("foobarbaztootartaz", "foo")
timeseries{
        0000-00-00 00:00:00.000000001: ["foo"]
}
>>> reFindCaptures("foobarbaztootartaz", "(foo)")
timeseries{
        0000-00-00 00:00:00.000000001: ["foo", "foo"]
}
>>> reFindCaptures("foobarbaztootartaz", "f(oo)")
timeseries{
        0000-00-00 00:00:00.000000001: ["foo", "oo"]
}
>>> reFindCaptures("foobarbaztootartaz", "(oo)")
timeseries{
        0000-00-00 00:00:00.000000001: ["oo", "oo"]
        0000-00-00 00:00:00.000000002: ["oo", "oo"]
}
>>> reFindCaptures("foobarbaztootartaz", "[ft](oo)")
timeseries{
        0000-00-00 00:00:00.000000001: ["foo", "oo"]
        0000-00-00 00:00:00.000000002: ["too", "oo"]
}
>>> reFindCaptures("foobarbaztootartaz", "([ft])(oo)")
timeseries{
        0000-00-00 00:00:00.000000001: ["foo", "f", "oo"]
        0000-00-00 00:00:00.000000002: ["too", "t", "oo"]
}
>>> reFindCaptures("foobarbaztootartaz", "[ft](oo).*(az)")
timeseries{
        0000-00-00 00:00:00.000000001: ["foobarbaztootartaz", "oo", "az"]
}

CLI-only Functions

Warning

The functions described in this section can only be used in CLI. They cannot be called from a service or through a Web interface.

help

Added in revision 1

Function help returns the help of all filters and functions as a formatted str.

>>> help()
# Functions
## now
- Function `now` returns the current time. Time is constant across all the script, so that all operations and queries have the same reference time
[...]

dump

Added in revision 1

Function dump attempts to dump variables from the interpreter into a file.

  • The first and only argument is the path to the file (str)

>>> let myVar = 2
>>> dump("file.dump")

load

Added in revision 1

Function load attempts to load variables into the interpreter from a file.

  • The first and only argument is the path to the file (str)

>>> load("file.dump")
true
>>> myVar
2
>>> let myVar = 5
>>> if load("file.dump") {
...     myVar
... }
2

plot

Added in revision 1

Function plot plots a timeseries or dict of num values.

  • The first argument is the timeseries or dict of num values to plot

  • The second argument (optional) is the path (str) to the image PNG file to write the plot to. If not specified, defaults to plot.png

>>> plot(myTimeseriesOrDict, "myplotimg.png")

Filters

field

Added in revision 1

Filter field applies to a timeseries of dicts. Returns a timeseries of the value at the specified key for each entry of the timeseries that contains this field. Entries that don’t contain the key are not in the output timeseries.

  • The filtered value is a timeseries of dicts

  • The first and only parameter is the key to keep in the dicts

>>> `analytics:/path/to/data`[1]
timeseries{
    tstamp1: dict{key1: val1, key2: val2, key3: val3}
    tstamp2: dict{key1: val4, key2: val5}
}
>>> _ | field("key1")
timeseries{
    tstamp1: val1
    tstamp2: val4
}

fields

Added in revision 3

Filter fields applies to a dict. It filters it and returns a new dict containing only the key/value pairs whose key is passed as parameter.

  • The filtered value is a dict

  • There is a variable (\(0\) to \(n\)) number of parameters: they are the keys to keep in the output dict

Note

If a specified key is missing from the source dict, the filter will not fail but the output dict will also be missing that key

>>> let d = `analytics:/path/to/data/*` | map(merge(_value))
>>> d
dict{
    key0: dict{key1: val1, key2: val2, key3: val3}
    key01: dict{key1: val4, key2: val5}
    key02: dict{key1: val6, key2: val7}
}
>>> d | fields("key0", "key01")
dict{
    key0: dict{key1: val1, key2: val2, key3: val3}
    key01: dict{key1: val4, key2: val5}
}
>>> d | fields("k")
dict{
}
>>> d | fields()
dict{
}
>>> d | fields("key01") | map(_value | fields("key2"))
dict{
    key01: dict{key2: val5}
}

setFields

Added in revision 3

Filter setFields sets some key/value pairs in a dict. If the key already existed in the filtered dict, its value will be replaced with the new one in the output dict (like all filters, setFields returns a filtered copy of the dict and does not alter the source). If the key did not exist in the filtered dict, the key/value pair will just be added to the output dict.

  • The filtered value is a dict

  • There is a variable (0 to n) even number of parameters: they correspond to the list of key/value pairs

>>> let d = newDict() | setFields("k1", "v1", "k2", 2.3, "k3", 3)
>>> d
dict{
    k1: v1
    k2: 2.3
    k3: 3
}
>>> d | setFields("k4", newDict() | setFields("k5", "v5"))
dict{
    k1: v1
    k2: 2.3
    k3: 3
    k4: dict{
        k5: v5
    }
}
>>> d
dict{
    k1: v1
    k2: 2.3
    k3: 3
} # the source dict is not altered

applyDeletes

Added in revision 4

Filter applyDeletes applies the deletes to a timeseries. This timeseries must be freshly returned by a query. Most filters remove the deletes information from timeseries, so this should be called before any other filter or function.

If no argument is passed, applying a delete will remove all entries with that delete’s key that were updated prior to the delete itself. This use-case is mostly appropriate when used with the result of a query that does not contain historical data (state-only). With historical data, this would wipe deleted entries from ever having existed in the timeseries, instead of signaling the end of the entry at the moment of deletion.

If an argument is passed, then the expression defines a value that will be written at the moment of the delete for that key. This use-case is more appropriate with historical data because it will not remove entries, but instead create an entry that signals the end of the value.

  • The filtered value is a timeseries that still contains delete information.

  • The only and optional parameter is the expression. Its value can be of any type after evaluation.

Usable metavariables in the expression are:

  • _key or _1: key matching the delete

  • _index: index of the delete in the timeseries

  • _updindex: index of the last update for this key in the timeseries

  • _time or _2: time of the delete in the timeseries

  • _updtime: time of the last update for this key in the timeseries

  • _value or _3: last value prior to the delete for the deleted key

  • _src or _4: reference to the timeseries being filtered

Example
>>> let a = `analytics:/tags/BugAlerts/Query/gNMIEnabled`[5]
>>> a
timeseries{
    start: 2021-03-17 02:48:58.205235103 +0100 CET
    end: 2022-10-19 13:30:33.722908 +0200 CEST
    2021-03-17 02:48:58.205235103 +0100 CET: dict{
        JAS12200014: true
        JAS16040045: true
        JAS17250006: true
        JAS17250010: true
        JAS17510146: true
        JPE14171444: true
        JPE17191574: true
        SSJ17371234: true
    }
    2021-05-12 17:32:58.269740014 +0200 CEST: dict{
        HSH14075043: true
        HSH14075051: true
    }
    2021-11-03 17:09:46.753872494 +0100 CET: dict{
        HSH14280171: true
        HSH14420467: true
        JPE14250224: true
        JPE14383408: true
        SSJ17049015: true
        SSJ17374660: true
    }
    2021-11-11 05:09:22.273451668 +0100 CET: dict{
        JAS14170008: true
        JAS14210057: true
        JAS17070003: true
        JAS18170075: true
        JPE14120478: true
        JPE19280519: true
    }
    2022-02-18 23:08:10.204460235 +0100 CET: dict{
        2568DB4A33177968A78C4FD5A8232159: true
        6323DA7D2B542B5D09630F87351BEA41: true
        BAD032986065E8DC14CBB6472EC314A6: true
        CD0EADBEEA126915EA78E0FB4DC776CA: true
    }
    2022-02-22 00:48:45.347884243 +0100 CET: dict{0123F2E4462997EB155B7C50EC148767: true}
    2022-07-18 18:10:07.772750473 +0200 CEST: dict{JPE20244151: true}
}
>>> deletes(a)
timeseries{
    start: 2021-03-17 02:48:58.205235103 +0100 CET
    end: 2022-10-19 13:30:33.722908 +0200 CEST
    2021-11-23 11:09:21.716099165 +0100 CET: dict{
        HSH14075043: <nil>
        HSH14075051: <nil>
        HSH14280171: <nil>
        HSH14420467: <nil>
        JAS14170008: <nil>
        JAS14210057: <nil>
        JAS16040045: <nil>
        JAS17070003: <nil>
        JAS17250006: <nil>
        JAS17250010: <nil>
        JAS17510146: <nil>
        JAS18170075: <nil>
        JPE14120478: <nil>
        JPE14171444: <nil>
        JPE14250224: <nil>
        JPE14383408: <nil>
        JPE17191574: <nil>
        JPE19280519: <nil>
        SSJ17049015: <nil>
        SSJ17371234: <nil>
        SSJ17374660: <nil>
    }
    2022-02-22 00:48:45.347884243 +0100 CET: dict{
        2568DB4A33177968A78C4FD5A8232159: <nil>
        6323DA7D2B542B5D09630F87351BEA41: <nil>
        BAD032986065E8DC14CBB6472EC314A6: <nil>
        CD0EADBEEA126915EA78E0FB4DC776CA: <nil>
    }
}
>>> a | applyDeletes()
timeseries{
    start: 2021-03-17 02:48:58.205235103 +0100 CET
    end: 2022-10-19 13:30:33.722908 +0200 CEST
    2021-03-17 02:48:58.205235103 +0100 CET: dict{JAS12200014: true}
    2022-02-22 00:48:45.347884243 +0100 CET: dict{0123F2E4462997EB155B7C50EC148767: true}
    2022-07-18 18:10:07.772750473 +0200 CEST: dict{JPE20244151: true}
}
>>> a | applyDeletes(_key+" is deleted, its value was " + str(_value))
timeseries{
    start: 2021-03-17 02:48:58.205235103 +0100 CET
    end: 2022-10-19 13:30:33.722908 +0200 CEST
    2021-03-17 02:48:58.205235103 +0100 CET: dict{
        JAS12200014: true
        JAS16040045: true
        JAS17250006: true
        JAS17250010: true
        JAS17510146: true
        JPE14171444: true
        JPE17191574: true
        SSJ17371234: true
    }
    2021-05-12 17:32:58.269740014 +0200 CEST: dict{
        HSH14075043: true
        HSH14075051: true
    }
    2021-11-03 17:09:46.753872494 +0100 CET: dict{
        HSH14280171: true
        HSH14420467: true
        JPE14250224: true
        JPE14383408: true
        SSJ17049015: true
        SSJ17374660: true
    }
    2021-11-11 05:09:22.273451668 +0100 CET: dict{
        JAS14170008: true
        JAS14210057: true
        JAS17070003: true
        JAS18170075: true
        JPE14120478: true
        JPE19280519: true
    }
    2021-11-23 11:09:21.716099165 +0100 CET: dict{
        HSH14075043: HSH14075043 is deleted, its value was true
        HSH14075051: HSH14075051 is deleted, its value was true
        HSH14280171: HSH14280171 is deleted, its value was true
        HSH14420467: HSH14420467 is deleted, its value was true
        JAS14170008: JAS14170008 is deleted, its value was true
        JAS14210057: JAS14210057 is deleted, its value was true
        JAS16040045: JAS16040045 is deleted, its value was true
        JAS17070003: JAS17070003 is deleted, its value was true
        JAS17250006: JAS17250006 is deleted, its value was true
        JAS17250010: JAS17250010 is deleted, its value was true
        JAS17510146: JAS17510146 is deleted, its value was true
        JAS18170075: JAS18170075 is deleted, its value was true
        JPE14120478: JPE14120478 is deleted, its value was true
        JPE14171444: JPE14171444 is deleted, its value was true
        JPE14250224: JPE14250224 is deleted, its value was true
        JPE14383408: JPE14383408 is deleted, its value was true
        JPE17191574: JPE17191574 is deleted, its value was true
        JPE19280519: JPE19280519 is deleted, its value was true
        SSJ17049015: SSJ17049015 is deleted, its value was true
        SSJ17371234: SSJ17371234 is deleted, its value was true
        SSJ17374660: SSJ17374660 is deleted, its value was true
    }
    2022-02-18 23:08:10.204460235 +0100 CET: dict{
        2568DB4A33177968A78C4FD5A8232159: true
        6323DA7D2B542B5D09630F87351BEA41: true
        BAD032986065E8DC14CBB6472EC314A6: true
        CD0EADBEEA126915EA78E0FB4DC776CA: true
    }
    2022-02-22 00:48:45.347884243 +0100 CET: dict{
        2568DB4A33177968A78C4FD5A8232159: 2568DB4A33177968A78C4FD5A8232159 is deleted, its value was true
        6323DA7D2B542B5D09630F87351BEA41: 6323DA7D2B542B5D09630F87351BEA41 is deleted, its value was true
        BAD032986065E8DC14CBB6472EC314A6: BAD032986065E8DC14CBB6472EC314A6 is deleted, its value was true
        CD0EADBEEA126915EA78E0FB4DC776CA: CD0EADBEEA126915EA78E0FB4DC776CA is deleted, its value was true
    }
    2022-02-22 00:48:45.347884243 +0100 CET: dict{0123F2E4462997EB155B7C50EC148767: true}
    2022-07-18 18:10:07.772750473 +0200 CEST: dict{JPE20244151: true}
}

renameFields

Added in revision 3

Filter renameFields renames some keys in a dict. The keys which are not specified in the arguments will be kept in the output dict. Use the fields filter to remove them.

  • The filtered value is a dict

  • There is a variable (\(0\) to \(n\)) even number of parameters: they correspond to the list of old-key/new-key pairs

Note

If a specified key is missing from the source dict, the filter will not fail and that pair will just be ignored

>>> let d = `analytics:/path/to/data/*` | map(merge(_value))
>>> d
dict{
    key0: dict{key1: val1, key2: val2, key3: val3}
    key01: dict{key1: val4, key2: val5}
}
>>> d | renameFields("key0", "newkey0")
dict{
    newkey0: dict{key1: val1, key2: val2, key3: val3}
    key01: dict{key1: val4, key2: val5}
}
>>> d | renameFields("key0", "newkey0", "key01", "newkey01")
dict{
    newkey0: dict{key1: val1, key2: val2, key3: val3}
    newkey01: dict{key1: val4, key2: val5}
}
>>> d | fields("key01") | map(_value | renameFields("key2", "newkey2"))
dict{
    key01: dict{key1: val4, newkey2: val5}
}

where

Added in revision 1

Filter where returns a filtered timeseries or dict containing exclusively the entries of the input where the predicate passed as parameter is true.

  • The first and only parameter is the predicate. It is an expression, the value of which must be a boolean after evaluation.

Usable metavariables in the predicate for timeseries are:

  • _index or _1: index of the current element (starting at \(0\))

  • _time or _2: timestamp of the current element

  • _value or _3: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

Usable metavariables in the predicate for dicts are:

  • _key or _1: key of the current element

  • _value or _2: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

>>> `analytics:/path/to/data`[3] | field("key1")
timeseries{
    tstamp1: 1
    tstamp2: 2
    tstamp3: 3
    tstamp4: 4
}
>>> _ | where(_value >= 3)
timeseries{
    tstamp3: 3
    tstamp4: 4
}
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["k3"] = 1
>>> d["k4"] = 1
>>> d | where(strContains(_key, "key"))
dict{
    "key1": 13
    "key2": 1
}

map

Added in revision 1

Filter map returns a timeseries or dict containing the results of the expression passed as parameter applied to each entry of the filtered timeseries or dict.

  • The first and only parameter is the expression. Its value can be of any type after evaluation.

Usable metavariables in the expression for timeseries are:

  • _index or _1: index of the current element (starting at \(0\))

  • _time or _2: timestamp of the current element

  • _value or _3: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

Usable metavariables in the expression for dicts are:

  • _key or _1: key of the current element

  • _value or _2: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

>>> `analytics:/path/to/data`[3]
timeseries{
    tstamp1: dict{key1: 1, key2: 12, key3: 11}
    tstamp2: dict{key1: 2, key2: 123}
    tstamp3: dict{key1: 3, key2: 78, key3: 42}
    tstamp4: dict{key1: 4, key2: 68}
}
>>> _ | map(_value["key1"] + 1)
timeseries{
    tstamp1: 2
    tstamp2: 3
    tstamp3: 4
    tstamp4: 5
}
>>> let d = newDict()
>>> d["key1"] = 13
>>> d["key2"] = 1
>>> d["k3"] = 1
>>> d["k4"] = 1
>>> d | map(_key + "l")
dict{
    "key1": key1l
    "key2": key2l
    "k3": k3l
    "k4": k4l
}
>>> d | map(_value^2)
dict{
    "key1": 169
    "key2": 1
    "k3": 1
    "k4": 1
}

mapne

Added in revision 1

Filter mapne (map-not-empty) returns a timeseries or dict containing the results of the expression passed as first parameter applied to the result of the expression passed as second parameter if its result is not empty. This applies to each entry of the filtered timeseries or dict.

  • The first parameter is the main expression. Its value can be of any type after evaluation.

    Usable metavariables in the expression for timeseries are:

    • _index or _1: index of the current element (starting at \(0\))

    • _time or _2: timestamp of the current element

    • _value or _3: result of the second expression applied to the current element

    • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

    Usable metavariables in the expression for :ref:`dict`s are:

    • _key or _1: key of the current element

    • _value or _2: result of the second expression applied to the current element

    • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

  • the second parameter is the filtering expression. Its value can be of any type after evaluation.

    Usable metavariables in the expression for timeseries are:

    • _index or _1: index of the current element (starting at 0)

    • _time or _2: timestamp of the current element

    • _value or _3: value of the current element

    • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

    Usable metavariables in the expression for dicts are:

    • _key or _1: key of the current element

    • _value or _3 value of the current element

    • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

>>> `analytics:/path/to/*/data/with/wildcard`[3]
dict {
    pathElement1: timeseries{t1:1, t2:2, t3:3, t4:4}
    pathElement2: timeseries{t5:5, t6:6, t7:7, t8:8}
    pathElement3: timeseries{}
    pathElement4: timeseries{t9:9, t10:10, t11:11, t12:12}
}
>>> _ | map(mean(_value))
error: cannot compute mean of empty timeseries
>>> _ | mapne(mean(_value), _value)
dict {
    pathElement1: 2.5
    pathElement2: 6.5
    pathElement4: 10.5
}
>>> `analytics:/path/to/data`[3]
timeseries{
    tstamp1: dict{k1:1, k2:2, k3:3, k4:4}
    tstamp2: dict{k1:1, k2:2, k3:3, k4:4}
    tstamp3: dict{}
    tstamp4: dict{k1:1, k2:2, k3:3, k4:4}
}
>>> _ | map(mean(_value))
error: cannot compute mean of empty dict
>>> _ | mapne(mean(_value) + 12, _value)
timeseries{
    tstamp1: 14.5
    tstamp2: 14.5
    tstamp4: 14.5
}

recmap

Added in revision 1

Filter recmap returns a timeseries or dict containing the results of the expression passed as parameter applied to each entry of the filtered timeseries or dict, at the specified depth.

  • The first parameter is the recursion depth (num).

  • The second parameter is the expression. Its value can be of any type after evaluation.

Usable metavariables in the expression for timeseries are:

  • _index or _1: index of the current element (starting at \(0\))

  • _time or _2: timestamp of the current element

  • _value or _3: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

Usable metavariables in the expression for dicts are:

  • _key or _1: key of the current element

  • _value or _2: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

>>> `analytics:/path/to/*/data/with/*/2/wildcards`
dict {
    pe1: dict{pe1.1: timeseries{1, 2, 3}, pe1.2: timeseries{1, 2, 3}}
    pe2: dict{pe2.1: timeseries{1, 2, 3}, pe2.2: timeseries{1, 2, 3}}
    pe3: dict{pe3.1: timeseries{1, 2, 3}, pe3.2: timeseries{1, 2, 3}}
} # we want the same recursion depth for every branch here, and stop at the timeseries level
>>> let data = _
>>> data | map(_value | map(mean(_value)))
dict {
    pe1: dict{pe1.1: 2, pe1.2: 2}
    pe2: dict{pe2.1: 2, pe2.2: 2}
    pe3: dict{pe3.1: 2, pe3.2: 2}
} # nested map filters work but are very verbose
>>> data | recmap(2, mean(_value))
dict {
    pe1: dict{pe1.1: 2, pe1.2: 2}
    pe2: dict{pe2.1: 2, pe2.2: 2}
    pe3: dict{pe3.1: 2, pe3.2: 2}
}
# recmap is much clearer.

topK

Added in revision 3

Filter topK filters the collection to keep only the k highest values. This filter can be applied to a timeseries or a dict.

  • The first parameter is the k parameter, which is the number of values to keep in the filtered collection.

  • The second parameter is an expression that returns for each entry of the collection the value to compare. The return type of this expression must be comparable (num, str, time, or duration)

Usable metavariables in the expression for timeseries are:

  • _index or _1: index of the current element (starting at \(0\))

  • _time or _2: timestamp of the current element

  • _value or _3: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

Usable metavariables in the expression for dicts are:

  • _key or _1: key of the current element

  • _value or _2: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

>>> let data = `analytics:/path/to/some/*/data` | map(merge(_value))
>>> data
dict{
    Ethernet49/1: dict{
        in: 11.845057565692196
        out: 20.816078774499992
    }
    Ethernet49/5: dict{
        in: 4.021321282808746
        out: 8.868898231943206
    }
    Ethernet51/1: dict{
        in: 2.1800167411644353
        out: 2.413745251460854
    }
    Ethernet51/2: dict{
        in: 3.126216167169341
        out: 26.05024018915018
    }
    Ethernet51/3: dict{
        in: 54.1046901332212
        out: 5.035469519006775
    }
    Ethernet51/4: dict{
        in: 7.313228804713885
        out: 4.899238295809337
    }
    Ethernet8: dict{
        in: 0
        out: 71.6547381850231
    }
    Management1: dict{
        in: 6.139184309225689
        out: 0.7010378175218949
    }
    Port-Channel512: dict{
        in: 7.864572656164906
        out: 14.724350983923758
    }
    Port-Channel532: dict{
        in: 16.652391153117858
        out: 9.562088032011452
    }
}
>>> data | topK(2, _value["in"])
dict{
    Ethernet51/3: dict{
        in: 54.1046901332212
        out: 5.035469519006775
    }
    Port-Channel532: dict{
        in: 16.652391153117858
        out: 9.562088032011452
    }
}
>>> data | map(_value["in"]) | topK(2, _value)
dict{
    Ethernet51/3: 54.1046901332212
    Port-Channel532: 16.652391153117858
}

bottomK

Added in revision 3

Filter bottomK filters the collection to keep only the k lowest values. This filter can be applied to a timeseries or a dict.

  • The first parameter is the k parameter, which is the number of values to keep in the filtered collection.

  • The second parameter is an expression that returns for each entry of the collection the value to compare. The return type of this expression must be comparable (num, str, time, or duration)

Usable metavariables in the expression for timeseries are:

  • _index or _1: index of the current element (starting at \(0\))

  • _time or _2: timestamp of the current element

  • _value or _3: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

Usable metavariables in the expression for dicts are:

  • _key or _1: key of the current element

  • _value or _2: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

>>> let data = `analytics:/path/to/some/*/data` | map(merge(_value))
>>> data
dict{
    Ethernet49/1: dict{
        in: 11.845057565692196
        out: 20.816078774499992
    }
    Ethernet49/5: dict{
        in: 4.021321282808746
        out: 8.868898231943206
    }
    Ethernet51/1: dict{
        in: 2.1800167411644353
        out: 2.413745251460854
    }
    Ethernet51/2: dict{
        in: 3.126216167169341
        out: 26.05024018915018
    }
    Ethernet51/3: dict{
        in: 54.1046901332212
        out: 5.035469519006775
    }
    Ethernet51/4: dict{
        in: 7.313228804713885
        out: 4.899238295809337
    }
    Ethernet8: dict{
        in: 0
        out: 71.6547381850231
    }
    Management1: dict{
        in: 6.139184309225689
        out: 0.7010378175218949
    }
    Port-Channel512: dict{
        in: 7.864572656164906
        out: 14.724350983923758
    }
    Port-Channel532: dict{
        in: 16.652391153117858
        out: 9.562088032011452
    }
}
>>> data | bottomK(2, _value["in"])
dict{
    Ethernet51/1: dict{
        in: 2.1800167411644353
        out: 2.413745251460854
    }
    Ethernet8: dict{
        in: 0
        out: 71.6547381850231
    }
}
>>> data | map(_value["in"]) | bottomK(2, _value)
dict{
    Ethernet51/1: 2.1800167411644353
    Ethernet8: 0
}

deepmap

Added in revision 1

Filter deepmap returns a timeseries or dict containing the results of the expression passed as parameter applied to each entry of the filtered timeseries or dict, which can contain nested timeseries or dicts.

  • The first and only parameter is the expression. Its value can be of any type after evaluation.

  • Metavariables are applicable to the collection containing the leaf node to which the expression is applied, which can be nested under several layers.

Usable metavariables in the expression for timeseries are:

  • _index or _1: index of the current element (starting at \(0\))

  • _time or _2: timestamp of the current element

  • _value or _3: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

Usable metavariables in the expression for dicts are:

  • _key or _1: key of the current element

  • _value or _2: value of the current element

  • _src or _4 (revision 4+): reference to the timeseries or dict being filtered

>>> `analytics:/path/to/*/data/with/wildcard`[3]
dict {
    pathElement1: timeseries{t1:1, t2:2, t3:3, t4:4}
    pathElement2: timeseries{t5:5, t6:6, t7:7, t8:8}
    pathElement3: timeseries{dict{k10:10}, dict{k11:11}}
}
>>> _ | deepmap(_value + 1)
dict {
    pathElement1: timeseries{t1:2, t2:3, t3:4, t4:5}
    pathElement2: timeseries{t5:6, t6:7, t7:8, t8:9}
    pathElement3: timeseries{dict{k10:11}, dict{k11:12}}
} # recursion depth can be different between branches, deepmap will recurse as long as the value is either a dict or timeseries

resample

Added in revision 1

Filter resample returns a timeseries resampled with the given duration as constant interval. CloudVision timeseries are state-based, so any value in the output timeseries will be the latest value prior to the output timestamp in the original timeseries.

  • The first and only parameter, of type duration, specifies the interval of the output timeseries.

>>> `analytics:/path/to/data`[3] | field("numfield")
timeseries{
    2019-08-31 00:00:00: 13
    2019-08-31 00:06:23: 1
    2019-08-31 00:08:29: 2
    2019-08-31 00:11:43: 200
}
>>> _ | resample(2m)
timeseries{
    2019-08-31 00:00:00: 13
    2019-08-31 00:02:00: 13
    2019-08-31 00:04:00: 13
    2019-08-31 00:06:00: 13
    2019-08-31 00:08:00: 13
    2019-08-31 00:10:00: 2
    2019-08-31 00:12:00: 200
}