aboutsummaryrefslogtreecommitdiff
path: root/files/munin/xen-multi
blob: c57a2b8df8f03b95a73aee14bfcd5912e120d79a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#! /usr/bin/perl

# -*- perl -*-

=head1 NAME

xen_multi - Munin multigraph plugin to monitor Xen domains activity

=head1 APPLICABLE SYSTEMS

This plugin should work on any system running a Xen hypervisor and where xentop
is installed. It also needs Munin 1.4.0 or higher, since it uses AREASTACK
(available from 1.3.3) and multigraph (available from 1.4.0).

=head1 CONFIGURATION

xentop requires superuser privileges, so you need to include in your
configuration:

 [xen-multi]
 user root

Then restart munin-node and you're done.

=head1 INTERPRETATION

This plugin produces four different graphs: CPU usage, memory usage, disk IOs
and network traffic.

In each graph, all Xen domains (including dom0) have their data stacked, giving
an overall amount of ressources used.

NOTE: xentop always reports 0 for dom0's disk IOs and network traffic, but
both graphs show its entry all the same, so each domain can keep its own color
along the different graphs.

=head2 CPU usage

This graph shows a percentage of the CPU time used by each domain.

=head2 Memory usage

This graph shows the amount of memory (in bytes) used by each domain.

=head2 Disk IOs

This graph shows the number of disk read and write operations for each domain.

=head2 Network traffic

This graph shows the amount of bits received and transmitted for each domain.

=head1 ACKNOWLEDGEMENTS

Michael Renner for the C<diskstats> plugin which I borrowed some code from.

=head1 VERSION

0.90

=head1 MAGIC MARKERS

  #%# family=auto
  #%# capabilities=autoconf

=head1 AUTHOR

Raphael HALIMI <raphael.halimi@gmail.com>

=head1 LICENSE

GPLv2

=cut

use strict;
use Munin::Plugin;

# autoconf - quite simple
if ($ARGV[0] eq "autoconf") {
  if (`which xentop`) {
    print "yes\n";
  } else {
    print "no (xentop not found)\n";
  }
  exit 0;
}


#
# Common steps for both "config" and a normal run
#

#
# trim_label
#
# Trims a given label to it's non-wrapping size
# $type = 'pos' for normal graphs and 'neg' for mirror graphs
# pos: nnn.nnU_ times 4
# neg: nnn.nnU/nnn.nnU_ times 4

sub trim_label {
  my ($type, $label) = @_; my $data_characters;
  my ($graph_width, $graph_border_width, $padding_characters, $pixels_per_character) = (400,97,10,6);
  if ($type eq 'pos') {$data_characters = 32;} elsif ($type eq 'neg') {$data_characters = 64;} else {return $label;}

  my $available_characters = abs(($graph_width+$graph_border_width)/$pixels_per_character)-$padding_characters-$data_characters;

  # If the label is longer than the available space, we write as many
  # characters as we can on both left and right, and two dots in the middle
  if ( $available_characters < length $label ) {
    my $center = ($available_characters-2)/2;
    $label = substr($label,0,($center)) . '..' . substr($label,-$center);
  }

  return $label;
}

# Global variables
my (%domains,$domain,$munindomain,$cpusecs,$memk,$nettxk,$netrxk,$vbdrd,$vbdwr);

open (XENTOP,"xentop -b -f -i1 |") or die "Could not execute xentop, $!";

# Now we build a hash of hashes to store information
while (<XENTOP>) {
  # Some cleaning first
  s/^\s+//; chomp;
  # Skip the headers
  next if /^NAME/;

  # We define only what we need
  ($domain,undef,$cpusecs,undef,$memk,undef,undef,undef,undef,undef,$nettxk,$netrxk,undef,undef,$vbdrd,$vbdwr,undef,undef,undef) = split(/\s+/);

  # We have to store the sanitised domain name in a separate variable
  $domains{$domain}{'munindomain'} = clean_fieldname($domain);

  # We need the remaining data only for a normal run
  if ($ARGV[0] eq "") {
    $domains{$domain}{'cpusecs'} = $cpusecs;
    $domains{$domain}{'mem'} = $memk;
    $domains{$domain}{'nettx'} = $nettxk;
    $domains{$domain}{'netrx'} = $netrxk;
    $domains{$domain}{'vbdrd'} = $vbdrd;
    $domains{$domain}{'vbdwr'} = $vbdwr;
  }
}


#
# config - quite simple, too
#

