Skip to content

Commit

Permalink
Started work on time-based stats and graphing
Browse files Browse the repository at this point in the history
  • Loading branch information
jcameron committed Sep 1, 2007
1 parent c1d02a4 commit 70c40fc
Show file tree
Hide file tree
Showing 23 changed files with 6,041 additions and 0 deletions.
1 change: 1 addition & 0 deletions IDEAS
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,6 @@
- xoops installer should be more automated

- graphing of stats
- for VM2 as well, for each machine

- add 'mail' attribute with all addresses to LDAP users (optional)
72 changes: 72 additions & 0 deletions collect-lib.pl
Original file line number Diff line number Diff line change
Expand Up @@ -206,5 +206,77 @@ sub refresh_possible_packages
&save_collected_info($info);
}

# add_historic_collected_info(&info, time)
# Add to the collected info log files the current CPU load, memory uses, swap
# use, disk use and other info we might want to graph
sub add_historic_collected_info
{
local ($info, $time) = @_;
if (!-d $historic_info_dir) {
&make_dir($historic_info_dir, 0700);
}
local @stats;
push(@stats, [ "load", $info->{'load'}->[0] ]) if ($info->{'load'});
push(@stats, [ "procs", $info->{'procs'} ]) if ($info->{'procs'});
if ($info->{'mem'}) {
push(@stats, [ "memused",
($info->{'mem'}->[0]-$info->{'mem'}->[1])*1024 ]);
if ($info->{'mem'}->[2]) {
push(@stats, [ "swapused",
($info->{'mem'}->[2]-$info->{'mem'}->[3])*1024 ]);
}
}
if ($info->{'disk_total'}) {
push(@stats, [ "diskused",
$info->{'disk_total'}-$info->{'disk_free'} ]);
}
# XXX more?
# XXX total quota allocated
foreach my $stat (@stats) {
open(HISTORY, ">>$historic_info_dir/$stat->[0]");
print HISTORY $time," ",$stat->[1],"\n";
close(HISTORY);
}
}

# list_historic_collected_info(stat, [start], [end])
# Returns an array of times and values for some stat, within the given
# time period
sub list_historic_collected_info
{
local ($stat, $start, $end) = @_;
local @rv;
open(HISTORY, "$historic_info_dir/$stat");
while(<HISTORY>) {
chop;
local ($time, $value) = split(" ", $_);
if ((!defined($start) || $time >= $start) &&
(!defined($end) || $time <= $end)) {
push(@rv, [ $time, $value ]);
}
if (defined($end) && $time > $end) {
last; # Past the end point
}
}
close(HISTORY);
return @rv;
}

# list_all_historic_collected_info([start], [end])
# Returns a hash mapping stats to data within some time period
sub list_all_historic_collected_info
{
local ($start, $end) = @_;
opendir(HISTDIR, $historic_info_dir);
foreach my $f (readdir(HISTDIR)) {
if ($f =~ /^[a-z]$/) {
local @rv = &list_historic_collected_info($f, $start, $end);
$all{$f} = \@rv;
}
}
closedir(HISTDIR);
return \%all;
}

1;

2 changes: 2 additions & 0 deletions collectinfo.pl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package virtual_server;
$main::no_acl_check++;
require './virtual-server-lib.pl';
$start = time();

