Skip to content
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
902d864
feat: LID for query splitting
jeschkies Mar 31, 2025
b1bc171
Add porposal for Arrow Flight RPC
jeschkies Mar 31, 2025
beac6d3
Update 0006-api-expose-split.md
jeschkies Mar 31, 2025
3b74ead
Update docs/sources/community/lids/0006-api-expose-split.md
jeschkies Apr 2, 2025
dcd6a0f
Update docs/sources/community/lids/0006-api-expose-split.md
jeschkies Apr 2, 2025
74ade1a
Update docs/sources/community/lids/0006-api-expose-split.md
jeschkies Apr 2, 2025
873f26d
Update docs/sources/community/lids/0006-api-expose-split.md
jeschkies Apr 2, 2025
a8aff24
Update docs/sources/community/lids/0006-api-expose-split.md
jeschkies Apr 2, 2025
a52e702
Change response format
jeschkies Apr 2, 2025
5760aa6
Clearify parameter semantics
jeschkies Apr 4, 2025
d2f2b98
Update docs/sources/community/lids/0006-api-expose-split.md
jeschkies Apr 8, 2025
0fd5d30
Update docs/sources/community/lids/0006-api-expose-split.md
jeschkies Apr 8, 2025
5ffb1d5
Define split and shard
jeschkies Apr 9, 2025
a07ae5f
Merge remote-tracking branch 'grafana/main' into karsten/splitter-lid
jeschkies Apr 15, 2025
66382ee
Merge remote-tracking branch 'grafana/main' into karsten/splitter-lid
jeschkies Apr 16, 2025
cc4313f
Correct unlimited value
jeschkies Apr 16, 2025
819637e
Update docs/sources/community/lids/0006-api-expose-split.md
jeschkies Apr 22, 2025
972694c
Update docs/sources/community/lids/0006-api-expose-split.md
jeschkies Apr 22, 2025
6e1fdbc
Merge branch 'main' into karsten/splitter-lid
jeschkies Apr 22, 2025
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions docs/sources/community/lids/0006-api-expose-split.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
title: "0006: Expose Split Logic in API"
description: "0006: Expose Split Logic in API"
---

# 0006: Expose Split Logic in API

**Author:** Karsten Jeschkies (karsten.jeschkies@grafana.com)

**Date:** 03/2025

**Sponsor(s):** @trevorwhitney

**Type:** API

**Status:** Review

**Related issues/PRs:** N/A