if ($ARGV[0] eq "config") {
  print "multigraph xen_cpu_time\n";
  print "graph_title Xen domains CPU time\n";
  print "graph_args --base 1000 -l 0\n";
  print "graph_vlabel %\n";
  print "graph_scale no\n";
  print "graph_category xen\n";
  print "graph_info This graph shows CPU time for each Xen domain.\n";
  for $domain (sort(keys(%domains))) {
    print "$domains{$domain}{'munindomain'}_cpu_time.label ".trim_label('pos',$domain)."\n";
    print "$domains{$domain}{'munindomain'}_cpu_time.type DERIVE\n";
    print "$domains{$domain}{'munindomain'}_cpu_time.cdef $domains{$domain}{'munindomain'}_cpu_time,100,*\n";
    print "$domains{$domain}{'munindomain'}_cpu_time.min 0\n";
    print "$domains{$domain}{'munindomain'}_cpu_time.draw AREASTACK\n";
  }

  print "\nmultigraph xen_mem\n";
  print "graph_title Xen domains memory usage\n";
  print "graph_args --base 1024 -l 0\n";
  print "graph_vlabel bytes\n";
  print "graph_category xen\n";
  print "graph_info This graph shows memory usage for each Xen domain.\n";
  for $domain (sort(keys(%domains))) {
    print "$domains{$domain}{'munindomain'}_mem.label ".trim_label('pos',$domain)."\n";
    print "$domains{$domain}{'munindomain'}_mem.cdef $domains{$domain}{'munindomain'}_mem,1024,*\n";
    print "$domains{$domain}{'munindomain'}_mem.draw AREASTACK\n";
  }

  print "\nmultigraph xen_net\n";
  print "graph_title Xen domains network traffic\n";
  print "graph_args --base 1000\n";
  print "graph_vlabel bits per \${graph_period} in (-) / out (+)\n";
  print "graph_category xen\n";
  print "graph_info This graph shows network traffic for each Xen domain.\n";
  for $domain (sort(keys(%domains))) {
    print "$domains{$domain}{'munindomain'}_netrx.label none\n";
    print "$domains{$domain}{'munindomain'}_netrx.cdef $domains{$domain}{'munindomain'}_netrx,8192,*\n";
    print "$domains{$domain}{'munindomain'}_netrx.type COUNTER\n";
    print "$domains{$domain}{'munindomain'}_netrx.graph no\n";
    print "$domains{$domain}{'munindomain'}_nettx.label ".trim_label('neg',$domain)."\n";
    print "$domains{$domain}{'munindomain'}_nettx.cdef $domains{$domain}{'munindomain'}_nettx,8192,*\n";
    print "$domains{$domain}{'munindomain'}_nettx.type COUNTER\n";
    print "$domains{$domain}{'munindomain'}_nettx.draw AREASTACK\n";
    print "$domains{$domain}{'munindomain'}_nettx.negative $domains{$domain}{'munindomain'}_netrx\n";
  }

  print "\nmultigraph xen_disk\n";
  print "graph_title Xen domains disk IOs\n";
  print "graph_args --base 1000\n";
  print "graph_vlabel IOs per \${graph_period} read (-) / write (+)\n";
  print "graph_category xen\n";
  print "graph_info This graph shows disk IOs for each Xen domain.\n";
  for $domain (sort(keys(%domains))) {
    print "$domains{$domain}{'munindomain'}_vbdrd.label none\n";
    print "$domains{$domain}{'munindomain'}_vbdrd.type COUNTER\n";
    print "$domains{$domain}{'munindomain'}_vbdrd.graph no\n";
    print "$domains{$domain}{'munindomain'}_vbdwr.label ".trim_label('neg',$domain)."\n";
    print "$domains{$domain}{'munindomain'}_vbdwr.type COUNTER\n";
    print "$domains{$domain}{'munindomain'}_vbdwr.draw AREASTACK\n";
    print "$domains{$domain}{'munindomain'}_vbdwr.negative $domains{$domain}{'munindomain'}_vbdrd\n";
  }

  exit 0;
}


#
# Normal run
#

print "multigraph xen_cpu_time\n";
for $domain (sort(keys(%domains))) {
  print "$domains{$domain}{'munindomain'}_cpu_time.value $domains{$domain}{'cpusecs'}\n";
}

print "\nmultigraph xen_mem\n";
for $domain (sort(keys(%domains))) {
  print "$domains{$domain}{'munindomain'}_mem.value $domains{$domain}{'mem'}\n";
}

print "\nmultigraph xen_net\n";
for $domain (sort(keys(%domains))) {
  print "$domains{$domain}{'munindomain'}_nettx.value $domains{$domain}{'nettx'}\n";
  print "$domains{$domain}{'munindomain'}_netrx.value $domains{$domain}{'netrx'}\n";
}

print "\nmultigraph xen_disk\n";
for $domain (sort(keys(%domains))) {
  print "$domains{$domain}{'munindomain'}_vbdrd.value $domains{$domain}{'vbdrd'}\n";
  print "$domains{$domain}{'munindomain'}_vbdwr.value $domains{$domain}{'vbdwr'}\n";
}