-
-
Notifications
You must be signed in to change notification settings - Fork 69
LogQL Plugins
- WORK IN PROGRESS!
Missing a LogQL function in cLoki? Extend functionality in in no time using cLoki Plugins
For example you need to add a unwrapped range aggregator derivative
:
derivative=(last_unwrapped_value_in_range - first_unwrapped_value_in_range) / (last_time_in_range - first_time_in_range)
You need to add a js module into /plugins/unwrap_registry
directory with the next API:
/**
* @returns {{run: (function(*, number, number): *), approx: (function(*): number)}}
*/
module.exports.derivative = () => {}
So module.exports.<range aggregator name>
is a function returning an object with two methods: run
and approx
.
The run
method is called every time new unwrapped value accepted by the stream processor. Its declaration is:
/**
*
* @param sum {any} previous value for the current time bucket
* @param val {{unwrapped: number}} current values
* @param time {number} timestamp in ms for the current value
* @returns {any}
*/
const run = (sum, val, time) => {
sum = sum || {};
sum.first = sum && sum.first && time > sum.first.time ? sum.first : {time: time, val: val.unwrapped};
sum.last = sum && sum.last && time < sum.last ? sum.last : {time: time, val: val.unwrapped};
return sum;
}
So the run function accepts the previous aggregated value. The initial value is 0. The second is an object with current unwrapped value. And the time when the unwrapped value appeared in the database. The run function should return the new sum. Data immutability is preferred but optional.
The approx
method is called for each bucket at the end of processing. Its declaration is:
/**
* @param sum {any} sum of the time bucket you have created during "run"
* @returns {number}
*/
const approx = (sum) => {
return sum && sum.last && sum.first && sum.last.time > sum.first.time ?
(sum.last.val - sum.first.val) / (sum.last.time - sum.first.time) * 1000 : 0;
}
The only argument is the result of the latest run
call for the bucket.
The function should return number as result of the operator calculation for the provided time bucket.
The full code of the derivative
function:
/**
* @returns {{run: (function(*, number, number): *), approx: (function(*): number)}}
*/
module.exports.derivative = () => {
return {
/**
*
* @param sum {any} previous value for the current time bucket
* @param val {{unwrapped: number}} current values
* @param time {number} timestamp in ms for the current value
* @returns {any}
*/
run: (sum, val, time) => {
sum = sum || {};
sum.first = sum && sum.first && time > sum.first.time ? sum.first : {time: time, val: val.unwrapped};
sum.last = sum && sum.last && time < sum.last ? sum.last : {time: time, val: val.unwrapped};
return sum;
},
/**
* @param sum {any} sum of the time bucket you have created during "run"
* @returns {number}
*/
approx: (sum) => {
return sum && sum.last && sum.first && sum.last.time > sum.first.time ?
(sum.last.val - sum.first.val) / (sum.last.time - sum.first.time) * 1000 : 0;
}
}
}