Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: jinnko/nagios-extensions
base: c77c0be013
...
head fork: jinnko/nagios-extensions
compare: 44cd7745e1
Checking mergeability… Don't worry, you can still create the pull request.
  • 2 commits
  • 1 file changed
  • 0 commit comments
  • 1 contributor
Showing with 762 additions and 0 deletions.
  1. +762 −0 libexec/check_mysql_performance
View
762 libexec/check_mysql_performance
@@ -0,0 +1,762 @@
+#!/usr/bin/perl
+
+use FindBin qw($Bin);
+use lib "$Bin/../perl/lib", "/usr/local/nagios/libexec";
+
+use strict;
+use warnings;
+
+#use Nagios::Plugin::DieNicely;
+use Nagios::Plugin;
+
+my $np = Nagios::Plugin->new(
+ 'usage' => <<EOH,
+Usage: %s [-H host] [-d DSN] -u -p --group
+EOH
+ 'version' => '1.00',
+ 'url' => 'http://www.capside.com',
+ 'extra' => <<EOH,
+
+Threshold formats are specified at:
+ http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT
+
+ 'blurb' => qq{Copyright (c) CAPSiDE.
+
+This plugin montitors the % use of CPU usage on Linux systems for various types of CPU usage.
+EOH
+);
+
+$np->add_arg(
+ spec => 'perfdata=s',
+ help => <<EOH,
+--perfdata performance data to output
+ Host to query
+EOH
+ required => 0,
+);
+
+$np->add_arg(
+ spec => 'H=s',
+ help => <<EOH,
+-H host
+ Host to query
+EOH
+ required => 0,
+);
+
+$np->add_arg(
+ spec => 'D=s',
+ help => <<EOH,
+-D DSN
+ DBI dsn without the DBI:mysql: part
+EOH
+ required => 0,
+ default => 'host=localhost'
+);
+
+$np->add_arg(
+ spec => 'u=s',
+ help => <<EOH,
+-u user
+ user to connect to mysql
+EOH
+ required => 0,
+);
+
+$np->add_arg(
+ spec => 'p=s',
+ help => <<EOH,
+-p password
+ password for mysql
+EOH
+ required => 0,
+ default => ''
+);
+
+$np->getopts;
+
+my $dsn;
+if ( defined $np->opts->H ) {
+ $dsn = 'host=' . $np->opts->H;
+}
+else {
+ $dsn = $np->opts->D;
+}
+
+my $mysql = new MySQL::Stats( 'dsn' => $dsn, 'user' => $np->opts->u, 'pass' => $np->opts->p );
+
+my $fname_component = crypt( ( $np->opts->u || '' ) . ( $np->opts->perfdata || '' ), "a3" );
+$fname_component =~ s/\//_/;
+
+my $diff = Nagios::Plugin::Differences->new( 'file' => sprintf( '/tmp/nagios_mysql_perf_%s_%s.tmp', $np->opts->H || "localhost", $fname_component ) );
+
+eval { $diff->load_last; };
+if ($@) {
+ my $read_data = $mysql->get_stats;
+ $diff->new_reading($read_data);
+ $diff->persist;
+
+ $np->nagios_exit( UNKNOWN, "Couldn't see last state $@" );
+}
+
+my $read_data = $mysql->get_stats;
+$diff->new_reading($read_data);
+$diff->persist;
+my $stat = $diff->rate('forward_difference_unknown_wrap');
+
+$SIG{'ALRM'} = sub {
+ $np->nagios_exit( CRITICAL, 'ERROR: Timed out.' );
+};
+
+#my ( $code, $message ) = ( OK, 'All parameters OK' );
+my ( $code, $message ) = ( undef, undef );
+$np->add_message( OK, "All parameters OK" );
+
+my @fields;
+if ( not $np->opts->perfdata ) {
+ @fields = keys %{ $mysql->{'stats'} };
+}
+else {
+ @fields = split( /,/, $np->opts->perfdata );
+
+ # @fields = split /,/, join ',', @{$np->opts->perfdata};
+}
+
+# Add all performance data
+my $thresholds;
+my $value;
+my $warning;
+my $critical;
+my $minimum;
+my $maximum;
+foreach my $key (@fields) {
+ if ( $key =~ /=/ ) {
+ ($key, $thresholds) = split( /=/, $key );
+ ($warning, $critical) = split ( /;/, $thresholds );
+ } else {
+ $thresholds = undef;
+ $warning = undef;
+ $critical = undef;
+ }
+ if ( $mysql->{'stats'}->{$key}->{'type'} eq 'ABS' ) {
+ next if ( not defined $read_data->{$key} );
+ $value = $read_data->{$key};
+ } elsif ( $mysql->{'stats'}->{$key}->{'type'} eq 'DERIVE' ) {
+ next if ( not defined $stat->{$key} );
+ $value = $stat->{$key};
+ }
+ $np->add_perfdata(
+ 'label' => $key,
+ 'value' => $value,
+ 'uom' => '',
+ 'warning' => $warning,
+ 'critical' => $critical,
+ );
+ if ( $thresholds ) {
+ #$message = "$message, key={$key}, warning={$warning}, critical={$critical}";
+ $code = $np->check_threshold(
+ 'check' => $value,
+ 'warning' => $warning,
+ 'critical' => $critical,
+ );
+ if ( $code ) {
+ $np->add_message($code, "$key beyond thresholds,");
+ }
+ }
+}
+($code, $message) = $np->check_messages();
+$np->nagios_exit( $code, $message );
+
+package MySQL::Stats;
+
+use DBI;
+
+sub new {
+ my ( $class, %options ) = @_;
+
+ my $self = {
+ 'dbh' => 'host=localhost',
+ 'user' => '',
+ 'pass' => '',
+ %options
+ };
+ $self->{'stats'} = {
+ 'Aborted_clients' => { 'type' => 'DERIVE' },
+ 'Aborted_connects' => { 'type' => 'DERIVE' },
+ 'Binlog_cache_disk_use' => { 'type' => 'ABS' },
+ 'Binlog_cache_use' => { 'type' => 'ABS' },
+ 'Bytes_received' => { 'type' => 'DERIVE' },
+ 'Bytes_sent' => { 'type' => 'DERIVE' },
+ 'Com_admin_commands' => { 'type' => 'DERIVE' },
+ 'Com_alter_db' => { 'type' => 'DERIVE' },
+ 'Com_alter_table' => { 'type' => 'DERIVE' },
+ 'Com_analyze' => { 'type' => 'DERIVE' },
+ 'Com_backup_table' => { 'type' => 'DERIVE' },
+ 'Com_begin' => { 'type' => 'DERIVE' },
+ 'Com_change_db' => { 'type' => 'DERIVE' },
+ 'Com_change_master' => { 'type' => 'DERIVE' },
+ 'Com_check' => { 'type' => 'DERIVE' },
+ 'Com_checksum' => { 'type' => 'DERIVE' },
+ 'Com_commit' => { 'type' => 'DERIVE' },
+ 'Com_create_db' => { 'type' => 'DERIVE' },
+ 'Com_create_function' => { 'type' => 'DERIVE' },
+ 'Com_create_index' => { 'type' => 'DERIVE' },
+ 'Com_create_table' => { 'type' => 'DERIVE' },
+ 'Com_create_user' => { 'type' => 'DERIVE' },
+ 'Com_dealloc_sql' => { 'type' => 'DERIVE' },
+ 'Com_delete' => { 'type' => 'DERIVE' },
+ 'Com_delete_multi' => { 'type' => 'DERIVE' },
+ 'Com_do' => { 'type' => 'DERIVE' },
+ 'Com_drop_db' => { 'type' => 'DERIVE' },
+ 'Com_drop_function' => { 'type' => 'DERIVE' },
+ 'Com_drop_index' => { 'type' => 'DERIVE' },
+ 'Com_drop_table' => { 'type' => 'DERIVE' },
+ 'Com_drop_user' => { 'type' => 'DERIVE' },
+ 'Com_execute_sql' => { 'type' => 'DERIVE' },
+ 'Com_flush' => { 'type' => 'DERIVE' },
+ 'Com_grant' => { 'type' => 'DERIVE' },
+ 'Com_ha_close' => { 'type' => 'DERIVE' },
+ 'Com_ha_open' => { 'type' => 'DERIVE' },
+ 'Com_ha_read' => { 'type' => 'DERIVE' },
+ 'Com_help' => { 'type' => 'DERIVE' },
+ 'Com_insert' => { 'type' => 'DERIVE' },
+ 'Com_insert_select' => { 'type' => 'DERIVE' },
+ 'Com_kill' => { 'type' => 'DERIVE' },
+ 'Com_load' => { 'type' => 'DERIVE' },
+ 'Com_load_master_data' => { 'type' => 'DERIVE' },
+ 'Com_load_master_table' => { 'type' => 'DERIVE' },
+ 'Com_lock_tables' => { 'type' => 'DERIVE' },
+ 'Com_optimize' => { 'type' => 'DERIVE' },
+ 'Com_preload_keys' => { 'type' => 'DERIVE' },
+ 'Com_prepare_sql' => { 'type' => 'DERIVE' },
+ 'Com_purge' => { 'type' => 'DERIVE' },
+ 'Com_purge_before_date' => { 'type' => 'DERIVE' },
+ 'Com_rename_table' => { 'type' => 'DERIVE' },
+ 'Com_repair' => { 'type' => 'DERIVE' },
+ 'Com_replace' => { 'type' => 'DERIVE' },
+ 'Com_replace_select' => { 'type' => 'DERIVE' },
+ 'Com_reset' => { 'type' => 'DERIVE' },
+ 'Com_restore_table' => { 'type' => 'DERIVE' },
+ 'Com_revoke' => { 'type' => 'DERIVE' },
+ 'Com_revoke_all' => { 'type' => 'DERIVE' },
+ 'Com_rollback' => { 'type' => 'DERIVE' },
+ 'Com_savepoint' => { 'type' => 'DERIVE' },
+ 'Com_select' => { 'type' => 'DERIVE' },
+ 'Com_set_option' => { 'type' => 'DERIVE' },
+ 'Com_show_binlog_events' => { 'type' => 'DERIVE' },
+ 'Com_show_binlogs' => { 'type' => 'DERIVE' },
+ 'Com_show_charsets' => { 'type' => 'DERIVE' },
+ 'Com_show_collations' => { 'type' => 'DERIVE' },
+ 'Com_show_column_types' => { 'type' => 'DERIVE' },
+ 'Com_show_create_db' => { 'type' => 'DERIVE' },
+ 'Com_show_create_table' => { 'type' => 'DERIVE' },
+ 'Com_show_databases' => { 'type' => 'DERIVE' },
+ 'Com_show_errors' => { 'type' => 'DERIVE' },
+ 'Com_show_fields' => { 'type' => 'DERIVE' },
+ 'Com_show_grants' => { 'type' => 'DERIVE' },
+ 'Com_show_innodb_status' => { 'type' => 'DERIVE' },
+ 'Com_show_keys' => { 'type' => 'DERIVE' },
+ 'Com_show_logs' => { 'type' => 'DERIVE' },
+ 'Com_show_master_status' => { 'type' => 'DERIVE' },
+ 'Com_show_ndb_status' => { 'type' => 'DERIVE' },
+ 'Com_show_new_master' => { 'type' => 'DERIVE' },
+ 'Com_show_open_tables' => { 'type' => 'DERIVE' },
+ 'Com_show_privileges' => { 'type' => 'DERIVE' },
+ 'Com_show_processlist' => { 'type' => 'DERIVE' },
+ 'Com_show_slave_hosts' => { 'type' => 'DERIVE' },
+ 'Com_show_slave_status' => { 'type' => 'DERIVE' },
+ 'Com_show_status' => { 'type' => 'DERIVE' },
+ 'Com_show_storage_engines' => { 'type' => 'DERIVE' },
+ 'Com_show_tables' => { 'type' => 'DERIVE' },
+ 'Com_show_triggers' => { 'type' => 'DERIVE' },
+ 'Com_show_variables' => { 'type' => 'DERIVE' },
+ 'Com_show_warnings' => { 'type' => 'DERIVE' },
+ 'Com_slave_start' => { 'type' => 'DERIVE' },
+ 'Com_slave_stop' => { 'type' => 'DERIVE' },
+ 'Com_stmt_close' => { 'type' => 'DERIVE' },
+ 'Com_stmt_execute' => { 'type' => 'DERIVE' },
+ 'Com_stmt_fetch' => { 'type' => 'DERIVE' },
+ 'Com_stmt_prepare' => { 'type' => 'DERIVE' },
+ 'Com_stmt_reset' => { 'type' => 'DERIVE' },
+ 'Com_stmt_send_long_data' => { 'type' => 'DERIVE' },
+ 'Com_truncate' => { 'type' => 'DERIVE' },
+ 'Com_unlock_tables' => { 'type' => 'DERIVE' },
+ 'Com_update' => { 'type' => 'DERIVE' },
+ 'Com_update_multi' => { 'type' => 'DERIVE' },
+ 'Com_xa_commit' => { 'type' => 'DERIVE' },
+ 'Com_xa_end' => { 'type' => 'DERIVE' },
+ 'Com_xa_prepare' => { 'type' => 'DERIVE' },
+ 'Com_xa_recover' => { 'type' => 'DERIVE' },
+ 'Com_xa_rollback' => { 'type' => 'DERIVE' },
+ 'Com_xa_start' => { 'type' => 'DERIVE' },
+ 'Connections' => { 'type' => 'DERIVE' },
+ 'Created_tmp_disk_tables' => { 'type' => 'DERIVE' },
+ 'Created_tmp_files' => { 'type' => 'DERIVE' },
+ 'Created_tmp_tables' => { 'type' => 'DERIVE' },
+ 'Delayed_errors' => { 'type' => 'DERIVE' },
+ 'Delayed_insert_threads' => { 'type' => 'ABS' },
+ 'Delayed_writes' => { 'type' => 'DERIVE' },
+ 'Flush_commands' => { 'type' => 'DERIVE' },
+ 'Handler_commit' => { 'type' => 'DERIVE' },
+ 'Handler_delete' => { 'type' => 'DERIVE' },
+ 'Handler_discover' => { 'type' => 'DERIVE' },
+ 'Handler_prepare' => { 'type' => 'DERIVE' },
+ 'Handler_read_first' => { 'type' => 'DERIVE' },
+ 'Handler_read_key' => { 'type' => 'DERIVE' },
+ 'Handler_read_next' => { 'type' => 'DERIVE' },
+ 'Handler_read_prev' => { 'type' => 'DERIVE' },
+ 'Handler_read_rnd' => { 'type' => 'DERIVE' },
+ 'Handler_read_rnd_next' => { 'type' => 'DERIVE' },
+ 'Handler_rollback' => { 'type' => 'DERIVE' },
+ 'Handler_savepoint' => { 'type' => 'DERIVE' },
+ 'Handler_savepoint_rollback' => { 'type' => 'DERIVE' },
+ 'Handler_update' => { 'type' => 'DERIVE' },
+ 'Handler_write' => { 'type' => 'DERIVE' },
+ 'Innodb_buffer_pool_pages_data' => { 'type' => 'ABS' },
+ 'Innodb_buffer_pool_pages_dirty' => { 'type' => 'ABS' },
+ 'Innodb_buffer_pool_pages_flushed' => { 'type' => 'DERIVE' },
+ 'Innodb_buffer_pool_pages_free' => { 'type' => 'ABS' },
+ 'Innodb_buffer_pool_pages_latched' => { 'type' => 'ABS' },
+ 'Innodb_buffer_pool_pages_misc' => { 'type' => 'ABS' },
+ 'Innodb_buffer_pool_pages_total' => { 'type' => 'ABS' },
+ 'Innodb_buffer_pool_read_ahead_rnd' => { 'type' => 'DERIVE' },
+ 'Innodb_buffer_pool_read_ahead_seq' => { 'type' => 'DERIVE' },
+ 'Innodb_buffer_pool_read_requests' => { 'type' => 'DERIVE' },
+ 'Innodb_buffer_pool_reads' => { 'type' => 'DERIVE' },
+ 'Innodb_buffer_pool_wait_free' => { 'type' => 'DERIVE' },
+ 'Innodb_buffer_pool_write_requests' => { 'type' => 'DERIVE' },
+ 'Innodb_data_fsyncs' => { 'type' => 'DERIVE' },
+ 'Innodb_data_pending_fsyncs' => { 'type' => 'ABS' },
+ 'Innodb_data_pending_reads' => { 'type' => 'ABS' },
+ 'Innodb_data_pending_writes' => { 'type' => 'ABS' },
+ 'Innodb_data_read' => { 'type' => 'DERIVE' },
+ 'Innodb_data_reads' => { 'type' => 'DERIVE' },
+ 'Innodb_data_writes' => { 'type' => 'DERIVE' },
+ 'Innodb_data_written' => { 'type' => 'DERIVE' },
+ 'Innodb_dblwr_pages_written' => { 'type' => 'DERIVE' },
+ 'Innodb_dblwr_writes' => { 'type' => 'DERIVE' },
+ 'Innodb_log_waits' => { 'type' => 'DERIVE' },
+ 'Innodb_log_write_requests' => { 'type' => 'DERIVE' },
+ 'Innodb_log_writes' => { 'type' => 'DERIVE' },
+ 'Innodb_os_log_fsyncs' => { 'type' => 'DERIVE' },
+ 'Innodb_os_log_pending_fsyncs' => { 'type' => 'ABS' },
+ 'Innodb_os_log_pending_writes' => { 'type' => 'ABS' },
+ 'Innodb_os_log_written' => { 'type' => 'DERIVE' },
+ 'Innodb_page_size' => { 'type' => 'ABS' },
+ 'Innodb_pages_created' => { 'type' => 'DERIVE' },
+ 'Innodb_pages_read' => { 'type' => 'DERIVE' },
+ 'Innodb_pages_written' => { 'type' => 'DERIVE' },
+ 'Innodb_row_lock_current_waits' => { 'type' => 'ABS' },
+ 'Innodb_row_lock_time' => { 'type' => 'DERIVE' },
+ 'Innodb_row_lock_time_avg' => { 'type' => 'ABS' },
+ 'Innodb_row_lock_time_max' => { 'type' => 'ABS' },
+ 'Innodb_row_lock_waits' => { 'type' => 'DERIVE' },
+ 'Innodb_rows_deleted' => { 'type' => 'DERIVE' },
+ 'Innodb_rows_inserted' => { 'type' => 'DERIVE' },
+ 'Innodb_rows_read' => { 'type' => 'DERIVE' },
+ 'Innodb_rows_updated' => { 'type' => 'DERIVE' },
+ 'Key_blocks_not_flushed' => { 'type' => 'ABS' },
+ 'Key_blocks_unused' => { 'type' => 'ABS' },
+ 'Key_blocks_used' => { 'type' => 'ABS' },
+ 'Key_read_requests' => { 'type' => 'DERIVE' },
+ 'Key_reads' => { 'type' => 'DERIVE' },
+ 'Key_write_requests' => { 'type' => 'DERIVE' },
+ 'Key_writes' => { 'type' => 'DERIVE' },
+ 'Max_used_connections' => { 'type' => 'ABS' },
+ 'Open_files' => { 'type' => 'ABS' },
+ 'Open_streams' => { 'type' => 'ABS' },
+ 'Open_tables' => { 'type' => 'ABS' },
+ 'Opened_tables' => { 'type' => 'DERIVE' },
+ 'Prepared_stmt_count' => { 'type' => 'ABS' },
+ 'Qcache_free_blocks' => { 'type' => 'ABS' },
+ 'Qcache_free_memory' => { 'type' => 'ABS' },
+ 'Qcache_hits' => { 'type' => 'DERIVE' },
+ 'Qcache_inserts' => { 'type' => 'DERIVE' },
+ 'Qcache_lowmem_prunes' => { 'type' => 'DERIVE' },
+ 'Qcache_not_cached' => { 'type' => 'DERIVE' },
+ 'Qcache_queries_in_cache' => { 'type' => 'ABS' },
+ 'Qcache_total_blocks' => { 'type' => 'ABS' },
+ 'Questions' => { 'type' => 'DERIVE' },
+ 'Select_full_join' => { 'type' => 'DERIVE' },
+ 'Select_full_range_join' => { 'type' => 'DERIVE' },
+ 'Select_range' => { 'type' => 'DERIVE' },
+ 'Select_range_check' => { 'type' => 'DERIVE' },
+ 'Select_scan' => { 'type' => 'DERIVE' },
+ 'Slave_open_temp_tables' => { 'type' => 'ABS' },
+ 'Slave_retried_transactions' => { 'type' => 'DERIVE' },
+ 'Slow_launch_threads' => { 'type' => 'DERIVE' },
+ 'Slow_queries' => { 'type' => 'DERIVE' },
+ 'Sort_merge_passes' => { 'type' => 'DERIVE' },
+ 'Sort_range' => { 'type' => 'DERIVE' },
+ 'Sort_rows' => { 'type' => 'DERIVE' },
+ 'Sort_scan' => { 'type' => 'DERIVE' },
+ 'Ssl_accept_renegotiates' => { 'type' => 'DERIVE' },
+ 'Ssl_accepts' => { 'type' => 'DERIVE' },
+ 'Ssl_callback_cache_hits' => { 'type' => 'DERIVE' },
+ 'Ssl_client_connects' => { 'type' => 'DERIVE' },
+ 'Ssl_connect_renegotiates' => { 'type' => 'DERIVE' },
+ 'Ssl_ctx_verify_depth' => { 'type' => 'ABS' },
+ 'Ssl_ctx_verify_mode' => { 'type' => 'ABS' },
+ 'Ssl_default_timeout' => { 'type' => 'ABS' },
+ 'Ssl_finished_accepts' => { 'type' => 'DERIVE' },
+ 'Ssl_finished_connects' => { 'type' => 'DERIVE' },
+ 'Ssl_session_cache_hits' => { 'type' => 'DERIVE' },
+ 'Ssl_session_cache_misses' => { 'type' => 'DERIVE' },
+ 'Ssl_session_cache_overflows' => { 'type' => 'DERIVE' },
+ 'Ssl_session_cache_size' => { 'type' => 'ABS' },
+ 'Ssl_session_cache_timeouts' => { 'type' => 'DERIVE' },
+ 'Ssl_sessions_reused' => { 'type' => 'DERIVE' },
+ 'Ssl_used_session_cache_entries' => { 'type' => 'DERIVE' },
+ 'Ssl_verify_depth' => { 'type' => 'ABS' },
+ 'Ssl_verify_mode' => { 'type' => 'ABS' },
+ 'Table_locks_immediate' => { 'type' => 'DERIVE' },
+ 'Table_locks_waited' => { 'type' => 'DERIVE' },
+ 'Tc_log_max_pages_used' => { 'type' => 'ABS' },
+ 'Tc_log_page_size' => { 'type' => 'ABS' },
+ 'Tc_log_page_waits' => { 'type' => 'DERIVE' },
+ 'Threads_cached' => { 'type' => 'ABS' },
+ 'Threads_connected' => { 'type' => 'ABS' },
+ 'Threads_created' => { 'type' => 'DERIVE' },
+ 'Threads_running' => { 'type' => 'ABS' }
+ };
+
+ bless $self, $class;
+}
+
+sub get_stats {
+ my ($self) = @_;
+
+ my $dbh;
+ if ( not $self->{'_dbh'} ) {
+ $dbh = $self->{'_dbh'} = DBI->connect( "DBI:mysql:$self->{'dsn'}", $self->{'user'}, $self->{'pass'}, { 'RaiseError' => 1 } );
+ }
+ else {
+ $dbh = $self->{'_dbh'};
+ }
+
+ my $status = $dbh->prepare('SHOW GLOBAL STATUS');
+ $status->execute;
+ my $result = {};
+ while ( my $row = $status->fetchrow_hashref ) {
+ $result->{ $row->{'Variable_name'} } = $row->{'Value'};
+ }
+ return ( $self->{_data}{status} = $result );
+}
+
+1;
+
+package Nagios::Plugin::Differences;
+
+use strict;
+no warnings;
+
+use Carp;
+use File::Basename qw//;
+use Storable qw//;
+
+=head1 NAME
+
+Nagios::Plugin::Differences - Module to streamline Nagios plugins
+that need to store temporary data and calculate the differences
+between the readings.
+
+=head1 VERSION
+
+Version 0.01
+
+=cut
+
+our $VERSION = '0.01';
+
+=head1 SYNOPSIS
+
+This module is useful for when there is need to store a set of values
+that need to be reread at the next invocation of the plugin. It provides
+a set of functions to calculate the differences between the readings.
+
+ use Nagios::Plugin::Differences;
+
+ my $npd = Nagios::Plugin::Differences->new();
+ $npd->load_last;
+ # suppose last reading was
+ # { 'bytes' => 200, 'packets' => 3 }
+ # at time 1234567890
+ $npd->new_reading({
+ 'bytes' => 500
+ 'packets' => 6
+ });
+ # new reading is at time 123456900
+ $npd->persist;
+ my $rate = $npd->rate('difference');
+ # rate returns the bytes/s and the packets/s that had to be
+ # attained to get from the last reading to the new reading
+ # in the time passed between readings
+ # { 'bytes' => 30,
+ # 'packets' => 0.3 }
+
+=head1 FUNCTIONS
+
+=head2 new(%options)
+
+Constructor for the Nagios::Plugin::Differences object. You
+can pass 'file' => '/tmp/xxx' to override the default file
+('/tmp/_nagios_plugin_$0.tmp').
+
+=cut
+
+sub new {
+ my ( $class, %options ) = @_;
+
+ my $self = {
+ 'file' => sprintf( "/tmp/_nagios_plugin_%s.tmp", File::Basename::basename($0) ),
+ %options
+ };
+ bless $self, $class;
+}
+
+=head2 new_reading($data, [$ts])
+
+Report a new reading. The reading has to be a hashref. You can optionally
+pass the timestamp for the reading. If you don't pass $ts, the timestamp
+of the invocation of the method will be used.
+
+=cut
+
+sub new_reading {
+ my ( $self, $data, $ts ) = @_;
+ croak "cannot store non-hashref data" if ( ref($data) ne 'HASH' );
+ $ts = time() if ( not defined $ts );
+
+ $self->{'last'} = $self->{'current'} if ( defined $self->{'current'} );
+ $self->{'current'} = { 'ts' => $ts, 'data' => $data };
+}
+
+=head2 persist([$file])
+
+Write the stored data to the temporary file
+
+=cut
+
+sub persist {
+ my ( $self, $file ) = @_;
+ $file ||= $self->{'file'};
+ Storable::lock_store( $self->{'current'}, $file );
+}
+
+=head2 load_last([$file])
+
+Load the last reading from the temporary file.
+
+=cut
+
+sub load_last {
+ my ( $self, $file ) = @_;
+ $file ||= $self->{'file'};
+ $self->{'last'} = $self->{'current'} if ( defined $self->{'current'} );
+ $self->{'current'} = Storable::retrieve($file);
+}
+
+#head2 difference_from_zero
+#
+#Calculate the difference between current and zero.
+#
+#cut
+#
+#sub difference_from_zero {
+# my ($self) = @_;
+# return ($self->{'current'}->{'data'});
+#}
+
+=head1 CALCULATING DIFFERENCES
+
+=head2 difference
+
+Calculates the difference between current reading and last reading.
+
+=cut
+
+sub difference {
+ my ($self) = @_;
+
+ die 'no new_reading' if ( not defined $self->{'current'} );
+ die 'no last' if ( not defined $self->{'last'} );
+
+ my $current_data = $self->{'current'}->{'data'};
+ my $last_data = $self->{'last'}->{'data'};
+ my $delta = {};
+
+ foreach my $item ( keys %$last_data ) {
+
+ # if we don't have item, $data_last->{ xxx } will be undef. The correct reading would be zero
+ $delta->{$item} = $current_data->{$item} - ( $last_data->{$item} || 0 );
+ }
+ return ($delta);
+}
+
+=head2 forward_difference($wrap_at)
+
+=cut
+
+sub forward_difference {
+ my ( $self, $wrap_at ) = @_;
+
+ die 'no new_reading' if ( not defined $self->{'current'} );
+ die 'no last' if ( not defined $self->{'last'} );
+
+ my $current_data = $self->{'current'}->{'data'};
+ my $last_data = $self->{'last'}->{'data'};
+ my $delta = {};
+
+ foreach my $item ( keys %$last_data ) {
+ if ( $current_data->{$item} >= $last_data->{$item} ) {
+ $delta->{$item} = $current_data->{$item} - ( $last_data->{$item} || 0 );
+ }
+ else {
+
+ # If the current reading is smaller than the last time we saw it, then we have to
+ # take into account the wrap value.
+ # time |=======|------------|===========|
+ # 0 current last wrap
+ $delta->{$item} = ( $wrap_at - $last_data->{$item} ) + $current_data->{$item};
+ }
+ }
+ return ($delta);
+}
+
+=head2 forward_difference_unknown_wrap
+
+If the value of a key from the current reading is less than the last reading, the
+difference will be taken from zero. This is handy when you are storing counters
+that increment, but can be reset to zero.
+
+=cut
+
+sub forward_difference_unknown_wrap {
+ my ($self) = @_;
+
+ die 'no new_reading' if ( not defined $self->{'current'} );
+ die 'no last' if ( not defined $self->{'last'} );
+
+ my $current_data = $self->{'current'}->{'data'};
+ my $last_data = $self->{'last'}->{'data'};
+ my $delta = {};
+
+ foreach my $item ( keys %$last_data ) {
+ if ( $current_data->{$item} >= $last_data->{$item} ) {
+ $delta->{$item} = $current_data->{$item} - ( $last_data->{$item} || 0 );
+ }
+ else {
+
+ # If the current reading is smaller than the last time we saw it, then we have to
+ # discard the last reading. The counter has been reset, and we cannot know what
+ # happened between the last reading and the current one.
+ # time |=======|------------|???????....
+ # current last
+ $delta->{$item} = $current_data->{$item};
+ }
+ }
+ return ($delta);
+}
+
+=head2 rate($method, [params_to_method])
+
+Calculate the rate of change (derive) between the current reading and the last reading.
+To calculate rate of change, you need to calculate the change. The change gets calculated
+with any of the "difference" methods
+
+ $npd->rate('difference');
+
+ $npd->rate('forward_difference', 1000);
+
+ $npd->rate('forward_difference_unknown_wrap');
+
+=cut
+
+sub rate {
+ my ( $self, $method, @params_to_method ) = @_;
+
+ my $delta = $self->$method(@params_to_method);
+ my $time = $self->{'current'}->{'ts'} - $self->{'last'}->{'ts'};
+
+ my $rates = {};
+ foreach my $item ( keys %$delta ) {
+ $rates->{$item} = $delta->{$item} / $time;
+ }
+
+ return $rates;
+}
+
+=head2 proportion(
+
+Calculate the proportions of the values of one key respect to the total sum of all the values.
+
+ proportion({ 'red' => 5, 'green' => 15 });
+ # returns: { 'red' => 0.25, 'green' => 0.75 }
+
+=cut
+
+sub proportion {
+ my ( $self, $hashref ) = @_;
+
+ my $total = 0;
+ map { $total += $_ } values %$hashref;
+
+ my $proportion = {};
+ foreach my $item ( keys %$hashref ) {
+ $proportion->{$item} = $hashref->{$item} / $total;
+ }
+ return ($proportion);
+}
+
+1;
+
+=head1 AUTHOR
+
+JLMARTIN, C<< <jlmartinez at capside.com> >>
+
+=head1 BUGS
+
+Please report any bugs or feature requests to C<bug-nagios-plugin-differences at rt.cpan.org>, or through
+the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Nagios-Plugin-Differences>. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
+
+=head1 SUPPORT
+
+You can find documentation for this module with the perldoc command.
+
+ perldoc Nagios::Plugin::Differences
+
+You can also look for information at:
+
+=over 4
+
+=item * RT: CPAN's request tracker
+
+L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Nagios-Plugin-Differences>
+
+=item * AnnoCPAN: Annotated CPAN documentation
+
+L<http://annocpan.org/dist/Nagios-Plugin-Differences>
+
+=item * CPAN Ratings
+
+L<http://cpanratings.perl.org/d/Nagios-Plugin-Differences>
+
+=item * Search CPAN
+
+L<http://search.cpan.org/dist/Nagios-Plugin-Differences>
+
+=back
+
+=head1 ACKNOWLEDGEMENTS
+
+=head1 COPYRIGHT & LICENSE
+
+Copyright 2009 Jose Luis Martinez Torres, all rights reserved.
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+
+=cut
+
+1; # End of Nagios::Plugin::Differences

No commit comments for this range

Something went wrong with that request. Please try again.