Logarithm::Systemd::JournalEntry
Represents a single entry from the systemd journal.
Each journal entry contains structured metadata and field data captured when the log message was recorded. The journal stores entries in a binary format with rich metadata beyond traditional syslog format.
Core Properties
- cursor: Opaque string uniquely identifying entry position
- realtime: Microsecond-precision timestamp since Unix epoch
- monotonic: Microsecond timestamp since system boot
- fields: Hash of all journal fields (MESSAGE, PRIORITY, etc.)
Common Journal Fields
Standard Fields
MESSAGE: The actual log message textPRIORITY: Syslog priority level (0-7)SYSLOG_IDENTIFIER: Program name or identifier_SYSTEMD_UNIT: Systemd unit name (service, socket, etc.)
Timestamp Fields
_SOURCE_REALTIME_TIMESTAMP: When message was logged (microseconds)__REALTIME_TIMESTAMP: When journald received the message__MONOTONIC_TIMESTAMP: Monotonic timestamp since boot
Process Fields
_PID: Process ID that logged the message_UID: User ID of the process_GID: Group ID of the process_COMM: Command name (from /proc/pid/comm)_EXE: Executable path
System Fields
_BOOT_ID: System boot identifier_MACHINE_ID: Machine identifier_HOSTNAME: System hostname_TRANSPORT: How message was received (journal, syslog, etc.)
Usage Examples
Basic Entry Processing
entry = reader.next_entry
puts "Time: #{entry.timestamp}"
puts "Message: #{entry.message}"
puts "Priority: #{entry.priority}"
puts "Unit: #{entry.syslog_identifier}"
Advanced Field Access
entry = reader.next_entry
# Access standard fields
message = entry.fields["MESSAGE"]
priority = entry.fields["PRIORITY"]?.try(&.to_i)
# Access process information
pid = entry.fields["_PID"]?.try(&.to_i)
uid = entry.fields["_UID"]?.try(&.to_i)
# Access custom fields (if logged)
request_id = entry.fields["REQUEST_ID"]
correlation_id = entry.fields["CORRELATION_ID"]
Filtering by Fields
entries = [] of JournalEntry
while entry = reader.next_entry
# Only process entries from specific unit
if entry.fields["_SYSTEMD_UNIT"] == "nginx.service"
entries << entry
end
# Only process error-level messages
if entry.fields["PRIORITY"]?.try(&.to_i) <= 3
entries << entry
end
end
Timestamp Handling
entry = reader.next_entry
# Use the timestamp() method for Time object
log_time = entry.timestamp
# Access raw microsecond timestamps
realtime_usec = entry.realtime
monotonic_usec = entry.monotonic
# Convert to different formats
iso_time = log_time.to_s("%Y-%m-%d %H:%M:%S")
unix_time = log_time.to_unix
Memory Considerations
- JournalEntry instances contain references to field data
- Field strings are owned by the entry and freed when entry is garbage collected
- For long-term storage, copy field values as needed
Thread Safety
JournalEntry instances are not thread-safe. If sharing entries between threads, implement proper synchronization or copy the data.
Constructors
Instance methods
Extracts the main log message from the MESSAGE field.
Returns: The log message text, or nil if not present
Gets the syslog priority level (0-7, where 0=emerg, 7=debug).
Returns: Priority as string, or nil if not present
Gets the systemd unit or syslog identifier for this entry.
Returns: Unit name or identifier, or nil if not present
Converts the realtime timestamp to a Crystal Time object.
Returns: Time object representing when this entry was logged