root / plugins / apache / apache_status @ ef960abc
Historique | Voir | Annoter | Télécharger (7,16 ko)
| 1 | 1b2574a4 | Diego Elio Pettenò | #!/usr/bin/env perl |
|---|---|---|---|
| 2 | # -*- cperl -*- |
||
| 3 | |||
| 4 | =head1 NAME |
||
| 5 | |||
| 6 | apache_status - Munin multigraph plugin to monitor Apache statistics. |
||
| 7 | |||
| 8 | =head1 NOTES |
||
| 9 | |||
| 10 | This plugin will produce multiple graphs showing: |
||
| 11 | |||
| 12 | - the number of accesses to Apache servers; |
||
| 13 | - the number of apache processes running on the machine; |
||
| 14 | de8f24a4 | Diego Elio Pettenò | - the volume of data sent from Apache servers. |
| 15 | 1b2574a4 | Diego Elio Pettenò | |
| 16 | =head1 APPLICABLE SYSTEMS |
||
| 17 | |||
| 18 | Apache HTTP servers with C</server-status> enabled. |
||
| 19 | |||
| 20 | =head1 CONFIGURATION |
||
| 21 | |||
| 22 | The plugin needs access to http://localhost/server-status?auto (or |
||
| 23 | modify the URL for another host). See your Apache documentation on |
||
| 24 | how to set up this URL in your httpd.conf. Apache needs ExtendedStatus |
||
| 25 | enabled for this plugin to work. |
||
| 26 | |||
| 27 | Tip: To see if it's already set up correctly, just run this plugin |
||
| 28 | with the parameter "autoconf". If you get a "yes", everything should |
||
| 29 | work like a charm already. |
||
| 30 | |||
| 31 | This configuration section shows the defaults of the plugin: |
||
| 32 | |||
| 33 | [apache_status] |
||
| 34 | env.url http://127.0.0.1:%d/server-status?auto |
||
| 35 | env.ports 80 |
||
| 36 | |||
| 37 | The %d in the url will be replaced with the port. The default port is |
||
| 38 | 80 as shown. |
||
| 39 | |||
| 40 | The port list is a space separated list of ports. NOTE that one |
||
| 41 | single Apache can have several open ports, and the plugin needs only |
||
| 42 | to contact one to get the servers global status. The list of ports is |
||
| 43 | only needed if you have several B<different> Apaches configured on |
||
| 44 | your host. |
||
| 45 | |||
| 46 | If you need authenticated access to the URL you can specify the |
||
| 47 | username and password in the URL. For example: |
||
| 48 | |||
| 49 | [apache_status] |
||
| 50 | env.url http://munin:spamalot@localhost/server-status?auto |
||
| 51 | |||
| 52 | This will provide for HTTP basic authentication. |
||
| 53 | |||
| 54 | =head1 INTERPRETATION |
||
| 55 | |||
| 56 | =head2 APACHE ACCESES |
||
| 57 | |||
| 58 | The graph shows the number of accesses (pages and other items served) |
||
| 59 | globally on the Apache server. |
||
| 60 | |||
| 61 | =head2 APACHE PROCESSES |
||
| 62 | |||
| 63 | The graph shows the number of Apache processes running on the |
||
| 64 | machine, and in addition separate "busy" and "idle" servers count. |
||
| 65 | |||
| 66 | If there is a flat ceiling effect on the graph where the number of |
||
| 67 | servers does not increase any more, in spite of no idle servers, then |
||
| 68 | the server has probably reached its C<MaxClients> setting. In this |
||
| 69 | case it's very likely that some clients are getting connection refused |
||
| 70 | or some other problem when connecting to your server. In this case |
||
| 71 | increase the C<MaxClients> setting. Unless there is also no more free |
||
| 72 | memory. |
||
| 73 | |||
| 74 | =head2 APACHE VOLUME |
||
| 75 | |||
| 76 | The graph shows the Apache HTTP servers global data volume in |
||
| 77 | bytes. I.e. how many bytes the server has served. |
||
| 78 | |||
| 79 | If there is a flat ceiling effect on the graph you may have reached |
||
| 80 | some kind of bandwidth limit on your outgoing connection. |
||
| 81 | |||
| 82 | =head1 MAGIC MARKERS |
||
| 83 | |||
| 84 | #%# family=auto |
||
| 85 | #%# capabilities=autoconf |
||
| 86 | |||
| 87 | =head1 BUGS |
||
| 88 | |||
| 89 | Does not support digest authentication. |
||
| 90 | |||
| 91 | =head1 AUTHOR |
||
| 92 | |||
| 93 | Rewritten by Diego Elio Pettenò <flameeyes@flameeyes.eu> based upon |
||
| 94 | original apache_accesses, apache_processes and apache_volume plugins |
||
| 95 | of unknown origin. |
||
| 96 | |||
| 97 | =head1 LICENSE |
||
| 98 | |||
| 99 | GPLv2 |
||
| 100 | |||
| 101 | =cut |
||
| 102 | |||
| 103 | use strict; |
||
| 104 | use warnings; |
||
| 105 | use Munin::Plugin; |
||
| 106 | |||
| 107 | 569e801e | Diego Elio Pettenò | $0 =~ /apache_status(?:_(.+))$/; |
| 108 | my $HOSTNAME = $1; |
||
| 109 | |||
| 110 | 1b2574a4 | Diego Elio Pettenò | my $ret = undef; |
| 111 | |||
| 112 | if (! eval "require LWP::UserAgent;") {
|
||
| 113 | $ret = "LWP::UserAgent not found"; |
||
| 114 | if ( ! defined $ARGV[0] ) {
|
||
| 115 | die $ret; |
||
| 116 | } |
||
| 117 | } |
||
| 118 | |||
| 119 | 569e801e | Diego Elio Pettenò | if ( exists $ENV{'hostname'} ) {
|
| 120 | $HOSTNAME = $ENV{'hostname'};
|
||
| 121 | } |
||
| 122 | |||
| 123 | my $URL = "http://127.0.0.1:%d/server-status?auto"; |
||
| 124 | if ( exists $ENV{'url'} ) {
|
||
| 125 | $URL = $ENV{'url'};
|
||
| 126 | } elsif ( defined $HOSTNAME ) {
|
||
| 127 | $URL = "http://$HOSTNAME:%d/server-status?auto" |
||
| 128 | } |
||
| 129 | |||
| 130 | 1b2574a4 | Diego Elio Pettenò | my @PORTS = exists $ENV{'ports'} ? split(' ', $ENV{'ports'}) : (80);
|
| 131 | my $UA = LWP::UserAgent->new(timeout => 30, |
||
| 132 | agent => sprintf("munin/%s (libwww-perl/%s)", $Munin::Common::Defaults::MUNIN_VERSION, $LWP::VERSION));
|
||
| 133 | |||
| 134 | if ( defined $ARGV[0] and $ARGV[0] eq "autoconf" ) {
|
||
| 135 | if ($ret) {
|
||
| 136 | print "no ($ret)\n"; |
||
| 137 | exit 0; |
||
| 138 | } |
||
| 139 | |||
| 140 | foreach my $port (@PORTS) {
|
||
| 141 | my $url = sprintf $URL, $port; |
||
| 142 | my $response = $UA->request(HTTP::Request->new('GET',$url));
|
||
| 143 | if ($response->is_success) {
|
||
| 144 | if ($response->content =~ /^Total Accesses:/im ) {
|
||
| 145 | next; |
||
| 146 | } else {
|
||
| 147 | print "no (ExtendedStatus option for apache" |
||
| 148 | . " mod_status is missing on port $port)\n"; |
||
| 149 | exit 0; |
||
| 150 | } |
||
| 151 | } elsif ($response->code == 404) {
|
||
| 152 | print "no (apache server-status not found. check if mod_status is enabled)\n"; |
||
| 153 | exit 0; |
||
| 154 | } else {
|
||
| 155 | print "no (Port $port: ". $response->message .")\n"; |
||
| 156 | exit 0; |
||
| 157 | } |
||
| 158 | } |
||
| 159 | print "yes\n"; |
||
| 160 | exit 0; |
||
| 161 | } |
||
| 162 | |||
| 163 | if ( defined $ARGV[0] and $ARGV[0] eq "config" ) {
|
||
| 164 | 569e801e | Diego Elio Pettenò | if ( defined $HOSTNAME ) {
|
| 165 | print "host_name $HOSTNAME\n"; |
||
| 166 | } |
||
| 167 | |||
| 168 | 1b2574a4 | Diego Elio Pettenò | print <<END; |
| 169 | |||
| 170 | multigraph apache_accesses |
||
| 171 | graph_title Apache accesses |
||
| 172 | graph_args --base 1000 -l 0 |
||
| 173 | graph_vlabel accesses / \${graph_period}
|
||
| 174 | graph_category apache |
||
| 175 | END |
||
| 176 | |||
| 177 | foreach my $port (@PORTS) {
|
||
| 178 | print <<END; |
||
| 179 | accesses$port.label port $port |
||
| 180 | accesses$port.type DERIVE |
||
| 181 | accesses$port.info The number of accesses (pages and other items served) globally on the Apache server |
||
| 182 | dbb14174 | Diego Elio Pettenò | accesses$port.min 0 |
| 183 | 1b2574a4 | Diego Elio Pettenò | END |
| 184 | print_thresholds("accesses$port");
|
||
| 185 | } |
||
| 186 | |||
| 187 | print <<END; |
||
| 188 | |||
| 189 | multigraph apache_processes |
||
| 190 | graph_title Apache processes |
||
| 191 | graph_args --base 1000 -l 0 |
||
| 192 | graph_vlabel processes |
||
| 193 | graph_total total |
||
| 194 | graph_category apache |
||
| 195 | END |
||
| 196 | |||
| 197 | print "graph_order "; |
||
| 198 | foreach my $port (@PORTS) {
|
||
| 199 | print "busy$port idle$port free$port "; |
||
| 200 | } |
||
| 201 | print "\n"; |
||
| 202 | |||
| 203 | foreach my $port (@PORTS) {
|
||
| 204 | print <<END; |
||
| 205 | busy$port.label busy servers on port $port |
||
| 206 | busy$port.draw LINE2 |
||
| 207 | dbb14174 | Diego Elio Pettenò | busy$port.min 0 |
| 208 | 1b2574a4 | Diego Elio Pettenò | idle$port.label idle servers on port $port |
| 209 | idle$port.draw STACK |
||
| 210 | dbb14174 | Diego Elio Pettenò | idle$port.min 0 |
| 211 | 1b2574a4 | Diego Elio Pettenò | free$port.label free slots on port $port |
| 212 | free$port.draw STACK |
||
| 213 | dbb14174 | Diego Elio Pettenò | free$port.min 0 |
| 214 | 1b2574a4 | Diego Elio Pettenò | END |
| 215 | |||
| 216 | print_thresholds("busy$port");
|
||
| 217 | print_thresholds("idle$port");
|
||
| 218 | print_thresholds("free$port");
|
||
| 219 | } |
||
| 220 | |||
| 221 | print <<END; |
||
| 222 | |||
| 223 | multigraph apache_volume |
||
| 224 | graph_title Apache volume |
||
| 225 | graph_args --base 1024 -l 0 |
||
| 226 | ecd21d50 | Diego Elio Pettenò | graph_vlabel KiB per \${graph_period}
|
| 227 | 1b2574a4 | Diego Elio Pettenò | graph_category apache |
| 228 | END |
||
| 229 | |||
| 230 | foreach my $port (@PORTS) {
|
||
| 231 | print <<END; |
||
| 232 | volume$port.label port $port |
||
| 233 | volume$port.type DERIVE |
||
| 234 | dbb14174 | Diego Elio Pettenò | volume$port.min 0 |
| 235 | 1b2574a4 | Diego Elio Pettenò | END |
| 236 | |||
| 237 | print_thresholds("volume$port");
|
||
| 238 | } |
||
| 239 | |||
| 240 | exit 0; |
||
| 241 | } |
||
| 242 | |||
| 243 | my %multigraphs = ( |
||
| 244 | accesses => "multigraph apache_accesses\n", |
||
| 245 | processes => "multigraph apache_processes\n", |
||
| 246 | de8f24a4 | Diego Elio Pettenò | volume => "multigraph apache_volume\n" |
| 247 | 1b2574a4 | Diego Elio Pettenò | ); |
| 248 | |||
| 249 | foreach my $port (@PORTS) {
|
||
| 250 | my $url = sprintf $URL, $port; |
||
| 251 | my $response = $UA->request(HTTP::Request->new('GET',$url));
|
||
| 252 | |||
| 253 | if ($response->content =~ /^Total Accesses:\s+(.+)$/im) {
|
||
| 254 | $multigraphs{accesses} .= "accesses$port.value $1\n";
|
||
| 255 | } else {
|
||
| 256 | $multigraphs{accesses} .= "accesses$port.value U\n";
|
||
| 257 | } |
||
| 258 | |||
| 259 | if ($response->content =~ /^Busy(?:Servers|Workers):\s+(.+)$/im) {
|
||
| 260 | $multigraphs{processes} .= "busy$port.value $1\n";
|
||
| 261 | } else {
|
||
| 262 | $multigraphs{processes} .= "busy$port.value U\n";
|
||
| 263 | } |
||
| 264 | if ($response->content =~ /^Idle(?:Servers|Workers):\s+(.+)$/im) {
|
||
| 265 | $multigraphs{processes} .= "idle$port.value $1\n";
|
||
| 266 | } else {
|
||
| 267 | $multigraphs{processes} .= "idle$port.value U\n";
|
||
| 268 | } |
||
| 269 | if ($response->content =~ /^(Scoreboard: .*)$/m) {
|
||
| 270 | my $count = () = $1 =~ /\./g; |
||
| 271 | $multigraphs{processes} .= "free$port.value $count\n";
|
||
| 272 | } else {
|
||
| 273 | $multigraphs{processes} .= "free$port.value U\n";
|
||
| 274 | } |
||
| 275 | |||
| 276 | if ($response->content =~ /^Total kBytes:\s+(.+)$/im) {
|
||
| 277 | $multigraphs{volume} .= "volume$port.value $1\n";
|
||
| 278 | } else {
|
||
| 279 | $multigraphs{volume} .= "volume$port.value U\n";
|
||
| 280 | } |
||
| 281 | } |
||
| 282 | |||
| 283 | foreach my $graph (keys %multigraphs) {
|
||
| 284 | print $multigraphs{$graph};
|
||
| 285 | } |
||
| 286 | |||
| 287 | # vim:syntax=perl |
