File Coverage

blib/lib/Munin/Plugin/ApacheRequest.pm
Criterion Covered Total %
statement 39 39 100.0
branch 10 10 100.0
condition 5 8 62.5
subroutine 3 3 100.0
pod 1 1 100.0
total 58 61 95.0


line stmt bran cond sub pod time code
1             package Munin::Plugin::ApacheRequest;
2              
3 6     6   73413 use warnings;
  6         12  
  6         179  
4 6     6   21 use strict;
  6         8  
  6         3269  
5              
6             our $VERSION = '0.04';
7              
8             =head1 NAME
9              
10             Munin::Plugin::ApacheRequest - Monitor Apache requests with Munin
11              
12             =head1 SYNOPSIS
13              
14             This is the contents of a apache_request_$VHOST file, stored in the
15             /etc/munin/plugins directory.
16              
17             #!/usr/bin/perl -w
18             use strict;
19              
20             use Munin::Plugin::ApacheRequest;
21              
22             my ($VHOST) = ($0 =~ /_([^_]+)$/);
23             Munin::Plugin::ApacheRequest::Run($VHOST,1000);
24              
25             =head1 DESCRIPTION
26              
27             C provides the mechanism to trigger Apache
28             request monitoring for a specific VHOST, using Munin.
29              
30             This distribution is based on a script written by Nicolas Mendoza.
31              
32             NOTE: In order to use this module, you will need to add a field in your Apache
33             logs showing time executed. This is normally done using the %T (seconds) or
34             %D (microseconds). For instance:
35              
36             LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %T %v"
37              
38             See L for
39             more info.
40              
41             =head1 VARIABLES
42              
43             By default several variables are set by default, based on traditional paths and
44             log format orders. However, should you need to amend these, you can amend them
45             with in the calling script, before calling Run().
46              
47             =over 4
48              
49             =item * ACCESS_LOG_PATTERN
50              
51             The sprintf format string. If this selects the path based on the named VHOST.
52             By default this is "/var/www/logs/%s-access.log", where your access log uses a
53             VHOST prefix. If you don't require this, simple change this to the explicit
54             path, e.g. "/var/www/logs/access.log".
55              
56             If you have several log files, which are rotated and/or gzipped, you can
57             include a catchall in the path such as: "/var/www/logs/%s-access.log.*".
58              
59             =item * TIME_FIELD_INDEX
60              
61             By default this assumes the second to last field of the output line of the log,
62             which is set as '-2'. Setting this to a positive value, will select the
63             respective field from left to right.
64              
65             =back
66              
67             =cut
68              
69             #----------------------------------------------------------------------------
70             # Base Settings
71              
72             our $ACCESS_LOG_PATTERN = "/var/www/logs/%s-access.log"; # log pattern
73             our $TIME_FIELD_INDEX = -2; # second last field
74              
75             my $types = {
76             # any kind of request
77             total => {
78             munin_fields => {
79             label => 'All requests',
80             draw => 'LINE2',
81             info => 'Average seconds per any request',
82             },
83             sum => 0,
84             lines => 0,
85             matches => sub {
86             return 1;
87             },
88             },
89              
90             # image requests
91             images => {
92             munin_fields => {
93             label => 'Image requests',
94             draw => 'LINE2',
95             info => 'Average seconds per image request',
96             },
97             sum => 0,
98             lines => 0,
99             matches => sub {
100             my ($fields) = @_;
101             my $script;
102             ($script = $fields->[6]) =~ s/\?.*\z //mx;
103             return $script =~ m{ \.(png|jpe?g|jpg|gif|tiff|ilbm|tga) \z }mx;
104             },
105             },
106             };
107              
108             #----------------------------------------------------------------------------
109             # Functions
110              
111             =head1 FUNCTIONS
112              
113             =over 4
114              
115             =item * Run
116              
117             This is used to call the underlying plugin process. If the script is called
118             with the 'config' argument, the configuration details are returned, otherwise
119             the current values are calculated and returned.
120              
121             =back
122              
123             =cut
124              
125             sub Run {
126 4     4 1 10525 my ($VHOST,$LAST_N_REQUESTS) = @_;
127 4   50     13 $LAST_N_REQUESTS ||= 1000; # calculate based on this amount of requests
128              
129 4 100       19 my $access_log_pattern =
130             $ACCESS_LOG_PATTERN =~ /\%s/
131             ? sprintf $ACCESS_LOG_PATTERN, $VHOST
132             : $ACCESS_LOG_PATTERN;
133              
134 4         13 my $config =<< "CONFIG"
135             graph_title $VHOST ave msecs last $LAST_N_REQUESTS requests
136             graph_args --base 1000
137             graph_scale no
138             graph_vlabel Average request time (msec)
139             graph_category Apache
140             graph_info This graph shows average request times for the last $LAST_N_REQUESTS requests
141             images.warning 30000000
142             images.critical 60000000
143             total.warning 10000000
144             total.critical 60000000
145             CONFIG
146             ;
147              
148 4 100 66     22 if (@ARGV && ($ARGV[0] eq 'config')) {
149 1         27 print $config;
150              
151 1         2 for my $type (sort keys %{$types}) {
  1         6  
152 2         4 for my $key (sort keys %{$types->{$type}->{'munin_fields'}}) {
  2         10  
153 6         55 printf "%s.%s %s\n", ($type, $key, $types->{$type}->{'munin_fields'}->{$key});
154             }
155             }
156 1         4 return;
157             }
158              
159 3         4 my $config_file;
160 3         4 eval { $config_file = `ls -1 $access_log_pattern 2>/dev/null| tail -1`; };
  3         14077  
161              
162 3         23 chomp $config_file;
163 3 100 66     39 if($@ || !$config_file) {
164 1         1 for my $type (sort keys %{$types}) {
  1         14  
165 2         63 printf "%s.value U\n", $type;
166             }
167             }
168              
169 3         11484 my @lines = `tail -$LAST_N_REQUESTS "$config_file"`;
170              
171 3         45 for my $line (@lines) {
172 470         322 for my $type (keys %{$types}) {
  470         641  
173 940         4996 my @fields = split /\s+/, $line;
174 940 100       1745 if ($types->{$type}->{'matches'}(\@fields)) {
175 911         1095 $types->{$type}->{'sum'} += $fields[$TIME_FIELD_INDEX];
176 911         2276 $types->{$type}->{'lines'}++;
177             }
178             }
179             }
180              
181 3         5 for my $type (sort keys %{$types}) {
  3         25  
182 6 100       76 my $value = $types->{$type}->{'lines'}
183             ? sprintf "%.10f", $types->{$type}->{'sum'} / $types->{$type}->{'lines'} : 'U';
184 6         174 printf "%s.value %s\n", ($type, $value);
185             }
186              
187 3         85 return;
188             }
189              
190             1;
191              
192             # Author: Nicolas Mendoza - 2008-06-18
193             # Modified by Barbie - 2008-10-21
194              
195             =head1 AUTHOR
196              
197             Barbie, for
198             Miss Barbell Productions, L
199              
200             =head1 COPYRIGHT & LICENSE
201              
202             Copyright (C) 2008-2014 Barbie for Miss Barbell Productions
203             All Rights Reserved.
204              
205             This distribution is free software; you can redistribute it and/or
206             modify it under the Artistic Licence v2.
207              
208             =cut