Apache-VMonitor
view release on metacpan or search on metacpan
lib/Apache/VMonitor.pm view on Meta::CPAN
}
### procs ###
sub data_procs {
my $self = shift;
unless ($Apache::VMonitor::PROC_REGEX) {
warn "Don't know what processes to display..." .
'int: set $Apache::VMonitor::PROC_REGEX' .
'e.g. \$Apache::VMonitor::PROC_REGEX = join "\|", qw(httpd mysql);';
return {};
}
my $gtop = $self->{gtop};
unless ($gtop) {
warn "GTop not installed, not displaying process data";
return {};
}
my($proclist, $entries) = $gtop->proclist;
my %procs = ();
for my $pid ( @$entries ) {
my $cmd = $gtop->proc_state($pid)->cmd;
push @{ $procs{$cmd} }, $pid
if $cmd =~ /$Apache::VMonitor::PROC_REGEX/o;
}
# finding out various max lenthgs for a proper column formatting
# set the minimum width here
my %max_len = (
pid => 3,
cmd => 3,
tty => 3,
uid => 3,
);
my @recs = ();
my $cat_id = 0;
for my $cat (sort keys %procs) {
my $cnt = 0;
$cat_id++;
for my $pid ( @{ $procs{$cat} } ) {
$cnt++;
my $state = $gtop->proc_state($pid);
my $uid = $gtop->proc_uid($pid);
my $mem = $gtop->proc_mem($pid);
my $tty = $uid->tty;
$tty = ' ' if $tty == -1;
push @recs, {
cat_id => $cat_id,
count => $cnt,
pid => $pid,
pid_link => fixup_url($self->{url}, pid => $pid),
uid => scalar(getpwuid($state->uid)),
fsize => size_string($mem->size($pid)),
fshare => size_string($mem->share($pid)),
fvsize => size_string($mem->vsize($pid)),
frss => size_string($mem->rss($pid)),
tty => $tty,
state => $state->state,
cmd => $state->cmd,
};
my $len = length $pid;
$max_len{pid} = $len if $len > $max_len{pid};
$len = length $state->cmd;
$max_len{cmd} = $len if $len > $max_len{cmd};
$len = length $uid->tty;
$max_len{tty} = $len if $len > $max_len{tty};
$len = length scalar getpwuid $state->uid;
$max_len{uid} = $len if $len > $max_len{uid};
}
}
return {
max_len => \%max_len,
records => \@recs,
};
}
sub tmpl_procs {
return \ <<'EOT';
<hr>
<pre>
[%-
USE format_procs =
format("%4s %${max_len.pid}s %-${max_len.uid}s %5s %5s %5s %5s %${max_len.tty}s %-2s %-${max_len.cmd}s");
"<b>";
format_procs('##', "PID", "UID", "Size", "Share", "VSize", "Rss", "TTY", "St", "Command");
"</b>\n";
space = " ";
FOR rec = records;
times = max_len.pid - rec.pid.length;
spacing = times > 0 ? space.repeat(times) : "";
pid_link = "$spacing<a href=\"${rec.pid_link}\">${rec.pid}</a>";
item_class = rec.cat_id % 2 ? "item_odd" : "item_even";
"<span class=\"$item_class\">";
format_procs(rec.count, pid_link, rec.uid, rec.fsize, rec.fshare, rec.fvsize, rec.frss, rec.tty, rec.state, rec.cmd);
"</span>\n";
END;
-%]
</pre>
EOT
}
### apache_single ###
sub data_apache_single {
my $self = shift;
# XXX:
# worker == 0, no worker data to display
# consider showing workers under control of this pid
if (MP2 && $Apache::Scoreboard::VERSION < 2.0) {
die "Apache::Scoreboard 2.0 or higher is wanted, " .
"this is only version $Apache::Scoreboard::VERSION";
}
my $pid = $self->{pid};
my $data;
### proc command name/args
my($proclist, $entries) = $gtop->proclist;
lib/Apache/VMonitor.pm view on Meta::CPAN
}
$data->{mem} = {
size => $mem->{size},
share => $mem->{share},
vsize => $mem->{vsize},
rss => $mem->{rss},
fsize => size_string($mem->{size}),
fshare => size_string($mem->{share}),
fvsize => size_string($mem->{vsize}),
frss => size_string($mem->{rss}),
};
if (my $parent_score = $self->pid2parent_score($pid)) {
my $worker_score;
if ($self->{tid}) {
warn "tid: $self->{tid}\n";
my $image = $self->scoreboard_image();
my $parent_idx = $image->parent_idx_by_pid($pid);
$worker_score = $image->worker_score($parent_idx, $self->{tid});
}
else {
$worker_score = MP2 ? $parent_score->worker_score : $parent_score;
}
my $rec = $self->score2record($worker_score);
my $lastreq = $rec->{lastreq} ? $rec->{lastreq}/1000 : 0;
$data->{rec} = {
is_httpd_proc => 1,
proc_type => ($pid == getppid ? "Parent" : "Child"),
mode_long => $Apache::VMonitor::longflags{$rec->{mode}},
elapsed => $rec->{elapsed},
felapsed => format_time($rec->{elapsed}),
lastreq => $lastreq,
flastreq => format_time($lastreq),
fserved => format_counts($rec->{served}),
client => $rec->{client},
vhost => $rec->{vhost},
request => $rec->{request},
access_count => $worker_score->access_count,
my_access_count => $worker_score->my_access_count,
bytes_served => $worker_score->bytes_served,
fbytes_served => size_string($worker_score->bytes_served),
my_bytes_served => $worker_score->my_bytes_served,
fmy_bytes_served => size_string($worker_score->my_bytes_served),
};
my @cpu_cols = qw(total utime stime cutime cstime);
my @cpu_times = $worker_score->times();
my $cpu_total = eval join "+", @cpu_times;
for ($cpu_total, @cpu_times) {
my $key = "cpu_" . shift @cpu_cols;
$data->{rec}->{$key} = $_/100;
}
}
### generic process info
my $proc_info;
# UID and STATE
my $state = $gtop->proc_state($pid);
$proc_info->{uid} = scalar getpwuid $state->uid;
$proc_info->{gid} = scalar getgrgid $state->gid;
$proc_info->{state} = $state->state;
# TTY
my $proc_uid = $gtop->proc_uid($pid);
my $tty = $proc_uid->tty;
$tty = 'None' if $tty == -1;
$proc_info->{tty} = $tty;
# ARGV
$proc_info->{argv} = join " ", @{($gtop->proc_args($pid))[1]};
$data->{proc} = $proc_info;
### memory segments usage
my $proc_segment = $gtop->proc_segment($pid);
no strict 'refs';
for (qw(text_rss shlib_rss data_rss stack_rss)) {
my $size = $proc_segment->$_($pid);
$data->{mem_segm}->{$_} = $size;
$data->{mem_segm}->{"f$_"} = size_string($size);
}
### memory maps
my($procmap, $maps) = $gtop->proc_map($pid);
my $number = $procmap->number;
my %libpaths = ();
my @maps = ();
for (my $i = 0; $i < $number; $i++) {
my $filename = $maps->filename($i) || "-";
$libpaths{$filename}++;
my $device = $maps->device($i);
push @maps, {
start => $maps->start($i),
end => $maps->end($i),
offset => $maps->offset($i),
device_major => (($device >> 8) & 255),
device_minor => ($device & 255),
inode => $maps->inode($i),
perm => $maps->perm_string($i),
filename => $filename,
};
}
$data->{mem_maps} = {
records => \@maps,
ptr_size => (length(pack("p", 0)) == 8 ? 16 : 8),
};
### loaded shared libs sizes
my %libsizes = map { $_ => -s $_ }
grep { -e $_} grep !/^-$/, keys %libpaths;
my @lib_sizes = ();
my $total = 0;
for (sort { $libsizes{$b} <=> $libsizes{$a} } keys %libsizes) {
$total += $libsizes{$_};
push @lib_sizes, {
size => $libsizes{$_},
fsize => size_string($libsizes{$_}),
filename => $_,
( run in 1.346 second using v1.01-cache-2.11-cpan-d06a3f9ecfd )