widgets library

The log page and its parts. Separate from log_trail_flutter.dart so that code without screens does not depend on Material.

The ready-made page is LogViewerPage. A custom page can use the same parts: LogViewerController (state, pages, filter), LogEntryTile, LogEntryDetailsPage, LogFilterSheet, plus LogViewerStrings (strings via Localizations), LogViewerTheme and colorForTag for colors.

The viewer reads the log via LogReader and works with LogFilter and StoredLogEntry, so the library re-exports package:log_trail/storage.dart.

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.
LogEntryDetailsPage
Page for a single entry: all fields, error, extra attributes and stack trace. Strings come from LogViewerStrings.of.
LogEntryTile
Entry list tile: level, message, tags and time.
LogFilter
Selection conditions for entries: period, levels, tags, attributes, text. All conditions are combined with AND; an empty condition accepts any entry.
LogFilterSheet
Bottom sheet for choosing a filter: text search, levels and tags. Every change is passed to onFilterChanged: levels and tags immediately, text after searchDelay since the last keystroke or when the sheet closes, if the pause has not yet elapsed.
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.
LogViewerController
Widget-free state of the log viewer: first page from reader, loading more older entries, the filter, and updates from LogReader.changes.
LogViewerPage
Log page: a list of entries, newest first, with loading more on scroll, search, a filter by levels and tags, an entry page on tap, and export (onExport). State is managed by LogViewerController; strings come from LogViewerStrings.of, colors from LogViewerTheme.of.
LogViewerStrings
Log viewer strings. English by default.
LogViewerStringsDelegate
LogViewerStrings delegate for localizationsDelegates: stringsFor picks the strings for the app's locale. Supports any locale: stringsFor is responsible for the translation.
LogViewerTheme
Log viewer colors: an extension of the app theme.
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.
colorForTag(String tag) → Color
Tag color: the same tag is always colored the same, on every platform.
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.
LogEntrySelectedCallback = void Function(BuildContext context, StoredLogEntry entry)
Handler for tapping an entry in LogViewerPage: the entry with its store id, by which the app can open it via its own route.
LogExportCallback = Future<void> Function(BuildContext context, LogFilter filter)
Log export from LogViewerPage with the page's current filter.
LogFilterUpdate = LogFilter Function(LogFilter current)
Filter edit: builds a new filter from current, the filter in effect when the edit is applied (LogViewerController.updateFilter). A part of the screen that edits several conditions (the filter sheet: levels, tags, text) thus does not overwrite conditions someone else may have changed in the meantime.
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.