root / plugins / redis / redis_ @ 3e56b658
Historique | Voir | Annoter | Télécharger (8,68 ko)
| 1 | b54782b7 | Gleb Voronich | #!/usr/bin/perl -w |
|---|---|---|---|
| 2 | |||
| 3 | # |
||
| 4 | ## Copyright (C) 2009 Gleb Voronich <http://stanly.net.ua/> |
||
| 5 | ## |
||
| 6 | ## This program is free software; you can redistribute it and/or |
||
| 7 | ## modify it under the terms of the GNU General Public License |
||
| 8 | ## as published by the Free Software Foundation; version 2 dated June, |
||
| 9 | ## 1991. |
||
| 10 | ## |
||
| 11 | ## This program is distributed in the hope that it will be useful, |
||
| 12 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 13 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 14 | ## GNU General Public License for more details. |
||
| 15 | ## |
||
| 16 | ## You should have received a copy of the GNU General Public License |
||
| 17 | ## along with this program; if not, write to the Free Software |
||
| 18 | ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
| 19 | ## |
||
| 20 | ## |
||
| 21 | ## $Log$ |
||
| 22 | ## |
||
| 23 | ## Based on Redis module code v0.08 2009/from http://svn.rot13.org/index.cgi/Redis |
||
| 24 | ## |
||
| 25 | ## Installation process: |
||
| 26 | ## |
||
| 27 | ## 1. Download the plugin to your plugins directory (e.g. /usr/share/munin/plugins) |
||
| 28 | ## 2. Create 3 symlinks at the directory that us used by munin for plugins detection (e.g. /etc/munin/plugins): redis_connected_clients, redis_per_sec and and redis_used_memory |
||
| 29 | a7be1b20 | Vadim Istratov | ## 3. Edit plugin-conf.d/munin-node if it is needed (env.host and env.port variables are accepted; set env.password for password protected Redis server) |
| 30 | b54782b7 | Gleb Voronich | ## 4. Restart munin-node service |
| 31 | 016400bd | Matt West | ## |
| 32 | ## Magic Markers |
||
| 33 | #%# family=auto |
||
| 34 | #%# capabilities=autoconf suggest |
||
| 35 | b54782b7 | Gleb Voronich | |
| 36 | use strict; |
||
| 37 | use IO::Socket::INET; |
||
| 38 | use Switch; |
||
| 39 | |||
| 40 | my $HOST = exists $ENV{'host'} ? $ENV{'host'} : "127.0.0.1";
|
||
| 41 | my $PORT = exists $ENV{'port'} ? $ENV{'port'} : 6379;
|
||
| 42 | a7be1b20 | Vadim Istratov | my $PASSWORD = exists $ENV{'password'} ? $ENV{'password'} : undef;
|
| 43 | b54782b7 | Gleb Voronich | |
| 44 | 016400bd | Matt West | my $sock = &get_conn(); |
| 45 | my $config = ( defined $ARGV[0] and $ARGV[0] eq "config" ); |
||
| 46 | my $autoconf = ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ); |
||
| 47 | if ( $autoconf ) {
|
||
| 48 | if ( defined( $sock ) ) {
|
||
| 49 | print "yes\n"; |
||
| 50 | exit 0; |
||
| 51 | } else {
|
||
| 52 | print "no (unable to connect to $HOST\[:$PORT\])\n"; |
||
| 53 | exit 0; |
||
| 54 | } |
||
| 55 | } |
||
| 56 | my $suggest = ( defined $ARGV[0] and $ARGV[0] eq "suggest" ); |
||
| 57 | if ( $suggest ) {
|
||
| 58 | if ( defined( $sock ) ) {
|
||
| 59 | my @plugins = ('connected_clients', 'key_ratio', 'keys_per_sec', 'per_sec', 'used_keys', 'used_memory');
|
||
| 60 | foreach my $plugin (@plugins) {
|
||
| 61 | print "$plugin\n"; |
||
| 62 | } |
||
| 63 | exit 0; |
||
| 64 | } else {
|
||
| 65 | print "no (unable to connect to $HOST\[:$PORT\])\n"; |
||
| 66 | exit 0; |
||
| 67 | } |
||
| 68 | a7be1b20 | Vadim Istratov | } |
| 69 | |||
| 70 | 3e56b658 | Rafał Trójniak | my $hash=&get_info(); |
| 71 | b54782b7 | Gleb Voronich | |
| 72 | $0 =~ s/(.+)redis_//g; |
||
| 73 | |||
| 74 | switch ($0) {
|
||
| 75 | case "connected_clients" {
|
||
| 76 | 5a489679 | raszi | if ( $config ) {
|
| 77 | 3e56b658 | Rafał Trójniak | my $maxclients= get_config("maxclients")->{"maxclients"};
|
| 78 | b54782b7 | Gleb Voronich | print "graph_title Connected clients\n"; |
| 79 | print "graph_vlabel Connected clients\n"; |
||
| 80 | print "graph_category redis\n"; |
||
| 81 | 016400bd | Matt West | print "graph_args -l 0\n"; |
| 82 | 3e56b658 | Rafał Trójniak | print "connected_clients.line $maxclients:ff0000:Limit\n"; |
| 83 | 016400bd | Matt West | print "connected_clients.label connected clients\n"; |
| 84 | b54782b7 | Gleb Voronich | exit 0; |
| 85 | 5a489679 | raszi | } |
| 86 | |||
| 87 | print "connected_clients.value " . $hash->{'connected_clients'} . "\n";
|
||
| 88 | b54782b7 | Gleb Voronich | } |
| 89 | |||
| 90 | |||
| 91 | 016400bd | Matt West | case "keys_per_sec" {
|
| 92 | if ( $config ) {
|
||
| 93 | print "graph_title Keys Per Second\n"; |
||
| 94 | print "graph_vlabel per \${graph_period}\n";
|
||
| 95 | print "graph_category redis\n"; |
||
| 96 | print "graph_args -l 0\n"; |
||
| 97 | print "hits.label hits\n"; |
||
| 98 | print "hits.type COUNTER\n"; |
||
| 99 | print "misses.label misses\n"; |
||
| 100 | print "misses.type COUNTER\n"; |
||
| 101 | print "expired.label expirations\n"; |
||
| 102 | print "expired.type COUNTER\n"; |
||
| 103 | print "evictions.label evictions\n"; |
||
| 104 | print "evictions.type COUNTER\n"; |
||
| 105 | exit 0; |
||
| 106 | } |
||
| 107 | |||
| 108 | print "hits.value " . $hash->{'keyspace_hits'} . "\n";
|
||
| 109 | print "misses.value " . $hash->{'keyspace_misses'} . "\n";
|
||
| 110 | print "expired.value " . $hash->{'expired_keys'} . "\n";
|
||
| 111 | print "evictions.value " . $hash->{'evicted_keys'} . "\n";
|
||
| 112 | } |
||
| 113 | |||
| 114 | case "key_ratio" {
|
||
| 115 | if ( $config ) {
|
||
| 116 | print "graph_title Key Hit vs Miss Ratio\n"; |
||
| 117 | print "graph_vlabel per \${graph_period}\n";
|
||
| 118 | print "graph_category redis\n"; |
||
| 119 | print "graph_args -u 100 -l 0 -r --base 1000\n"; |
||
| 120 | print "hitratio.label hit ratio\n"; |
||
| 121 | print "hitratio.type GAUGE\n"; |
||
| 122 | print "hitratio.draw AREA\n"; |
||
| 123 | print "missratio.label miss ratio\n"; |
||
| 124 | print "missratio.type GAUGE\n"; |
||
| 125 | print "missratio.draw STACK\n"; |
||
| 126 | exit 0; |
||
| 127 | } |
||
| 128 | |||
| 129 | my $total = $hash->{'keyspace_hits'} + $hash->{'keyspace_misses'};
|
||
| 130 | 285c11cd | iborodikhin | my $hitratio = 0; |
| 131 | my $missratio = 0; |
||
| 132 | if ($total > 0) {
|
||
| 133 | $hitratio = $hash->{'keyspace_hits'} / $total * 100;
|
||
| 134 | $missratio = $hash->{'keyspace_misses'} / $total * 100;
|
||
| 135 | } |
||
| 136 | printf("hitratio.value %.2f\n", $hitratio);
|
||
| 137 | printf("missratio.value %.2f\n", $missratio);
|
||
| 138 | 016400bd | Matt West | } |
| 139 | |||
| 140 | |||
| 141 | b54782b7 | Gleb Voronich | case "per_sec" {
|
| 142 | 5a489679 | raszi | if ( $config ) {
|
| 143 | b54782b7 | Gleb Voronich | print "graph_title Per second\n"; |
| 144 | print "graph_vlabel per \${graph_period}\n";
|
||
| 145 | print "graph_category redis\n"; |
||
| 146 | 016400bd | Matt West | print "graph_args -l 0\n"; |
| 147 | b54782b7 | Gleb Voronich | print "requests.label requests\n"; |
| 148 | print "requests.type COUNTER\n"; |
||
| 149 | print "connections.label connections\n"; |
||
| 150 | print "connections.type COUNTER\n"; |
||
| 151 | exit 0; |
||
| 152 | 5a489679 | raszi | } |
| 153 | |||
| 154 | print "requests.value ". $hash->{'total_commands_processed'} ."\n";
|
||
| 155 | print "connections.value ". $hash->{'total_connections_received'} ."\n";
|
||
| 156 | b54782b7 | Gleb Voronich | } |
| 157 | |||
| 158 | |||
| 159 | case "used_memory" {
|
||
| 160 | 5a489679 | raszi | if ( $config ) {
|
| 161 | 3e56b658 | Rafał Trójniak | my $maxmemory = get_config("maxmemory")->{"maxmemory"};
|
| 162 | b54782b7 | Gleb Voronich | print "graph_title Used memory\n"; |
| 163 | print "graph_vlabel Used memory\n"; |
||
| 164 | print "graph_category redis\n"; |
||
| 165 | b6b77ef9 | Michael Renner | print "graph_args -l 0 --base 1024\n"; |
| 166 | 3e56b658 | Rafał Trójniak | print "used_memory.line $maxmemory:ff0000:Limit\n"; |
| 167 | 016400bd | Matt West | print "used_memory.label used memory\n"; |
| 168 | 3e56b658 | Rafał Trójniak | print "used_memory_peak.label used memory in peak\n"; |
| 169 | print "used_memory_rss.label Resident set size memory usage\n"; |
||
| 170 | b54782b7 | Gleb Voronich | exit 0; |
| 171 | 5a489679 | raszi | } |
| 172 | |||
| 173 | print "used_memory.value ". $hash->{'used_memory'} ."\n";
|
||
| 174 | 3e56b658 | Rafał Trójniak | print "used_memory_rss.value ". $hash->{'used_memory_rss'} ."\n";
|
| 175 | print "used_memory_peak.value ". $hash->{'used_memory_peak'} ."\n";
|
||
| 176 | 5a489679 | raszi | } |
| 177 | |||
| 178 | case "used_keys" {
|
||
| 179 | my $dbs; |
||
| 180 | foreach my $key (keys %{$hash}) {
|
||
| 181 | if ( $key =~ /^db\d+$/ && $hash->{$key} =~ /keys=(\d+),expires=(\d+)/ ) {
|
||
| 182 | $dbs->{$key} = [ $1, $2 ];
|
||
| 183 | } |
||
| 184 | } |
||
| 185 | |||
| 186 | if ( $config ) {
|
||
| 187 | print "graph_title Used keys\n"; |
||
| 188 | print "graph_vlabel Used keys\n"; |
||
| 189 | print "graph_category redis\n"; |
||
| 190 | 016400bd | Matt West | print "graph_args -l 0\n"; |
| 191 | 5a489679 | raszi | |
| 192 | foreach my $db (keys %{$dbs}) {
|
||
| 193 | printf "%s_keys.label %s keys\n", $db, $db; |
||
| 194 | printf "%s_expires.label %s expires\n", $db, $db; |
||
| 195 | } |
||
| 196 | |||
| 197 | exit 0; |
||
| 198 | } |
||
| 199 | |||
| 200 | foreach my $db (keys %{$dbs}) {
|
||
| 201 | printf "%s_keys.value %d\n", $db, $dbs->{$db}[0];
|
||
| 202 | printf "%s_expires.value %d\n", $db, $dbs->{$db}[1];
|
||
| 203 | } |
||
| 204 | b54782b7 | Gleb Voronich | } |
| 205 | } |
||
| 206 | 5a489679 | raszi | |
| 207 | 3e56b658 | Rafał Trójniak | close ($sock); |
| 208 | |||
| 209 | 016400bd | Matt West | sub get_conn {
|
| 210 | my $sock = IO::Socket::INET->new( |
||
| 211 | PeerAddr => $HOST, |
||
| 212 | PeerPort => $PORT, |
||
| 213 | Timeout => 10, |
||
| 214 | Proto => 'tcp' |
||
| 215 | ); |
||
| 216 | if ( defined( $PASSWORD ) ) {
|
||
| 217 | print $sock "AUTH ", $PASSWORD, "\r\n"; |
||
| 218 | my $result = <$sock> || die "can't read socket: $!"; |
||
| 219 | } |
||
| 220 | return $sock; |
||
| 221 | } |
||
| 222 | |||
| 223 | 3e56b658 | Rafał Trójniak | sub get_info{
|
| 224 | print $sock "INFO\r\n"; |
||
| 225 | my $result = <$sock> || die "can't read socket: $!"; |
||
| 226 | |||
| 227 | my $rep; |
||
| 228 | # +2 characters for \r\n at end of the data block |
||
| 229 | read($sock, $rep, substr($result,1)+2) || die "can't read from socket: $!"; |
||
| 230 | |||
| 231 | my $hash; |
||
| 232 | foreach (split(/\r\n/, substr($rep, 0, -2))) {
|
||
| 233 | my ($key,$val) = split(/:/, $_, 2); |
||
| 234 | if (defined($key)) {
|
||
| 235 | $hash->{$key} = $val;
|
||
| 236 | } |
||
| 237 | } |
||
| 238 | return $hash; |
||
| 239 | } |
||
| 240 | |||
| 241 | # This subroutine returns configuration matched to supplied as object |
||
| 242 | sub get_config{
|
||
| 243 | |||
| 244 | print $sock "*3\r\n\$6\r\nCONFIG\r\n\$3\r\nGET\r\n\$".length($_[0])."\r\n".$_[0]."\r\n"; |
||
| 245 | # Response will look like like |
||
| 246 | # *2\r\n$9\r\nmaxmemory\r\n$10\r\n3221225472\r\n |
||
| 247 | |||
| 248 | my $type = <$sock> || die "can't read socket: $!"; |
||
| 249 | |||
| 250 | my $conf; |
||
| 251 | if( substr($type,0,1) ne "*" ) {
|
||
| 252 | return $conf; |
||
| 253 | } |
||
| 254 | |||
| 255 | my $count=substr($type,1); |
||
| 256 | |||
| 257 | my ( $namesize, $name, $valuesize, $value ); |
||
| 258 | while ( $count > 1 ){
|
||
| 259 | $count=$count-2; |
||
| 260 | |||
| 261 | $namesize=<$sock>; |
||
| 262 | read($sock, $name, substr($namesize,1)+2) || die "can't read from socket: $!"; |
||
| 263 | |||
| 264 | $valuesize=<$sock>; |
||
| 265 | read($sock, $value, substr($valuesize,1)+2) || die "can't read from socket: $!"; |
||
| 266 | |||
| 267 | $conf->{substr($name, 0, -2)}=substr($value, 0, -2);
|
||
| 268 | } |
||
| 269 | |||
| 270 | return $conf; |
||
| 271 | } |
||
| 272 | |||
| 273 | 5a489679 | raszi | # vim: ft=perl ai ts=4 sw=4 et: |
