NAME

Plack::Middleware::Statsd - send statistics to statsd

VERSION

version v0.9.0

SYNOPSIS

use Plack::Builder;
use Net::Statsd::Tiny;

builder {

  enable "Statsd",
    client      => Net::Statsd::Tiny->new( ... ),
    sample_rate => 1.0;

  ...

  sub {
    my ($env) = @_;

    # Send statistics via other middleware

    if (my $stats = $env->{'psgix.monitor.statsd'}) {

      $stats->increment('myapp.wibble');

    }

    # Securely count the number of unique session ids

    if (my $secure_set_add = $env->{'psgix.monitor.statsd_secure_set_add'}) {

      my $options = $c->req->env->{'psgix.session.options'};
      $secure_set_add->( 'myapp.sessions', $options->{id} );

    }

  };

};

DESCRIPTION

This middleware gathers metrics from the application send sends them to a statsd server.

ATTRIBUTES

client

This is a statsd client, such as an instance of Net::Statsd::Tiny.

It is required.

The psgix.monitor.statsd key in the environment will be set to the current client if it is not set.

The only restriction on the client is that it has the same API as Net::Statsd::Tiny or similar modules, by supporting the following methods:

  • increment

  • timing_ms or timing

  • set_add

This has been tested with Net::Statsd::Lite and Net::Statsd::Client.

Other statsd client modules may be used via a wrapper class.

sample_rate

The default sampling rate to be used, which should be a value between 0 and 1. This will override the default rate of the "client", if there is one.

The default is 1.

histogram

This is a code reference to a wrapper around the "client" timing method. You do not need to set this unless you want to override it.

It takes as arguments the Plack environment and the arguments to pass to the client method, and calls that method. If there are errors then it attempts to log them.

increment

This is a code reference to a wrapper around the "client" increment method. You do not need to set this unless you want to override it.

It takes as arguments the Plack environment and the arguments to pass to the client method, and calls that method. If there are errors then it attempts to log them.

set_add

This is a code reference to a wrapper around the "client" set_add method. You do not need to set this unless you want to override it.

It takes as arguments the Plack environment and the arguments to pass to the client method, and calls that method. If there are errors then it attempts to log them.

catch_errors

If this is set to "1", then any fatal errors in the PSGI application will be caught and logged, and metrics will continue to be logged.

Alternatively, you may specify a subroutine that handles the errors and returns a valid response, for example.

sub handle_errors {
  my ( $env, $error ) = @_;

  if ( my $logger = $env->{'psgix.logger'} ) {
      $logger->( { level => 'error', message => $error } );
  }
  else {
      $env->{'psgi.errors'}->print($error);
  }

  return [
    503,
    [
       'Content-Type'   => 'text/plain',
       'Content-Length' => 11,
    ],
    [ 'Unavailable' ]
  ];
}

...

enable "Statsd",
   catch_errors => \&handle_errors;

This is disabled by default, which means that no metrics will be logged if there is a fatal error.

Added in v0.5.0.

secure_set_key

enable "Statsd",
  client      => Net::Statsd::Tiny->new( ... ),
  sample_rate => 1.0,
  secure_set_key => $key;

This is a secret key used for hashing the secrets before adding them to sets.

When this is set, the psgix.monitor.statsd_secure_set_add key is added to the environment, allowing other middleware to securely add items to sets.

Note that it is more secure if a random key is chosen each time that the application is started. However, there may be side effects: if the server forks before this middleware is initialised, then each worker will log secure set data uniquely, and statistics such as the number of unique IP addresses may be multiplied by the number of workers. Even when the key is set before forking, there may be a brief spike in the statistics whenever the server is restarted.

Added in v0.9.0.

secure_set_hash

This is the hashing algorithm used for encrypting secrets using an HMAC digest. It defaults to "SHA1".

Added in v0.9.0.

METRICS

The following metrics are logged:

psgi.request.method.$METHOD

This increments a counter for the request method.

If the request method is anything other than an ASCII word, then it will be counted as "other".

psgi.request.remote_addr

An encrypted remote address is added to the set, if "secure_set_key" is defined. Otherwise it is not logged.

Note: this was changed since version v0.9.0 in order to avoid leaking personally identifiable information when the "client" does not have a secured connection to the statsd server.

psgi.request.content-length

The content-length of the request, if it is specified in the header.

This is treated as a timing rather than a counter, so that statistics can be saved.

