Skip to main content

FileTailer

Struct FileTailer 

Source
pub struct FileTailer { /* private fields */ }
Expand description

Polls a log file for new data at a configurable interval.

Opens Player.log read-only with shared access (no file locking conflicts with MTGA), seeks to the end on startup, and reads only new bytes from the last offset on each poll cycle. Raw lines are fed into a LineBuffer for log entry boundary detection.

§Connection health

The last_event_at timestamp is updated whenever new data is read, providing a heartbeat signal for connection health monitoring.

§Example

use std::path::Path;
use manasight_parser::log::tailer::FileTailer;

let mut tailer = FileTailer::open(Path::new("/path/to/Player.log")).await?;

// Poll once for new data.
let entries = tailer.poll().await?;
for entry in &entries {
    println!("Got entry: {:?}", entry.header);
}

// Check when data was last seen.
if let Some(ts) = tailer.last_event_at() {
    println!("Last data at: {ts}");
}

Implementations§

Source§

impl FileTailer

Source

pub async fn open(path: &Path) -> Result<Self, TailerError>

Opens a log file for tailing, seeking to the end.

The file is opened read-only. On startup, the file position is set to the end so that only new data written after this point is returned by subsequent poll calls.

§Errors

Returns TailerError::Io if the file cannot be opened or the seek operation fails.

Source

pub async fn open_from_start(path: &Path) -> Result<Self, TailerError>

Opens a log file for tailing from the beginning.

Unlike open, this does not seek to the end. All existing content will be read on the first poll. Useful for testing or for catch-up parsing of Player-prev.log.

§Errors

Returns TailerError::Io if the file cannot be opened.

Source

pub fn set_poll_interval_ms(&mut self, ms: u64)

Sets the poll interval in milliseconds.

The default is 50 ms. Values below 10 ms are clamped to 10 ms to avoid busy-spinning.

Source

pub fn poll_interval_ms(&self) -> u64

Returns the poll interval in milliseconds.

Source

pub fn last_event_at(&self) -> Option<DateTime<Utc>>

Returns the timestamp of the last successful data read.

None if no data has been read yet. This is intended for connection health monitoring — if this timestamp is stale, the log file may not be updating (MTGA closed, crashed, etc.).

Source

pub fn offset(&self) -> u64

Returns the current byte offset in the file.

This is the position from which the next poll will read.

Source

pub fn path(&self) -> &Path

Returns a reference to the file path being tailed.

Source

pub fn take_rotation(&mut self) -> Option<RotationInfo>

Takes the rotation info from the last poll cycle, if any.

Returns Some(RotationInfo) exactly once after a rotation is detected by poll. Subsequent calls return None until the next rotation.

Source

pub async fn poll(&mut self) -> Result<Vec<LogEntry>, TailerError>

Polls the file for new data and returns any complete log entries.

Reads all new bytes appended since the last poll, splits them into lines, and feeds each line into the LineBuffer. Any complete log entries (flushed by a new header boundary) are collected and returned.

A partial line at the end of the read (not terminated by a newline) is buffered internally and prepended to the next read.

Returns an empty Vec if no new data is available.

§Errors

Returns TailerError::Io if the read operation fails.

Source

pub fn flush(&mut self) -> Vec<LogEntry>

Flushes any remaining buffered entries from the line buffer.

Call this when the input stream ends (EOF or file rotation) to retrieve any accumulated entries that have not yet been flushed by a subsequent header boundary.

Returns a Vec because flushing a partial line that is itself a log entry header can produce two entries: the previously buffered entry (flushed by the new header) and the new header’s own entry (drained from the line buffer or, for single-line headers, emitted directly by push_line).

Source

pub async fn run( &mut self, entry_tx: Sender<LogEntry>, shutdown: Receiver<bool>, ) -> Result<(), TailerError>

Runs the polling loop, sending complete log entries to the provided channel.

This method runs indefinitely until the shutdown signal is received. It polls the file at the configured interval and sends each complete LogEntry to the entry_tx channel.

§Cancellation

The loop exits when shutdown resolves. Callers should use a tokio::sync::watch or CancellationToken to signal shutdown.

§Errors

Returns TailerError::Io if a read operation fails. Callers should decide whether to retry or propagate the error.

Source

pub async fn run_once(&mut self) -> Result<Vec<LogEntry>, TailerError>

Reads the entire file and returns all complete log entries.

Polls until no new complete entries are returned (typically at EOF), then flushes the line buffer to capture any trailing entry. Unlike run, this method does not poll indefinitely or require a shutdown signal.

Note: the entire file is buffered into a Vec<LogEntry> before returning. This is suitable for batch processing (smoke tests, replay analysis, Player-prev.log imports) but not for memory-constrained streaming of very large files.

Works with any tailer opened from the start of a file via open_from_start.

§Errors

Returns TailerError::Io if a read operation fails.

Trait Implementations§

Source§

impl Debug for FileTailer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.