storage library

Storing, reading and viewing the log: the store contract (LogStore, LogReader) and the base for custom stores (LogStoreBase, collectLogPage), the sink that writes entries to a store (LogStoreSink), the in-memory store (InMemoryLogStore, queryInMemory), queries (LogQuery, LogFilter, LogCursor), store changes (LogStoreChange), the viewer list model (LogWindow) and export (exportLog).

Separate from log_trail.dart: code that only writes to the log does not need the store contract, while store implementations (SqliteLogStore from log_trail_sqlite, a file) and the viewer depend on this library. The entry format for stores (logEntryJson) and the export formats (LogExportFormat) stay in log_trail.dart: they describe an entry, not a store, and are needed without one (JSON console output, transfer between isolates).

Classes

AllLogEntriesRemoved
All entries were removed (LogStore.clear).
InMemoryLogStore
In-memory store: the current session's log without a database.
LogAfterCondition
Entries strictly after time.
LogAttributeCondition
Entries whose attribute with the same field name as attribute equals its value. Encoded values are compared (LogAttribute.encode), like LogValue.==: a store that compares them in serialized form (JSON text in a column) must serialize canonically, with sorted map keys.
LogBeforeCondition
Entries strictly before time.
LogCandidate
A row a store read for collectLogPage: the entry still as its JSON text (logEntryJsonText), with the columns that give its position in store order. Decoded only once it has passed the raw text check (LogTextCondition.mayMatchJson) of every text condition.
LogCondition
One selection condition for entries: LogFilter decomposes into them (LogFilter.conditions), and an entry matches the filter if it matches all of its conditions.
LogCursor
An entry's position in store order: time, then id (StoredLogEntry.id). A page continues from it (LogQuery.startAfter): entries written between pages do not shift the next page, and entries with equal time are neither lost nor repeated at its boundary.
LogEntriesAdded
Entries were written, in write order, with assigned ids. One event per batch (LogStore.writeEntries): the subscriber updates once, not per entry.
LogEntriesRemoved
Entries were removed. The subtype says exactly which, so the subscriber drops them locally without rereading the log: otherwise a store with a limit, evicting old entries on every write, would force constant rereads.
LogEntriesRemovedBefore
All entries strictly before time were removed, and only they (LogStore.removeBefore).
LogEntriesRemovedById
Entries with these ids (StoredLogEntry.id) were removed, and only they, for example evicted by the store limit. Ids are passed, not entries: the store does not need to read what it removes (in SQL, DELETE … RETURNING id), and the subscriber does not need to compare whole entries.
LogFilter
Selection conditions for entries: period, levels, tags, attributes, text. All conditions are combined with AND; an empty condition accepts any entry.
LogLevelCondition
Entries of one of levels (a non-empty set).
LogPage
A page of a LogQuery result.
LogQuery
A query for entries to LogReader: selection conditions (filter), order and page.
LogReader
Reading the log from a store: everything the viewer needs.
LogStore
A store of log entries: SQLite, a file, etc. Stores, serves (LogReader) and removes entries; queueing, batching and failure handling on the way from the logger are LogStoreSink's. The viewer takes it as a LogReader.
LogStoreBase
Base class for a store (LogStore): carries what every store would otherwise repeat, leaving the implementation the primitives onWriteEntries, onQueryEntries, onQueryTags, onClear, onRemoveBefore, onRetainNewest and onClose.
LogStoreChange
A change to the contents of a LogStore: the viewer updates from it instead of rereading the whole log for every write.
LogStoreInvalidated
The contents changed in a way the store cannot cheaply describe: for example, it removed entries by file size on its own and does not know which. The subscriber needs to reread the entries it needs.
LogStoreSink
A sink that persists entries to store.
LogTagCondition
Entries with the tag tag.
LogTextCondition
Entries where one of the texts (searchableTexts) contains the substring text (a non-empty string), case-insensitively.
LogWindow
Loaded window of the log under filter: entries newest first, with no duplicates by StoredLogEntry.id, contiguous from the newest entries to the last one loaded; next follows it. The list model for a viewer that reads the log in pages and receives store changes (LogStoreChange); independent of the UI.
StoredLogEntry
An entry saved by a store: the entry and the store-assigned id.

Functions

collectLogPage(LogQuery query, {required LogCandidateFetch fetch, required List<LogTextCondition> textConditions}) → Future<LogPage>
Builds the page of query for a store whose query language selects only candidates and leaves the text conditions (textConditions) to Dart: SQL narrows (an FTS index or LogTextCondition.prefilterTokens), LogTextCondition.matches decides.
exportLog(LogReader reader, StringSink output, {LogFilter filter = const LogFilter(), LogEntryFormat format = LogExportFormat.text, int pageSize = 500}) → Future<int>
Exports the entries of reader matching filter to output, oldest to newest, one entry per LogEntryFormat.format plus a newline: for an error report or sending to support. Entries for which format returned null are skipped. Returns the number of exported entries.
queryInMemory(List<StoredLogEntry> entries, LogQuery query) → LogPage
Runs query over entries in memory: for in-memory stores (InMemoryLogStore, fakes in tests).

Typedefs

LogCandidateFetch = Future<List<LogCandidate>> Function(LogCursor? after, int? limit)
Reads candidates for a page in query order, strictly after after (null: from the start), at most limit of them (null: all). See collectLogPage.
LogWriteErrorHandler = void Function(Object error, StackTrace stackTrace, List<LogEntry> entries)
Handler for a failed write of the batch entries to the store.

Exceptions / Errors

LogStoreException
A failure of a store's backend (SQLite, a file, a remote service) in a store operation: what the application needs to handle or report it, without the query parameters, which for a write are the whole entry.