index

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package index is the local index of file streams: for each plan granule of a stream, its record count, its time span, and per-minute counts of the tuples of the source's trusted low-cardinality fields.

The index holds raw values of trusted fields (masked by the engine when an answer is built) and lives in the console's home volume (directory 0700, files 0600). A value a detector flags is stored as Redacted, never in clear; a field with more than MaxDistinct values in a stream is dropped from that stream's index.

Index

Constants

View Source
const (
	// Version of the on-disk format; another version is rebuilt. 2:
	// line fields and labels (LabelKey) are separate namespaces (1 fell
	// back from a field to a frame attribute).
	Version = 2
	// MaxDistinct is the most distinct values a field may have in one
	// stream and stay indexed.
	MaxDistinct = 64
	// MaxTuples bounds the distinct tuples of one minute of a granule;
	// beyond it the remaining records count under Other values.
	MaxTuples = 256
)
View Source
const (
	// Absent is the value of a field the record does not have.
	Absent = ""
	// Redacted replaces a value a detector flagged.
	Redacted = "\x00redacted"
	// Other replaces values beyond MaxTuples in a minute.
	Other = "\x00other"
)

Special tuple values. They cannot collide with field values: parsed text never holds NUL.

Variables

This section is empty.

Functions

func LabelKey

func LabelKey(name string) string

LabelKey is the indexed name of the label name: the index holds line fields and labels side by side, each in its own namespace.

func Lookup

func Lookup(ev parse.Event, name string) (string, bool)

Lookup returns the scalar text of a line field of ev: a top-level member named name, else a dotted path through nested objects. Frame attributes (labels) are another namespace (LookupAttr): the engine's scan reads a field predicate on the line's fields only, and so does the index.

func LookupAttr

func LookupAttr(ev parse.Event, name string) (string, bool)

LookupAttr returns the scalar text of a frame attribute (label) of ev.

func Run

func Run(ctx context.Context, srcs []Indexer, o RunOptions)

Run builds the indexes of srcs until ctx ends, under a token bucket of BytesPerHour (capacity one minute of budget).

func SplitKey

func SplitKey(key string) (name string, label bool)

SplitKey returns the field or label an indexed name stands for.

func TermKey

func TermKey(name string, label bool) string

TermKey is the indexed name a field (label unset) or label stands for.

func Value

func Value(ev parse.Event, key string) string

Value returns the indexed value of key (a line field, or a label as LabelKey) on ev: its scalar text, Absent when nothing is at the path, or Redacted (unknown) when the path is ambiguous: several leaves (a repeated key, an array, a dotted name also stored as one key) or an object or other non-scalar. The scan matches a predicate on any leaf at the path, so an ambiguous value must never prune a granule nor be counted by one.

func Values

func Values(ev parse.Event, keys []string, sensitive func(field, value string) bool) []string

Values returns the record's values of keys (line fields, and labels as LabelKey), in order: the scalar text of the field or label (dotted paths reach nested objects), Absent when missing or not a scalar, Redacted when sensitive flags it.

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder accumulates the records of one granule.

func NewBuilder

func NewBuilder(fields []string, sensitive func(field, value string) bool) *Builder

NewBuilder indexes the given fields; sensitive reports values a detector flags (nil: none).

func (*Builder) Add

func (b *Builder) Add(ev parse.Event)

Add counts one record.

func (*Builder) Finish

func (b *Builder) Finish(n, start, end int64, sealed bool) Granule

Finish returns the granule.

type Count

type Count struct {
	Vals []string `json:"v"`
	N    int64    `json:"n"`
}

Count is the number of records with one tuple of values.

type Granule

type Granule struct {
	// N is the granule number: the granule covers stream offsets
	// [N*size, (N+1)*size), clipped to the stream.
	N     int64 `json:"g"`
	Start int64 `json:"s"`
	End   int64 `json:"e"`
	// Sealed is false for the tail granule of a stream that may grow;
	// it is indexed again once the stream has grown past it.
	Sealed  bool  `json:"sealed,omitempty"`
	Records int64 `json:"r"`
	// From and To bound the timed records (Unix ns); zero when none.
	From int64 `json:"from,omitempty"`
	To   int64 `json:"to,omitempty"`
	// Minutes are sorted by minute. Untimed counts records without a
	// time.
	Minutes []Minute `json:"min,omitempty"`
	Untimed []Count  `json:"untimed,omitempty"`
}

