journal

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 1, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SipHash24

func SipHash24(key [16]byte, data []byte) uint64

SipHash24 computes a 64-bit SipHash-2-4 hash of data keyed by a 16-byte key. The key is split into two 64-bit little-endian values (k0, k1). Reference: https://github.com/veorq/SipHash

Types

type Entry

type Entry struct {
	Timestamp time.Time
	Fields    map[string]string
	BootID    string
	MessageID string
	Priority  int
	UID       uint32
	GID       uint32
	PID       uint32
	Transport string
	// contains filtered or unexported fields
}

Entry represents a single journald log record. Fields contains all key-value pairs from the entry (MESSAGE, _SYSTEMD_UNIT, etc.). Timestamp is derived from the entry's realtime clock value. Seqnum and Realtime provide raw access to the on-disk values for use in cursor-based navigation.

func (*Entry) Get

func (e *Entry) Get(key string) string

Get returns the value for an arbitrary field key. For well-known fields, prefer the typed accessors (Message, Unit, etc.) which are self-documenting.

func (*Entry) Hostname

func (e *Entry) Hostname() string

Hostname returns the _HOSTNAME field value.

func (*Entry) Message

func (e *Entry) Message() string

Message returns the MESSAGE field value, or empty string if unset.

func (*Entry) Realtime

func (e *Entry) Realtime() uint64

Realtime returns the entry's wall-clock timestamp as microseconds since the Unix epoch. Use for SeekRealtime comparisons. For human-readable time, use the Timestamp field instead.

func (*Entry) Seqnum

func (e *Entry) Seqnum() uint64

Seqnum returns the entry's monotonic sequence number. Seqnums are unique within a journal file and increase with each entry. Use for cursor-based iteration — a File's containsSeqnum checks whether a seqnum falls within a file's range.

func (*Entry) String

func (e *Entry) String() string

String returns a human-readable summary: "[RFC3339] message text".

func (*Entry) SyslogFacility

func (e *Entry) SyslogFacility() string

SyslogFacility returns the SYSLOG_FACILITY field value (e.g. "4" for cron).

func (*Entry) SyslogIdentifier

func (e *Entry) SyslogIdentifier() string

SyslogIdentifier returns the SYSLOG_IDENTIFIER field value (e.g. "sshd").

func (*Entry) Unit

func (e *Entry) Unit() string

Unit returns the _SYSTEMD_UNIT field value (e.g. "sshd.service").

type File

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

File reads a single journald journal file. It holds one entry at a time in memory (streaming iteration, not eager load). For multi-file journals, use Journal instead — File is strictly single-file.

File is not safe for concurrent use. Each goroutine should open its own.

func Open

func Open(path string) (*File, error)

Open opens a journald journal file for reading. Returns error if the file doesn't exist, isn't a valid journal file, or can't be read. The File starts positioned at the first entry (after the header).

func (*File) ArenaSize

func (f *File) ArenaSize() uint64

ArenaSize returns the total byte size of the data arena (all objects after the header).

func (*File) Close

func (f *File) Close() error

Close releases the underlying file descriptor. After Close, all methods return zero values or errors.

func (*File) Entry

func (f *File) Entry() *Entry

Entry returns the current entry, or nil if no entry has been read yet.

func (*File) Exists

func (f *File) Exists() bool

Exists reports whether the file still exists on disk. Used by Journal to detect deleted files during cleanup.

func (*File) FieldValues

func (f *File) FieldValues(name string, limit int) ([]string, bool, error)

FieldValues returns all distinct values for the named field (label) in this journal file, up to limit values. If truncated is true, the limit was reached and the result is not cached — the caller may retry with a higher limit. For archived (non-rotating) files, complete (non-truncated) results are cached after the first call.

func (*File) Fields

func (f *File) Fields() ([]string, error)

Fields returns all distinct field names (label names) present in this journal file. For archived (non-rotating) files, results are cached after the first call.

func (*File) HeadEntryRealtime

func (f *File) HeadEntryRealtime() uint64

HeadEntryRealtime returns the wall-clock timestamp (microseconds since Unix epoch) of the oldest entry in this file. Used by Journal.SeekRealtime to pick the best file.

func (*File) HeadEntrySeqnum

func (f *File) HeadEntrySeqnum() uint64

HeadEntrySeqnum returns the smallest sequence number in this file (the oldest entry). Files are sorted by this value in Journal. Used for seqnum-based file lookup.

func (*File) HeaderSize

func (f *File) HeaderSize() uint64

HeaderSize returns the byte size of the file header. Entries begin at this offset.

func (*File) NEntries

func (f *File) NEntries() uint64

NEntries returns the total number of log entries recorded in this file's header. This is the count at file open time — use Next() to iterate and count actual entries reachable from the current offset.

