├── README └── ganglia_memcached.pl /README: -------------------------------------------------------------------------------- 1 | ganglia_memcached.pl: 2 | 3 | script to record various ganglia metrics, with history 4 | 5 | 6 | installation: 7 | 8 | copy into a directory on you system, typically /usr/local/sbin/. 9 | setup a cron job to run this every minute, to push metrics 10 | to ganglia. 11 | 12 | crontab example: 13 | 14 | #gmetric_memcache collection 15 | * * * * * /usr/local/bin/ganglia_memcached.pl >/dev/null 2>&1 16 | 17 | -------------------------------------------------------------------------------- /ganglia_memcached.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | ############################################################# 4 | # This is memcached collection script for Ganglia 5 | # Author: Vladimir Vuksan http://vuksan.com/linux/ 6 | # Based off mymemcalc http://code.google.com/p/mymemcalc/ 7 | # modifications to include gets and sets by geoff papilion 8 | ############################################################# 9 | use strict; 10 | use warnings FATAL => 'all'; 11 | use English qw ( -no_match_vars ); 12 | use XML::Simple; 13 | use Cache::Memcached; 14 | use Getopt::Long; 15 | 16 | #################################################################################### 17 | # YOU MAY NEED TO MODIFY FOLLOWING 18 | # Adjust this variables appropriately. Feel free to add any options to gmetric_command 19 | # necessary for running gmetric in your environment to gmetric_options e.g. -c /etc/gmond.conf 20 | #################################################################################### 21 | my $gmetric_exec = "/usr/bin/gmetric"; 22 | my $gmetric_options = " -d 120 "; 23 | #################################################################################### 24 | my $gmetric_command = $gmetric_exec . $gmetric_options; 25 | my $host = "127.0.0.1"; 26 | my $port = "11211"; 27 | my $opt_help; 28 | my $old_time; 29 | #################################################################################### 30 | # Where to store the last stats file 31 | #################################################################################### 32 | my $tmp_dir_base="/tmp/memcached_stats"; 33 | my $tmp_stats_file=$tmp_dir_base . "/" . "memcached_stats"; 34 | 35 | # If the tmp directory doesn't exit create it 36 | if ( ! -d $tmp_dir_base ) { 37 | system("mkdir -p $tmp_dir_base"); 38 | } 39 | 40 | 41 | GetOptions("help" => \$opt_help, #flag 42 | "h=s" => \$host, 43 | "p=s" => \$port 44 | ); 45 | 46 | if(defined($opt_help)){ 47 | print <<'END_USAGE' 48 | Usage: ganglia_memcached.pl [OPTION]... 49 | Collect memcached statistics 50 | 51 | Options: 52 | -help Usage information 53 | -h Hostname of memcached. If not supplied defaults to 127.0.0.1 54 | -p Port of memcached. If not supplied defaults to 11211 55 | END_USAGE 56 | ; 57 | exit; 58 | } 59 | 60 | my $debug = 0; 61 | 62 | # we need separate files for each port for $time_diff to not be 0 or a few seconds 63 | $tmp_stats_file.=$port; 64 | 65 | # Set up the memcache pool 66 | my @mp; 67 | 68 | push(@mp, "$host:$port" ); 69 | 70 | my $mcache = new Cache::Memcached(); 71 | $mcache->set_servers(\@mp); 72 | 73 | #use Data::Dumper; 74 | 75 | # Get the stats 76 | my %stats=(); 77 | my %old_stats; 78 | %stats = %{$mcache->stats('misc')}; 79 | 80 | #print Dumper (%stats); 81 | 82 | 83 | ################################################################################# 84 | # Decide if we need to use a metric suffix 85 | ################################################################################# 86 | my $metric_suffix; 87 | # If port metric is not 11211 append the port to metric name 88 | if ( $port != "11211" ) { 89 | $metric_suffix = "_" . $port; 90 | } else { 91 | $metric_suffix = ""; 92 | } 93 | 94 | ################################################################################# 95 | # Memcache Hit Ratio 96 | ################################################################################# 97 | my $hits = $stats{'total'}->{'get_hits'} || 0; 98 | my $misses = $stats{'total'}->{'get_misses'} || 0; 99 | my $hitsplusmisses = $hits + $misses; 100 | my $hit_ratio; 101 | if ( $hitsplusmisses == 0 ) { 102 | $hit_ratio = 0.0; 103 | } else { 104 | $hit_ratio = $hits / $hitsplusmisses; 105 | } 106 | 107 | print 'memcache_hit_ratio: ' . substr( ( $hit_ratio * 100 ), 0, 5 ) . "%\n"; 108 | 109 | if ( $debug == 0 ) { 110 | system($gmetric_command . " -u ratio -tfloat -n memcache_hit_ratio".$metric_suffix." -v " . $hit_ratio); 111 | } 112 | 113 | ################################################################################# 114 | # Calculate Memcache Fill Ratio 115 | ################################################################################# 116 | my $total_bytes = 0; 117 | my $used_bytes = 0; 118 | my $curr_connections = 0; 119 | my $curr_items = 0; 120 | my $fill_ratio = 0; 121 | my $evictions = 0; 122 | my $bytes_read = 0; 123 | my $bytes_written = 0; 124 | my $gets = 0; 125 | my $sets = 0; 126 | my $new_time = time; 127 | 128 | foreach my $host ( keys %{ $stats{ 'hosts' } } ) { 129 | 130 | $total_bytes += $stats { 'hosts' }{ $host }{ 'misc' }->{ 'limit_maxbytes' }; 131 | $used_bytes += $stats { 'hosts' }{ $host }{ 'misc' }->{ 'bytes' }; 132 | $fill_ratio = $used_bytes / $total_bytes; 133 | $curr_connections = $stats { 'hosts' }{ $host }{ 'misc' }->{ 'curr_connections' }; 134 | $curr_items = $stats { 'hosts' }{ $host }{ 'misc' }->{ 'curr_items' }; 135 | # 136 | $evictions = $stats { 'hosts' }{ $host }{ 'misc' }->{ 'evictions' }; 137 | $bytes_read = $stats { 'hosts' }{ $host }{ 'misc' }->{ 'bytes_read' }; 138 | $bytes_written = $stats { 'hosts' }{ $host }{ 'misc' }->{ 'bytes_written' }; 139 | $gets = $stats { 'hosts' }{ $host }{ 'misc' }->{ 'cmd_get' }; 140 | $sets = $stats { 'hosts' }{ $host }{ 'misc' }->{ 'cmd_set' }; 141 | } 142 | 143 | 144 | if ( $debug == 0 ) { 145 | system($gmetric_command . " -u ratio -tfloat -n memcache_fill_ratio".$metric_suffix." -v " . $fill_ratio ); 146 | system($gmetric_command . " -u connections -tfloat -n memcache_curr_connections".$metric_suffix." -v " . $curr_connections ); 147 | system($gmetric_command . " -u items -tfloat -n memcache_curr_items".$metric_suffix." -v " . $curr_items ); 148 | } 149 | 150 | print 'memcache_fill_ratio: ' . substr( ( ( $fill_ratio ) ) * 100, 0, 5 ) . "%\n"; 151 | print "memcache_items: " . $curr_items . "\n"; 152 | print "memcache_curr_conn: " . $curr_connections . "\n"; 153 | print "memcache_gets: " . $gets . "\n"; 154 | print "memcache_sets: " . $sets . "\n"; 155 | 156 | sub write_stats_file () { 157 | 158 | open(NEWSTATUS, "> $tmp_stats_file"); 159 | 160 | print NEWSTATUS "evictions=" . $evictions . "\n"; 161 | print NEWSTATUS "bytes_read=" .$bytes_read . "\n"; 162 | print NEWSTATUS "bytes_written=" . $bytes_written . "\n"; 163 | print NEWSTATUS "cmd_get=" . $gets . "\n"; 164 | print NEWSTATUS "cmd_set=" . $sets . "\n"; 165 | 166 | close(NEWSTATUS); 167 | 168 | } 169 | 170 | ############################################################################### 171 | # Now I need to calculate counter metrics such as bytes in/out and evictions 172 | # We need to store a baseline with statistics. If it's not there let's dump 173 | # it into a file. Don't do anything else 174 | ############################################################################### 175 | if ( ! -f $tmp_stats_file ) { 176 | print "Creating baseline. No output this cycle\n"; 177 | write_stats_file; 178 | } else { 179 | 180 | ###################################################### 181 | # Let's read in the file from the last poll 182 | open(OLDSTATUS, "< $tmp_stats_file"); 183 | 184 | while() 185 | { 186 | if (/(.*)=(.*)/) { 187 | $old_stats{$1}=${2}; 188 | } 189 | } 190 | 191 | # added some new stats, don't want to log in everywhere. 192 | # this just adds the current value is it doesn't exist. 193 | if (! $old_stats{'cmd_get'} ) { 194 | $old_stats{'cmd_get'} = $gets; 195 | } 196 | 197 | if (! $old_stats{'cmd_set'} ) { 198 | $old_stats{'cmd_set'} = $sets; 199 | } 200 | 201 | # Get the time stamp when the stats file was last modified 202 | $old_time = (stat $tmp_stats_file)[9]; 203 | close(OLDSTATUS); 204 | 205 | if ( $debug == 0 ) { 206 | # Make sure we are not getting negative numbers since they would indicate server was restarted 207 | if ( $bytes_read >= $old_stats{'bytes_read'} ) { 208 | my $time_diff = $new_time - $old_time; 209 | #division by zero errors 210 | exit 0 unless ($time_diff > 0); 211 | system($gmetric_command . " -u number -tuint32 -n memcache_evictions".$metric_suffix." -v " . eval($evictions - $old_stats{'evictions'}) ); 212 | system($gmetric_command . " -u bytes/s -tfloat -n memcache_bytes_read".$metric_suffix." -v " . eval ( ($bytes_read - $old_stats{'bytes_read'}) / $time_diff) ); 213 | system($gmetric_command . " -u bytes/s -tfloat -n memcache_bytes_written".$metric_suffix." -v " . eval( ($bytes_written - $old_stats{'bytes_written'}) / $time_diff ) ); 214 | system($gmetric_command . " -u gets/s -tfloat -n memcache_gets".$metric_suffix." -v " . eval( ($gets - $old_stats{'cmd_get'}) / $time_diff ) ); 215 | system($gmetric_command . " -u sets/s -tfloat -n memcache_sets".$metric_suffix." -v " . eval( ($sets - $old_stats{'cmd_set'}) / $time_diff ) ); 216 | } 217 | write_stats_file; 218 | 219 | } 220 | 221 | 222 | } 223 | --------------------------------------------------------------------------------