The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/plugins/datasource/loki/metricTimeSplitting.ts

52 lines
2.0 KiB

// every timestamp in this file is a number which contains an unix-timestamp-in-millisecond format,
// like returned by `new Date().getTime()`. this is needed because the "math"
// has to be done on integer numbers.
// we are trying to be compatible with
// https://github.com/grafana/loki/blob/089ec1b05f5ec15a8851d0e8230153e0eeb4dcec/pkg/querier/queryrange/split_by_interval.go#L327-L336
function expandTimeRange(startTime: number, endTime: number, step: number): [number, number] {
// startTime is decreased to the closes multiple-of-step, if necessary
const newStartTime = startTime - (startTime % step);
// endTime is increased to the closed multiple-of-step, if necessary
let newEndTime = endTime;
const endStepMod = endTime % step;
if (endStepMod !== 0) {
newEndTime += step - endStepMod;
}
return [newStartTime, newEndTime];
}
export function splitTimeRange(
startTime: number,
endTime: number,
step: number,
idealRangeDuration: number
): Array<[number, number]> {
if (idealRangeDuration < step) {
// we cannot create chunks smaller than `step`
return [[startTime, endTime]];
}
// we make the duration a multiple of `step`, lowering it if necessary
const alignedDuration = Math.trunc(idealRangeDuration / step) * step;
const [alignedStartTime, alignedEndTime] = expandTimeRange(startTime, endTime, step);
const result: Array<[number, number]> = [];
// we iterate it from the end, because we want to have the potentially smaller chunk at the end, not at the beginning
for (let chunkEndTime = alignedEndTime; chunkEndTime > alignedStartTime; chunkEndTime -= alignedDuration + step) {
// when we get close to the start of the time range, we need to be sure not
// to cross over the startTime
const chunkStartTime = Math.max(chunkEndTime - alignedDuration, alignedStartTime);
result.push([chunkStartTime, chunkEndTime]);
}
// because we walked backwards, we need to reverse the array
result.reverse();
return result;
}