TSL stands for Time Series Language and is a proxy to request directly a TSDB. For now you can request a Warp 10 or a Prometheus backend using the following request. It's built to simplify the developer experience to query it's metrics.
As example a simple TSL query will simply looks like:
select("sys.cpu.nice").where("host=web01").from(1346846400000,to=1346847000005)
To retrieve data, TSL have a select method to choose the metrics name to retrieve, a where clauses to select specific labels and a from or last method to select the temporal period to get.
Once the data are available, with TSL you can apply a lot of functions: from sampling, to grouping, to metrics operation or to operation between metrics.
As with TSL the goal is to simplify metrics queries, inside a query a user can store variables that will re-used, we will see how to use it. TSL offers the possibilities to fetch data from different backend and to dynamically execute queries on them from a same script using the connect method. Besides we will see how to update metrics meta-data (name and labels) and storing the request result in the specified backend.
The first instructions used to select data is the method select.
Select contains only one parameter:
- The series name as a string. It can also be asterisk to retrieve all series of the current application.
Example:
// Will load the last points of all sys.cpu.nice
select("sys.cpu.nice")
// Will load the last points of all series of this application (only on a Warp 10 backend)
select(*)
TSL supports native backend. At current time, for Prometheus you need to specify the exact classname of the metrics to load. When for Warp 10, you can use native regexp. As example "~sys.*" is a working Warp 10 REGEXP to select all series starting with sys.
The where method allow the user to filter the metrics to load matching labels clauses.
Where can contains one to n parameter(s):
- The labels selector string formed as "key=label".
With the "key=label" string, we use an equals label matcher. The TSL valid matcher are =, ~, != and !~. The first one encounters in the string will be used.
Example:
// Will load the last points of sys.cpu.nice series where 'dc' equals 'lga'
select("sys.cpu.nice").where("dc=lga")
// Will load the last points of sys.cpu.nice series where 'dc' equals 'lga' and have labels 'web'
select("sys.cpu.nice").where("dc=lga", "web~.*")
You can chain as many where clauses as wanted in a TSL query, example: select(...).where(...).where(...) as long as you are defining the data to retrieve.
TSL includes post-select statements to return only the series names, labels or selectors of the select results. The available methods are:
- The names method return the unique names of a series set, example: .names()
- The labels method return the unique labels maps of a series set. To retrieve a specific label values you can add a label key string as parameter to the labels function. It will then return the unique values for this specific label. Examples: .labels(), .labels("host")
- The attributes method return the unique attributes maps of a series set. To retrieve a specific attribute values you can add an attribute key string as parameter to the attributes function. It will then return the unique values for this specific attribute. Examples: .attributes(), .attributes("host")
- The selectors method return the unique selectors string of a series set, example: .selectors()
The last methods to define the data to retrieve are last and from. They are used to set the time limits to retrieve the data.
The from method is used to select physical time limits.
From can contains one or two parameters:
- from: retrieve data from this date, can be valid timestamp or date string of the backend
- to: retrieve data until this date, can be valid timestamp or date string of the backend
A valid timestamp for Warp 10 is a long in time unit (on our Metrics platform it's in micro-seconds: 1346846400000 is valid), when a valid timestamp for Prometheus may be provided as a Unix timestamp in seconds, with optional decimal places for sub-second precision (on our Metrics platform, you can have timestamp in ms: 1524376786.878 is valid).
A valid date string for Warp 10 are ISO 8601 dates string and for Prometheus are date in RFC3339 format: "2018-04-22T00:57:00-05:00" is valid for both backends.
By default, if only one parameter is set, it considers that it corresponds to the from parameter and will load all data from the current date. Be careful as it can retrieve a lot of data.
When using the from method, you can prefix the parameter with from or to prefix.
Example:
// Will load all values set after timestamp 0 of sys.cpu.nice series.
select("sys.cpu.nice")
.from(0)
// Will load all values between two timestamps of sys.cpu.nice series.
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
// Will load all values between two timestamps of sys.cpu.nice series.
select("sys.cpu.nice")
.from(from=1346846400000000, to=1346847000006000)
// Will load all values between two timestamps of sys.cpu.nice series.
select("sys.cpu.nice")
.from(to=1346847000006000, from=1346846400000000)
// Will load all values between two dates of sys.cpu.nice series.
select("sys.cpu.nice")
.from("2018-04-22T00:57:00-05:00",to="2018-04-22T01:00:00-05:00")
// From a Prometheus backend
select("sys.cpu.nice")
.from(to=1346847000.005, from=1346846400.000)
To resume from valid parameters are listed below. A parameter can be optional or mandatory. When a prefix is indicated, it means that this parameter can be set using a prefix name.
name | type | mandatory | prefix | Complementary information |
---|---|---|---|---|
from | Integer,String | [x] | from | Only on Warp 10, ISO 8601 dates string |
from | Integer, Double, String | [x] | from | Only on Prometheus, RFC3339 format |
to | Integer,String | [] | to | Only on Warp 10, ISO 8601 dates string |
to | Integer, Double, String | [] | to | Only on Prometheus, RFC3339 format |
The last method is used to select the last recorded datapoints after a valid date.
Last can contains one or three parameters:
- The first parameter must be a time duration (Prometheus and Warp 10) or a fix number (Warp10). A time duration will fetch all the data points in the time window before the current date or specified timestamp. On a Warp 10 backend, a number to retrieve as many points as specified before the current date or the specified Timestamp.
- And optionnaly the second or third parameter can be a timestamp or a string date to load data before.
- And optionnaly the second or third parameter can be an other time duration corresponding to a shift duration (loading one hour specified tick).
Example:
// Will load last point before the current date of sys.cpu.nice series.
select("sys.cpu.nice")
.last(1)
// Will load last minute before the current date of sys.cpu.nice series.
select("sys.cpu.nice")
.last(1m)
// Will load 10 points before 1528240512000000 of sys.cpu.nice series.
select("sys.cpu.nice")
.last(10, timestamp=1528240512000000)
// Will load last minute before "2018-04-22T01:00:00-05:00" of sys.cpu.nice series.
select("sys.cpu.nice")
.last(2m, date="2018-04-22T01:00:00-05:00")
// Will load last minute one hour before NOW of sys.cpu.nice series.
select("sys.cpu.nice")
.last(2m, shift=1h)
To resume last valid parameters are listed below. A parameter can be optional or mandatory. When a prefix is indicated, it means that this parameter can be set using a prefix name.
name | type | mandatory | prefix | Complementary information |
---|---|---|---|---|
span | Duration value | [x] | None | first parameter |
count | Integer | [x] | None | Only on Warp 10, first parameter |
date | String | [] | date | On Prometheus, RFC3339 format and on Warp 10, ISO 8601 dates string |
timestamp | Integer | [] | timestamp | Only on Warp 10 |
timestamp | Integer, Double | [] | timestamp | Only on Prometheus |
shift | Duration value | [] | shift |
In the case you are using TSL on Warp 10, the attributePolicy method allow you to choose how to handle the attributes in TSL series set result. You can choose between merging the Attributes with the series Labels, between keeping them splitted from the labels or simply remove them. By default TSL kept the split mode. The attributePolicy valid parameter is one of merge, split or remove.
select("sys.cpu.nice").where("dc=lga", "web~.*")
.last(2m, shift=1h)
.attributePolicy(remove)
The attributePolicy method should be put right after a select statement, as a where, from or last method but before any further metrics operations.
When collecting servers or application metrics, the data stored are often unsynchronised. To start processing our stored metrics, it's often mandatory to sample the data. Sampling the data corresponds to split metrics data points per time window. All values in this time window are send as parameter to a function that will provide one value as result.
This can be done using the TSL sampleBy method.
The sampleBy method expects as first parameter (mandatory):
- span: that correponds to the time window duration (duration format: 1m, 2M, 10s)
- or count: that correponds to a number of splits of the series as number (1, 2, ...).
The sampleBy method expects as second parameter (mandatory):
- An aggregator function to use: can be one of max, mean, min, first, last, sum, join, median, count, percentile, and or or. TSL expects the aggregator to be set as an ident field.
The sampleBy method takes also two optionals parameters:
- A boolean to indicate whether we should keep a relative sampling (true) or use an absolute one (default, and params at false): absolute sampling means that data would be round up (ex: with a 5 minutes span series at time 12:03 it would be 12:05, 12:00, 11:55, when with a relative sampling times would be at 12:03, 11:58, 11:53).
- A sampling policy can be auto, none, interpolate, next or previous. TSL expects the policy to be set as string (example "auto") or a list of strings, containing the policiy to apply in order. This list is restrained to values equals to interpolate, next or previous. Using interpolate policy will compute the interpolation of the intermediary values, next will fill missing values with the next values it found, and previous will fill missing values by the previous value of the series found. The none one will let empty missing values. When auto means that an interpolation is applied first to field intermediary missing values, previous to fill missing values before the first data-point and next to fill missing values after the last data-point. To fill missing value you can also use the method fill as policy. Fill expects a single parameter, the value to fill the series with. When no policy it's set it used auto by default.
The span duration format is a number followed by one of M for month(s), w for week(s), d for day(s), h for hour(s), m for minute(s), s for second(s), ms for milli-second(s), us for micro-second(s), ns for nano-second(s) and ps for pico-second(s). With a Prometheus back-end, we use the step query parameter to sample the data. It's handled a bit differently as by default Prometheus will sample by the last value recorded (until last 5 minutes).
When using sampleBy in TSL on Prometheus you can only set a span and an aggregator equals to last as parameters.
Example:
// Will load all values between of sys.cpu.nice series with 1 minute samples (one point per minute), aggegrated using a mean function.
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean)
// Will load all values between of sys.cpu.nice series with 1 minute samples (one point per minute), aggegrated using a max function.
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(30, max)
// Will load all values between of sys.cpu.nice series with 1 minute samples aggegrated using a mean function. One point per minute when at least one point exists in each minute.
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean, "none")
// Will load all values between of sys.cpu.nice series with 1 minute samples aggegrated using a mean function, filling intermediary missing point by a values interpolation and not using a relative sampling.
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean, "interpolate", false)
// Valid parameters prefixes
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(span=1m, aggregator=mean, fill="interpolate", relative=false)
// Using a list as fill policy
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(span=1m, aggregator="mean", fill=["interpolate", "next", "previous"], relative=false)
// Using the fill value method policy to fill missing values by Zero
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(span=1m, aggregator="mean", fill=fill(0), relative=false)
// Using the fill value method policy to fill missing values by Zero
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(span=1m, aggregator="mean", fill(0), relative=false)
To resume sampleBy valid parameters are listed below. A parameter can be optional or mandatory. When a prefix is indicated, it means that this parameter can be set using a prefix name.
name | type | mandatory | prefix | Complementary information |
---|---|---|---|---|
span | Duration value | [x] | span | |
count | Number | [x] | count | |
aggregator | Operator | [x] | aggregator | Operator value can be one of: max, mean, min, first, last, sum, join, median, count, percentile, and, or |
fill | String | [] | fill | Fill value can be one of auto, none, interpolate, next, previous |
fill | List of string | [] | fill | Each values of the list can be one of interpolate, next, previous |
relative | Boolean | [] | relative |
When building a metrics data flow, once we sampled the data, we may want to regroup similar metrics. This is what the group and groupBy methods are build to. The user defines the aggregation function and custom rules to applied to reduce to a single value all metrics values occuring at the same time.
The group method will generate a single series using the specified aggregator.
The group method takes one parameter:
- The aggregator function to use: can be one of max, mean, min, sum, join, median, count, percentile, and or or. TSL expects the policy to be set as an ident field.
// Valid parameters prefix
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean)
.group(sum)
The groupBy method allow to specify labels to limit the aggegator on series that have the same values for each labels key specified. For example, when using our example, if we specify dc and host, it will reduce the data into two series: both with "dc=lga" and one with host equals to "web01" and the second with "web02".
The groupBy method takes two to n parameters:
- A labels key as string to group the data on. To select more than one label string you can use a label string list as parameter
- The aggregator function to use: can be one of max, mean, min, sum, join, median, count, percentile, and or or. TSL expects the policy to be set as an ident field.
Example:
// Valid parameters prefix
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean)
.groupBy("dc", mean)
// Valid parameters prefix
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean)
.groupBy(["host","dc"],mean)
To resume groupBy valid parameters are listed below. A parameter can be optional or mandatory. When a prefix is indicated, it means that this parameter can be set using a prefix name.
name | type | mandatory | prefix | Complementary information |
---|---|---|---|---|
label | String | [x] | None | a label key as first parameter |
labels | List of string | [x] | None | a label key list as first parameter |
aggregator | Operator | [x] | None | Operator value can be one of: max, mean, min, sum, join, median, count, percentile, and or or as second parameter |
The groupWithout methods works the same way as the groupBy one exept it will compute the minimal equivalence classes and then remove the labels given as parameters to group the series on. groupWithout behavior is similar to the PromQL aggregation operators.
Example:
// Valid parameters prefix
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean)
.groupWithout("dc", mean)
// Valid parameters prefix
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean)
.groupWithout(["host","dc"],mean)
When using TSL on prometheus, you can also use the groupLeft and groupRight to match PromQL group_left and group_right operators.
Sometimes, we just want to update our series values (adding 2, checking the values with a threshold, rounded the value, compute a rate, and so on). In TSL, we have a large variety of Time series operator available than can be applied directly on a series result.
This can be done using the TSL window method.
The window method expects
- At least a window function to use: can be one of max, mean, min, first, last, sum, delta, stddev, stdvar, join, median, count, percentile, and or or. TSL expects the window function to be set as an ident field.
- A single duration time window to compute the over_time method on for Prometheus or Warp10.
- Warp10 MAP frame supports two parameters as TSL window function a pre and/or post parameter. The pre and post parameters can be a number of points to compute the window on, or a duration if the series was sampled before.
As Warp 10 is more flexible, you can either specify a duration or a number of points to apply on with the pre and/or post parameter.
Example:
// With only a duration (Prometheus or Warp10)
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, last)
.window(mean, 1m)
// With pre and post as durations (Warp10)
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, last)
.window(sum, 2m, 1m)
// With pre and post as integer (Warp10)
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.window(sum, 2, 10)
// With percentile operator, with pre and post (Warp10)
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.window(percentile, 42, 2, 10)
// With percentile operator, without pre and post (Warp10)
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.window(percentile, 42)
// With join operator, with pre and post (Warp10)
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.window(join, '-', 2, 10)
Instead of the window function, the cumulative method can aslo be applied. It takes:
- A window function to use: can be one of max, mean, min, first, last, sum, delta, stddev, stdvar, join, median, count, percentile, and or or. TSL expects the window function to be set as an ident field.
This function will apply the function on all windows that appears before each points. This can be useful to complete a cumulative sum on a time series.
// Cumulative with sum
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, last)
.cumulative(sum)
// Cumulative with delta
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, last)
.cumulative(delta)
// Cumulative with Percentile
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, last)
.cumulative(percentile, 42)
The cumulative operator is not available on Prometheus.
The following TSL methods can be used to apply arithmetic operators on metrics:
- The add operator. Add takes one number parameter, example: .add(2)
- The sub operator. Sub takes one number parameter, example: .sub(2)
- The mul operator. Mul takes one number parameter, example: .mul(2)
- The div operator. Div takes one number parameter, example: .div(2)
- The abs operator. Compute the absolute value of all values of the series, example: .abs()
- The ceil operator. Round all values of the series at the nearest integer above, example: .ceil()
- The floor operator. Round all values of the series at the nearest integer below, example: .floor()
- The round operator. Round all values of the series at the nearest integer, example: .round()
- The ln operator. Compute values ln, example: .ln()
- The log2 operator. Compute values log2, example: .log2()
- The log10 operator. Compute values log10, example: .log10()
- The logN operator. Compute values logN of the number parameter, example: .logN(2)
- The rate operator. Compute a rate (by default per second when no parameter are sets) or on a specify duration, example: .rate(), .rate(1m)
- The sqrt operator. Compute values square root, example: .sqrt()
- The quantize operator. Compute the amount of values inside a step on the complete query range or per parameter duration. This generate a single metric per step, based on the label key specified as first parameter. The second parameter corresponds to the step value: it can be a single number or integer value, or a fix step set modelised as a number or integer list. The last optional parameter for the quantize method is the quantize duration. This method can be useful to compute histograms, use example: .quantize("quantile", [ 0, 10 ], 2m), .quantize("quantile", 0.1)
The logN operator is not available on Prometheus.
With Warp 10 you can use the finite mapper to remove the NaN values, you can do the same in TSL:
- The finite operator. Remove NaN values, example: .finite()
The following TSL methods can be used to apply equality operators on metrics:
- The equal operator. Only values that are stricly equals to equal parameter are kept, example: .equal(2)
- The notEqual operator. Only values that are not equals to notEqual parameter are kept, example: .notEqual(2)
- The greaterThan operator. Only values that are stricly above to greaterThan number parameter are kept, example: .greaterThan(2)
- The greaterOrEqual operator. Only values that are above or equals to greaterOrEqual number parameter are kept, example: .greaterOrEqual(2)
- The lessThan operator. Only values that are stricly below to lessThan number parameter are kept, example: .lessThan(2)
- The lessOrEqual operator. Only values that are below or equals to lessOrEqual number parameter are kept, example: .lessOrEqual(2)
The following TSL methods can be used to apply limit operators on metrics:
- The maxWith operator. MaxWith will test all values to keep only the one above maxWith parameter and replace all other values per maxWith parameter, example: .maxWith(2)
- The minWith operator. MinWith will test all values to keep only the one below minWith parameter and replace all other values per minWith parameter, example: .minWith(2)
The following TSL methods can be used to convert metrics values:
- The toboolean operator used to convert all metrics values to boolean, example: .toboolean().
- The todouble operator used to convert all metrics values to double, example: .todouble().
- The tolong operator used to convert all metrics values to long, example: .tolong().
- The tostring operator used to convert all metrics values to long, example: .tostring().
The following TSL methods can be used to apply time related operators on metrics:
- The shift operator used to shift all points by a duration parameter, example: .shift(2m).
- The day operator used to replace each points per the day of the month of each points (in UTC time), example: .day().
- The weekday operator used to replace each points per the day of the week of each points (in UTC time), example: .weekday().
- The hour operator used to replace each points per their hours (in UTC time), example: .hour().
- The minute operator used to replace each points per their minutes (in UTC time), example: .minute().
- The month operator used to replace each points per their month (in UTC time), example: .month().
- The year operator used to replace each points per their year (in UTC time), example: .year().
- The timestamp operator used to replace each points per their timestamp (in UTC time), example: .timestamp().
- The keepLastValues operator used to keep the last N values of the operator (from 0 to the current metrics size, by default return only the last metric value), example: .keepLastValues()., .keepLastValues(10).
- The keepLastValue singular form of the previous method, example: .keepLastValue().
- The keepFirstValues operator used to keep the first N values of the operator (from 0 to the current metrics size, by default return only the first metric value), example: .keepFirstValues()., .keepFirstValues(10).
- The keepFirstValue singular form of the previous method, example: .keepFirstValue().
- The shrink operator used to shrinks the number of values specified as parameter of each metrics of the set, example: .shrink(5).
- The timeclip operator used to keep only values in a specific time interval. timeclip expects 2 parameters: the last tick of the interval to keep and the duration time to keep before (as number or as duration). You can also specified two ISO8601 string date to set the time interval to keep. With timeclip, using the now keyword will push NOW as a timestamp in the correct unit time of the platform. Example: .timeclip(1535641320000000, 2m), .timeclip(now, 200000), .timeclip("2018-04-22T00:57:00-05:00","2018-04-22T01:00:00-05:00")
- The timemodulo operator used to split metrics per a time modulo given as parameter. This will add to each series a new label key (second parameter) and the value of original timestamp quotient. Use example: .timemodulo(42,"quotient").
- The timescale operator used to multiply each series timestamp by the value set as the method parameter, example: .timescale(42).
- The timesplit operator used to split timeseries based on quiesce periods. The first parameter is the time duration value of the quiesce period, it can be a duration value, a long or the keyword now. The second one in the minimal amount of points to keep a new series (to reduce noise when creating series), and the last one the new label key for each split series. example: .timesplit(now, 42, 'test')., .timesplit(1h, 4, 'test')., .timesplit(20000000, 1, 'test').
For keepLastValue(s) and keepFirstValue(s) functions, if the parameter specified is greater than the actual size of the metric, those functions will then return the complete metrics.
The keepFirstValue(s), shrink, timeclip, timemodulo, timescale and timesplit are currently not supported on a Prometheus backend.
ThekeepLastValue(s) works on a Prometheus backend, calling an instant query. This means that on a Prometheus keepLastValue(s) expects no parameters or only the value 1
.
TSL introduces some methods to sort metrics by their samples values.
- The sort operator used to sort metrics data by their globals mean value in ascending order. Use example: .sort().
- The sortDesc operator used to sort metrics data by their globals mean value in descending order. Use example: .sortDesc().
- The sortBy operator used to sort metrics data according to the result of a global operator in ascending order. The operator function can be one of: last, first, max, mean, min, sum, median, count, percentile, and or or. Use example: .sortBy(max)., .sortBy(percentile, 42).
- The sortDescBy operator used to sort metrics data according to the result of a global operator in descending order. The operator function can be one of: last, first, max, mean, min, sum, median, count, percentile, and or or. Use example: _.sortDescBy(max).
- The topN operator used to get the top N series (sorted by their globals mean value in descending order) Use example: .topN(2).
- The bottomN operator used to get the lowest N series (sorted by their globals mean value in ascending order). Use example: .bottomN(2).
- The topNBy operator used to get the top N series (sorted according to the result of a global operator in descending order. The operator function can be one of: last, first, max, mean, min, sum, median, count, percentile, and or or). Use example: .topNBy(2, min)., .topNBy(2, percentile, 42).
- The bottomNBy operator used to get the lowest N series (sorted according to the result of a global operator in ascending order. The operator function can be one of: last, first, max, mean, min, sum, median, count, percentile, and or or). Use example: .topNBy(2, max).
- All sort operations here can be used to sort the resulting series set based on it's meta using a sort operator with a meta operator as names, selectors, labels or attributes. Use example: .sortBy(names)., .topNBy(2, selectors)., _.sortDescBy(labels, "l0")., .sortBy(attributes, [ test, "l1"])..
The sortBy, sortDescBy, topNBy and bottomNBy operators are not available for Prometheus.
TSL includes a few methods to filter the metrics result set:
- The filterByLabels method to keep only the metrics matching some labels rules defined as parameters. filterByLabels expects at least one label clause string, and optionally as many as needed. Use example: .filterByLabels("label~42.*", "host=server-01").
- The filterByName method to keep only the metrics matching a name rule defined as parameters. filterByName expects a single string rule. Use example: .filterByName("test"), .filterByName("~test")
- The filterByLastValue method to keep only the metrics matching a rule on their last value defined as parameters. filterByLastValue expects at least one string rule, and optionally as many as needed. Use example: .filterByLastValue(">=42"), .filterByName("!='mystring'"). The valid filterByLastValue parameters are <=, <, !=, =, >= and >.
- The filterWithoutLabels method to keep only with metrics without the labels keys specified as parameters. Use example: .filterWithoutLabels("label", "host").
When we load several set of data, we may want to apply operation on metrics sets. TSL allow us to apply operators on metrics.
A metrics operators will apply an operation on several set of metrics.
For example: we can add the values of a first series with a second one. Value will be added when ticks have an exact match, this is why it's important to sample the data before executing such an operation.
- The add operator between metrics sets, example: add(select(...), select(...), ...)
- The sub operator between two metrics sets, example: sub(select(...), select(...))
- The mul operator between metrics sets, example: mul(select(...), select(...), ...)
- The div operator between two metrics sets, example: div(select(...), select(...))
- The and operator between metrics sets, example: and(select(...), select(...), ...)
- The or operator between metrics sets, example: or(select(...), select(...), ...)
- The equal operator between metrics sets, example: equal(select(...), select(...), ...)
- The notEqual operator between metrics sets, example: notEqual(select(...), select(...), ...)
- The greaterThan operator between metrics sets, example: greaterThan(select(...), select(...), ...)
- The greaterOrEqual operator between metrics sets, example: greaterOrEqual(select(...), select(...), ...)
- The lessThan operator between metrics sets, example: lessThan(select(...), select(...), ...)
- The lessOrEqual operator between metrics sets, example: lessOrEqual(select(...), select(...), ...)
- The mask operator to use a Warp 10 mask, example: mask(select(...).toboolean(), select(...))
- The negmask operator to use a Warp 10 negmask, example: negmask(select(...).toboolean(), select(...))
Example:
// Valid parameters prefix
add(
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.where("host=web01")
.sampleBy(1m, mean),
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.where("host=web02")
.sampleBy(1m, mean)
)
By default, on Warp 10 only one metrics will be computed as result except if we use the on and/or ignoring method explained below. By default, on Prometheus the minimal equivalence class matching a maximum of labels will be computed as result except if we use the on and/or ignoring method explained below.
To limit operation on specific labels, the method on can be-used post a metrics operator one.
For example the following TSL query will return two series one where all values of the "web01" host series are summed and a second one for the "web02" host series.
// Add on label "host"
add(
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean),
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.sampleBy(1m, mean)
).on("host")
The Ignoring method will remove the selected labels of the equivalence class for the operator method.
Example:
// Compute an add on all series
add(
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.where("host=web01")
.sampleBy(1m, mean),
select("sys.cpu.nice")
.from(1346846400000000,1346847000006000)
.where("host=web02")
.sampleBy(1m, mean)
).ignoring("host")
TSL allow the user to set it's own variable. Just set a name followed by an "=" sign.
To reuse a variable, just use it's name. To execute a query store in a variable, just write the variable name in a new line.
Example:
// Store a two minutes duration
customDuration = 2m
// Store a series name
seriesName = "sys.cpu.nice"
// Store a label name
labelName = "host=web02"
// Store a number
myNumber = 100
// Store a select instruction and it's operation
mySelect = select(seriesName)
.from(1346846400000000,1346847000006000)
.where(labelName)
.sample(30s)
.add(100)
// Get it's result
mySelect
// Store a label name
labelName = "host=web02"
// Store a single select
mySelect = select("sys.cpu.nice").from(1346846400000000,1346847000006000)
// Apply post select operation and get result
mySelect.where(labelName).ln()
mySelect.where(labelName).add(100)
// Store a label name
labelName = "host=web02"
// Use variables in operation
mySelect = select("sys.cpu.nice").from(1346846400000000,1346847000006000)
add(mySelect.where(labelName).ln(),mySelect
.where("host=web01"))
// Store multiples series operation result in variable
addSave = add(mySelect.where(labelName).ln(),mySelect
.where("host=web01"))
// Get multiples series operation result from addSave variable
addSave.on("host").add(100)
You can define a variable and re-use it directly inside a TSL string using a template as shown in the example below:
host = "my.host"
select("my.series")
.where(["host=${host}"])
You can declare and use TSL lists in a variable:
labelsNames = ["host=web02", "dc~.*"]
On a TSL list you can apply:
- The add method to add elements to the current list. Use example : .add("test=42")
- The remove method to remove elements of the current list. Use example : .remove("test=42")
For example to use it in a where statement:
select("sys.cpu.nice").where(labelsNames)
In TSL, we can directly use the Connect method to update the set the backend on which queries are processed. For a warp10 backend it's:
connect("warp10","http://localhost:9090", "TOKEN")
or when no Token is needed:
connect("warp10","http://localhost:9090")
For a prometheus it's
connect("prometheus","http://localhost:9090")
or with a user/password if Prometheus is behind a basic auth:
connect("prometheus","http://localhost:9090","user","pwd")
The update metrics meta-data in TSL you can use one of the following function:
- The addPrefix to add a prefix to each metrics name of a set. Use example: .addPrefix("prefix").
- The addSuffix to add a suffix to each metrics name of a set. Use example: .addSuffix("suffix").
- The rename to rename each metrics of a set. Use example: .rename("newName").
- The renameBy to rename each metrics per one of it's labels. Use example: .renameBy("host").
- The removeLabels to remove one or several labels of a metrics set. Use example: .removeLabels("host", "dc").
- The renameLabelKey to rename a label key. Use example: .renameLabelKey("dc", "Data-center").
- The renameLabelValue to rename a label value. Use example: .renameLabelValue("dc", "new").
- The renameLabelValue to rename a label value matching a regexp. Use example: .renameLabelValue("dc", "lg.*", "new-dc").
- The renameTemplate expect a Template string to rename a series. The
${this.name}
corresponds to the current series name, the${this.labels.key}
to a series label key. Use example: .renameTemplate("my.new.series.${this.name}.is.great"), .renameTemplate('${this.labels.hostname} (${this.labels.datacenter}) ${this.labels.hostname} ${this.name} ${ this.name }'). - The setLabelFromName to set each metric name (fully or partly with a regex) in a label. Expects a string as first parameter to specify the label name to use. Optionally a second parameter, a regex string, can be specified to set only a part of the metric name. Each matching group of the regex will be joined to form the value in the label, and if the regex don't match, the label will not be set.
None of those methods are currently available for Prometheus.
At the same level as the select statement, you can use the create one. It will create a Time Series List. Create then accepts n series functions as parameter.
Example:
create(series(), series())
The series method is used to create a Time Series, only in Warp 10 for now, you can give the Time Series name as parameter. To set the created series labels, you can use the setLabels method. You can also use the setValues to add values to this newly created series.
The setValues takes n parameter, the first one (optional) is the base Timestamp of the values (by default zero). Then the other are a two elements array composed of a timestamp (that would be add to the base one) and the value to set. Use example: .setValues([0, 1], [100, 2]).
The setLabels takes a single parameter: a labels string list where the key and values are split per the equals symbol.
At the end of the create statement, all other Time Series set methods can be apply on.
A more complex but valid tsl statement to create 2 Time Series would be:
create(
series("test")
.setLabels([ "l0=42", "l1=42" ])
.setValues("now", [-5m, 2], [0, 1])
.setValues("now",[2m, 3]),series("test2")
.setLabels([ "l0=42", "l1=42" ])
.setValues(now, [-5m, 2], [0, 1]))
.sampleBy(30s, max)
TSL can also be used to store query result back on the backend. This can be done using the store method. Store expects a token as unique parameter. Use example: .store("WRITE_TOKEN").
store is only avaible on a Warp 10 backend.
To resets counters values the method resets can be applied in TSL. Use example: .resets().
You can exchange with us here or on our gitter room.
Any feedback or idea about TSL would be warmly welcome!