Net-Prometheus-ServerStatusLiteCollector
view release on metacpan or search on metacpan
lib/Net/Prometheus/ServerStatusLiteCollector.pm view on Meta::CPAN
}
if (! scalar %$stats) {
$self->warn("There is no status file in scoreboard directory. Maybe all processes are idle state and do not serve any request yet.");
return ();
}
# Check counter file
my $counter_fh;
if ($self->counter_file) {
unless (open($counter_fh, '<:unix', $self->counter_file)) {
$self->error("Could not open counter file: $!");
return ();
}
}
# Check scoreboard stats is valid
my @all_workers = keys %$stats;
my $pstatus = eval {
$JSON->decode($stats->{$all_workers[0]} || '{}');
};
if (!$pstatus->{ppid} || !$pstatus->{uptime} || !$pstatus->{ppid}) {
$self->error("Status file does not have some necessary variables");
return ();
}
my $parent_pid = $pstatus->{ppid};
# Begin compiling stats
my @samples = ();
push @samples,
MetricSamples('plack_uptime', gauge => 'Uptime of Plack server',
[Sample('plack_uptime', $self->labels, (time - $pstatus->{uptime}))]);
# Compile request counter stats
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);
push @samples,
MetricSamples('plack_number_served_requests', gauge => 'Number of requests served by Plack process',
[Sample('plack_number_served_requests', $self->labels, $counter)]);
push @samples,
MetricSamples('plack_total_kbytes_served', gauge => 'Total Kilobytes served by Plack process',
[Sample('plack_total_kbytes_served', $self->labels, $total_kbytes)]);
}
# Obtain all worker process IDs
@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;
}
# Count busy and idle workers
my $idle = 0;
my $busy = 0;
my @process_status;
for my $pid (@all_workers) {
my $json = $stats->{$pid};
$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};
push @process_status, $pstatus;
}
push @samples,
MetricSamples('plack_busy_workers', gauge => 'Number of busy Plack workers',
[Sample('plack_busy_workers', $self->labels, $busy)]);
push @samples,
MetricSamples('plack_idle_workers', gauge => 'Number of idle Plack workers',
[Sample('plack_idle_workers', $self->labels, $idle)]);
$stats = {};
foreach my $pstatus (@process_status) {
foreach my $stat (qw(method uri remote_addr protocol)) {
$stats->{$stat}{$pstatus->{$stat}}++ if $pstatus->{$stat};
}
}
foreach my $stat (qw(method uri remote_addr protocol)) {
my $stat_counts = $stats->{$stat};
push @samples,
MetricSamples("plack_sample_$stat", gauge => "Count of $stat for sample of requests",
[
map {
Sample(
"plack_sample_$stat",
[@{$self->labels}, $stat => $_],
$stat_counts->{$_}
)
}
(keys %$stat_counts)
]
);
}
return @samples;
}
1;
__END__
=encoding utf-8
=head1 SYNOPSIS
use Net::Prometheus::ServerStatusLiteCollector;
=head1 DESCRIPTION
Net::Prometheus::ServerStatusLiteCollector is ...
=head1 AUTHOR
Steven Leung E<lt>stvleung@gmail.comE<gt>
=cut
( run in 0.775 second using v1.01-cache-2.11-cpan-39bf76dae61 )