A pure Go library for reading and writing systemd journal files.
No cgo, no libsystemd dependency.
Reader
- Offset-based random access to all object types
- Entry iteration via entry array chains
- Entry resolution (ENTRY -> DATA -> key=value fields)
- XZ, LZ4, and ZSTD decompression
- Compact mode support (modern systemd)
- Keyed hash flag detection
Writer
- Create new journal files with proper header and hash tables
- Append entries with automatic DATA/FIELD dedup via hash tables
- XZ, LZ4, and ZSTD compression
- Correct hash table collision chain management
- Entry array allocation with doubling
- Auto-reads machine-id and boot-id from the system
Verifier
- Sequential object scan with structural validation
- Jenkins hash verification for DATA and FIELD objects
- XOR hash verification for entries
- Entry sequence number ordering checks
- Object count cross-check against header
import "github.com/lemenkov/journald.go"jf, err := OpenJournalFile("/var/log/journal/.../system.journal")
if err != nil {
log.Fatal(err)
}
defer jf.Close()
jf.ForEachEntry(func(e *JournalEntry) error {
fmt.Printf("%s %s\n", e.Time().Format(time.RFC3339), e.Get("MESSAGE"))
return nil
})jw, err := CreateJournalFile("output.journal", JournalWriteOptions{
Compression: CompressionLZ4,
})
if err != nil {
log.Fatal(err)
}
err = jw.AppendEntry([]EntryField{
{Name: "MESSAGE", Value: "hello from Go"},
{Name: "PRIORITY", Value: "6"},
{Name: "_HOSTNAME", Value: "myhost"},
})
if err != nil {
log.Fatal(err)
}
jw.Close()Written files are readable by journalctl --file=output.journal.
jf, _ := OpenJournalFile("system.journal")
defer jf.Close()
if err := jf.Verify(); err != nil {
log.Fatalf("integrity check failed: %v", err)
}make
or
go test -v ./...
- Journal File Format (current)
- journal-def.h (authoritative source)
Apache-2.0. See LICENSE.