psgi.request.content-type.$TYPE.$SUBTYPE

A counter for the content type of request bodies is incremented, e.g. psgi.request.content-type.application.x-www-form-urlencoded.

Any modifiers in the type, e.g. charset, will be ignored.

psgi.response.content-length

The content-length of the response, if it is specified in the header.

This is treated as a timing rather than a counter, so that statistics can be saved.

psgi.response.content-type.$TYPE.$SUBTYPE

A counter for the content type is incremented, e.g. for a JPEG image, the counter psgi.response.content-type.image.jpeg is incremented.

Any modifiers in the type, e.g. charset, will be ignored.

psgi.response.status.$CODE

A counter for the HTTP status code is incremented.

psgi.response.time

The response time, in ms.

As of v0.3.1, this is no longer rounded up to an integer. If this causes problems with your statsd daemon, then you may need to use a subclassed version of your statsd client to work around this.

psgi.response.x-sendfile

This counter is incremented when the X-Sendfile header is added.

The header is configured using the plack.xsendfile.type environment key, otherwise the HTTP_X_SENDFILE_TYPE environment variable.

See Plack::Middleware::XSendfile for more information.

psgi.worker.pid

The worker PID is added to the set.

Note that this is set after the request is processed. This means that while the set size can be used to indicate the number of active workers, if the workers are busy (i.e. longer request processing times), then this will show a lower number.

This was added in v0.3.10.

psgix.harakiri

This counter is incremented when the harakiri flag is set.

If you want to rename these, or modify sampling rates, then you will need to use a wrapper class for the "client".

EXAMPLES

Using from Catalyst

You can access the configured statsd client from Catalyst:

sub finalize {
  my $c = shift;

  if (my $statsd = $c->req->env->{'psgix.monitor.statsd'}) {
    ...
  }

  $c->next::method(@_);
}

Alternatively, you can use Catalyst::Plugin::Statsd.

Using with Plack::Middleware::SizeLimit

Plack::Middleware::SizeLimit version 0.11 supports callbacks that allow you to monitor process size information. In your app.psgi:

use Net::Statsd::Tiny;
use Try::Tiny;

my $statsd = Net::Statsd::Tiny->new( ... );

builder {

  enable "Statsd",
    client      => $statsd,
    sample_rate => 1.0;

  ...

  enable "SizeLimit",
    ...
    callback => sub {
        my ($size, $shared, $unshared) = @_;
        try {
            $statsd->timing_ms('psgi.proc.size', $size);
            $statsd->timing_ms('psgi.proc.shared', $shared);
            $statsd->timing_ms('psgi.proc.unshared', $unshared);
        }
        catch {
            warn $_;
        };
    };

KNOWN ISSUES

Non-standard HTTP status codes

If your application is returning a status code that is not handled by HTTP::Status, then the metrics may not be logged for that response.

psgix.informational

This does not add a wrapper around the psgix.informational callback. If you are making use of it in your code, then you will need to add metrics logging yourself.

SECURITY CONSIDERATIONS

If the "client" does not have a secure communications channel to the statsd server, then there is the risk that information such as IP addresses or session ids will be leaked.

Other middleware or frameworks that make use of the psgix.monitor.statsd client should use the psgix.monitor.statsd_secure_set_add method when adding set data that contains personally identifiable information, authentication tokens or other sensitive data.

SEE ALSO

Net::Statsd::Client

Net::Statsd::Tiny

PSGI

SOURCE

The development version is on github at https://github.com/robrwo/Plack-Middleware-Statsd and may be cloned from https://github.com/robrwo/Plack-Middleware-Statsd.git

SUPPORT

Only the latest version of this module will be supported.

This module requires Perl v5.20 or later. Future releases may only support Perl versions released in the last ten (10) years.

Reporting Bugs and Submitting Feature Requests

Please report any bugs or feature requests on the bugtracker website https://github.com/robrwo/Plack-Middleware-Statsd/issues

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

If the bug you are reporting has security implications which make it inappropriate to send to a public issue tracker, then see SECURITY.md for instructions how to report security vulnerabilities.

AUTHOR

Robert Rothenberg <perl@rhizomnic.com>

The initial development of this module was sponsored by Science Photo Library https://www.sciencephoto.com.

COPYRIGHT AND LICENSE

This software is Copyright (c) 2018-2026 by Robert Rothenberg.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)