The Perl Advent Calendar needs more articles for 2022. Submit your idea today!


Log::Progress - Conveniently write progress messages to logger or file handle


version 0.12


  my $progress= Log::Progress->new(to => \*STDERR); # The default
  $progress->squelch(.1); # only emit messages every 10%
  my $max= 1000;
  $progress->at(0, $max);
  for (my $i= 1; $i <= $max; $i++) {
    # do the thing
  # or, if you don't have a loop variable:
  $progress->at(0, scalar @things);
  for (@things) {
    $progress->inc;  # "++" would be fun, but L<overload> causes object cloning


This module assists with writing progress messages to your log file, which can then be parsed with Log::Progress::Parser. It can write to file handles, log objects (like Log::Any), or custom coderefs.

Note that this module enables autoflush if you give it a file handle.



The destination for progress messages. It can be one of:

File Handle (or object with print method)

The print method is used, and passed a single newline-terminated string.

If the object also has a method autoflush, this module calls it before writing any messages. (to avoid that behavior, use a coderef instead)

Logger object (with info method)

The progress messages are passed to the info method, without a terminating newline.


The progress messages are passed as the only argument, without a terminating newline. The return value becomes the return value of the call to "progress" and should probably be a boolean to match behavior of IO::Handle::print.

  sub { my ($progress_message)= @_; ... }


The progress number is written as text, with "precision" digits after the decimal point. The default precision is 2. This default corresponds with a default "squelch" of 0.01, so that calls to ->at with less than 1% change from the previous call are suppressed.

If you set only one of precision or squelch, the other will default to something appropriate. For example, setting precision to 5 results in a squelch of .00001. Likewise a squelch of 1/60 gives a precision of 2.

Once set, precision will not receive a default value from changes to squelch. (but you can un-define it to restore that behavior)


You can prevent spamming your log file with tiny progress updates using squelch, which limits progress messages to one per some fraction of overall progress. For example, the default squelch of .01 will only emit at most 101 progress messages. (assuming your progress is non-decreasing)

If you set squelch but not precision, the second will use a sensible default. See example in "precision"

Once set, squelch will not receive a default value from changing precision. (but you can un-define it to restore that behavior)


If this object is reporting the progress of a sub-step, set this ID to the step name.

The default value for this field comes from $ENV{PROGRESS_STEP_ID}, so that programs that perform simple progress reporting can be nested as child processes of a larger job without having to specifically plan for that ability in the child process.


The current progress fraction numerator. Used by "inc". Setting this attribute directly bypasses the printing of progress.


The progress fraction denominator. Used by "inc" and "at". Setting this attribute directly bypasses the printing of progress.



  $p->at( $current, $total );
  $p->at( $current, $total, $message );

Report progress (but only if the progress since the last output is greater than squelch). Message is optional.

If $total is undefined, it uses any previous value of $total, else 1. If the total is exactly '1', then this will print $current as a formatted decimal. Otherwise it prints the fraction of $current/$total. When using fractional form, the decimal precision is omitted if $current is a whole number.

This function stores $current and $total for later calls.


Backward-compatible name for "at", but doesn't preserve previous $total.


  $progress->inc;               # increment by 1
  $progress->inc(5)             # increment by 5
  $progress->inc(1, $message);  # increment by 1 and include a message

Increment the numerator of the progress, and print if it is greater than "squelch".


If you want to write any progress-associated data, use this method. The data must be a hashref. It gets encoded as pure-ascii JSON.


  $progress_obj= $progress->substep( $id, $contribution, $title );

Create a named sub-step progress object, and declare it on the output.

$id and $title are required. The $contribution rate (a multiplier for applying the sub-step's progress to the parent progress bar) is recommended but not required.

Note that the sub-step gets declared on the output stream each time you call this method, but it isn't harmful to do so multiple times for the same step.


Michael Conrad <>


This software is copyright (c) 2020 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.