Important: This documentation is about an older version. It's relevant only to the release noted, many of the features and functions have been updated or replaced. Please view the current version.
Use k6 to load test log queries
When designing a test scenario for load testing the read path of a Loki installation, it is important to know what types of queries you expect.
Supported query types
Loki has 5 types of queries:
- instant query
- range query
- labels query
- label values query
- series query
In a real-world use-case, such as querying Loki using it as a Grafana datasource, all of these queries are used. Each of them has a different API endpoint. The xk6-loki extension provides a Javascript API for all these query types.
Instant query
Instant queries can be executed using the function instantQuery(query, limit)
on the loki.Client
instance:
Javascript example code fragment:
export default () => {
client.instantQuery(`rate({app="my-app-name"} | logfmt | level="error" [5m])`);
}
Range query
Range queries can be executed using the function rangeQuery(query, duration, limit)
on the loki.Client
instance:
Javascript example code fragment:
export default () => {
client.rangeQuery(`{app="my-app-name"} | logfmt | level="error"`, "15m");
}
Labels query
Labels queries can be executed using the function labelsQuery(duration)
on the loki.Client
instance:
Javascript example code fragment:
export default () => {
client.labelsQuery("10m");
}
Label values query
Label values queries can be executed using the function labelValuesQuery(label, duration)
on the loki.Client
instance:
Javascript example code fragment:
export default () => {
client.labelValuesQuery("app", "10m");
}
Series query
Series queries can be executed using the function seriesQuery(matcher, range)
on the loki.Client
instance:
Javascript example code fragment:
export default () => {
client.seriesQuery(`match[]={app=~"loki-.*"}`, "10m");
}
Metrics
The extension collects metrics that are printed in the end-of-test summary in addition to the built-in metrics. These metrics are collected only for instant and range queries.
name | description |
---|---|
loki_bytes_processed_per_second | amount of bytes processed by Loki per second |
loki_bytes_processed_total | total amount of bytes processed by Loki |
loki_lines_processed_per_second | amount of lines processed by Loki per second |
loki_lines_processed_total | total amount of lines processed by Loki |
Labels pool
With the xk6-loki extension, you can use the field labels
on the Config
object. It contains label names and values that are generated in a reproducible
manner. Use the same labels cardinality configuration for both write
and
read
testing.
Javascript example code fragment:
const labelCardinality = {
"app": 5,
"namespace": 2,
};
const conf = new loki.Config(BASE_URL, 10000, 1.0, labelCardinality);
const client = new loki.Client(conf);
function randomChoice(items) {
return items[Math.floor(Math.random() * items.length)];
}
export default() {
let app = randomChoice(conf.labels.app);
let namespace = randomChoice(conf.labels.namespace);
client.rangeQuery(`{app="${app}", namespace="${namespace}"} | logfmt | level="error"`, "15m");
}
Alternatively, you can define your own pool of label names and values, and then randomly select labels from your pool instead of a generated pool.
Javascript example
A more complex example of a read scenario can be found in xk6-loki repository. The test file read-scenario.js can be resused and extended for your needs.
It allows you to configure ratios for each type of query and the ratios of time ranges.
Javascript example:
const queryTypeRatioConfig = [
{
ratio: 0.1,
item: readLabels
},
{
ratio: 0.15,
item: readLabelValues
},
{
ratio: 0.05,
item: readSeries
},
{
ratio: 0.5,
item: readRange
},
{
ratio: 0.2,
item: readInstant
},
];
This configuration would execute approximately
- 10% labels requests
- 15% label values requests
- 5% requests for series
- 50% range queries
- 20% instant queries
during a test run.