root / plugins / virtualization / xen-multi @ e5ce7492
Historique | Voir | Annoter | Télécharger (7,67 ko)
| 1 | 20afb679 | Rapha?l HALIMI | #! /usr/bin/perl |
|---|---|---|---|
| 2 | |||
| 3 | # -*- perl -*- |
||
| 4 | |||
| 5 | =head1 NAME |
||
| 6 | |||
| 7 | xen_multi - Munin multigraph plugin to monitor Xen domains activity |
||
| 8 | |||
| 9 | =head1 APPLICABLE SYSTEMS |
||
| 10 | |||
| 11 | This plugin should work on any system running a Xen hypervisor and where xentop |
||
| 12 | is installed. It also needs Munin 1.4.0 or higher, since it uses AREASTACK |
||
| 13 | (available from 1.3.3) and multigraph (available from 1.4.0). |
||
| 14 | |||
| 15 | =head1 CONFIGURATION |
||
| 16 | |||
| 17 | xentop requires superuser privileges, so you need to include in your |
||
| 18 | configuration: |
||
| 19 | |||
| 20 | 4a525a31 | Niall Donegan | [xen-multi] |
| 21 | 20afb679 | Rapha?l HALIMI | user root |
| 22 | |||
| 23 | Then restart munin-node and you're done. |
||
| 24 | |||
| 25 | =head1 INTERPRETATION |
||
| 26 | |||
| 27 | This plugin produces four different graphs: CPU usage, memory usage, disk IOs |
||
| 28 | and network traffic. |
||
| 29 | |||
| 30 | In each graph, all Xen domains (including dom0) have their data stacked, giving |
||
| 31 | an overall amount of ressources used. |
||
| 32 | |||
| 33 | NOTE: xentop always reports 0 for dom0's disk IOs and network traffic, but |
||
| 34 | both graphs show its entry all the same, so each domain can keep its own color |
||
| 35 | along the different graphs. |
||
| 36 | |||
| 37 | =head2 CPU usage |
||
| 38 | |||
| 39 | This graph shows a percentage of the CPU time used by each domain. |
||
| 40 | |||
| 41 | =head2 Memory usage |
||
| 42 | |||
| 43 | This graph shows the amount of memory (in bytes) used by each domain. |
||
| 44 | |||
| 45 | =head2 Disk IOs |
||
| 46 | |||
| 47 | This graph shows the number of disk read and write operations for each domain. |
||
| 48 | |||
| 49 | =head2 Network traffic |
||
| 50 | |||
| 51 | This graph shows the amount of bits received and transmitted for each domain. |
||
| 52 | |||
| 53 | =head1 ACKNOWLEDGEMENTS |
||
| 54 | |||
| 55 | Michael Renner for the C<diskstats> plugin which I borrowed some code from. |
||
| 56 | |||
| 57 | =head1 VERSION |
||
| 58 | |||
| 59 | 0.90 |
||
| 60 | |||
| 61 | =head1 MAGIC MARKERS |
||
| 62 | |||
| 63 | #%# family=auto |
||
| 64 | #%# capabilities=autoconf |
||
| 65 | |||
| 66 | =head1 AUTHOR |
||
| 67 | |||
| 68 | Raphael HALIMI <raphael.halimi@gmail.com> |
||
| 69 | |||
| 70 | =head1 LICENSE |
||
| 71 | |||
| 72 | GPLv2 |
||
| 73 | |||
| 74 | =cut |
||
| 75 | |||
| 76 | use strict; |
||
| 77 | 1e301c2d | Alex Tomlins | use Munin::Plugin; |
| 78 | 20afb679 | Rapha?l HALIMI | |
| 79 | # autoconf - quite simple |
||
| 80 | if ($ARGV[0] eq "autoconf") {
|
||
| 81 | if (`which xentop`) {
|
||
| 82 | print "yes\n"; |
||
| 83 | } else {
|
||
| 84 | print "no (xentop not found)\n"; |
||
| 85 | } |
||
| 86 | exit 0; |
||
| 87 | } |
||
| 88 | |||
| 89 | |||
| 90 | # |
||
| 91 | # Common steps for both "config" and a normal run |
||
| 92 | # |
||
| 93 | |||
| 94 | # |
||
| 95 | # trim_label |
||
| 96 | # |
||
| 97 | # Trims a given label to it's non-wrapping size |
||
| 98 | # $type = 'pos' for normal graphs and 'neg' for mirror graphs |
||
| 99 | # pos: nnn.nnU_ times 4 |
||
| 100 | # neg: nnn.nnU/nnn.nnU_ times 4 |
||
| 101 | |||
| 102 | sub trim_label {
|
||
| 103 | my ($type, $label) = @_; my $data_characters; |
||
| 104 | my ($graph_width, $graph_border_width, $padding_characters, $pixels_per_character) = (400,97,10,6); |
||
| 105 | if ($type eq 'pos') {$data_characters = 32;} elsif ($type eq 'neg') {$data_characters = 64;} else {return $label;}
|
||
| 106 | |||
| 107 | my $available_characters = abs(($graph_width+$graph_border_width)/$pixels_per_character)-$padding_characters-$data_characters; |
||
| 108 | |||
| 109 | # If the label is longer than the available space, we write as many |
||
| 110 | # characters as we can on both left and right, and two dots in the middle |
||
| 111 | if ( $available_characters < length $label ) {
|
||
| 112 | my $center = ($available_characters-2)/2; |
||
| 113 | $label = substr($label,0,($center)) . '..' . substr($label,-$center); |
||
| 114 | } |
||
| 115 | |||
| 116 | return $label; |
||
| 117 | } |
||
| 118 | |||
| 119 | # Global variables |
||
| 120 | 1e301c2d | Alex Tomlins | my (%domains,$domain,$munindomain,$cpusecs,$memk,$nettxk,$netrxk,$vbdrd,$vbdwr); |
| 121 | 20afb679 | Rapha?l HALIMI | |
| 122 | 1e301c2d | Alex Tomlins | open (XENTOP,"xentop -b -f -i1 |") or die "Could not execute xentop, $!"; |
| 123 | 20afb679 | Rapha?l HALIMI | |
| 124 | # Now we build a hash of hashes to store information |
||
| 125 | 1e301c2d | Alex Tomlins | while (<XENTOP>) {
|
| 126 | 20afb679 | Rapha?l HALIMI | # Some cleaning first |
| 127 | s/^\s+//; chomp; |
||
| 128 | 1e301c2d | Alex Tomlins | # Skip the headers |
| 129 | next if /^NAME/; |
||
| 130 | |||
| 131 | # We define only what we need |
||
| 132 | ($domain,undef,$cpusecs,undef,$memk,undef,undef,undef,undef,undef,$nettxk,$netrxk,undef,undef,$vbdrd,$vbdwr,undef,undef,undef) = split(/\s+/); |
||
| 133 | |||
| 134 | # We have to store the sanitised domain name in a separate variable |
||
| 135 | $domains{$domain}{'munindomain'} = clean_fieldname($domain);
|
||
| 136 | |||
| 137 | # We need the remaining data only for a normal run |
||
| 138 | if ($ARGV[0] eq "") {
|
||
| 139 | $domains{$domain}{'cpusecs'} = $cpusecs;
|
||
| 140 | $domains{$domain}{'mem'} = $memk;
|
||
| 141 | $domains{$domain}{'nettx'} = $nettxk;
|
||
| 142 | $domains{$domain}{'netrx'} = $netrxk;
|
||
| 143 | $domains{$domain}{'vbdrd'} = $vbdrd;
|
||
| 144 | $domains{$domain}{'vbdwr'} = $vbdwr;
|
||
| 145 | 20afb679 | Rapha?l HALIMI | } |
| 146 | } |
||
| 147 | |||
| 148 | |||
| 149 | # |
||
| 150 | # config - quite simple, too |
||
| 151 | # |
||
| 152 | |||
| 153 | if ($ARGV[0] eq "config") {
|
||
| 154 | 1e301c2d | Alex Tomlins | print "multigraph xen_cpu_time\n"; |
| 155 | print "graph_title Xen domains CPU time\n"; |
||
| 156 | print "graph_args --base 1000 -l 0\n"; |
||
| 157 | 20afb679 | Rapha?l HALIMI | print "graph_vlabel %\n"; |
| 158 | print "graph_scale no\n"; |
||
| 159 | print "graph_category xen\n"; |
||
| 160 | 1e301c2d | Alex Tomlins | print "graph_info This graph shows CPU time for each Xen domain.\n"; |
| 161 | 20afb679 | Rapha?l HALIMI | for $domain (sort(keys(%domains))) {
|
| 162 | 1e301c2d | Alex Tomlins | print "$domains{$domain}{'munindomain'}_cpu_time.label ".trim_label('pos',$domain)."\n";
|
| 163 | print "$domains{$domain}{'munindomain'}_cpu_time.type COUNTER\n";
|
||
| 164 | print "$domains{$domain}{'munindomain'}_cpu_time.cdef $domains{$domain}{'munindomain'}_cpu_time,100,*\n";
|
||
| 165 | print "$domains{$domain}{'munindomain'}_cpu_time.draw AREASTACK\n";
|
||
| 166 | 20afb679 | Rapha?l HALIMI | } |
| 167 | |||
| 168 | print "\nmultigraph xen_mem\n"; |
||
| 169 | print "graph_title Xen domains memory usage\n"; |
||
| 170 | print "graph_args --base 1024 -l 0\n"; |
||
| 171 | print "graph_vlabel bytes\n"; |
||
| 172 | print "graph_category xen\n"; |
||
| 173 | print "graph_info This graph shows memory usage for each Xen domain.\n"; |
||
| 174 | for $domain (sort(keys(%domains))) {
|
||
| 175 | print "$domains{$domain}{'munindomain'}_mem.label ".trim_label('pos',$domain)."\n";
|
||
| 176 | print "$domains{$domain}{'munindomain'}_mem.cdef $domains{$domain}{'munindomain'}_mem,1024,*\n";
|
||
| 177 | print "$domains{$domain}{'munindomain'}_mem.draw AREASTACK\n";
|
||
| 178 | } |
||
| 179 | |||
| 180 | print "\nmultigraph xen_net\n"; |
||
| 181 | print "graph_title Xen domains network traffic\n"; |
||
| 182 | print "graph_args --base 1000\n"; |
||
| 183 | print "graph_vlabel bits per \${graph_period} in (-) / out (+)\n";
|
||
| 184 | print "graph_category xen\n"; |
||
| 185 | print "graph_info This graph shows network traffic for each Xen domain.\n"; |
||
| 186 | for $domain (sort(keys(%domains))) {
|
||
| 187 | print "$domains{$domain}{'munindomain'}_netrx.label none\n";
|
||
| 188 | print "$domains{$domain}{'munindomain'}_netrx.cdef $domains{$domain}{'munindomain'}_netrx,8192,*\n";
|
||
| 189 | print "$domains{$domain}{'munindomain'}_netrx.type COUNTER\n";
|
||
| 190 | print "$domains{$domain}{'munindomain'}_netrx.graph no\n";
|
||
| 191 | print "$domains{$domain}{'munindomain'}_nettx.label ".trim_label('neg',$domain)."\n";
|
||
| 192 | print "$domains{$domain}{'munindomain'}_nettx.cdef $domains{$domain}{'munindomain'}_nettx,8192,*\n";
|
||
| 193 | print "$domains{$domain}{'munindomain'}_nettx.type COUNTER\n";
|
||
| 194 | print "$domains{$domain}{'munindomain'}_nettx.draw AREASTACK\n";
|
||
| 195 | print "$domains{$domain}{'munindomain'}_nettx.negative $domains{$domain}{'munindomain'}_netrx\n";
|
||
| 196 | } |
||
| 197 | |||
| 198 | print "\nmultigraph xen_disk\n"; |
||
| 199 | print "graph_title Xen domains disk IOs\n"; |
||
| 200 | print "graph_args --base 1000\n"; |
||
| 201 | print "graph_vlabel IOs per \${graph_period} read (-) / write (+)\n";
|
||
| 202 | print "graph_category xen\n"; |
||
| 203 | print "graph_info This graph shows disk IOs for each Xen domain.\n"; |
||
| 204 | for $domain (sort(keys(%domains))) {
|
||
| 205 | print "$domains{$domain}{'munindomain'}_vbdrd.label none\n";
|
||
| 206 | print "$domains{$domain}{'munindomain'}_vbdrd.type COUNTER\n";
|
||
| 207 | print "$domains{$domain}{'munindomain'}_vbdrd.graph no\n";
|
||
| 208 | print "$domains{$domain}{'munindomain'}_vbdwr.label ".trim_label('neg',$domain)."\n";
|
||
| 209 | print "$domains{$domain}{'munindomain'}_vbdwr.type COUNTER\n";
|
||
| 210 | print "$domains{$domain}{'munindomain'}_vbdwr.draw AREASTACK\n";
|
||
| 211 | print "$domains{$domain}{'munindomain'}_vbdwr.negative $domains{$domain}{'munindomain'}_vbdrd\n";
|
||
| 212 | } |
||
| 213 | |||
| 214 | exit 0; |
||
| 215 | } |
||
| 216 | |||
| 217 | |||
| 218 | # |
||
| 219 | # Normal run |
||
| 220 | # |
||
| 221 | |||
| 222 | 1e301c2d | Alex Tomlins | print "multigraph xen_cpu_time\n"; |
| 223 | 20afb679 | Rapha?l HALIMI | for $domain (sort(keys(%domains))) {
|
| 224 | 1e301c2d | Alex Tomlins | print "$domains{$domain}{'munindomain'}_cpu_time.value $domains{$domain}{'cpusecs'}\n";
|
| 225 | 20afb679 | Rapha?l HALIMI | } |
| 226 | |||
| 227 | print "\nmultigraph xen_mem\n"; |
||
| 228 | for $domain (sort(keys(%domains))) {
|
||
| 229 | print "$domains{$domain}{'munindomain'}_mem.value $domains{$domain}{'mem'}\n";
|
||
| 230 | } |
||
| 231 | |||
| 232 | print "\nmultigraph xen_net\n"; |
||
| 233 | for $domain (sort(keys(%domains))) {
|
||
| 234 | print "$domains{$domain}{'munindomain'}_nettx.value $domains{$domain}{'nettx'}\n";
|
||
| 235 | print "$domains{$domain}{'munindomain'}_netrx.value $domains{$domain}{'netrx'}\n";
|
||
| 236 | } |
||
| 237 | |||
| 238 | print "\nmultigraph xen_disk\n"; |
||
| 239 | for $domain (sort(keys(%domains))) {
|
||
| 240 | print "$domains{$domain}{'munindomain'}_vbdrd.value $domains{$domain}{'vbdrd'}\n";
|
||
| 241 | print "$domains{$domain}{'munindomain'}_vbdwr.value $domains{$domain}{'vbdwr'}\n";
|
||
| 242 | } |