**Thread from [mailing list](https://groups.google.com/forum/#!forum/lokiproject):** N/A

---

## Background

Loki has an internal logic to split and shard log and metric queries by time into multiple queries. However, this logic is not
accessible outside of the code base. This proposal intends to create an API for clients to split queries by exposing the
internal split logic.

A split query is divided by time. The results of a split query can be concatenated in order to form the final
result.

A sharded query is divided by label values. The results of a sharded cannot always be concatenated but require some
extra logic to form the final result. Some queries, such as `topk` cannot be sharded at all.

## Problem Statement

Loki clients such as the Grafana Loki datasource or the [Trino Loki
connector](https://github.com/trinodb/trino/tree/master/plugin/trino-loki) benefit from splitting LogQL queries into multiple sub-queries either to process
smaller chunks or to distribute work on query results.

Splitting a query requires parsing the LogQL query first but there are no parsers for other languages except Go and
JavaScript.

## Goals

The intended goal is to enable any client to split a query into multiple sub-queries that can be either executed
sequentially or in parallel. The joined result of the sub-queries must be the same as executing the same query.

## Non-Goals

This proposal does not aim to provide pagination for query results.

## Proposals

### Proposal 0: Do nothing

Without an API each client will have to use a LogQL parser.

*Pros*
- The split logic in Loki can be changed at will without breaking client behavior.
- There is no maintanence overhead for an API.

*Cons*
- Currently, the LogQL grammar is specific to Go. It is not easy to port it and the parser to other languages.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worth at least calling out there's a JS implementation as well, but I acknowledge it is largely a copy and paste and has a maintenance burden

- Any changes to the splitting logic must be implemented for each client/platform.

### Proposal 1: Expose Splitting in an API

A new endpoint `GET /loki/api/v1/split_query` is introduced that takes a `splits` parameter and the same parameters as the [/loki/api/v1/query_range](https://grafana.com/docs/loki/latest/reference/loki-http-api/#query-logs-within-a-range-of-time) endpoint. The new endoint returns sub-queries split by time.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

split-by-time

will this endpoint determine optimal splits? currently the split-by is hardcoded in the loki config per tenant, in which case it seems pretty trivial for a client to be able to arbitrarily create the same splits. is it a goal of this project that this endpoint would be capable of more intelligent splitting rather than just applying the tenant's split-by config?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this endpoint determine optimal splits?

It kind of depends what we mean by optimal 🙂 I think the internal sharding layer tries some optimal sharding. Anyhow, we need something to hang on to. Either number of splits, interval or max response size.


The `splits` parameter optionally defines the number of desired splits. The API is allowed to return fewer splits than requested.

The `limit` parameter has extended semantics. Setting it to `0` for a log stream query indicates to query all logs.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameters I would pass to this endpoint are:

  • query (or queries)
  • limit, which should represent the total amount of results between the first and last splitted requests
  • direction

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the step? I'm wondering if that is important for splitting.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming back to the limit, it's a bit more complicated. For metric queries there's no expected limit, as you expect the data for the requested interval.

For querying logs it's a different story, because you might hit the limit with the first request. For example, let's say you want 5000 logs from the last 3 days, split in 3/6/12/etc. You can easily hit that limit on the first day, so maybe the endpoint should just return a single split.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my case I often want all logs. So I'll allow limit=-1 to indicate that all logs should be returned.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to clarify here, is limit=-1 saying explicitly construct the splits such that each split falls below any loki limits? I think that gets pretty complicated. if instead limit=-1 is just saying "I don't care about limits", it would probably be simpler to just omit that parameter in that case (rather than using -1)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many users have the issue that they want to query all logs in a time range but do not know how large the log line limit should be. It defaults to 100. There should be a way to tell the split endpoint that I want to get all log lines.

The response body is JSON encoded:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some thoughts on the response. is it important to the user to differentiate between a single split that just happens to be a single split because it was optimal, and a single split because the query could not be split? certain metric queries will not be able to be split in a way they can be re-combined in the client to produce the same result, so should we add a warnings field, or some other metadata to communicate this back to the client?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

certain metric queries will not be able to be split in a way they can be re-combined in the client to produce the same resul

That would be sharding. E.g. for certain metric queries. I should specify in the doc that split is always by time and sharding is by stream labels.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I think those are good distinctions to call out and align with our language elsewhere


```json
{
"resultType": "matrix" | "streams" | "vector",
"subqueries": [
{
start: <timestamp nanoseconds>,
end: <timestamp nanoseconds>,
limit: <number>,
query: <query string>
},
{
start: <timestamp nanoseconds>,
end: <timestamp nanoseconds>,
limit: <number>,
query: <query string>
}
]
}
```

*Pros*
- Clients can split queries independent on the implemation language and platform.
- Split logic is controlled by Loki and not the client. This means it can be improved, for example, by introducing sharding

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the strongest argument for doing this work IMO. being able to improve split logic to produce optimal splits, as well as centralize what can and can't be split.

labels.

*Cons*
- A new API endpoint increases the compatiblity surface area and thus maintanence overhead for Loki maintainers.

### Proposal 2: Support Apache Arrow Flight RPC

Loki could support Apache [Arrow Flight RPC](https://arrow.apache.org/docs/format/Flight.html) which is designed to
exchange large data sets in shards between services.

*Pros*
- Supporting an open standard comes with support for other non-Loki clients.

*Cons*
- Loki would have to support Apache Arrow which make the implementation more complicated.
- Arrow Flight RPC assumes the data is being queried on the first request. Which means all shards are available at the
same time. However, the intent of this document is that shards can be queried independently.