func (*File) NObjects

func (f *File) NObjects() uint64

NObjects returns the total number of objects (entries, data fields, hash tables, etc.) in the file's arena.

func (*File) Next

func (f *File) Next() bool

Next advances to the next entry in the file, skipping non-entry objects (data fields, hash tables, etc.). Returns true and stores the entry if found. Returns false at EOF or on read error. Call after Open or SeekHead/SeekRealtime to read the first entry.

func (*File) NextEntry

func (f *File) NextEntry() (*Entry, bool)

NextEntry is a convenience wrapper: calls Next() then returns (Entry(), true) on success, or (nil, false) if no more entries.

func (*File) Path

func (f *File) Path() string

Path returns the filesystem path of the underlying file, or empty string if the File was constructed from an in-memory source.

func (*File) Previous

func (f *File) Previous() bool

Previous moves the cursor to the entry just before the current one by sequence number. Uses the file header to check if the previous seqnum is in range, then calls Seek(target). If there is a gap (Seek lands past the target), decrements and retries until a match is found or the head seqnum is reached.

Returns false if there is no previous entry (already at head) or if no entry has been read yet. O(n) per Seek call — acceptable for bounded backward iteration but not for repeated random access.

func (*File) ReloadHeader

func (f *File) ReloadHeader() error

ReloadHeader re-reads the file header from disk and updates the cached size. Use after the active journal file may have grown or been rotated to an archived state. Calls readHeader internally, so header fields (HeadEntrySeqnum, TailEntrySeqnum, State, etc.) are refreshed on success.

func (*File) Seek

func (f *File) Seek(seqnum uint64) bool

Seek positions the reader at the entry with the given seqnum and reads it into Entry(). If seqnum < HeadEntrySeqnum, loads the first entry (may be after the target). If seqnum >= TailEntrySeqnum, loads the last entry. Returns true if the loaded entry's seqnum is >= seqnum.

func (*File) SeekHead

func (f *File) SeekHead()

SeekHead resets the read position to the first entry in the file. The next call to Next() will return the oldest entry.

func (*File) SeekRealtime

func (f *File) SeekRealtime(t time.Time) bool

SeekRealtime positions the reader at the first entry whose realtime timestamp is >= t and reads it into Entry(). If t is before the head realtime, loads the first entry (may be after t). If t is after the tail realtime, loads the last entry. Returns true if the loaded entry's timestamp is >= t.

func (*File) SeekTail

func (f *File) SeekTail()

SeekTail positions the reader at the last entry in the file and reads it into Entry(). Equivalent to Seek(tailSeqnum).

func (*File) Signature

func (f *File) Signature() string

Signature returns the 8-byte magic string that identifies valid journald files.

func (*File) State

func (f *File) State() uint8

State returns the file's lifecycle state from its header: 0=offline, 1=online (active, receiving new entries), 2=archived (rotated, no new entries).

func (*File) TailEntryRealtime

func (f *File) TailEntryRealtime() uint64

TailEntryRealtime returns the wall-clock timestamp (microseconds since Unix epoch) of the newest entry in this file. Used by Journal.SeekRealtime to skip files entirely before the target time.

func (*File) TailEntrySeqnum

func (f *File) TailEntrySeqnum() uint64

TailEntrySeqnum returns the largest sequence number in this file (the newest entry). Used for rotation detection and gap detection in Journal.Next().

func (*File) TailObjectOffset

func (f *File) TailObjectOffset() uint64

TailObjectOffset returns the byte offset of the tail object (most recently written).

type FileHeader

type FileHeader struct {
	Signature            [8]byte
	CompatibleFlags      uint32
	IncompatibleFlags    uint32
	State                uint8
	Reserved             [7]byte
	FileID               [16]byte
	MachineID            [16]byte
	TailEntryBootID      [16]byte
	SeqnumID             [16]byte
	HeaderSize           uint64
	ArenaSize            uint64
	DataTableOffset      uint64
	DataTableSize        uint64
	FieldTableOffset     uint64
	FieldTableSize       uint64
	TailObjectOffset     uint64
	NObjects             uint64
	NEntries             uint64
	TailEntrySeqnum      uint64
	HeadEntrySeqnum      uint64
	EntryArrayOffset     uint64
	HeadEntryRealtime    uint64
	TailEntryRealtime    uint64
	TailEntryMonotonic   uint64
	NData                uint64
	NFields              uint64
	NTags                uint64
	NEntryArrays         uint64
	DataHashChainDepth   uint64
	FieldHashChainDepth  uint64
	TailEntryArrayOffset uint32
	TailEntryArrayNEnts  uint32
	TailEntryOffset      uint64
}

