CloudWatch Alarm/Logs管理ツールを作った / CloudWatch Logsについて

CloudWatch Logsを本格的に使いたかったので、CloudWatch Alarm/Logsの管理ツールを作りました。 また、その過程でCloudWatch Logsについていくつか知見がたまったのでメモしておきます。

Radiosonde: CloudWatch Alarm管理ツール

https://github.com/winebarrel/radiosonde

毎度おなじみ「DSLAWSを管理しようぜ!」シリーズです。

以下のDSLでCloudWatchのAlarmを管理できます。

require 'other/alarmfile'

alarm "alarm1" do
  namespace "AWS/EC2"
  metric_name "CPUUtilization"
  dimensions "InstanceId"=>"i-XXXXXXXX"
  period 300
  statistic :average
  threshold ">=", 50.0
  evaluation_periods 1
  actions_enabled true
  alarm_actions []
  ok_actions []
  insufficient_data_actions ["arn:aws:sns:us-east-1:123456789012:my_topic"]
end

alarm "alarm2" do
  ...
end

「namespaceとかでグルーピングした方がいいのかなぁ…」とも思ったのですが、どのようなユースケースがあるか分からなかったので、データ構造をおおむねそのまま反映するようにしました。

要望・Pull Request・バグ報告は随時受付中です。

Meteorlog: CloudWatch Alarm管理ツール

https://github.com/winebarrel/meteorlog

こちらも「DSLAWSを管理しようぜ!」シリーズです。

以下のDSLでCloudWatch Logsを管理できます。

require 'other/logsfile'

log_group "any-group" do
  log_stream "my-stream"

  # Please write the following if you do not want to manage log_streams
  #any_log_streams

  metric_filter "MyAppAccessCount" do
    # see http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/FilterAndPatternSyntax.html
    filter_pattern '[ip, user, username, timestamp, request, status_code, bytes > 1000]'
    metric :name=>"EventCount", :namespace=>"YourNamespace", :value=>"1"
  end

  metric_filter "MyAppAccessCount2" do
    metric :name=>"EventCount2", :namespace=>"YourNamespace2", :value=>"2"
  end
end

log_group "/var/log/maillog" do
  ...
end

log_streamを管理しておきたくない場合はany_log_streamsと書くと管理外になります。

要望・Pull Request・バグ報告は随時受付中です。

CloudWatch Logsについて

CloudWatch Logsを触ってみて気がついたことをメモしておきます。

ドキュメント

APIドキュメントを結構探してしまったのですが、CloudWatchとは別にありました。 http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/Welcome.html

使い方についてはCloudWatchのドキュメントに含まれていました。 http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/WhatIsCloudWatchLogs.html

fluent-plugin-cloudwatch-logs

@ryot_a_raiさんがfluent-plugin-cloudwatch-logsを公開しています。 https://github.com/ryotarai/fluent-plugin-cloudwatch-logs

空白区切りの文字列をテキストをロギングするためのPull Requestをマージしてもらいました。

Aws::CloudWatchLogs

aws-skd-ruby 1.x系ではまだCloudWatchLogsがサポートされていないですが、2.x系ではサポートされていました。 http://docs.aws.amazon.com/sdkforruby/api/Aws/CloudWatchLogs.html

Log Streamについて

PutLogEventsするとき、新規Stream以外の場合はSequenceTokenが必要になるのはなんなんでしょうね…TokenなしでPutできたら楽なのに。

手元で同じStreamにたいしてPutLogEventsしようとしたら、うまく動かせませんでした。 ポリシーとして1スレッド・1ストリームなんでしょうか?

Metric Filterについて

metric_filter "MyAppAccessCount" do
  filter_pattern '[ip, user, username, timestamp, request, status_code, bytes > 1000]'
  metric :name=>"EventCount", :namespace=>"YourNamespace", :value=>"1"
end

filter_pattern

ドキュメントを読む限り、空白区切りの文字列を構造化されたレコードとして扱うようです。そのうちJSONとかもサポートするのかな?

コマンドラインaws logs test-metric-filterを実行すると、メッセージがどのようにパターンにマッチするのかが分かります。

/*
aws logs test-metric-filter \
  --filter-pattern '[...]' \
  --log-event-messages '127.0.0.1 - frank [10/Oct/2000:13:25:15 -0700] "GET /apache_pb.gif HTTP/1.0" 200 1534'
*/
{
    "matches": [
        {
            "eventNumber": 1,
            "eventMessage": "127.0.0.1 - frank [10/Oct/2000:13:25:15 -0700] \"GET /apache_pb.gif HTTP/1.0\" 200 1534",
            "extractedValues": {
                "$6": "200",
                "$7": "1534",
                "$4": "10/Oct/2000:13:25:15 -0700",
                "$5": "GET /apache_pb.gif HTTP/1.0",
                "$2": "-",
                "$3": "frank",
                "$1": "127.0.0.1"
            }
        }
    ]
}

[]""で囲まれると空白を含んでいても1フィールドとして扱われるようです。 また、タブは空白と同じ扱いでした。

よくわからないのは'' () {}で囲んでも1フィールドとして扱われないんですよね…Apacheのログに無理矢理合わせた感が。

"..."内での"のエスケープの仕方をご存じの方がいたらご教授いただけると幸いです(どうもできなさそうな…)

metric

valueはイベントがPutされたときにMetricに記録する値のようです。 数値以外にも"Error"とか設定できます。

またリクエストのデータ構造を見る限り、複数のMetricTransformationを設定できるようにも見えるのですがLength constraints: Minimum of 1 item(s) in the list. Maximum of 1 item(s) in the list.とのこと…

CloudWatch Logs Agent

なにそれ?おいしいの?