Gangliaでディスク使用率のグラフを追加してみた

GangliaのWebインターフェースはgmetricで送信した量を自動でグラフ化してくれるのだが、取った量を個別にグラフ化する形になるため、ディスク使用率などファイルシステムごとに取ったグラフを重ねて見たい場合には、個別にカスタマイズを行うことになる。今回、試しとして、/boot”, “/” のディスク使用率をgmetricで取得し、グラフ化できるようにしてみた。

まず、各パーティションの使用率はこちらのスクリプトで取得するようにした。
http://ganglia.sourceforge.net/gmetric/view.php?id=13

このスクリプトはdfの結果からファイルシステムをくくりだし、各ファイルシステムについて使用率を送付してくれる。テスト用として、 1. /dev/shm は送付しない。 2. “df” コマンドでは -P (Posix準拠)を使い、長いファイルシステム名にも対応できるようにする。 の2点を変更した。


この状態で、gmetadが動いているサーバーで、次のコマンドを入力することでファイルシステム使用量についてのグラフが見られるはずである。

 $ cd /var/lib/ganglia/rrds/clustername/nodename
 $ rrdtool graph /tmp/aaa.png --imgformat=PNG \
DEF:root=disk_percent_used_root.rrd:sum:AVERAGE \
DEF:boot=disk_percent_used_boot.rrd:sum:AVERAGE \
LINE1:root#00aaaa:"root" LINE1:boot#aaaa00:"boot" \
--start 適切なUnix時刻

この後、出来たグラフをWebインターフェースに組み込むには、大きくわけて、1. 画像作成用のPHP作成, 2. NodeViewでテンプレートの変更 の2点が必要になる。
Fedora12では、graph.d/ へのPHPファイル追加と、, templates/default/host_view.tpl の2ファイルを変更することで実施できた。(それぞれ /usr/share/ganglia からの相対パスで指定。)

