Apache-VMonitor
view release on metacpan or search on metacpan
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 => $_,
};
}
$data->{libs} = {
records => \@lib_sizes,
total => $total,
ftotal => size_string($total),
};
return $data;
}
# given the pid return the corresponding parent score object or undef
# if it's not an httpd proc.
sub pid2parent_score {
my($self, $pid) = @_;
my $image = $self->scoreboard_image();
if (MP2) {
my $parent_idx = $image->parent_idx_by_pid($pid);
return $parent_idx == -1 ? undef : $image->parent_score($parent_idx);
}
else {
# XXX: mp1 untested
my $i;
my $is_httpd_child = 0;
for ($i = 0; $i < $Apache::Constants::HARD_SERVER_LIMIT; $i++) {
$is_httpd_child = 1, last if $pid == $image->parent($i)->pid;
}
$i = -1 if $pid == getppid();
if ($is_httpd_child || $i == -1) {
return $image->servers($i);
}
}
}
sub tmpl_apache_single {
#return \'';
return \ <<'EOT';
<hr>
[%-
"[ <a href=\"$link_back\">Back to multiproc mode</a> ]";
IF proc_is_dead;
"Sorry, the process $pid ($cmd) doesn't exist anymore!";
ELSE;
"<h3 align='middle'>Extensive Status for PID $pid ($cmd) </h3>";
PROCESS single_process;
END;
-%]
[% BLOCK single_process %]
<pre>
[%-
PROCESS single_httpd_process IF rec.is_httpd_proc;
"<hr><b>General process info:</b>\n";
USE format_proc_item = format(" <b>%-25s</b> : %s\n");
format_proc_item("UID", proc.uid);
format_proc_item("GID", proc.gid);
format_proc_item("State", proc.state);
format_proc_item("TTY", proc.tty);
format_proc_item("Command line arguments", proc.argv);
# memory usage
"\n<hr><b>Memory Usage</b> (in bytes):\n\n";
USE format_mem_item = format(" %-10.10s : %10d (%s)\n");
format_mem_item("Size", mem.size, mem.fsize);
format_mem_item("Share", mem.share, mem.fshare);
format_mem_item("VSize", mem.vsize, mem.fvsize);
format_mem_item("RSS", mem.rss, mem.frss);
# memory segments usage
"\n<HR><B>Memory Segments Usage</B> (in bytes):\n\n";
USE format_mem_segment_item = format(" %-10.10s : %10d (%s)\n");
format_mem_segment_item("Text", mem_segm.text_rss, mem_segm.ftext_rss);
format_mem_segment_item("Shlib", mem_segm.shlib_rss, mem_segm.fshlib_rss);
format_mem_segment_item("Data", mem_segm.data_rss, mem_segm.fdata_rss);
format_mem_segment_item("Stack", mem_segm.stack_rss, mem_segm.fstack_rss);
# memory maps
"<hr><b>Memory Maps:</b>\n\n";
ptr_size = mem_maps.ptr_size;
USE format_map_header = format(" <b>%${ptr_size}s-%-${ptr_size}s %${ptr_size}s %3s:%3s %7s - %4s - %s</b>\n");
format_map_header("start", "end", "offset", "maj", "min", "inode", "perm", "filename");
USE format_map_item =
format(" %0${ptr_size}lx-%0${ptr_size}lx %0${ptr_size}lx - %02x:%02x %08lu - %4s - %s\n");
FOR rec = mem_maps.records.sort('filename');
format_map_item(rec.start, rec.end, rec.offset, rec.device_major, rec.device_minor, rec.inode, rec.perm, rec.filename);
END;
# loaded shared libs sizes
"<hr><b>Loaded Libs Sizes:</b> (in bytes)\n\n";
USE format_shared_lib = format("%10d (%s): %s\n");
FOR rec = libs.records.sort('filename');
format_shared_lib(rec.size, rec.fsize, rec.filename);
END;
USE format_shared_lib_total = format("\n<b>%10d (%s): %s</b>\n");
format_shared_lib_total(libs.total, libs.ftotal, "Total");
-%]
</pre>
[% END %]
[% BLOCK single_httpd_process %]
[%-
USE HTML;
"<hr><b>httpd-specific Info:</b>\n\n";
USE format_item = format(" <b>%-25s</b> : %s\n");
format_item("Process type", rec.proc_type);
format_item("Status", rec.mode_long);
IF rec.elapsed;
elapsed_class = rec.elapsed > 15 ? "alert" : "normal";
rec.felapsed = "<span class=\"$elapsed_class\"><b>${rec.felapsed}</b></span>";
format_item("Cur. req. is running for", rec.felapsed);
ELSE;
( run in 1.054 second using v1.01-cache-2.11-cpan-ceb78f64989 )