share facebook facebook2 twitter menu hatena pocket slack

2013.01.18 FRI

FluentdからCloudWatchのカスタムメトリクスにデータを登録してみた(UPDATE!)

鈴木 宏康

WRITTEN BY鈴木 宏康

本記事は少し古いものになりますので、新しい情報は「FluentdからCloudWatchのカスタムメトリクスにデータを
登録してみた(UPDATE2!)
」を参照下さい。

以前の記事(「FluentdからCloudWatchのカスタムメトリクスにデータを登録してみた」)にて仕組みと
それを実現するFluentdのプラグイン(out_cloudwatch.rb)を紹介しました。
今回は、それを更に次のようなことができるようにアップデートしてみました。


※historyはbashのHistoryログが対象です。

また、auditはauditdのAuditログが対象となります。

上記の紹介記事からの改良点

  • 複数のDataCounterプラグインで集計をした結果を、一つのCloudWatchプラグインでデータ登録
    できるように。
  • 一つのCloudWatchプラグインで、複数のカスタムメトリクスを対象にできるように。
  • Dimensionにタグ(Tag)とホスト名(Hostname)を登録。
  • 同じデータをDimensionがタグ(Tag)のみのものと、タグ(Tag)とホスト名(HostName)のもので登録。
  • AWSコンソールでタグ(Tag)で各ホストを集約したグラフが確認できるように。
  • CloudWatchプラグインの親クラスをTimeSlicedOutputにして、任意のインターバルでデータ登録
    できるように。
  • IAM Roleの有効期限が切れても対応できるように。

○CloudWatchの表示

結果から紹介いたします。
まずは、ホスト名とタグの両方をDimensionに指定したものになります。

次に、タグで複数のホストを集約したものになります。


(MetricNameはBashCountではなく、SyslogCountの方がよかったかもしれません)

○設定ファイル(/etc/td-agent/td-agent.conf)

CloudWatchプラグインのポイントを挙げてみます。

  • flush_intervalで任意のインターバルでCloudWatchにデータ登録。
  • metricでtagごとにカスタムメトリクスが指定可能。

type tail
format syslog
path /opt/suz-lab/var/log/syslog/all.log
pos_file /opt/suz-lab/var/lib/td-agent/pos/tail.syslog.pos
tag tail.syslog


type copy

type file
path /tmp/tail.syslog


type datacounter
unit minute
aggregate all
count_key ident
pattern1 history ^-bash$7
tag history.datacounter.syslog


type datacounter
unit minute
aggregate all
count_key ident
pattern1 audit ^audispd$
tag audit.datacounter.syslog



type copy

type file
path /tmp/datacounter.syslog


type cloudwatch
buffer_type file
buffer_path /opt/suz-lab/var/lib/td-agent/buf/cloudwatch.datacounter.syslog
flush_interval 5m
cloud_watch_endpoint monitoring.ap-northeast-1.amazonaws.com
namespace SUZ-LAB/TEST

tag history.datacounter.syslog
name BashCount
key history_count
unit Count


tag audit.datacounter.syslog
name BashCount
key audit_count
unit Count


○CloudWatchプラグイン(/etc/td-agent/plugin/out_cloudwatch.rb)

下記のコードで上記の仕様を実装

module Fluent
require 'aws-sdk'
class CloudWatchOutput < TimeSlicedOutput

MAX_METRIC_DATA_SIZE = 20
Fluent::Plugin.register_output('cloudwatch', self)
config_param :aws_key_id, :string, :default => nil
config_param :aws_sec_key, :string, :default => nil
config_param :cloud_watch_endpoint, :string, :default => 'monitoring.ap-northeast-1.amazonaws.com'
config_param :namespace, :string

def initialize
super
@metrics = {}
end

def configure(conf)
super
conf.elements.select {|e|
e.name == 'metric'
}.each do |e|
@metrics[e['tag']] = {
'name' => e['name'],
'key' => e['key'],
'unit' => e['unit']
}
end
end

def start
super
AWS.config(
:access_key_id => @aws_key_id,
:secret_access_key => @aws_sec_key,
:cloud_watch_endpoint => @cloud_watch_endpoint
)
end

def shutdown
super
end

def format(tag, time, record)
record["tag"] = tag
record["timestamp"] = Time.at(time).iso8601
record.to_msgpack
end

def write(chunk)
metric_data = []
chunk.msgpack_each do |record|
$log.debug(record.inspect)
tmp_data_by_tag = {
:metric_name => @metrics[record['tag']]['name'],
:timestamp => record['timestamp'],
:value => record[@metrics[record['tag']]['key']],
:unit => @metrics[record['tag']]['unit'],
:dimensions => [ { :name => 'Tag', :value => record['tag'] }
}
metric_data << tmp_data_by_tag
tmp_data_by_tag_and_hostname = Marshal.load(Marshal.dump(tmp_data_by_tag))
tmp_data_by_tag_and_hostname[:dimensions] << {
:name => 'HostName', :value => Socket.gethostname
}
metric_data << tmp_data_by_tag_and_hostname
end
$log.debug(metric_data.inspect)
until metric_data.length <= 0 do
tmp_data = metric_data.slice!(0, MAX_METRIC_DATA_SIZE)
$log.debug(tmp_data.inspect)
AWS::CloudWatch.new.put_metric_data(
:namespace => @namespace,
:metric_data => tmp_data
)
end
end

end
end

こちらの記事はなかの人(suz-lab)監修のもと掲載しています。
元記事は、こちら

鈴木 宏康

鈴木 宏康

愛知県生まれ。東京工業大学大学院修士課程修了。在学時より、ベンチャー企業でインターネットに関する業務に携わり、現在はクラウド(主にAmazon Web Services)上での開発・運用を軸とした事業の、業務の中心として活躍。