Guard::Stats - Create guard objects and gather averall usage statistics from them.


Suppose we have a long-running application making heavy use of closures, and need to monitor the number of executed, not executed, and gone subrefs.

So we put a guard into each closure to update the statistics:

    # in initial section
    use Guard::Stats;
    my $stat = Guard::Stats->new;

    # when running
    my $guard = $stat->guard;
    my $callback = sub {
        $guard->finish("taken route 1");
        # now do useful stuff
    # ... do whatever we need and call $callback eventually

    # in diagnostic procedures triggered by an external event
    my $data = $stat->get_stat;
    warn "$data->{running} callbacks still waiting to be executed";

Of course, alive/dead counts of any objects (not only sub refs) may be monitored in a similar way.


A guard is a special object that does something useful in destructor, typically freeing a resource or lock. These guards however don't free anything. Instead, they call home to keep their master (YOU) informed.

The classes

Guard::Stats is a long-lived object that spawns guards and gathers statistical information.

Its public methods are guard() and various statistic getters.

Guard::Stats::Instance is the guard. When it is DESTROYed, it signals the stat object which created it.

Its public methods are end( [$result] ) and is_done().

The counters

When a guard is created, the total counter increases. When it's detroyed, dead counter increases. alive = total - dead is the number of guards that still exist.

Additionally, guards implement a end() method which indicates that the action associates with the guard is complete. Typically a guard should be destroyed soon afterwards. The guards for which neither DESTROY nor end were called are considered running (this is used in on_level).

The full matrix or DESTROY()/end() combinations is as follows:

    DESTROY: *        0        1
    end:*    total+   alive    dead
    end:0    ?        running  broken+
    end:1    done+    zombie   complete+

A "+" marks values directly measured by Guard::Stats. They all happen to be monotonous. Other statistics are derived from these.

Note that counter showing end() NOT called regardless of DESTROY() does not have a meaningful name (yet?).

Running count callback

Whenever number of guards in the running state passes given level, a function may be called. This can be used to monitor load, prevent uncontrolled memory usage growth, etc.

See on_level below.


new (%options)

%options may include:

  • time_stat - an object or class to store time statistics. The class should support new and add_data( $number ) operations for this to work. Suitable candidates are Statistics::Descriptive::Sparse and Statistics::Descriptive::LogScale (both have sublinear memory usage).

  • guard_class - packge name to override default guard class. See "overriding guard class" below.

Creating and using guards

guard( %options )

Create a guard object. All options will be forwarded to the guard's new() "as is", except for owner and want_time which are reserved.

As of current, the built-in guard class supports no other options, so supplying a hash is useless unless the guard class is redefined. See "overriding guard class" below. See also Guard::Stats::Instance for the detailed description of default guard class.

$guard->end( [ $result ] )

Signal that action associated with the guard is over. If $result is provided, it is saved in a special hash (see get_stat_result() below). This can be used e.g. to measure the number of successful/unsuccessful actions.

Calling end() a second time on the same guard will result in a warning, and change no counters.


Tell whether end() was ever called on the guard.

undef $guard

The guard's DESTROY() method will signal stats object that guard is gone, and whether it was finished before destruction.


The following getters represent numbers of guards in respective states:

  • total() - all guards ever created;

  • dead() - DESTROY was called;

  • alive() - DESTROY was NOT called;

  • done() - end() was called;

  • complete() - both end() and DESTROY were called;

  • zombie() - end() was called, but not DESTROY;

  • running() - neither end() nor DESTROY called;

  • broken() - number of guards for which DESTROY was called, but NOT end().

Growing broken and/or zombie counts usually indicate something went wrong.


Get all statistics as a single hashref.


Provide statistics on agruments provided to end() method.


Return time statistics object, if any.

on_level( $n, CODEREF )

Set on_level callback. If $n is positive, run CODEREF->($n) when number of running guard instances is increased to $n.

If $n is negative or 0, run CODEREF->($n) when it is decreased to $n.

CAVEAT: Normally, CODEREF should not die as it may be called within a destructor.

Overriding guard class

Custom guard classes may be used with Guard::Stats.

A guard_class supplied to new() must exhibit the following properties:

  • It must have a new() method, accepting a hash. owner=object and want_time=0|1 parameters MUST be acceptable.

  • The object returned by new() MUST have end(), is_done() and DESTROY() methods.

  • end() method MUST accept one or zero parameters.

  • end() method MUST call add_stat_end() with one or zero parameters on the owner object discussed above when called for the first time.

  • end() method MUST do nothing and emit a warning if called more than once. It MAY die then.

  • is_done() method MUST return true if end() was ever called, and false otherwise.

  • DESTROY() method MUST call add_stat_destroy method on owner object with one boolean parameter equivalent to is_done() return value.

  • end() and DESTROY() methods MAY call add_stat_time() method on the owner object with one numeric parameter. Each guard object MUST call add_stat_time only once.

See example/check_my_guard_class.t.

Guard instance callbacks

The following methods are called by the guard object in different stages of its life. They should NOT be called directly (unless there's a need to fool the stats object) and are only described for people who want to extend the guard object class.

add_stat_end( [ $result ] )

add_stat_destroy( $end_was_called )

add_stat_time( $time )


Konstantin S. Uvarin, <khedin at>


Please report any bugs or feature requests to bug-guard-stat at, or through the web interface at I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


You can find documentation for this module with the perldoc command.

                perldoc Guard::Stats

You can also look for information at:


This module was initially written as part of my day job at

Vadim Vlasov was the first user of this package, and proposed the zombie counter.


AnyEvent - This module was created for monitoring callback usage in AnyEvent-driven application. However, it allows for a broadeer usage.

Twiggy - A single-threaded web-server handling multiple simultaneous requests is probably the most natural environment for callback counting. See example/under_twiggy.psgi in this distribution.

Devel::Leak::Cb - Another module for finding leaked callbacks.


Copyright 2013 Konstantin S. Uvarin.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See for more information.