Human readable user beancounters

From OpenVZ Virtuozzo Containers Wiki
Revision as of 15:52, 6 May 2011 by Drodriguez (talk | contribs)
Jump to: navigation, search
User Beancounters
Definition
/proc/user_beancounters
/proc/bc/
General information
Units of measurement
VSwap
Parameters description
Primary parameters
numproc, numtcpsock, numothersock, vmguarpages
Secondary parameters
kmemsize, tcpsndbuf, tcprcvbuf, othersockbuf, dgramrcvbuf, oomguarpages, privvmpages
Auxiliary parameters
lockedpages, shmpages, physpages, numfile, numflock, numpty, numsiginfo, dcachesize, numiptent, swappages
Internals
User pages accounting
RSS fractions accounting
On-demand accounting
UBC consistency
Consistency formulae
System-wide configuration
vzubc(8)
Configuration examples
Basic
Derived
Intermediate configurations
Tables
List of parameters
Parameter properties
Consistency
Config examples

For newbies to openvz it is fairly difficult to understand the meaning of the numbers in /proc/user_beancounters file. Calculating the values to something understandable for human brain everytime you look at these statistics is much work. I have written a perl script which reformats the output to human-readable values in kbyte and mbyte.

Just be sure you have Perl installed on your HN/VE, copy this script to somewhere on your machine, give it executable rights and start it. The output will be like this:

BEANS FOR UID 254
resource                     held              maxheld              barrier                limit              failcnt
kmemsize                 15.14 mb             18.72 mb            150.30 mb            167.00 mb                    0
lockedpages                     0                    0             16.00 mb             16.00 mb                    0
privvmpages             433.79 mb            544.63 mb           2929.69 mb           3222.66 mb                    0
shmpages                 11.58 mb             11.64 mb            512.00 mb            512.00 mb                    0
numproc                        84                  101                  500                  500                    0
physpages               278.24 mb            395.75 mb                    0            unlimited                    0
vmguarpages                     0                    0            244.14 mb            unlimited                    0
oomguarpages            279.66 mb            396.98 mb            122.07 mb            unlimited                    0
numtcpsock                     25                   53                  500                  500                    0
numflock                       18                   22                  200                  220                    0
numpty                          4                    4                   64                   64                    0
numsiginfo                      0                   11                  512                  512                    0
tcpsndbuf               569.75 kb            679.25 kb              5.12 mb             10.00 mb                    0
tcprcvbuf               400.00 kb              1.28 mb              5.12 mb             10.00 mb                    0
othersockbuf            213.00 kb            284.25 kb              1.43 mb              3.88 mb                    0
dgramrcvbuf               0.00 kb              8.25 kb            256.00 kb            256.00 kb                    0
numothersock                  155                  175                  500                  500                    0
dcachesize              619.68 kb            656.68 kb              4.00 mb              4.12 mb                    0
numfile                      2008                 2397                 9312                 9312                    0
numiptent                      10                   10                  128                  128                    0

The script is the following, just copy and paste:

#!/usr/bin/perl

###############################################################################
# vzstats.pl
#
# this script reads /proc/user_beancounters on openvz HNs and VEs and displays
# the values in human-readable format (megabytes/kilobytes).
#
# The script can be distributed freely for everybody who finds it usable.
#
# Christian Anton <mail |_at_| christiananton.de> 2008-09-18



open(BEANS,"/proc/user_beancounters");
chomp ($arch = `uname -m`);

sub check_maxulong {
	my $number = shift;

	if ($arch eq "x86_64") {
		if ($number == 9223372036854775807) {
			return 1;
		} else {
			return undef;
		}
	} else {
		if ($number == 2147483647) {
			return 1;
		} else {
			return undef;
		}
	}
}

sub recalc_bytes {
	my $bytes = shift;

	if (defined(&check_maxulong($bytes))) { return "unlimited"; }

	my $kbytes = $bytes / 1024;
	my $ret;
	
	# if over 1mb, show mb values
	if ($kbytes > 1024) {
		my $mbytes = $kbytes / 1024;
		$ret = sprintf("%.2f", $mbytes) . " mb";
		return $ret;
	} else {
		$ret = sprintf("%.2f", $kbytes) . " kb";
		return $ret;
	}
}

sub recalc_pages {
	my $pages = shift;

	if ($pages == 0) { return "0"; }
	if (defined(&check_maxulong($pages))) { return "unlimited"; }

	my $kbytes = $pages * 4;
	my $ret;

	if ($kbytes > 1024) {
		my $mbytes = $kbytes / 1024;
		$ret = sprintf("%.2f", $mbytes) . " mb";
		return $ret;
	} else {
		$ret = sprintf("%.2f", $kbytes) . " kb";
		return $ret;
	}
}

sub recalc_nothing {
	my $number = shift;
	if (defined(&check_maxulong($number))) { return "unlimited"; }

	return $number;
}

sub printline {
	my $mode = shift; # 0=normal, 1=bytes, 2=pages
	my $ident = shift;
	my $held = shift;
	my $maxheld = shift;
	my $barrier = shift;
	my $limit = shift;
	my $failcnt = shift;

	if ($mode == 0) {
		printf ("%-15s",$ident);
		printf ("%18s",&recalc_nothing($held));
		printf ("%21s",&recalc_nothing($maxheld));
		printf ("%21s",&recalc_nothing($barrier));
		printf ("%21s",&recalc_nothing($limit));
		printf ("%21s",$failcnt);
		print "\n";
	} elsif ($mode == 1) {
		printf ("%-15s",$ident);
		printf ("%18s",&recalc_bytes($held));
		printf ("%21s",&recalc_bytes($maxheld));
		printf ("%21s",&recalc_bytes($barrier));
		printf ("%21s",&recalc_bytes($limit));
		printf ("%21s",$failcnt);
		print "\n";
	} elsif ($mode == 2) {
		printf ("%-15s",$ident);
		printf ("%18s",&recalc_pages($held));
		printf ("%21s",&recalc_pages($maxheld));
		printf ("%21s",&recalc_pages($barrier));
		printf ("%21s",&recalc_pages($limit));
		printf ("%21s",$failcnt);
		print "\n";
	}
}