Granule is the index of one plan granule.

func (*Granule) Span

func (g *Granule) Span() (from, to time.Time, ok bool)

Span returns the time span of the granule's timed records.

type Indexer

type Indexer interface {
	// IndexStep indexes about maxBytes and reports the bytes processed and
	// whether nothing was left to index. With upkeep false it does only
	// backfill (streams and granules never indexed), not the re-indexing
	// of grown tails.
	IndexStep(ctx context.Context, maxBytes int64, upkeep bool) (processed int64, done bool, err error)
}

Indexer is a source that can build its local index step by step.

type Minute

type Minute struct {
	M      int64   `json:"m"`
	Counts []Count `json:"c"`
}

Minute holds the counts of one minute (Unix minutes).

type RunOptions

type RunOptions struct {
	// BytesPerHour is the index building budget (a rolling budget of its
	// own, apart from the agents' budgets).
	BytesPerHour int64
	// Busy reports that agent calls are running. While busy, only the
	// backfill runs (first start, a new file, at the full budget); the
	// upkeep of grown tails waits.
	Busy func() bool
	// Flush persists the index (Store.Flush); called after steps, at most
	// every FlushEvery.
	Flush      func() error
	FlushEvery time.Duration
	// Idle is the pause when every source is done (new data is picked up
	// on the next pass).
	Idle time.Duration
	// OnError is told of a step's error (the source is retried later).
	OnError func(Indexer, error)
	// Now and Sleep are the clock (tests).
	Now   func() time.Time
	Sleep func(context.Context, time.Duration) bool
}

RunOptions configure Run.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store keeps the stream indexes of every source in a directory.

func Open

func Open(dir string) (*Store, error)

Open opens (creating it 0700) the index directory and loads it. Files of another version, or unreadable ones, are ignored (and rebuilt).

func (*Store) Delete

func (st *Store) Delete(source string, dev, ino uint64)

Delete forgets a stream's index (its file is removed at the next Flush).

func (*Store) Dir

func (st *Store) Dir() string

Dir returns the store's directory.

func (*Store) Flush

func (st *Store) Flush() error

Flush writes the changed stream indexes atomically (0600). The streams are copied under the lock and written outside it, so queries are not held up by disk writes.

func (*Store) With

func (st *Store) With(source string, dev, ino uint64, fn func(*Stream) *Stream)

With calls fn with the index of the stream (nil when none), under the store's lock. fn may modify the stream or return a new one to store (replace); returning a non-nil stream marks it dirty.

type Stream

type Stream struct {
	Version int `json:"version"`
	// Dev, Ino, Gen identify the stream; PrefixLen/PrefixHash are the
	// latest hashed prefix (a stream whose prefix no longer hashes the
	// same is another stream).
	Dev        uint64 `json:"dev"`
	Ino        uint64 `json:"ino"`
	Gen        string `json:"gen"`
	PrefixLen  int    `json:"prefix_len"`
	PrefixHash string `json:"prefix_hash"`
	// Compression of the file ("", "gzip", "zstd"). Size is the length
	// of the decompressed stream once a full pass measured it, else -1.
	Compression string `json:"compression,omitempty"`
	Size        int64  `json:"size"`
	// FileSize is a compressed file's own size when it was measured.
	FileSize int64 `json:"file_size,omitempty"`
	// Fields are the indexed fields, in tuple order; Dropped those
	// dropped for cardinality.
	Fields  []string `json:"fields"`
	Dropped []string `json:"dropped,omitempty"`
	// Tag is the source's tag the stream was indexed under (the docker
	// source's container name); another tag means another index.
	Tag string `json:"tag,omitempty"`
	// Granules, by granule number.
	Granules map[int64]*Granule `json:"-"`
	List     []*Granule         `json:"granules"`
	// contains filtered or unexported fields
}

Stream is the index of one file stream.

func NewStream

func NewStream(dev, ino uint64, gen string, fields []string) *Stream

NewStream returns an empty stream index for the given fields.

func (*Stream) Put

func (s *Stream) Put(g Granule)

Put stores a granule, replacing an earlier one of the same number, and drops fields that exceed MaxDistinct values across the stream.

func (*Stream) PutBuilt

func (s *Stream) PutBuilt(g Granule, fields []string)

PutBuilt stores a granule built over fields (the source's trusted fields, a superset of s.Fields once fields were dropped): its tuples are first projected onto s.Fields, merging tuples that become equal.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL