osbase/logtree: add WithStartPosition option
To allow users to not always request all messages,
we introduce another option to the logtree.LogReader
which allows for starting at a specific global log id.
This, for example, makes implementing scrollback easier.
Change-Id: I1773288f670f476706d94baf3f052fe1e5da9eb0
Reviewed-on: https://review.monogon.dev/c/monogon/+/4452
Tested-by: Jenkins CI
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/osbase/logtree/logtree_access.go b/osbase/logtree/logtree_access.go
index 1582a8f..1b4f90d 100644
--- a/osbase/logtree/logtree_access.go
+++ b/osbase/logtree/logtree_access.go
@@ -10,6 +10,13 @@
"source.monogon.dev/go/logging"
)
+type ReadDirection int
+
+const (
+ ReadDirectionAfter ReadDirection = iota
+ ReadDirectionBefore
+)
+
// LogReadOption describes options for the LogTree.Read call.
type LogReadOption func(*logReaderOptions)
@@ -21,6 +28,8 @@
onlyRaw bool
leveledWithMinimumSeverity logging.Severity
withStreamBufferSize int
+ withStartPosition int
+ startPositionReadDirection ReadDirection
}
// WithChildren makes Read return/stream data for both a given DN and all its
@@ -54,6 +63,20 @@
return func(lro *logReaderOptions) { lro.withBacklog = count }
}
+// WithStartPosition makes Read return log entries from the given position.
+// It requires WithBacklog to be provided.
+//
+// The Journal keeps a global counter for all logs, starting at 0 for the
+// first message. Based on this the user can read entries
+// (based on the ReadDirection option) either after or before the given
+// position.
+func WithStartPosition(pos int, direction ReadDirection) LogReadOption {
+ return func(lro *logReaderOptions) {
+ lro.withStartPosition = pos
+ lro.startPositionReadDirection = direction
+ }
+}
+
// BacklogAllAvailable makes WithBacklog return all backlogged log data that
// logtree possesses.
const BacklogAllAvailable int = -1
@@ -107,7 +130,8 @@
}
var (
- ErrRawAndLeveled = errors.New("cannot return logs that are simultaneously OnlyRaw and OnlyLeveled")
+ ErrRawAndLeveled = errors.New("cannot return logs that are simultaneously OnlyRaw and OnlyLeveled")
+ ErrStartPositionWithoutBacklog = errors.New("cannot return logs that are WithStartingPosition and missing WithBacklog")
)
// Read and/or stream entries from a LogTree. The returned LogReader is influenced
@@ -121,6 +145,7 @@
lro := logReaderOptions{
withStreamBufferSize: 128,
+ withStartPosition: -1,
}
for _, opt := range opts {
@@ -131,7 +156,15 @@
return nil, ErrRawAndLeveled
}
+ isWithBacklog := lro.withBacklog > 0 || lro.withBacklog == BacklogAllAvailable
+ if lro.withStartPosition != -1 && !isWithBacklog {
+ return nil, ErrStartPositionWithoutBacklog
+ }
+
var filters []filter
+ if lro.withStartPosition != -1 {
+ filters = append(filters, filterStartPosition(lro.withBacklog, lro.withStartPosition, lro.startPositionReadDirection))
+ }
if lro.onlyLeveled {
filters = append(filters, filterOnlyLeveled)
}
@@ -148,7 +181,7 @@
}
var entries []*entry
- if lro.withBacklog > 0 || lro.withBacklog == BacklogAllAvailable {
+ if isWithBacklog {
if lro.withChildren {
entries = l.journal.scanEntries(lro.withBacklog, filters...)
} else {