Posts categorized "Ganglia" Feed

Feb 09, 2014
Mar 14, 2013

この前つくった fluent-plugin-ganglia を gem にしてバージョン 0.0.1 をリリースした。

前回のエントリーで書いた時点では、gmond を multicast かつ upd_send_channel を bind_hostname = "yes" として動かしている場合に実はうまくいっていなかった。うごいた!とおもってあのエントリーをよろこびいさんで書いた時点では、1台のホストでしかどうささせていなくて、同じ metric group にはいる他のホストで動かし始めたら全然グラフでてこない、という始末...。

これは gmetric gem の Ganglia::GMetric#send が、

conn = UDPSocket.new
conn.connect(host, port)

conn.send gmetric[0], 0
conn.send gmetric[1], 0
conn.close

こうなってて bind してないからだったようで、Ganglia::GMetric#send は使わずにプラグイン内で、

conn = UDPSocket.new
conn.bind(HOSTADDR, 0) if @bind_hostname
conn.send gmetric[0], 0, @host, @port
conn.send gmetric[1], 0, @host, @port
conn.close

こんなような感じで IPSocket.getaddress(Socket.gethostname) でとってきた IP (HOSTADDR定数のところ) に bind して送るようにしたらうまく行った。まぁ、つまり bind_hostname = "yes" なんで bind しろよ、ということと思われる。gmetric コマンドを strace してみてても bind してたし(というか strace して差分みてて気づいた)。

この multicast + bind_hostname してる環境で metric 送りつけるには、こういう設定。

<match metrics>
  type          ganglia
  host          239.2.11.71
  port          8649
  group         metric_group
  name_keys     metrics.field1,metrics.field2
  bind_hostname true
</match>

bind_hostname true で bind してから送るようになる。multicast だけど bind_hostname してなければいらない。

というのを経ての 0.0.1 はコレの本番環境で絶賛稼働中。unicast での Ganglia はためしたことがないのだけどたぶんうごくとおもうので、もし試せる方おりましたらフィードバックいただけると幸い...。

ご利用ください。

Feb 15, 2013

fluentd を使い始めて2日目。結局 ganglia に metric 送れないことには....、ということで plugin 書いてみた。

仕組み的には @sfujiwara さんの zabbix のやつとおんなじやろ、と思い https://github.com/fujiwara/fluent-plugin-zabbix からコピペしていくつかもにょもにょしただけ (・∀・)

LTSV なアクセスログをみて datacounter でステータスコード別に集計して ganglia に metric おくる、というのをやってみた。

<source>
  type tail_labeled_tsv
  path /var/log/users_access_log
  tag web.access
  pos_file /tmp/td-agent/users_access_log.pos
</source>

<match users.access>
  type copy

  <store>
    type datacounter
    tag web.access.status_count
    count_interval 60s 
    count_key status
    pattern1 2xx ^2\d\d$
    pattern2 3xx ^3\d\d$
    pattern3 4xx ^4\d\d$
    pattern4 5xx ^5\d\d$
  </store>
</match>

<match users.access.status_count>
  type copy
  <store>
    type stdout
  </store>
  <store>
    type             ganglia
    gmond_port       8701
    name_key_pattern [2345]xx_count
    value_type       uint32
    units            views/min 
    group            users_access
    spoof            192..0.2.100:web01
    dmax             30
  </store>
</match>

設定値は gmetric コマンドのロングオプション名とほぼ同じ。fluentd とかぶる名前が幾つかあるので

  • port = gmond_port
  • type = value_type

となっている。

ganglia に metric おくるのには gmetric というそのまんまの名前の gem があったのでそれを使ってぺっと送る。が、td-agent で使っている ruby 1.9.3 に対応していないのか以下のようなエラーがでる...。

2013-02-15 18:38:59 +0900: fluent/engine.rb:115:rescue in emit_stream: emit transaction failed  error="undefined method `reactor_running?' for EventMachine:Module"

とりあえず以下パッチをあてたらうごいた。

--- gmetric.rb.org  2013-02-15 18:41:17.000000000 +0900
+++ gmetric.rb        2013-02-15 18:41:05.000000000 +0900
@@ -1,5 +1,6 @@
 require "stringio"
 require "socket"
+require "eventmachine"

 module Ganglia
   class GMetric

が、こんなことでよいのか ruby 的なところがわからない...。問題なのはここの if 文。

  if defined?(EventMachine) and EventMachine.reactor_running?        # open an ephemereal UDP socket since
    # we do not plan on recieving any data
    conn = EM.open_datagram_socket('', 0)

    conn.send_datagram gmetric[0], host, port
    conn.send_datagram gmetric[1], host, port
    conn.close_connection_after_writing
  else
    conn = UDPSocket.new
    conn.connect(host, port)

    conn.send gmetric[0], 0
    conn.send gmetric[1], 0
    conn.close
  end

