spiffin
7/15/2015 - 10:01 PM

Munin plugin for displaying Pagespeed stats

Munin plugin for displaying Pagespeed stats

#!/usr/bin/perl
#
# Monitor mod_pagespeed statistics
#
# pagespeed_cache
# pagespeed_css
# pagespeed_js
# pagespeed_html
# pagespeed_img
# pagespeed_bw
#
# explanation: http://stackoverflow.com/questions/9115595/what-do-the-mod-pagespeed-statistics-mean
#
# Modified/updated version of https://github.com/alexisvannier/munin-pagespeed
#
# IMPORTANT: remove file extension (.pl) before use - and change 'ngx_pagespeed_global_statistics' (line 36) to your global stats URL.
#
# Magic markers:
#%# family=auto
#%# capabilities=autoconf

use strict;
use Munin::Plugin;

need_multigraph();

my $ret = undef;

if ( !eval "require LWP::UserAgent;" ) {
    $ret = "LWP::UserAgent not found";
}

my $URL
    = exists $ENV{'url'}
    ? $ENV{'url'}
    : "http://127.0.0.1:%d/ngx_pagespeed_global_statistics";
my @PORTS = exists $ENV{'ports'} ? split( ' ', $ENV{'ports'} ) : (80);

if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ) {
    if ($ret) {
        print "no ($ret)\n";
        exit 1;
    }

    my $ua = LWP::UserAgent->new(
        timeout => 30,
        agent   => sprintf(
            "munin/%s (libwww-perl/%s)",
            $Munin::Common::Defaults::MUNIN_VERSION,
            $LWP::VERSION
        )
    );

    my @badports;
    foreach my $port (@PORTS) {
        my $url = sprintf $URL, $port;
        my $response = $ua->request( HTTP::Request->new( 'GET', $url ) );
        push @badports, $port
            unless $response->is_success and $response->content =~ /^size:/im;
    }
    if (@badports) {
        print "no (mod_pagespeed_statistics)\n";
        exit 1;
    }
    else {
        print "yes\n";
        exit 0;
    }
}

