Documentation
¶
Overview ¶
Package eventlog shows Events and Lines read in order from a remote source too large to hold: an AWX job's events, an Elasticsearch index, a Prefect run's logs. It is pkg/logview's counterpart for data that is fetched in pages rather than streamed — logview stays the component for a stream held whole (CLAUDE.md rule 34).
The item is the unit. An Item has a Key, the Lines it draws as, and optional Data for an inspector: a multi-line event is drawn as a block, a 0-line item draws as a dim "· no output" line — it still happened, and may carry fields worth opening — and the cursor moves item by item. There is no sort — the order is the timeline.
Two kinds of source, one component:
- Seekable data (item N fetchable, with a total) arrives through SetPage at logical offsets. Adjacent pages merge into one contiguous range; a far jump replaces it. Drive it with source.Model and Options.MaxHeld.
- Anchored data (walked from an anchor, no total) is a Span: New with Options.Anchored, then Append and Prepend. Items are keyed by their cursors, and Edges gives the cursors to extend from. Drive it with source.Anchored.
Either way it holds at most Options.MaxItems, trimming the end furthest from the viewport, and reports what it holds in ViewportChangedMsg so the source can mirror it.
It shares its remote machinery with pkg/table: items that answer a query other than the committed one stay on screen dimmed, the border names what they answer and what is loading, and nothing blanks after the first answer. On top of that:
- Follow keeps the view on the newest item while data is Growing. Move away and new items are counted instead ("↓ 42 new"); G returns.
- Search jumps. "/" highlights resident items as you type; n/N jump among them, and past what is held emit FindMsg for the source to answer. The filter narrows the query instead (QueryChangedMsg) — they are separate controls.
- Enter or a double click emits ActivatedMsg with the item's Key and Data, for the screen to open in an inspector.
Index ¶
- Constants
- type ActivatedMsg
- type Answer
- type FindMsg
- type Item
- type Keys
- type Model
- func (m Model) Answered() (Answer, bool)
- func (m *Model) Append(items []Item, answered Answer)
- func (m *Model) Blur()
- func (m *Model) BlurFilter()
- func (m Model) Committed() Answer
- func (m Model) Cursor() int
- func (m Model) Edges() (older, newer string)
- func (m Model) Failed() bool
- func (m *Model) Focus() tea.Cmd
- func (m *Model) FocusFilter() tea.Cmd
- func (m *Model) FocusSearch() tea.Cmd
- func (m Model) FocusToken() focus.Token
- func (m Model) Focused() bool
- func (m Model) Following() bool
- func (m *Model) Found(ok bool, at int)
- func (m *Model) FoundAt(ok bool, k string)
- func (m Model) Help() []key.Binding
- func (m Model) HelpSections() []help.Section
- func (m Model) Init() tea.Cmd
- func (m Model) IsActivate(msg tea.Msg) bool
- func (m Model) IsCapturingKeys() bool
- func (m Model) Items() (start int, items []Item)
- func (m Model) Loading() bool
- func (m *Model) Prepend(items []Item, answered Answer)
- func (m Model) Query() QueryChangedMsg
- func (m *Model) Reanchor()
- func (m *Model) Restore(s State)
- func (m Model) Selected() (Item, bool)
- func (m *Model) SetCursor(i int)
- func (m *Model) SetFailed(q Answer)
- func (m *Model) SetFollow(b bool)
- func (m *Model) SetGrowing(b bool)
- func (m *Model) SetMatchTotal(n int)
- func (m *Model) SetMore(older, newer bool)
- func (m *Model) SetNew(n int, more bool)
- func (m *Model) SetPage(items []Item, offset, total int, answered Answer)
- func (m *Model) SetRect(r geom.Rect)
- func (m *Model) SetTerm(s string)
- func (m *Model) SetTitle(s string)
- func (m *Model) SetValue(s string)
- func (m Model) Stale() bool
- func (m Model) State() State
- func (m Model) Term() string
- func (m Model) Title() string
- func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)
- func (m Model) Value() string
- func (m Model) View() string
- type Options
- type QueryChangedMsg
- type State
- type ViewportChangedMsg
Constants ¶
const DefaultMaxItems = 5000
DefaultMaxItems is the resident cap when Options.MaxItems is zero.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ActivatedMsg ¶
ActivatedMsg reports enter or a double click on an item.
type Answer ¶
type Answer = remoteview.Answer
Answer names the query a set of items answers. See table.Answer.
type FindMsg ¶
type FindMsg struct {
Term string
Newer bool
// From is the logical index to search beyond (Seekable). Anchored
// sources start from the edge in the requested direction.
From int
// FromKey is the key of the item at From — what an API that searches
// by its own ids (AWX's counter__gt) needs, since positions stop
// matching ids once a filter is applied.
FromKey string
Token focus.Token
}
FindMsg asks for the next match beyond what is held — n or N ran out of resident items. Hand it to the source's Find; answer with Found.
type Item ¶
type Item struct {
// Key identifies the item across fetches — for Anchored data, its
// cursor. Merges skip keys already held.
Key string
// Lines is what the item draws as, oldest first. With none, the item
// draws as a dim "· no output" line.
Lines []string
// Data is carried to ActivatedMsg for the screen's inspector.
Data any
// Hole marks a position the source has no item for yet (an AWX event
// saved out of order). It draws as a placeholder and is not resident.
Hole bool
// Mark labels the item in the gutter: its timestamp, id or counter —
// what a reader would quote to find it again. Without one, Seekable
// items show their position; Anchored items, which have none, show
// nothing.
//
// A timestamp here is always the source's own — Elasticsearch's
// @timestamp, the kubelet's line time — never when the client fetched
// it. When the line's text already carries the time the application
// wrote, leave Mark empty rather than show two times for one event.
Mark string
}
Item is one entry in the timeline: an event or a line.
type Keys ¶
type Keys struct {
Up, Down, Top, Bottom, HalfUp, HalfDown key.Binding
Open key.Binding
Filter, Search, NextMatch, PrevMatch key.Binding
Pane pane.Keys
}
Keys is the eventlog's keymap. Horizontal scroll lives on Pane.
type Model ¶
type Model struct {
// contains filtered or unexported fields
}
Model is the eventlog. Embed by value; mutate through the setters.
func (*Model) Append ¶
Append adds items at the newer edge of a span, oldest first, merged by key: known keys are skipped and a late item lands where the page puts it.
func (*Model) BlurFilter ¶
func (m *Model) BlurFilter()
BlurFilter returns input from either field to the body.
func (*Model) FocusFilter ¶
FocusFilter moves input to the filter.
func (*Model) FocusSearch ¶
FocusSearch moves input to the search field.
func (Model) FocusToken ¶
FocusToken returns the eventlog's focus identity.
func (*Model) Found ¶
Found answers a FindMsg for Seekable data: the match is at logical index at, or there is none when ok is false. The cursor goes there and the source fetches around it.
func (*Model) FoundAt ¶
FoundAt answers a FindMsg for Anchored data. Re-anchor the source at the match's cursor; the cursor lands on the item keyed k when it arrives.
func (Model) HelpSections ¶
HelpSections groups the bindings by what they do (rule 10).
func (Model) IsActivate ¶
IsActivate reports whether msg opens the selection: enter, or this eventlog's own ActivatedMsg.
func (Model) IsCapturingKeys ¶
IsCapturingKeys reports whether a field is swallowing printable keys.
func (Model) Query ¶
func (m Model) Query() QueryChangedMsg
Query returns the committed filter as a QueryChangedMsg, for the first fetch.
func (*Model) Reanchor ¶
func (m *Model) Reanchor()
Reanchor says the source is re-anchoring (source.Anchored.SetAnchor): the next page replaces the span instead of extending it. What is on screen stays until then, so a jump to a search hit never blanks.
func (*Model) Restore ¶
Restore puts s back onto an eventlog built with the same Anchored setting. Items, query and failure come back as they were; the new Options keep the say over everything they set.
func (Model) Selected ¶
Selected returns the item under the cursor, and false when it isn't resident.
func (*Model) SetFailed ¶
SetFailed tells the eventlog the fetch for q failed. It takes effect for the committed query only. While following, a failure is a failed poll and the border says so until the next success.
func (*Model) SetFollow ¶
SetFollow pins the view to the newest item, or releases it. Before the first answer it decides where that answer lands: following (the default) lands on the newest item, not following on the first — the place to start reading a job that has already finished.
func (*Model) SetGrowing ¶
SetGrowing says whether items are still arriving at the newest end.
func (*Model) SetMatchTotal ¶
SetMatchTotal supplies an exact match count from a source that can count; -1 clears it.
func (*Model) SetMore ¶
SetMore sets whether each edge of a span has more beyond it — from the source after each page.
func (*Model) SetNew ¶
SetNew reports what a probe found while the user is not following: n items newer than those held, and whether there are more than that.
func (*Model) SetPage ¶
SetPage installs Seekable items at logical offset of a set total long, answering the query named by answered. A page touching what is held extends it; a far one replaces it. When the committed query's first answer lands, the cursor goes to its anchor: the newest item while following, else the top.
func (*Model) SetTitle ¶
SetTitle sets the label on the border; while stale or loading an edge, a suffix follows it.
func (Model) Stale ¶
Stale reports whether the items answer a query other than the committed one. Stale items are real records of the previous query.
type Options ¶
type Options struct {
Width, Height int
// Title labels the pane's border. Defaults to "events".
Title string
// Anchored makes the eventlog hold a span of Anchored data (Append /
// Prepend) rather than a range at logical offsets (SetPage).
Anchored bool
// Filterable adds a filter that narrows the query (f by default).
Filterable bool
// Searchable adds search (/ by default), which jumps to matches.
Searchable bool
// MaxItems caps what is resident. Zero means DefaultMaxItems.
MaxItems int
// Placeholder is drawn for an item not yet fetched. Defaults to the
// glyph set's placeholder.
Placeholder string
MatchStyle lipgloss.Style
SelectedStyle lipgloss.Style
CellStyle lipgloss.Style
// GutterStyle draws the gutter of positions or marks down the left.
GutterStyle lipgloss.Style
// NoGutter hides the gutter. It is on by default: in a long timeline
// the reader needs somewhere fixed to measure the cursor against.
NoGutter bool
// NewStyle draws the numbers of items that just loaded beside ones
// already on screen — a page reached by scrolling or by a search, or
// new items of Growing data — so the reader can tell what came in from
// what was there. A load that replaces everything marks nothing.
NewStyle lipgloss.Style
// NewFor is how long loaded items stay marked. Zero means 2s;
// negative never marks.
NewFor time.Duration
ActiveColor lipgloss.TerminalColor
InactiveColor lipgloss.TerminalColor
ActiveBorder lipgloss.Border
InactiveBorder lipgloss.Border
Glyphs glyph.Set
SlotBrackets pane.SlotBracketStyle
HScrollbar bool
SpinnerStyle lipgloss.Style
LoadingLabel string
// Filter styles both the filter and the search field.
Filter filter.Options
Keys Keys
}
Options configures an eventlog. Start from theme.Eventlog().
type QueryChangedMsg ¶
QueryChangedMsg reports a committed filter: enter, esc or blur, never per keystroke. Hand it to the source's SetQuery.
type State ¶
type State struct {
// contains filtered or unexported fields
}
State is what the source and the user did to an eventlog — the items it holds (a range or a span), the query they answer and whether it failed, the cursor and scroll, follow and growth, the filter and search — held across a rebuild. An eventlog built from new Options (a theme swap, rule 4) takes it back with Restore:
st := s.log.State() s.log = eventlog.New(opts) s.log.Restore(st)
A search or a hit still on its way is not carried: the rebuild answers neither, and a press after it asks again. A re-anchor waiting for its page is, so the page still replaces the span.
type ViewportChangedMsg ¶
type ViewportChangedMsg struct {
FirstVisible, LastVisible int
HeldStart, HeldCount int
// ToOlder and ToNewer count resident items between the viewport and
// each edge of what is held.
ToOlder, ToNewer int
}
ViewportChangedMsg reports what is on screen and what is held. Feed the visible range to source.Model.Viewport and the held range to SetHeld — or, for a span, ToOlder/ToNewer to source.Anchored.Viewport.