Plack-Middleware-ServerStatus-Lite

 view release on metacpan or  search on metacpan

bin/server-status  view on Meta::CPAN

my $parent_pid = $pstatus->{ppid};

my $upsince = time - $pstatus->{uptime};
my $duration = "";
my @spans = (86400 => 'days', 3600 => 'hours', 60 => 'minutes');
while (@spans) {
    my ($seconds,$unit) = (shift @spans, shift @spans);
    if ($upsince > $seconds) {
        $duration .= int($upsince/$seconds) . " $unit, ";
        $upsince = $upsince % $seconds;
    }
}
$duration .= "$upsince seconds";

my $body="Uptime: ".$pstatus->{uptime}." ($duration)\n";
my %status = ( 'Uptime' => $pstatus->{uptime} );

if ( $counter_fh ) {
    seek $counter_fh, 10, 0;
    sysread $counter_fh, my $counter, 20;
    sysread $counter_fh, my $total_bytes, 20;
    no warnings;
    $counter += 0;
    $total_bytes += 0;
    my $total_kbytes = int($total_bytes / 1_000);
    $body .= sprintf "Total Accesses: %s\n", $counter;
    $body .= sprintf "Total Kbytes: %s\n", $total_kbytes;
    $status{TotalAccesses} = $counter;
    $status{TotalKbytes} = $total_kbytes;
}

if ( $skip_ps_command ) {
    # none
}
elsif ( $^O eq 'cygwin' ) {
    @all_workers = ();
    my $ps = `ps -ef`;
    $ps =~ s/^\s+//mg;
    for my $line ( split /\n/, $ps ) {
        next if $line =~ m/^\D/;
        my @proc = split /\s+/, $line;
        push @all_workers, $proc[1] if $proc[2] == $parent_pid;
    }
}
elsif ( $^O !~ m!mswin32!i ) {
    @all_workers = ();
    my $psopt = $^O =~ m/bsd$/ ? '-ax' : '-e';
    my $ps = `LC_ALL=C command ps $psopt -o ppid,pid`;
    $ps =~ s/^\s+//mg;
    for my $line ( split /\n/, $ps ) {
        next if $line =~ m/^\D/;
        my ($ppid, $pid) = split /\s+/, $line, 2;
        push @all_workers, $pid if $ppid == $parent_pid;
    }
}
else {
    # todo windows?
}

my $idle = 0;
my $busy = 0;
my $process_status = '';
my @process_status;
for my $pid ( @all_workers  ) {
    my $json = $stats->{$pid};
    my $pstatus = eval { 
        $JSON->decode($json || '{}');
    };
    $pstatus ||= {};
    if ( $pstatus->{status} && $pstatus->{status} eq 'A' ) {
        $busy++;
    }
    else {
        $idle++;
    }
    
    if ( defined $pstatus->{time} ) {
        $pstatus->{ss} = time - $pstatus->{time};
    }
    $pstatus->{pid} ||= $pid;
    delete $pstatus->{time};
    delete $pstatus->{ppid};
    delete $pstatus->{uptime};
    $process_status .= sprintf "%s\n", 
        join(" ", map { defined $pstatus->{$_} ? $pstatus->{$_} : '' } qw/pid status remote_addr host method uri protocol ss/);
    push @process_status, $pstatus;
}

$body .= <<EOF;
BusyWorkers: $busy
IdleWorkers: $idle
--
pid status remote_addr host method uri protocol ss
$process_status
EOF
chomp $body;

$status{BusyWorkers} = $busy;
$status{IdleWorkers} = $idle;
$status{stats} = \@process_status;

if ( $json ) {
    print $JSON->encode(\%status);
}
else {
    print $body;
}
exit(0);

__END__

=head1 NAME

server-status - a script to show the status of the local server

=head1 SYNOPSIS

  % server-status --scoreboard server-status --counter server-status/access-counter

  Total Accesses: 123
  BusyWorkers: 2
  IdleWorkers: 3
  --
  pid status remote_addr host method uri protocol ss
  20060 A 127.0.0.1 localhost:10001 GET / HTTP/1.1 1
  20061 .
  20062 A 127.0.0.1 localhost:10001 GET /server-status HTTP/1.1 0
  20063 .
  20064 .

  # JSON format
  % server-status --json --counter ~/server-status/access-counter
  {"BusyWorkers":"2",
   "stats":[
     {"protocol":null,"remote_addr":null,"pid":"78639",
      "status":".","method":null,"uri":null,"host":null,"ss":null},
     {"protocol":"HTTP/1.1","remote_addr":"127.0.0.1","pid":"78640",
      "status":"A","method":"GET","uri":"/","host":"localhost:10226","ss":0},
     ...
  ],"IdleWorkers":"3"}

=head1 DESCRIPTION

This is a simple command-line script that examines the local server status
files to report on the status of a locally-running server, without incurring
any network overhead nor using a worker.

=head1 OPTIONS

=over 4

=item scoreboard

Required - same as the C<scoreboard> option in the middleware.

=item counter_file

Optional - same as the C<counter_file> option in the middleware.



( run in 1.827 second using v1.01-cache-2.11-cpan-437f7b0c052 )