package Apache::Scoreboard;
use strict;
use constant DEBUG => 0;
BEGIN {
no strict;
$VERSION = '0.10';
@ISA = qw(DynaLoader);
if ($ENV{MOD_PERL}) {
__PACKAGE__->bootstrap($VERSION);
}
else {
require Apache::DummyScoreboard;
}
}
my $ua;
sub http_fetch {
my($self, $url) = @_;
require LWP::UserAgent;
unless ($ua) {
no strict 'vars';
$ua = LWP::UserAgent->new;
$ua->agent(join '/', __PACKAGE__, $VERSION);
}
my $request = HTTP::Request->new('GET', $url);
my $response = $ua->request($request);
unless ($response->is_success) {
warn "request failed: ", $response->status_line if DEBUG;
return undef;
}
my $type = $response->header('Content-type');
unless ($type eq Apache::Scoreboard::REMOTE_SCOREBOARD_TYPE) {
warn "invalid scoreboard Content-type: $type" if DEBUG;
return undef;
}
$response->content;
}
sub fetch {
my($self, $url) = @_;
$self->thaw($self->http_fetch($url));
}
sub fetch_store {
my($self, $url, $file) = @_;
local *FH;
open FH, ">$file" or die "open $file: $!";
print FH $self->http_fetch($url);
close FH;
}
sub retrieve {
my($self, $file) = @_;
local *FH;
open FH, $file or die "open $file: $!";
local $/;
my $data = <FH>;
$self->thaw($data);
}
1;
__END__
=head1 NAME
Apache::Scoreboard - Perl interface to the Apache scoreboard structure
=head1 SYNOPSIS
use Apache::Scoreboard ();
#inside httpd
my $image = Apache::Scoreboard->image;
#outside httpd
my $image = Apache::Scoreboard->fetch("http://localhost/scoreboard");
=head1 DESCRIPTION
Apache keeps track of server activity in a structure known as the
I<scoreboard>. There is a I<slot> in the scoreboard for each child
server, containing information such as status, access count, bytes
served and cpu time. This same information is used by I<mod_status>
to provide current server statistics in a human readable form.
=head1 METHODS
=over 4
=item image
This method returns an object for accessing the scoreboard structure
when running inside the server:
my $image = Apache::Scoreboard->image;
=item fetch
This method fetches the scoreboard structure from a remote server,
which must contain the following configuration:
PerlModule Apache::Scoreboard
<Location /scoreboard>
SetHandler perl-script
PerlHandler Apache::Scoreboard::send
order deny,allow
deny from all
#same config you have for mod_status
allow from 127.0.0.1 ...
</Location>
If the remote server is not configured to use mod_perl or simply for a
smaller footprint, see the I<apxs> directory for I<mod_scoreboard_send>:
LoadModule scoreboard_send_module libexec/mod_scoreboard_send.so
<Location /scoreboard>
SetHandler scoreboard-send-handler
order deny,allow
deny from all
allow from 127.0.0.1 ...
</Location>
The image can then be fetched via http:
my $image = Apache::Scoreboard->fetch("http://remote-hostname/scoreboard");
=item fetch_store
=item retrieve
The I<fetch_store> method is used to fetch the image once from and
remote server and save it to disk. The image can then be read by
other processes with the I<retrieve> function.
This way, multiple processes can access a remote scoreboard with just
a single request to the remote server. Example:
Apache::Scoreboard->fetch_store($url, $local_filename);
my $image = Apache::Scoreboard->retrieve($local_filename);
=item parent
This method returns a reference to the first parent score entry in the
list, blessed into the I<Apache::ParentScore> class:
my $parent = $image->parent;
Iterating over the list of scoreboard slots is done like so:
for (my $parent = $image->parent; $parent; $parent = $parent->next) {
my $pid = $parent->pid; #pid of the child
my $server = $parent->server; #Apache::ServerScore object
...
}
=item pids
Returns an array reference of all child pids:
my $pids = $image->pids;
=back
=head2 The Apache::ParentScore Class
=over 4
=item pid
The parent keeps track of child pids with this field:
my $pid = $parent->pid;
=item server
Returns a reference to the corresponding I<Apache::ServerScore>
structure:
my $server = $parent->server;
=item next
Returns a reference to the next I<Apache::ParentScore> object in the list:
my $p = $parent->next;
=back
=head2 The Apache::ServerScore Class
=over 4
=item status
This method returns the status of child server, which is one of:
"_" Waiting for Connection
"S" Starting up
"R" Reading Request
"W" Sending Reply
"K" Keepalive (read)
"D" DNS Lookup
"L" Logging
"G" Gracefully finishing
"." Open slot with no current process
=item access_count
The access count of the child server:
my $count = $server->access_count;
=item request
The first 64 characters of the HTTP request:
#e.g.: GET /scoreboard HTTP/1.0
my $request = $server->request;
=item client
The ip address or hostname of the client:
#e.g.: 127.0.0.1
my $client = $server->client;
=item bytes_served
Total number of bytes served by this child:
my $bytes = $server->bytes_served;
=item conn_bytes
Number of bytes served by the last connection in this child:
my $bytes = $server->conn_bytes;
=item conn_count
Number of requests served by the last connection in this child:
my $count = $server->conn_count;
=item times
In a list context, returns a four-element list giving the user and
system times, in seconds, for this process and the children of this
process.
my($user, $system, $cuser, $csystem) = $server->times;
In a scalar context, returns the overall CPU percentage for this server:
my $cpu = $server->times;
=item start_time
In a list context this method returns a 2 element list with the seconds and
microseconds since the epoch, when the request was started. In scalar
context it returns floating seconds like Time::HiRes::time()
my($tv_sec, $tv_usec) = $server->start_time;
my $secs = $server->start_time;
=item stop_time
In a list context this method returns a 2 element list with the seconds and
microseconds since the epoch, when the request was finished. In scalar
context it returns floating seconds like Time::HiRes::time()
my($tv_sec, $tv_usec) = $server->stop_time;
my $secs = $server->stop_time;
=item req_time
Returns the time taken to process the request in microseconds:
my $req_time = $server->req_time;
=back
=head1 SEE ALSO
Apache::VMonitor(3), GTop(3)
=head1 AUTHOR
Doug MacEachern