だれかなおしてー (´・ω・`)

とりあえず、ganglia にいろいろ送れるようになったけど、設定的になんかいろいろもうすこし良いデフォルトがあるかなぁ(spoof のあたりとか title とか)と思うのでもう少しいじって安定したら gem 化などやってみる。

fluentd++

Feb 13, 2013

MySQL 5.5 で InnoDB status とれないまま長らく放置していた Ganglia の mysqld python module にパッチあてた。

DBUtil.py には python 2.5 未満でうごかん、みたいなことがほんのり書かれてるけど、Cent OS 5 の標準 python 2.4.3 で残念ながら動いてる(が、EPEL の python26 いれるのがいろいろ良いであろう)。ただ、log_bytes_written、log_bytes_flushed あたりは怪しい数値をだしてるけど...。

というか、だれもつかってないのかしらこのモジュール...。

Feb 06, 2013

Perlbal の Reproxy URL Cache の統計を Ganglia に送りつけるやっつけスクリプト。

mgmt のポートにつないで、show service <service name> で Reproxy URL Cache のキャッシュ数、ヒット数、ヒット率なんかが取れる。

% echo "show service web" | nc localhost 5700
show service tp_web
SERVICE tp_web
     listening: --
          role: reverse_proxy
  pend clients: 0
  pend backend: 0
    cache size: 0/1024 (0.00%)
    cache hits: 0
cache hit rate: 0.00%
 connect-ahead: 0/0
          pool: web_pool
         nodes:
                127.0.0.1:6500              0
.

(空っぽの状態だけど)これを parse して gmetric コマンドで定期的に ganglia に送りつけるだけ。

#!/usr/bin/env perl
use strict;
use warnings;
use Getopt::Long qw( :config posix_default no_ignore_case bundling auto_help );
use Pod::Usage;
use IO::Socket::INET;

GetOptions(\my %opt, qw( host=s service=s gmetric verbose ))
    or pod2usage(1);

my $sock = IO::Socket::INET->new(PeerAddr => $opt{host}, Timeout => 2, Proto => 'tcp')
    or die $!;
print $sock "show service $opt{service}\r\n";
my ($cached, $max, $hit, $rate);
while (my $line = <$sock>) {
    last if $line =~ m{^\.};
    chomp $line;
    if ($line =~ m{\s*cache size: (\d+)/(\d+) \((\d+(?:\.\d+)?)\%\)}) {
        $cached = $1;
        $max    = $2;
    }
    elsif ($line =~ m{\s*cache hits: (\d+)}) {
        $hit = $1;
    }
    elsif ($line =~ m{\s*cache hit rate: (\d+(?:\.\d+)?)\%}) {
        $rate = $1;
    }
}
die unless (defined $cached && defined $max && defined $hit && defined $rate);

if ($opt{verbose}) {
    print "$cached cached, $hit hits, $rate% hit\n";
}
if ($opt{gmetric}) {
    system 'gmetric', '--name', 'perlbal_reproxy_cache_urls', '--value', $cached, '--type', 'uint32', '--group', 'perlbal';
    system 'gmetric', '--name', 'perlbal_reproxy_cache_hits', '--value', $hit, '--type', 'uint32', '--group', 'perlbal';
    system 'gmetric', '--name', 'perlbal_reproxy_cache_hit_rate', '--value', $rate, '--type', 'float', '--group', 'perlbal';
}

__END__

=pod

=head1 NAME

reproxy_cache_stats.pl - get reproxy cache stats

=head1 SYNOPSIS

  % reproxy_cache_stats.pl --host=<host:port> --service=<name> [--gmetric] [--verbose]

=cut

というメモ。

Jan 10, 2013

Ganglia Web 3.4 ぐらいからつかえる Views の機能が、ホストの垣根を超えて任意のグラフの一覧を自由に作れて、かつ aggregate graph も作れるっぽくて大変よさげなので使ってみた。

view の作り方は、設定ファイルディレクトリ(デフォルトは /var/lib/ganglia/conf)に view_ で始まる .json ファイルに JSON 書くだけ。手始めに varnish の接続数にまつわる metric をまるっと集めてみた。

{
  "view_name": "varnish",
  "view_type": "standard",
  "items": [
    {
      "aggregate_graph": "true",
      "host_regex": [ { "regex":"bal" } ],
      "metric_regex": [ { "regex":"varnish_client_conn" } ],
      "graph_type": "stack",
      "title": "client connections"
    },
    {
      "aggregate_graph": "true",
      "host_regex": [ { "regex":"bal" } ],
      "metric_regex": [ { "regex":"varnish_client_req" } ],
      "graph_type": "stack",
      "title": "client request"
    },
    {
      "aggregate_graph": "true",
      "host_regex": [ { "regex":"bal" } ],
      "metric_regex": [ { "regex":"varnish_backend_req" } ],
      "graph_type": "stack",
      "title": "varnish request to backend"
    },
    {
      "aggregate_graph": "true",
      "host_regex": [ { "regex":"bal" } ],
      "metric_regex": [ { "regex":"varnish_cache_hit_ratio" } ],
      "title": "varnish cache hit ration"
    }
  ]
}

これを /var/lib/ganglia/conf/view_varnish.json として保存して、『Views』タブをクリックすると左側の view 一覧に表示されるのでクリッコ。

Gangliavarnishview

(・∀・)イイネ!!

JSON の内容は以下の模様。

  • view_name - view の名前
  • view_type - standard or regexp。regexp だと正規表現でホスト名を指定できるらしいがどう使うのかが不明(ホストは items の中で指定するし...)
  • items - metric/graph の詳細

これで、view を定義。item の内容は、

  • hostname / host_regexp - ホスト名
  • metric / metric_regexp - "load_one" とかの metric の名前。
  • graph / graph_regexp - "load_report" とかの "_report" で終わる graph の名前。
  • aggregate_graph - "true" で aggregate graph に。
  • graph_type - aggregate graph の描画方法。line(折れ線)がデフォルトで、stack(積算)もある。
  • title - graph のタイトル

あたり。aggregate_graph 作る場合に、組み合わせ的に無理なものもありそうだけど...。

View 作ることで cluster や host の画面でちまちまグラフをちまちま探したり、host ごとにブラウザのタブ開いて行ったり来たりとかしなくて済むので大変具合がよい。いっぱい作ろう。

ちなみに(検索ヂカラが低いので)どこ探してもみつからなかったこのへんの内容は、去年末にでた Ganglia 本にさっくりのってた。機能解説、設定方法が網羅さらてるので Ganglia ドキュメントとして大変よいです。Ganglia 使いの皆様におかれましては必読でないかと(まだ読み途中だけど...)。

Aug 29, 2012

Ganglia で python module なんかで新たに監視項目を増やそうとしたときに、.pyconf のサンプルが不親切すぎ、.py にも説明ないとかで、設定すべき metric name がよくわからない場合にそれを探す方法のメモ。

まずは使うモジュールのソースを読んであたりを付ける、もしくは特定できるようならそれで。だいたい Init_Metric 関数、metric_init 関数あたりをみればわかる。以下は multidisk.py の例。

def Init_Metric (line, name, tmax, type, units, slope, fmt, desc, handler):
    '''Create a metric definition dictionary object for a device.'''
    metric_name = line[0] + '-' + name

    d = {'name': metric_name.replace('/', '-').lstrip('-'),
        'call_back': handler,
        'time_max': tmax,
        'value_type': type,
        'units': units,
        'slope': slope,
        'format': fmt,
        'description': desc,
        'groups': 'disk',
        'mount': line[1]}
    return d

def metric_init(params):
    '''Discover all of the local disk devices on the system and create
    a metric definition dictionary object for each.'''
    global descriptors
    f = open('/proc/mounts', 'r')

    for l in f:
        line = l.split()
        if line[3].startswith('ro'): continue
        elif Remote_Mount(line[0], line[2]): continue
        elif (not line[0].startswith('/dev/')) and (not line[0].startswith('/dev2/')): continue;

        if ganglia.get_debug_msg_level() > 1:
            print 'Discovered device %s' % line[1]

        descriptors.append(Init_Metric(line, 'disk_total', int(1200),
            'double', 'GB', 'both', '%.3f',
            'Available disk space', DiskTotal_Handler))
        descriptors.append(Init_Metric(line, 'disk_used', int(180),
            'float', '%', 'both', '%.1f',
            'Percent used disk space', DiskUsed_Handler))

    f.close()
    return descriptors

Init_Metric 関数への第2引数をサフィックスにして name パラメーターにいれてるので、呼び出し元から "disk_used", "disk_total" が metric name のサフィックスなってるであろうことを確認。python 読めないけど、前半部分は /proc/mounts からなんかもってきて / を - に変換して、一番最初の / 削る、とかやってるぽい。けど、とりあえず disk_used を含む metric name 一覧で確認してみたい。

ひとまず、モジュールを有効にして gmond で使えるようにする。/etc/ganglia/conf.d/diskusage.pyconf に以下を入れて gmond reload。

modules {
  module {
    name = "multidisk"
    language = "python"
  }
}

で、metric name 一覧を取る(これを今回知った)。

$ /usr/sbin/gmond -m

とすると、利用可能な metric name と、どのモジュールで定義されているかの一覧がどばーっとでる。残念なことに python でかかれた module はすべてが "pyhotn_module" として出てしまうけど、まぁどうでもいいところなので。

$ /usr/sbin/gmond -m | grep disk_used
dev-sda1-disk_used      Percent used disk space (module python_module)
dev-sdd1-disk_used      Percent used disk space (module python_module)
dev-sdb1-disk_used      Percent used disk space (module python_module)
dev-sda3-disk_used      Percent used disk space (module python_module)
dev-sdc1-disk_used      Percent used disk space (module python_module)

ということで、こいつらを metric name にそれぞれいれて gmond reload。まぁ、それ以外のこまい設定はソースよまないとわからないので最後は結局ソース読むのだけど。

徐々に脱 Ganglia 初心者。