sub work_line {
	my $line = shift;
	my $ident = $line;
	my $held = $line;
	my $maxheld = $line;
	my $barrier = $line;
	my $limit = $line;
	my $failcnt = $line;



	$ident =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$1/;
	$held =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$2/;
	$maxheld =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$3/;
	$barrier =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$4/;
	$limit =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$5/;
	$failcnt =~ s/^\s+(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/$6/;

	# 0=normal, 1=bytes, 2=pages
	if ($ident eq "dummy") {
		# do nothing, skip this line
	} elsif ($ident =~ /pages/) {
		&printline(2,$ident,$held,$maxheld,$barrier,$limit,$failcnt);
	} elsif ($ident =~ /^num/) {
		&printline(0,$ident,$held,$maxheld,$barrier,$limit,$failcnt);
	} else {
		&printline(1,$ident,$held,$maxheld,$barrier,$limit,$failcnt);
	}

}

sub print_header {
	my $uid = shift;

	print "#####################################################################################################################\n";
	print "BEANS FOR UID $uid\n";
	print "resource                     held              maxheld              barrier                limit              failcnt\n";
}

# now eat your beans baby
while (<BEANS>) {
	chomp($line = $_);

	# skip processing of headline
	if ($line =~ /^\s+uid/) {
		# do nothing, skip this
	} elsif ($line =~ /^Ver/) {
		# do nothing, skip this
	} elsif ($line =~ /^\s+\d+:\s+kmem/) {
		$uid = $line;
		$line =~ s/^(\s+)(\d+):/$1/;
		$uid =~ s/^(\s+)(\d+):.*$/$2/;
		&print_header($uid);
		&work_line($line);
	} else {
		&work_line($line);
	}
}

close(BEANS);

Here's a quick patch which adds on VE hostname lookups. It depends on vzlist being in the path but won't break if it isn't.

*** beanCounters.pl-orig        Sun Nov  9 14:08:56 2008
--- beanCounters.pl     Sun Nov  9 14:08:21 2008
***************
*** 9,14 ****
--- 9,17 ----
  # The script can be distributed freely for everybody who finds it usable.
  #
  # Christian Anton <mail |_at_| christiananton.de> 2008-09-18
+ #
+ # David Osborn <ossdev -at- daoCon.com> 2008-11-09
+ #     Added VE name to output
   
   
   
***************
*** 147,158 ****
   
  sub print_header {
        my $uid = shift;
   
        print "#####################################################################################################################\n";
!       print "BEANS FOR UID $uid\n";
        print "resource                     held              maxheld              barrier               limit              failcnt\n";
  }
   
  # now eat your beans baby
  while (<BEANS>) {
        chomp($line = $_);
--- 150,193 ----
   
  sub print_header {
        my $uid = shift;
+       my $hostname = shift;
   
        print "#####################################################################################################################\n";
!       print "BEANS FOR UID $uid ($hostname)\n";
        print "resource                     held              maxheld              barrier                limit              failcnt\n";
  }
   
+ sub get_hostname {
+       my $uid = shift;
+       my @vzout;
+ 
+       # already retrieved list
+       if (defined %hostnames) {
+               if (defined $hostnames{$uid}) {
+                       return $hostnames{$uid};
+               } else {
+                       return 'not found';
+               }
+       # try to retrieve the list
+       } elsif ( eval(@vzout = `vzlist -H -o veid,hostname`) ) {
+               $hostnames{0} = 'HN';
+               while (@vzout) { 
+                       my $line = shift @vzout;
+                       my ($tuid,$hostname) = $line =~ /^\s+(\d+)\s+(\S+)/;
+                       $hostnames{$tuid} = $hostname;
+               }
+               return $hostnames{$uid};
+       } else {
+               # something's wrong
+               return 'unknown';
+       }
+ 
+ }
+ 
+ 
+ # Hash used to store uid to hostname lookups
+ my %hostnames;
+ 
  # now eat your beans baby
  while (<BEANS>) {
        chomp($line = $_);
***************
*** 166,172 ****
                $uid = $line;
                $line =~ s/^(\s+)(\d+):/$1/;
                $uid =~ s/^(\s+)(\d+):.*$/$2/;
!               &print_header($uid);
                &work_line($line);
        } else {
                &work_line($line);
--- 201,207 ----
                $uid = $line;
                $line =~ s/^(\s+)(\d+):/$1/;
                $uid =~ s/^(\s+)(\d+):.*$/$2/;
!               &print_header($uid, get_hostname($uid));
                &work_line($line);
        } else {
                &work_line($line);

Quick (and dirty) patch to only display the information of one container (first argument of the script). Usage:

$ beancounters.pl VEID
--- beancounters.pl	2011-05-06 01:06:58.000000000 -0300
+++ beancounters-container.pl	2011-05-06 12:43:09.000000000 -0300
@@ -11,8 +11,7 @@
 # Christian Anton <mail |_at_| christiananton.de> 2008-09-18
  
  
- 
-open(BEANS,"/proc/user_beancounters");
+open(BEANS,"cat /proc/user_beancounters | grep \" ${ARGV[0]}:\" -A 23  |");
 chomp ($arch = `uname -m`);
  
 sub check_maxulong {