作成した直後のdiff はこんな感じである。Sampleファイルをコピペして取り込んでいるおり、長くて見難しいので、後でSampleファイルとのdiffも貼ろうと思う。

 diff --git a/graph.d/disk_utilization_report.php b/graph.d/disk_utilization_report.php
 new file mode 100644
 index 0000000..387221b
 --- /dev/null
 +++ b/graph.d/disk_utilization_report.php
 @@ -0,0 +1,139 @@
 +<?php
 +
 +/* Sample report template */
 +
 +/* Instructions for adding custom reports
 +
 +1) Reports should have a primary function named:  "<yourtesthere>_report".
 +   This function will be called from the graph.php script automatically.
 +
 +2) The *_report script should return an array that contains at least the
 +   variables listed below.  Several have been pre-populated, and may not
 +   need to be changed.
 +   However, you will have to alter at least these:  $series, $title, and
 +   $vertical_label
 +
 +3) An array variable is passed to the function in order to make sure that
 +   certain variables are available for use.  This is PASSED BY REFERENCE
 +   and CAN BE CHANGED by your report function.
 +
 +NOTE:  These are all actually keys in a hash, not specific variables by
 +       themselves.
 +
 +A full list of variables that will be used:
 +
 +    $series          (string: holds the meat of the rrdgraph definition)
 +    $title           (string: title of the report)
 +    $vertical_label  (string: label for Y-Axis.)
 +
 +    $start           (string: Start time of the graph, can usually be
 +                              left alone)
 +    $end             (string: End time of the graph, also can usually be
 +                              left alone)
 +
 +    $width           (strings: Width and height of *graph*, the actual image
 +    $height                    will be slightly larger due to text elements
 +                               and padding.  These are normally set
 +                               automatically, depending on the graph size
 +                               chosen from the web UI)
 +
 +    $upper-limit     (strings: Maximum and minimum Y-value for the graph.
 +    $lower-limit               RRDTool normally will auto-scale the Y min
 +                               and max to fit the data.  You may override
 +                               this by setting these variables to specific
 +                               limits.  The default value is a null string,
 +                               which will force the auto-scale behavior)
 +
 +    $color           (array: Sets one or more chart colors.  Usually used
 +                             for setting the background color of the chart.
 +                             Valid array keys are BACK, CANVAS, SHADEA,
 +                             SHADEB, FONT, FRAME and ARROW.  Usually,
 +                             only BACK is set).
 +
 +    $extras          (Any other custom rrdtool commands can be added to this
 +                      variable.  For example, setting a different --base
 +                      value or use a --logarithmic scale)
 +
 +For more information and specifics, see the man page for 'rrdgraph'.
 +
 +*/
 +
 +function graph_disk_utilization_report ( &$rrdtool_graph ) {
 +
 +/*
 + * this is just the cpu_report (from revision r920) as an example, but
 + * with extra comments
 + */
 +
 +// pull in a number of global variables, many set in conf.php (such as colors
 +// and $rrd_dir), but other from elsewhere, such as get_context.php
 +
 +    global $context,
 +           $cpu_idle_color,
 +           $cpu_nice_color,
 +           $cpu_system_color,
 +           $cpu_user_color,
 +           $cpu_wio_color,
 +           $hostname,
 +           $range,
 +           $rrd_dir,
 +           $size,
 +           $strip_domainname;
 +
 +    if ($strip_domainname) {
 +       $hostname = strip_domainname($hostname);
 +    }
 +
 +    //
 +    // You *MUST* set at least the 'title', 'vertical-label', and 'series'
 +    // variables otherwise, the graph *will not work*.
 +    //
 +    $title = 'Sample Disk Utilization Report';
 +    if ($context != 'host') {
 +       //  This will be turned into: "Clustername $TITLE last $timerange",
 +       //  so keep it short
 +       $rrdtool_graph['title']  = $title;
 +    } else {
 +       $rrdtool_graph['title']  = "$hostname $title last $range";
 +    }
 +    $rrdtool_graph['vertical-label'] = 'Disk Utilization Percent';
 +    // Fudge to account for number of lines in the chart legend
 +    $rrdtool_graph['height']        += ($size == 'medium') ? 28 : 0;
 +    $rrdtool_graph['upper-limit']    = '100';
 +    $rrdtool_graph['lower-limit']    = '0';
 +    $rrdtool_graph['extras']         = '--rigid';
 +
 +    /*
 +     * Here we actually build the chart series.  This is moderately complicated
 +     * to show off what you can do.  For a simpler example, look at
 +     * network_report.php
 +     */
 +    if($context != "host" ) {
 +
 +        /*
 +         * If we are not in a host context, then we need to calculate
 +         * the average
 +         */
 +        $series = 
 +       "DEF:'boot'='${rrd_dir}/disk_percent_used_boot.rrd':'sum':AVERAGE "
 +       ."DEF:'root'='${rrd_dir}/disk_percent_used_root.rrd':'sum':AVERAGE "
 +       ."LINE2:'boot'#00aaaa:'boot' "
 +       ."LINE2:'root'#aaaa00:'root' ";
 +
 +    } else {
 +
 +        // Context is not "host"
 +        $series = 
 +       "DEF:'boot'='${rrd_dir}/disk_percent_used_boot.rrd':'sum':AVERAGE "
 +       ."DEF:'root'='${rrd_dir}/disk_percent_used_root.rrd':'sum':AVERAGE "
 +       ."LINE2:'boot'#00aaaa:'boot' "
 +       ."LINE2:'root'#aaaa00:'root' ";
 +    }
 +
 +    // We have everything now, so add it to the array, and go on our way.
 +    $rrdtool_graph['series'] = $series;
 +
 +    return $rrdtool_graph;
 +}
 +
 +?>
 diff --git a/templates/default/host_view.tpl b/templates/default/host_view.tpl
 index 1329f9d..e0872e0 100644
 --- a/templates/default/host_view.tpl
 +++ b/templates/default/host_view.tpl
 @@ -80,6 +80,10 @@ function toggleLayer( whichLayer )
  <IMG BORDER=0 ALT="{cluster_url} PACKETS"
     SRC="./graph.php?g=packet_report&z=medium&c={cluster_url}&{graphargs}">
  </A>
 +<A HREF="./graph.php?g=disk_utilization_report&z=large&c={cluster_url}&{graphargs}">
 +<IMG BORDER=0 ALT="{cluster_url} DISK_UTILIZATION" SRC="./graph.php?g=disk_utilization_report&z=medium&c={cluster_url}&{graphargs}">
 +</A>
  
  </TD>
  </TR>

