February 2013 posts

Feb 19, 2013

td-agent と fluent-gem コマンドでインストールした fluentd plugins、gem を管理するための Puppet モジュールつくってみた。

package provider に "fluentgem" が追加されているので、

include td-agent
package { 'fluent-plugin-datacounter':
  ensure   => 'installed',
  provider => 'fluentgem',
  require  => Package['td-agent'],
}

として、fluent plugin な gem などを追加することができるので、全部 /etc/td-agent/plugin にいれるとか、exec でほげほげしてふがふがして とか面倒なことしなくてもよくなった。あとは、最小限の td-agent.conf がはいっているのみ。

これで、 td-agent をばらまけるようになったし、先週書いた ganglia plugin で metric 収集も万全。ようやく fluentd スタート地点。

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

というメモ。