FileHeader holds the binary header of a journald journal file. HeadEntrySeqnum is the oldest (smallest) sequence number in the file; TailEntrySeqnum is the newest (largest). Head/TailRealtime are the corresponding wall-clock timestamps as microseconds since the Unix epoch. State indicates file lifecycle: 0=offline, 1=online (active), 2=archived (rotated).

type Journal

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

Journal reads a journald log across multiple journal files (active + archived). Files are sorted by HeadEntrySeqnum (smallest = oldest). The last file in the list is the active file receiving new entries. Handles file rotation, gap detection across files, and header reload when the active file grows.

Not safe for concurrent use. Each goroutine should acquire a dedicated Journal from a Pool.

func OpenJournal

func OpenJournal(dir, name string) (*Journal, error)

OpenJournal opens all journal files matching name in dir. Files are opened as name.journal (active) and name@*.journal (archived), sorted by HeadEntrySeqnum.

If name.journal is not found directly in dir, OpenJournal searches one level of subdirectories (e.g. the machine-id directory used by journald). If exactly one subdirectory contains name.journal, it is used automatically. Returns error if no matching files exist, multiple subdirectories match, or any file fails to open.

func (*Journal) Close

func (j *Journal) Close() error

Close closes all underlying Files. Returns the first error encountered; remaining files are still closed.

func (*Journal) Entry

func (j *Journal) Entry() *Entry

Entry returns the current entry, or nil if no entry has been read yet.

func (*Journal) FieldValues

func (j *Journal) FieldValues(name string, limit int) ([]string, bool, error)

FieldValues returns all distinct values for the named field across all files in the journal, up to limit values. If truncated is true, the limit was reached.

func (*Journal) Fields

func (j *Journal) Fields() ([]string, error)

Fields returns all distinct field names (label names) across all files in the journal.

func (*Journal) Files

func (j *Journal) Files() []*File

Files returns the open Readers sorted by HeadEntrySeqnum (index 0 = oldest). Useful for diagnostics (e.g. printing seqnum ranges with cmd/inspect).

func (*Journal) Follow

func (j *Journal) Follow(ctx context.Context, pollInterval time.Duration, fn func(*Entry) bool) error

Follow polls for new entries at the given interval and calls fn for each entry. Returns nil if fn returns false (stopped early). Returns the context cause if ctx is cancelled. Useful for tailing live journals:

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
err := j.Follow(ctx, 10*time.Millisecond, func(e *Entry) bool {
    fmt.Println(e)
    return true // keep following
})

func (*Journal) NFiles

func (j *Journal) NFiles() int

NFiles returns the number of open journal files (active + archived).

func (*Journal) Next

func (j *Journal) Next() bool

Next advances to the next entry in sequence-number order across all files. On first call (Entry() == nil), reads the first entry from the file with the smallest HeadEntrySeqnum. On subsequent calls, advances within the current file or jumps to the next file. Handles gaps between files by finding the file with the smallest HeadEntrySeqnum greater than the current seqnum. When caught up, reloads the active file's header to detect rotation or new entries. Returns false when no more entries are available.

func (*Journal) NextEntry

func (j *Journal) NextEntry() (e *Entry, ok bool)

NextEntry is a convenience wrapper: calls Next() then returns (Entry(), true) on success, or (nil, false) if no more entries.

func (*Journal) Previous

func (j *Journal) Previous() bool

Previous moves to the entry just before the current one in sequence-number order. Uses containsSeqnum to check if the previous seqnum is in a file, then delegates to File.Previous (which uses Seek). Handles cross-file gaps by falling back to the file with the largest tail before the current seqnum.

Returns false if there is no previous entry (at head of first file) or no entry has been read yet. O(n) per call — see File.Previous for details.

func (*Journal) Seek

func (j *Journal) Seek(seqnum uint64) bool

Seek positions the journal at the entry with the given seqnum and reads it into Entry(). Refreshes if seqnum is beyond the tail. Returns true if the resulting Entry()'s seqnum is >= seqnum.

func (*Journal) SeekHead

func (j *Journal) SeekHead()

SeekHead resets all files to their first entry and clears the current Entry. The next Next() call reads from the oldest entry across all files.

func (*Journal) SeekRealtime

func (j *Journal) SeekRealtime(t time.Time)

SeekRealtime positions the journal at the first entry whose timestamp is >= t. Files entirely before t are skipped. The best file (smallest HeadEntryRealtime that covers t) is SeekRealtime'd and its first entry is read into Entry(). Returns true if the resulting Entry()'s timestamp is >= t. Call Next() after SeekRealtime to continue iteration.

func (*Journal) SeekTail

func (j *Journal) SeekTail()

SeekTail positions the journal at the last entry (by seqnum) and reads it into Entry(). Assumes the active file is the tail file. The next Next() call returns false.

Jump to

Keyboard shortcuts

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