上のファイルのうち、graph.d 以下のファイル( graph.d/disk_utilization_report.php )は、同ディレクトリ内のsample_report.phpを変更する形で作成している。sample_report.phpとのdiffはこんな感じになる。。

 --- sample_report.php	2009-01-29 08:23:20.000000000 +0900
 +++ disk_utilization_report.php	2010-03-13 12:31:46.000000000 +0900
 @@ -58,7 +58,7 @@
  
  */
  
 -function graph_sample_report ( &$rrdtool_graph ) {
 +function graph_disk_utilization_report ( &$rrdtool_graph ) {
  
  /*
   * this is just the cpu_report (from revision r920) as an example, but
 @@ -88,7 +88,7 @@
      // You *MUST* set at least the 'title', 'vertical-label', and 'series'
      // variables otherwise, the graph *will not work*.
      //
 -    $title = 'Sample CPU Report';
 +    $title = 'Sample Disk Utilization Report';
      if ($context != 'host') {
         //  This will be turned into: "Clustername $TITLE last $timerange",
         //  so keep it short
 @@ -96,7 +96,7 @@
      } else {
         $rrdtool_graph['title']  = "$hostname $title last $range";
      }
 -    $rrdtool_graph['vertical-label'] = 'Sample Percent';
 +    $rrdtool_graph['vertical-label'] = 'Disk Utilization Percent';
      // Fudge to account for number of lines in the chart legend
      $rrdtool_graph['height']        += ($size == 'medium') ? 28 : 0;
      $rrdtool_graph['upper-limit']    = '100';
 @@ -114,45 +114,20 @@
           * If we are not in a host context, then we need to calculate
           * the average
           */
 -        $series =
 -              "DEF:'num_nodes'='${rrd_dir}/cpu_user.rrd':'num':AVERAGE "
 -            . "DEF:'cpu_user'='${rrd_dir}/cpu_user.rrd':'sum':AVERAGE "
 -            . "CDEF:'ccpu_user'=cpu_user,num_nodes,/ "
 -            . "DEF:'cpu_nice'='${rrd_dir}/cpu_nice.rrd':'sum':AVERAGE "
 -            . "CDEF:'ccpu_nice'=cpu_nice,num_nodes,/ "
 -            . "DEF:'cpu_system'='${rrd_dir}/cpu_system.rrd':'sum':AVERAGE "
 -            . "CDEF:'ccpu_system'=cpu_system,num_nodes,/ "
 -            . "DEF:'cpu_idle'='${rrd_dir}/cpu_idle.rrd':'sum':AVERAGE "
 -            . "CDEF:'ccpu_idle'=cpu_idle,num_nodes,/ "
 -            . "AREA:'ccpu_user'#$cpu_user_color:'User CPU' "
 -            . "STACK:'ccpu_nice'#$cpu_nice_color:'Nice CPU' "
 -            . "STACK:'ccpu_system'#$cpu_system_color:'System CPU' ";
 -
 -        if (file_exists("$rrd_dir/cpu_wio.rrd")) {
 -            $series .= "DEF:'cpu_wio'='${rrd_dir}/cpu_wio.rrd':'sum':AVERAGE "
 -                ."CDEF:'ccpu_wio'=cpu_wio,num_nodes,/ "
 -                ."STACK:'ccpu_wio'#$cpu_wio_color:'WAIT CPU' ";
 -        }
 -
 -        $series .= "STACK:'ccpu_idle'#$cpu_idle_color:'Idle CPU' ";
 +        $series = 
 +       "DEF:'boot'='${rrd_dir}/disk_percent_used_boot.rrd':'sum':AVERAGE "
 +       ."DEF:'root'='${rrd_dir}/disk_percent_used_root.rrd':'sum':AVERAGE "
 +       ."LINE2:'boot'#00aaaa:'boot' "
 +       ."LINE2:'root'#aaaa00:'root' ";
  
      } else {
  
          // Context is not "host"
 -        $series ="DEF:'cpu_user'='${rrd_dir}/cpu_user.rrd':'sum':AVERAGE "
 -        . "DEF:'cpu_nice'='${rrd_dir}/cpu_nice.rrd':'sum':AVERAGE "
 -        . "DEF:'cpu_system'='${rrd_dir}/cpu_system.rrd':'sum':AVERAGE "
 -        . "DEF:'cpu_idle'='${rrd_dir}/cpu_idle.rrd':'sum':AVERAGE "
 -        . "AREA:'cpu_user'#$cpu_user_color:'User CPU' "
 -        . "STACK:'cpu_nice'#$cpu_nice_color:'Nice CPU' "
 -        . "STACK:'cpu_system'#$cpu_system_color:'System CPU' ";
 -
 -        if (file_exists("$rrd_dir/cpu_wio.rrd")) {
 -            $series .= "DEF:'cpu_wio'='${rrd_dir}/cpu_wio.rrd':'sum':AVERAGE ";
 -            $series .= "STACK:'cpu_wio'#$cpu_wio_color:'WAIT CPU' ";
 -        }
 -
 -        $series .= "STACK:'cpu_idle'#$cpu_idle_color:'Idle CPU' ";
 +        $series = 
 +       "DEF:'boot'='${rrd_dir}/disk_percent_used_boot.rrd':'sum':AVERAGE "
 +       ."DEF:'root'='${rrd_dir}/disk_percent_used_root.rrd':'sum':AVERAGE "
 +       ."LINE2:'boot'#00aaaa:'boot' "
 +       ."LINE2:'root'#aaaa00:'root' ";
      }
  
      // We have everything now, so add it to the array, and go on our way.

$series の中身は先ほど確認のとき使用したrrdtoolのコマンドをそのまま使用する形になる。注意するところは、graph.d内のfunctiionは重複しないようにすることとぐらいだろうか。。
host_view.tpl については、次のように変更している。HostViewの右側のCPU, メモリ等の表示と続けて表示したかったので、そのままコピペする形で加えてある。

 diff --git a/templates/default/host_view.tpl b/templates/default/host_view.tpl
 index 1329f9d..e0872e0 100644
 --- a/templates/default/host_view.tpl
 +++ b/templates/default/host_view.tpl
 @@ -80,6 +80,10 @@ function toggleLayer( whichLayer )
  <IMG BORDER=0 ALT="{cluster_url} PACKETS"
     SRC="./graph.php?g=packet_report&z=medium&c={cluster_url}&{graphargs}">
  </A>
 +<A HREF="./graph.php?g=disk_utilization_report&z=large&c={cluster_url}&{graphargs}">
 +<IMG BORDER=0 ALT="{cluster_url} DISK_UTILIZATION"
 +   SRC="./graph.php?g=disk_utilization_report&z=medium&c={cluster_url}&{graphargs}">
 +</A>
  
  </TD>
  </TR>

上手くいくと、GangliaのHostViewに次のような表示が行われるはずである。。(右にディスク使用率が表示されている)


なお、PHPデバッグログ(文法ミスなど)の場合には、/var/log/httpd/error_log に出力される形になるので適宜そちらを利用するとやりやすそうだ。(筆者の場合、行末の”;” の抜けなどで何度か画像が表示されなかった。。orz )
host_view.tpl を編集する前でも URL内にgraph.d 内で定義した関数名を直打ちすることで、グラフを表示できるので、(Fedora12ではSampleReport.php も表示できていた。。w)あらかじめ稼働確認を行っておくと、デバッグ時の切り分けがやりやすいだろう。。
PHPの編集と考えると大変そうだが、編集内容自体は定形化されているため意外と簡単な印象だ。実運用で使う場合には積極的に使っていきたいところだ。積み重ねグラフにしたい量といえば、やはりApacheのservice-statusや、データソースごとの接続数等が対象だろうか。。w