# Make sure we are not already running
if (&test_lock($collected_info_file)) {
Expand All @@ -16,5 +17,6 @@ package virtual_server;
$info = &collect_system_info();
if ($info) {
&save_collected_info($info);
&add_historic_collected_info($info, $start);
}
&unlock_file($collected_info_file);
142 changes: 142 additions & 0 deletions history.cgi
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/usr/local/bin/perl
# Show a historic graph of one or more collected stats
# XXX multiple stats on same graph
# XXX scale to mem/disk free
# XXX put empty values to left where we don't have them
# XXX labels on graph
# XXX link from theme
# XXX link from left menu

require './virtual-server-lib.pl';
&can_show_history() || &error($text{'history_ecannot'});
&ReadParse();

@history_periods = (
[ 'year', 365*24*60*60 ],
[ 'month', 31*24*60*60 ],
[ 'week', 7*24*60*60 ],
[ 'day', 24*60*60 ],
[ 'hour', 60*60 ],
);

&ui_print_header(undef, $text{'history_title'}, "", undef, 0, 0, 0, undef,
"<script src=timeplot/timeplot-api.js></script>",
"onload='onLoad();' onresize='onResize();'");

# Work out the stat and time range we want
$stat = $in{'stat'} || "load";
$start = $in{'start'} || time()-60*60;
$period = $in{'period'} || 60*60;
$end = $start + $period;
if ($end > time()) {
# Too far in future .. shift back
$start = time()-$period;
$end = $start+$period;
}

# Generate DIV for the graph and navigation buttons
if ($period > 24*60*60) {
# Show dates only
$startmsg = &make_date($start, 1);
$endmsg = &make_date($end, 1);
}
else {
$startmsg = &make_date($start, 0);
$endmsg = &make_date($end, 0);
}
print "<b>",&text('history_range', $text{'history_stat_'.$stat},
$startmsg, $endmsg),"</b><p>\n";
print "<table cellpadding=0 cellspacing=0 width=100%><tr>\n";

# Move back links. The steps are 1, 2 and 4 times the period
# XXX what if off the end?
print "<td align=left>";
@llinks = ( );
for($i=1; $i<=4; $i*=2) {
$msg = "&lt;&lt;".&text('history_'.&period_to_name($period).'s', $i);
push(@llinks, "<a href='history.cgi?stat=$stat&period=$period&".
"start=".($start-$period*$i)."'>$msg</a>");
}
print &ui_links_row(\@llinks);
print "</td>\n";

# Time period links
@plinks = ( );
print "<td align=middle>";
foreach $p (map { [ $text{'history_'.$_->[0]}, $_->[1] ] } @history_periods) {
if ($period == $p->[1]) {
push(@plinks, "<b>$p->[0]</b>");
}
else {
push(@plinks, "<a href='history.cgi?stat=$stat&start=$start&".
"period=$p->[1]'>$p->[0]</a>");
}
}
print &ui_links_row(\@plinks);
print "</td>\n";

# Move forward links
# XXX what if off the end?
print "<td align=right>";
@rlinks = ( );
for($i=1; $i<=4; $i*=2) {
$msg = &text('history_'.&period_to_name($period).'s', $i)."&gt;&gt;";
push(@rlinks, "<a href='history.cgi?stat=$stat&period=$period&".
"start=".($start+$period*$i)."'>$msg</a>");
}
print &ui_links_row(\@rlinks);
print "</td>\n";

# The graph itself
print "</tr></table>\n";
print "<div id='history' style='height: 300px;'></div>\n";

# Generate
print <<EOF;
<script>
var timeplot;
function onLoad() {
var eventSource = new Timeplot.DefaultEventSource();
var plotInfo = [
Timeplot.createPlotInfo({
id: "plot1",
dataSource: new Timeplot.ColumnSource(eventSource,1),
valueGeometry: new Timeplot.DefaultValueGeometry({
gridColor: "#000000",
axisLabelsPlacement: "left",
}),
timeGeometry: new Timeplot.DefaultTimeGeometry({
gridColor: "#000000",
axisLabelsPlacement: "top"
}),
showValues: true,
})
];
timeplot = Timeplot.create(document.getElementById("history"), plotInfo);
timeplot.loadText("history_data.cgi?stat=$stat&start=$start&end=$end&nice=1", ",", eventSource);
}
var resizeTimerID = null;
function onResize() {
if (resizeTimerID == null) {
resizeTimerID = window.setTimeout(function() {
resizeTimerID = null;
timeplot.repaint();
}, 100);
}
}
</script>
EOF

&ui_print_footer("", $text{'index_return'});

sub period_to_name
{
local ($p) = @_;
foreach my $hp (@history_periods) {
return $hp->[0] if ($p == $hp->[1]);
}
return undef;
}
22 changes: 22 additions & 0 deletions history_data.cgi
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/local/bin/perl
# Output the CSV for some stat over some time

require './virtual-server-lib.pl';
&can_show_history() || &error($text{'history_ecannot'});
&ReadParse();
use POSIX;

@info = &list_historic_collected_info($in{'stat'}, $in{'start'} || undef,
$in{'end'} || undef);
print "Content-type: text/plain\n\n";
foreach $i (@info) {
$v = $i->[1];
if ($in{'nice'}) {
$v = $in{'stat'} eq 'memused' ||
$in{'stat'} eq 'swapused' ? $v/(1024*1024) :
$in{'stat'} eq 'diskused' ? $v/(1024*1024*1024) :
$v;
$v = int($v);
}
print strftime("%Y-%m-%d %H:%M:%S", localtime($i->[0])),",",$v,"\n";
}
19 changes: 19 additions & 0 deletions lang/en
Original file line number Diff line number Diff line change
Expand Up @@ -3668,3 +3668,22 @@ scriptwarn_dom=Domain name
scriptwarn_where=Upgrades can be done in Virtualmin, on each domains Install Scripts page.
scriptwarn_where2=Upgrades can be done in Virtualmin, on the page :\n$1
scriptwarn_subject=Virtualmin script upgrades available

history_title=System Statistics
history_ecannot=You are not allowed to view historic system statistics
history_year=1 year
history_years=$1 years
history_month=1 month
history_months=$1 months
history_week=1 week
history_weeks=$1 weeks
history_day=1 day
history_days=$1 days
history_hour=1 hour
history_hours=$1 hours
history_stat_load=CPU load
history_stat_procs=Running processes
history_stat_memused=Memory used (MB)
history_stat_swapused=Swap space used (MB)
history_stat_diskused=Disk space used (GB)
history_range=$1 from $2 to $3
Binary file added timeplot/images/copyright.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added timeplot/images/line_left.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added timeplot/images/line_right.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 70c40fc

Please sign in to comment.