Skip to content

Commit 8b22bc6

Browse files
lib/logstorage: add the ability to set a timestamp offset via options (#414)
Co-authored-by: Aliaksandr Valialkin <[email protected]>
1 parent a0f8f79 commit 8b22bc6

File tree

9 files changed

+397
-68
lines changed

9 files changed

+397
-68
lines changed

docs/victorialogs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
1818

1919
## tip
2020

21+
* FEATURE: [LogsQL](https://docs.victoriametrics.com/victorialogs/logsql/): add support for applying a global time offset to the `<q>` [query](https://docs.victoriametrics.com/victorialogs/logsql/#query-syntax) via `options(time_offset=<duration>) <q>` syntax. This is useful for comparing query results on some time range to query results on the same time range with the given offset (similar to the [`offset` modifier in PromQL](https://prometheus.io/docs/prometheus/latest/querying/basics/#offset-modifier)). See [these docs](https://docs.victoriametrics.com/victorialogs/logsql/#query-options) and [#78](https://github.com/VictoriaMetrics/VictoriaLogs/issues/78) for details.
2122
* FEATURE: [LogsQL](https://docs.victoriametrics.com/victorialogs/logsql/): speed up queries, which select big number of logs and end with [`| sort by (_time) desc offset M limit N` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#sort-pipe). E.g. these queries allow building simple pagination over the selected logs. See [#96](https://github.com/VictoriaMetrics/VictoriaLogs/issues/96).
2223

2324
## [v1.27.0](https://github.com/VictoriaMetrics/VictoriaLogs/releases/tag/v1.27.0)

docs/victorialogs/LogsQL.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ It is possible to specify generic offset for the selected time range by appendin
338338
- `_time:2023-07Z offset 5h30m` matches logs on July, 2023 by UTC with offset 5h30m.
339339
- `_time:[2023-02-01Z, 2023-03-01Z) offset 1w` matches logs the week before the time range `[2023-02-01Z, 2023-03-01Z)` by UTC.
340340

341+
See also [`time_offset` option](#query-options), which allows applying the given offset to all the filters on `_time` field without the need to modify the query.
342+
341343
Performance tips:
342344

343345
- It is recommended specifying the smallest possible time range during the search, since it reduces the amounts of log entries, which need to be scanned during the query.
@@ -4184,6 +4186,16 @@ VictoriaLogs supports the following options, which can be passed in the beginnin
41844186
options(concurrency=2) _time:1d | count_uniq(user_id)
41854187
```
41864188

4189+
- `time_offset` – subtracts the given offset from all the [time filters](#time-filter) in the query,
4190+
and then adds the given offset to the selected [`_time` field](https://docs.victoriametrics.com/victorialogs/keyconcepts/#time-field) values
4191+
before passing them to query [pipes](#pipes). Allows comparing query results for the same duration at different offsets.
4192+
Accepts any [duration value](#duration-values) like `12h`, `1d`, `1y`. For example, the following query returns the number of logs with `error` [words](#word)
4193+
over the last hour 7 days ago.
4194+
4195+
```logsql
4196+
options(time_offset=7d) _time:1h error | stats count() as 'errors_7d_ago'
4197+
```
4198+
41874199
- `ignore_global_time_filter` - allows ignoring time filter from `start` and `end` args of [HTTP querying API](https://docs.victoriametrics.com/victorialogs/querying/#http-api)
41884200
for the given (sub)query. For example, the following query returns the number of logs with `user_id` values seen in logs during December 2024, on the `[start...end]`
41894201
time range passed to [`/api/v1/query`](https://docs.victoriametrics.com/victorialogs/querying/#querying-logs):

lib/logstorage/block_header.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,13 @@ func (th *timestampsHeader) copyFrom(src *timestampsHeader) {
986986
th.marshalType = src.marshalType
987987
}
988988

989+
func (th *timestampsHeader) subTimeOffset(timeOffset int64) {
990+
if timeOffset != 0 {
991+
th.minTimestamp = subNoOverflowInt64(th.minTimestamp, timeOffset)
992+
th.maxTimestamp = subNoOverflowInt64(th.maxTimestamp, timeOffset)
993+
}
994+
}
995+
989996
// marshal appends marshaled th to dst and returns the result.
990997
func (th *timestampsHeader) marshal(dst []byte) []byte {
991998
dst = encoding.MarshalUint64(dst, th.blockOffset)

lib/logstorage/block_search.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ func (bs *blockSearch) search(ss *searchStats, bsw *blockSearchWork, bm *bitmap)
212212
bs.reset()
213213

214214
bs.ss = ss
215-
216215
bs.bsw = bsw
217216

218217
// search rows matching the given filter
@@ -488,6 +487,19 @@ func (bs *blockSearch) getValuesForColumn(ch *columnHeader) []string {
488487
return values.a
489488
}
490489

490+
func (bs *blockSearch) subTimeOffsetToTimestamps(timeOffset int64) {
491+
bs.bsw.bh.timestampsHeader.subTimeOffset(timeOffset)
492+
if bs.timestampsCache != nil {
493+
subTimeOffset(bs.timestampsCache.A, timeOffset)
494+
}
495+
}
496+
497+
func subTimeOffset(timestamps []int64, timeOffset int64) {
498+
for i := range timestamps {
499+
timestamps[i] = subNoOverflowInt64(timestamps[i], timeOffset)
500+
}
501+
}
502+
491503
// getTimestamps returns timestamps for the given bs.
492504
//
493505
// The returned timestamps belong to bs, so they become invalid after bs reset.
@@ -518,6 +530,7 @@ func (bs *blockSearch) getTimestamps() []int64 {
518530
if err != nil {
519531
logger.Panicf("FATAL: %s: cannot unmarshal timestamps: %s", bs.partPath(), err)
520532
}
533+
521534
bs.timestampsCache = timestamps
522535
return timestamps.A
523536
}

0 commit comments

Comments
 (0)