if ( defined $ARGV[0] and $ARGV[0] eq "config" ) {

    $0 =~ /pagespeed_(.+)*/;
    my $plugin = $1;

## mod_pagespeed_statistics cache
    if ( $plugin eq 'cache' ) {
        print('multigraph pagespeed_cache
graph_title Pagespeed Cache
graph_args --base 1000
graph_scale no
graph_vlabel Number
graph_category pagespeed

cache_hits.label Cache Hits
cache_hits.draw LINE1
cache_hits.min 0

cache_misses.label Cache Misses
cache_misses.draw LINE1
cache_misses.min 0

cache_expirations.label Cache Expirations
cache_expirations.draw LINE1
cache_expirations.min 0

cache_inserts.label Cache Inserts
cache_inserts.draw LINE1
cache_inserts.min 0

cache_deletes.label Cache Deletes
cache_deletes.draw LINE1
cache_deletes.min 0

cache_extensions.label Cache Extensions
cache_extensions.draw LINE1
cache_extensions.min 0
');
    }

## mod_pagespeed_statistics css
    elsif ( $plugin eq 'css' ) {
        print('multigraph pagespeed_css
graph_title Pagespeed CSS optimization
graph_args --base 1000
graph_scale no
graph_vlabel Number or Kb
graph_category pagespeed

css_file_count_reduction.label CSS file count reduction
css_file_count_reduction.draw LINE1
css_file_count_reduction.min 0

css_filter_blocks_rewritten.label CSS filter blocks rewritten
css_filter_blocks_rewritten.draw LINE1
css_filter_blocks_rewritten.min 0

css_filter_parse_failures.label CSS filter parse failures
css_filter_parse_failures.draw LINE1
css_filter_parse_failures.min 0

css_filter_rewrites_dropped.label CSS filter rewrites dropped
css_filter_rewrites_dropped.draw LINE1
css_filter_rewrites_dropped.min 0

css_filter_total_bytes_saved.label CSS filter total Kb saved
css_filter_total_bytes_saved.draw LINE1
css_filter_total_bytes_saved.min 0

css_filter_total_original_bytes.label CSS filter total original Kb
css_filter_total_original_bytes.draw LINE1
css_filter_total_original_bytes.min 0

css_filter_uses.label CSS filter uses
css_filter_uses.draw LINE1
css_filter_uses.min 0

css_imports_to_links.label CSS imports to links
css_imports_to_links.draw LINE1
css_imports_to_links.min 0

css_elements_moved.label CSS elements moved
css_elements_moved.draw LINE1
css_elements_moved.min 0
');
    }

## mod_pagespeed_statistics javascript
    elsif ( $plugin eq 'js' ) {
        print('multigraph pagespeed_js
graph_title Pagespeed Javascript optimization
graph_args --base 1000
graph_scale no
graph_vlabel Number or Kb
graph_category pagespeed

javascript_blocks_minified.label Javascript blocks minified
javascript_blocks_minified.draw LINE1
javascript_blocks_minified.min 0

javascript_minification_failures.label Javascript minification failures
javascript_minification_failures.draw LINE1
javascript_minification_failures.min 0

javascript_total_bytes_saved.label Javascript total Kb saved
javascript_total_bytes_saved.draw LINE1
javascript_total_bytes_saved.min 0

javascript_total_original_bytes.label Javascript total original Kb
javascript_total_original_bytes.draw LINE1
javascript_total_original_bytes.min 0

javascript_minify_uses.label Javascript minify uses
javascript_minify_uses.draw LINE1
javascript_minify_uses.min 0

js_file_count_reduction.label Javascript file count reduction
js_file_count_reduction.draw LINE1
js_file_count_reduction.min 0
');
    }

## mod_pagespeed_statistics html
    elsif ( $plugin eq 'html' ) {
        print('multigraph pagespeed_html
graph_title Pagespeed HTML optimization
graph_args --base 1000
graph_scale no
graph_vlabel Number or Kb
graph_category pagespeed

url_trims.label URL trims
url_trims.draw LINE1
url_trims.min 0

url_trim_saved_bytes.label URL trim saved Kb
url_trim_saved_bytes.draw LINE1
url_trim_saved_bytes.min 0

resource_url_domain_rejections.label Resource URL domain rejections
resource_url_domain_rejections.draw LINE1
resource_url_domain_rejections.min 0

rewrite_cached_output_missed_deadline.label Rewrite cached output missed deadline
rewrite_cached_output_missed_deadline.draw LINE1
rewrite_cached_output_missed_deadline.min 0

rewrite_cached_output_hits.label Rewrite cached output hits
rewrite_cached_output_hits.draw LINE1
rewrite_cached_output_hits.min 0

rewrite_cached_output_misses.label Rewrite cached output misses
rewrite_cached_output_misses.draw LINE1
rewrite_cached_output_misses.min 0

resource_fetches_cached.label Resource fetches cached
resource_fetches_cached.draw LINE1
resource_fetches_cached.min 0

resource_fetch_construct_successes.label Resource fetch construct successes
resource_fetch_construct_successes.draw LINE1
resource_fetch_construct_successes.min 0

resource_fetch_construct_failures.label Resource fetch construct failures
resource_fetch_construct_failures.draw LINE1
resource_fetch_construct_failures.min 0

num_flushes.label Rewrite number of flushes
num_flushes.draw LINE1
num_flushes.min 0

num_rewrites_executed.label Number of rewrites executed
num_rewrites_executed.draw LINE1
num_rewrites_executed.min 0

num_rewrites_dropped.label Number of rewrites dropped
num_rewrites_dropped.draw LINE1
num_rewrites_dropped.min 0

serf_fetch_request_count.label Serf fetch request count
serf_fetch_request_count.draw LINE1
serf_fetch_request_count.min 0

serf_fetch_bytes_count.label Serf fetch bytes count
serf_fetch_bytes_count.draw LINE1
serf_fetch_bytes_count.min 0

serf_fetch_time_duration_ms.label Serf fetch time duration (sec)
serf_fetch_time_duration_ms.draw LINE1
serf_fetch_time_duration_ms.min 0
');
    }

## mod_pagespeed_statistics images
    elsif ( $plugin eq 'img' ) {
        print('multigraph pagespeed_img
graph_title Pagespeed Image optimization
graph_args --base 1000
graph_scale no
graph_vlabel Number or Kb
graph_category pagespeed

#image_rewrite_total_original_bytes.label Image total Kb
#image_rewrite_total_original_bytes.draw LINE1
#image_rewrite_total_original_bytes.min 0

image_rewrite_total_bytes_saved.label Image filter total Kb saved
image_rewrite_total_bytes_saved.draw LINE1
image_rewrite_total_bytes_saved.min 0

image_rewrites.label Image rewrites
image_rewrites.draw LINE1
image_rewrites.min 0

image_rewrite_uses.label Image rewrite uses
image_rewrite_uses.draw LINE1
image_rewrite_uses.min 0

image_inline.label Image inline
image_inline.draw LINE1
image_inline.min 0

image_rewrite_latency_total_ms.label Image rewrite latency (sec)
image_rewrite_latency_total_ms.draw LINE1
image_rewrite_latency_total_ms.min 0
');
    }

## mod_pagespeed_statistics bandwidth saved
    elsif ( $plugin eq 'bw' ) {
        print('multigraph pagespeed_bw
graph_title Pagespeed bandwidth saved
graph_args --base 1024
graph_scale no
graph_vlabel Bytes
graph_category pagespeed

css_filter_total_original_bytes2.label CSS filter total original bytes
css_filter_total_original_bytes2.draw LINE2
css_filter_total_original_bytes2.min 0
css_filter_total_original_bytes2.type COUNTER

javascript_total_original_bytes2.label Javascript total original bytes
javascript_total_original_bytes2.draw LINE2
javascript_total_original_bytes2.min 0
javascript_total_original_bytes2.type COUNTER

#image_rewrite_total_original_bytes2.label Images total original bytes
#image_rewrite_total_original_bytes2.draw LINE2
#image_rewrite_total_original_bytes2.min 0
#image_rewrite_total_original_bytes2.type COUNTER

css_filter_total_bytes_saved2.label CSS filter total bytes saved
css_filter_total_bytes_saved2.draw AREA
css_filter_total_bytes_saved2.min 0
css_filter_total_bytes_saved2.type COUNTER

javascript_total_bytes_saved2.label Javascript total bytes saved
javascript_total_bytes_saved2.draw STACK
javascript_total_bytes_saved2.min 0
javascript_total_bytes_saved2.type COUNTER

image_rewrite_total_bytes_saved2.label Images filter total bytes saved
image_rewrite_total_bytes_saved2.draw STACK
image_rewrite_total_bytes_saved2.min 0
image_rewrite_total_bytes_saved2.type COUNTER

url_trim_saved_bytes2.label URL trim saved bytes
url_trim_saved_bytes2.draw STACK
url_trim_saved_bytes2.min 0
url_trim_saved_bytes2.type COUNTER
');
    }
    exit 0;
}

foreach my $port (@PORTS) {
    my $ua = LWP::UserAgent->new( timeout => 30 );
    my $url = sprintf $URL, $port;
    my $response = $ua->request( HTTP::Request->new( 'GET', $url ) );

    # CACHE
    if ( $response->content
        =~ /cache_hits:\s+([0-9\.]+)/im )
    {
        print "cache_hits.value $1\n";
    }
    else {
        print "cache_hits.value U\n";
    }

    if ( $response->content
        =~ /cache_misses:\s+([0-9\.]+)/im )
    {
        print "cache_misses.value $1\n";
    }
    else {
        print "cache_misses.value U\n";
    }

    if ( $response->content
        =~ /cache_expirations:\s+([0-9\.]+)/im )
    {
        print "cache_expirations.value $1\n";
    }
    else {
        print "cache_expirations.value U\n";
    }

    if ( $response->content
        =~ /cache_inserts:\s+([0-9\.]+)/im )
    {
        print "cache_inserts.value $1\n";
    }
    else {
        print "cache_inserts.value U\n";
    }

    if ( $response->content
        =~ /cache_deletes:\s+([0-9\.]+)/im )
    {
        print "cache_deletes.value $1\n";
    }
    else {
        print "cache_deletes.value U\n";
    }

    if ( $response->content
        =~ /cache_extensions:\s+([0-9\.]+)/im )
    {
        print "cache_extensions.value $1\n";
    }
    else {
        print "cache_extensions.value U\n";
    }

    # CSS
    if ( $response->content
        =~ /css_file_count_reduction:\s+([0-9\.]+)/im )
    {
        print "css_file_count_reduction.value $1\n";
    }
    else {
        print "css_file_count_reduction.value U\n";
    }

    if ( $response->content
        =~ /css_filter_blocks_rewritten:\s+([0-9\.]+)/im )
    {
        print "css_filter_blocks_rewritten.value $1\n";
    }
    else {
        print "css_filter_blocks_rewritten.value U\n";
    }

    if ( $response->content
        =~ /css_filter_parse_failures:\s+([0-9\.]+)/im )
    {
        print "css_filter_parse_failures.value $1\n";
    }
    else {
        print "css_filter_parse_failures.value U\n";
    }

    if ( $response->content
        =~ /css_filter_rewrites_dropped:\s+([0-9\.]+)/im )
    {
        print "css_filter_rewrites_dropped.value $1\n";
    }
    else {
        print "css_filter_rewrites_dropped.value U\n";
    }

    if ($response->content
        =~ /css_filter_total_bytes_saved:\s+([0-9\.]+)/im )
    {
        print "css_filter_total_bytes_saved.value "
            . sprintf( "%.2f", $1 / 1024 ) . "\n";
    }
    else {
        print "css_filter_total_bytes_saved.value U\n";
    }

    if ( $response->content
        =~ /css_filter_total_original_bytes:\s+([0-9\.]+)/im )
    {
        print "css_filter_total_original_bytes.value "
            . sprintf( "%.2f", $1 / 1024 ) . "\n";
    }
    else {
        print "css_filter_total_original_bytes.value U\n";
    }

    if ( $response->content
        =~ /css_filter_uses:\s+([0-9\.]+)/im )
    {
        print "css_filter_uses.value $1\n";
    }
    else {
        print "css_filter_uses.value U\n";
    }

    if ( $response->content
        =~ /css_imports_to_links:\s+([0-9\.]+)/im )
    {
        print "css_imports_to_links.value $1\n";
    }
    else {
        print "css_imports_to_links.value U\n";
    }

    if ( $response->content
        =~ /css_elements_moved:\s+([0-9\.]+)/im )
    {
        print "css_elements_moved.value $1\n";
    }
    else {
        print "css_elements_moved.value U\n";
    }

    # JAVASCRIPT
    if ( $response->content
        =~ /javascript_blocks_minified:\s+([0-9\.]+)/im )
    {
        print "javascript_blocks_minified.value $1\n";
    }
    else {
        print "javascript_blocks_minified.value U\n";
    }

    if ( $response->content
        =~ /javascript_minification_failures:\s+([0-9\.]+)/im )
    {
        print "javascript_minification_failures.value $1\n";
    }
    else {
        print "javascript_minification_failures.value U\n";
    }

    if ($response->content
        =~ /javascript_total_bytes_saved:\s+([0-9\.]+)/im )
    {
        print "javascript_total_bytes_saved.value "
            . sprintf( "%.2f", $1 / 1024 ) . "\n";
    }
    else {
        print "javascript_total_bytes_saved.value U\n";
    }

    if ( $response->content
        =~ /javascript_total_original_bytes:\s+([0-9\.]+)/im )
    {
        print "javascript_total_original_bytes.value "
            . sprintf( "%.2f", $1 / 1024 ) . "\n";
    }
    else {
        print "javascript_total_original_bytes.value U\n";
    }

    if ( $response->content
        =~ /javascript_minify_uses:\s+([0-9\.]+)/im )
    {
        print "javascript_minify_uses.value $1\n";
    }
    else {
        print "javascript_minify_uses.value U\n";
    }

    if ( $response->content
        =~ /js_file_count_reduction:\s+([0-9\.]+)/im )
    {
        print "js_file_count_reduction.value $1\n";
    }
    else {
        print "js_file_count_reduction.value U\n";
    }

    # HTML
    if ( $response->content
        =~ /url_trims:\s+([0-9\.]+)/im )
    {
        print "url_trims.value $1\n";
    }
    else {
        print "url_trims.value U\n";
    }

    if ( $response->content
        =~ /url_trim_saved_bytes:\s+([0-9\.]+)/im )
    {
        print "url_trim_saved_bytes.value "
            . sprintf( "%.2f", $1 / 1024 ) . "\n";
    }
    else {
        print "url_trim_saved_bytes.value U\n";
    }

    if ( $response->content
        =~ /resource_url_domain_rejections:\s+([0-9\.]+)/im )
    {
        print "resource_url_domain_rejections.value $1\n";
    }
    else {
        print "resource_url_domain_rejections.value U\n";
    }

    if ( $response->content
        =~ /rewrite_cached_output_missed_deadline:\s+([0-9\.]+)/im )
    {
        print "rewrite_cached_output_missed_deadline.value $1\n";
    }
    else {
        print "rewrite_cached_output_missed_deadline.value U\n";
    }

    if ( $response->content
        =~ /rewrite_cached_output_hits:\s+([0-9\.]+)/im )
    {
        print "rewrite_cached_output_hits.value $1\n";
    }
    else {
        print "rewrite_cached_output_hits.value U\n";
    }

    if ($response->content
        =~ /rewrite_cached_output_misses:\s+([0-9\.]+)/im )
    {
        print "rewrite_cached_output_misses.value $1\n";
    }
    else {
        print "rewrite_cached_output_misses.value U\n";
    }

    if ( $response->content
        =~ /resource_fetches_cached:\s+([0-9\.]+)/im )
    {
        print "resource_fetches_cached.value $1\n";
    }
    else {
        print "resource_fetches_cached.value U\n";
    }

    if ( $response->content
        =~ /resource_fetch_construct_successes:\s+([0-9\.]+)/im )
    {
        print "resource_fetch_construct_successes.value $1\n";
    }
    else {
        print "resource_fetch_construct_successes.value U\n";
    }

    if ( $response->content
        =~ /resource_fetch_construct_failures:\s+([0-9\.]+)/im )
    {
        print "resource_fetch_construct_failures.value $1\n";
    }
    else {
        print "resource_fetch_construct_failures.value U\n";
    }

    if ( $response->content
        =~ /num_flushes:\s+([0-9\.]+)/im )
    {
        print "num_flushes.value $1\n";
    }
    else {
        print "num_flushes.value U\n";
    }

    if ( $response->content
        =~ /num_rewrites_executed:\s+([0-9\.]+)/im )
    {
        print "num_rewrites_executed.value $1\n";
    }
    else {
        print "num_rewrites_executed.value U\n";
    }

    if ( $response->content
        =~ /num_rewrites_dropped:\s+([0-9\.]+)/im )
    {
        print "num_rewrites_dropped.value $1\n";
    }
    else {
        print "num_rewrites_dropped.value U\n";
    }

    if ( $response->content
        =~ /serf_fetch_request_count:\s+([0-9\.]+)/im )
    {
        print "serf_fetch_request_count.value $1\n";
    }
    else {
        print "serf_fetch_request_count.value U\n";
    }

    if ( $response->content
        =~ /serf_fetch_bytes_count:\s+([0-9\.]+)/im )
    {
        print "serf_fetch_bytes_count.value "
            . sprintf( "%.2f", $1 / 1024 ) . "\n";
    }
    else {
        print "serf_fetch_bytes_count.value U\n";
    }

    if ( $response->content
        =~ /serf_fetch_time_duration_ms:\s+([0-9\.]+)/im )
    {
        print "serf_fetch_time_duration_ms.value "
            . sprintf( "%.2f", $1 / 1000 ) . "\n";
    }
    else {
        print "serf_fetch_time_duration_ms.value U\n";
    }

    # IMAGES
    if ($response->content
        =~ /image_rewrite_total_original_bytes:\s+([0-9\.]+)/im )
    {
        print "image_rewrite_total_original_bytes.value "
            . sprintf( "%.2f", $1 / 1024 ) . "\n";
    }
    else {
        print "image_rewrite_total_original_bytes.value U\n";
    }

    if ($response->content
        =~ /image_rewrite_total_bytes_saved:\s+([0-9\.]+)/im )
    {
        print "image_rewrite_total_bytes_saved.value "
            . sprintf( "%.2f", $1 / 1024 ) . "\n";
    }
    else {
        print "image_rewrite_total_bytes_saved.value U\n";
    }

    if ($response->content
        =~ /image_rewrites:\s+([0-9\.]+)/im )
    {
        print "image_rewrites.value $1\n";
    }
    else {
        print "image_rewrites.value U\n";
    }

    if ($response->content
        =~ /image_rewrite_uses:\s+([0-9\.]+)/im )
    {
        print "image_rewrite_uses.value $1\n";
    }
    else {
        print "image_rewrite_uses.value U\n";
    }

    if ($response->content
        =~ /image_inline:\s+([0-9\.]+)/im )
    {
        print "image_inline.value $1\n";
    }
    else {
        print "image_inline.value U\n";
    }

    if ($response->content
        =~ /image_rewrite_latency_total_ms:\s+([0-9\.]+)/im )
    {
        print "image_rewrite_latency_total_ms.value "
            . sprintf( "%.2f", $1 / 1000 ) . "\n";
    }
    else {
        print "image_rewrite_latency_total_ms.value U\n";
    }

    # BANDWIDTH SAVED
    if ( $response->content
        =~ /css_filter_total_original_bytes:\s+([0-9\.]+)/im )
    {
        print "css_filter_total_original_bytes2.value $1\n";
    }
    else {
        print "css_filter_total_original_bytes2.value U\n";
    }

    if ( $response->content
        =~ /javascript_total_original_bytes:\s+([0-9\.]+)/im )
    {
        print "javascript_total_original_bytes2.value $1\n";
    }
    else {
        print "javascript_total_original_bytes2.value U\n";
    }

    if ($response->content
        =~ /image_rewrite_total_original_bytes:\s+([0-9\.]+)/im )
    {
        print "image_rewrite_total_original_bytes2.value $1\n";
    }
    else {
        print "image_rewrite_total_original_bytes2.value U\n";
    }

    if ($response->content
        =~ /css_filter_total_bytes_saved:\s+([0-9\.]+)/im )
    {
        print "css_filter_total_bytes_saved2.value $1\n";
    }
    else {
        print "css_filter_total_bytes_saved2.value U\n";
    }

    if ($response->content
        =~ /javascript_total_bytes_saved:\s+([0-9\.]+)/im )
    {
        print "javascript_total_bytes_saved2.value $1\n";
    }
    else {
        print "javascript_total_bytes_saved2.value U\n";
    }

    if ($response->content
        =~ /image_rewrite_total_bytes_saved:\s+([0-9\.]+)/im )
    {
        print "image_rewrite_total_bytes_saved2.value $1\n";
    }
    else {
        print "image_rewrite_total_bytes_saved2.value U\n";
    }

    if ( $response->content
        =~ /url_trim_saved_bytes:\s+([0-9\.]+)/im )
    {
        print "url_trim_saved_bytes2.value $1\n";
    }
    else {
        print "url_trim_saved_bytes2.value U\n";
    }

}

# vim:syntax=perl