This commit is contained in:
Aliaksandr Valialkin 2024-05-19 19:16:28 +02:00
parent 5ee582f07f
commit 0c77cb1f88
No known key found for this signature in database
GPG key ID: 52C003EE2BCDB9EB
3 changed files with 33 additions and 9 deletions

View file

@ -52,7 +52,10 @@ func ProcessHitsRequest(ctx context.Context, w http.ResponseWriter, r *http.Requ
return return
} }
q.AddCountByTimePipe(int64(step), int64(offset)) // Obtain field entries
fields := r.Form["field"]
q.AddCountByTimePipe(int64(step), int64(offset), fields)
q.Optimize() q.Optimize()
var wLock sync.Mutex var wLock sync.Mutex

View file

@ -102,10 +102,10 @@ The `<step>` arg can contain values in [the format specified here](https://docs.
If `<step>` is missing, then it equals to `1d` (one day). If `<step>` is missing, then it equals to `1d` (one day).
For example, the following command returns per-hour number of [log messages](https://docs.victoriametrics.com/victorialogs/keyconcepts/#message-field) For example, the following command returns per-hour number of [log messages](https://docs.victoriametrics.com/victorialogs/keyconcepts/#message-field)
with the `error` [word](https://docs.victoriametrics.com/victorialogs/logsql/#word) over logs for the 3 hour day: with the `error` [word](https://docs.victoriametrics.com/victorialogs/logsql/#word) over logs for the 3 hours:
```sh ```sh
curl http://localhost:9428/select/logsql/hits -d 'query=error' -d 'start=1d' -d 'step=1h' curl http://localhost:9428/select/logsql/hits -d 'query=error' -d 'start=3h' -d 'step=1h'
``` ```
Below is an example JSON output returned from this endpoint: Below is an example JSON output returned from this endpoint:
@ -130,6 +130,19 @@ Below is an example JSON output returned from this endpoint:
Additionally, the `offset=<offset>` arg can be passed to `/select/logsql/hits` in order to group buckets according to the given timezone offset. Additionally, the `offset=<offset>` arg can be passed to `/select/logsql/hits` in order to group buckets according to the given timezone offset.
The `<offset>` can contain values in [the format specified here](https://docs.victoriametrics.com/victorialogs/logsql/#duration-values). The `<offset>` can contain values in [the format specified here](https://docs.victoriametrics.com/victorialogs/logsql/#duration-values).
For example, the following command returns per-day number of logs with `error` [word](https://docs.victoriametrics.com/victorialogs/logsql/#word)
over the last week in New York time zone (`-4h`):
```logsql
curl http://localhost:9428/select/logsql/hits -d 'query=error' -d 'start=1w' -d 'step=1d' -d 'offset=-4h'
```
Additionally, any number of `field=<field_name>` args can be passed to `/select/logsql/hits` for grouping hits buckets by the mentioned `<field_name>` fields.
For example, the following query groups hits by `level` [field](https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model) additionally to the provided `step`:
```logsql
curl http://localhost:9428/select/logsql/hits -d 'query=*' -d 'start=1w' -d 'step=1d' -d 'field=level'
```
See also: See also:

View file

@ -220,13 +220,17 @@ func (q *Query) String() string {
return s return s
} }
// AddCountByTimePipe adds '| stats by (_time:step offset off) count() hits' to the end of q. // AddCountByTimePipe adds '| stats by (_time:step offset off, field1, ..., fieldN) count() hits' to the end of q.
func (q *Query) AddCountByTimePipe(step, off int64) { func (q *Query) AddCountByTimePipe(step, off int64, fields []string) {
{ {
// add 'stats by (_time:step offset off) count() hits' // add 'stats by (_time:step offset off, fields) count() hits'
stepStr := string(marshalDuration(nil, step)) stepStr := string(marshalDuration(nil, step))
offsetStr := string(marshalDuration(nil, off)) offsetStr := string(marshalDuration(nil, off))
s := fmt.Sprintf("stats by (_time:%s offset %s) count() hits", stepStr, offsetStr) byFieldsStr := "_time:" + stepStr + " offset " + offsetStr
for _, f := range fields {
byFieldsStr += ", " + quoteTokenIfNeeded(f)
}
s := fmt.Sprintf("stats by (%s) count() hits", byFieldsStr)
lex := newLexer(s) lex := newLexer(s)
ps, err := parsePipeStats(lex) ps, err := parsePipeStats(lex)
if err != nil { if err != nil {
@ -236,8 +240,12 @@ func (q *Query) AddCountByTimePipe(step, off int64) {
} }
{ {
// Add 'sort by (_time)' in order to get consistent order of the results. // Add 'sort by (_time, fields)' in order to get consistent order of the results.
s := "sort by (_time)" sortFieldsStr := "_time"
for _, f := range fields {
sortFieldsStr += ", " + quoteTokenIfNeeded(f)
}
s := fmt.Sprintf("sort by (%s)", sortFieldsStr)
lex := newLexer(s) lex := newLexer(s)
ps, err := parsePipeSort(lex) ps, err := parsePipeSort(lex)
if err != nil { if err != nil {