NAME
Log::Progress::Parser - Parse progress data from a file
SYNOPSIS
open my $fh, "<", $logfile or die;
my $parser= Log::Progress::Parser->new(input => $fh);
$parser->parse;
A practical application:
# Display a 40-character progress bar at 1-second intervals
$|= 1;
while (1) {
$parser->parse;
printf "\r%3d%% [%-40s] ",
$parser->state->{progress}*100,
"#" x int($parser->state->{progress}*40);
last if $parser->state->{progress} >= 1;
sleep 1;
}
print "\n";
DESCRIPTION
This module parses progress messages from a file handle or string. Repeated calls to the "parse" method will continue parsing the file where it left off, making it relatively efficient to repeatedly call "parse" on a live log file.
ATTRIBUTES
input
This is a seekable file handle or scalar of log text from which the progress data will be parsed. Make sure to set the utf-8 layer on the file handle if you want to read progress messages that are more than just ascii.
input_pos
Each call to parse makes a note of the start of the final un-finished line, so that the next call can pick up where it left off, assuming the file is growing and the file handle is seekable.
state
This is a hashref of data describing the progress found in the input.
{
progress => $number_between_0_and_1,
message => $current_progress_messsage, # empty string if no message
current => $numerator, # only present if progress was a fraction
total => $denominator, #
step => { $step_id => \%step_state, ... },
data => \%data, # most recent JSON data payload, decoded
}
Substeps may additionally have the keys:
idx => $order_of_declaration, # useful for sorting
title => $name_of_this_step,
contribution => $percent_of_parent_task, # can be undef
sticky_message
Defaults to false. If set to true, then progress lines lacking a message will not clear the message of a previous progress line.
on_data
Optional coderef to handle JSON data discovered on input. The return value of this coderef will be stored in the "data" field of the current step.
For example, you might want to combine all the data instead of overwriting it:
my $parser= Log::Progress::Parser->new(
on_data => sub {
my ($parser, $step_id, $data)= @_;
my $prev_data= $parser->step_state($step_id)->{data} || {};
return Hash::Merge::merge( $prev_data, $data );
}
);
METHODS
parse
Read (any additional) "input", and return the "state" field, or die trying.
my $state= $parser->parse;
Sets "input_pos" just beyond the end of the final complete line of text, so that the next call to "parse" can follow a growing log file.
step_state
my $state= $parser->step_state($step_id, $create_if_missing);
my $state= $parser->step_state($step_id, $create_if_missing, \@path_out);
Convenience method to traverse "state" to get the data for a step. If the second paramter is false, this returns undef if the step is not yet defined. Else it creates a new state node, with idx
initialized.
If you pass the third parameter @path_out
it will receive a list of the parent nodes of the returned state node.
AUTHOR
Michael Conrad <mike@nrdvana.net>
VERSION
version 0.13
COPYRIGHT AND LICENSE
This software is copyright (c) 2023 by Michael Conrad.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.