1
1

More than 1 year has passed since last update.

AWS CloudWatch Logsのput log eventsとメトリクスフィルターで簡易的な監視

Posted at

はじめに

AWS CloudWatch Logsのput-log-eventsでCloudWatch Logsへログを送り、メトリクスフィルターでログの内容を監視します。

CloudWatch Agentでログを送信した方が素直な実装です。

put-log-events

参考

put-log-events を行う時のBashスクリプト

#!/bin/bash -

readonly PROCNAME=${0##*/}
function log() {
  local fname=${BASH_SOURCE[1]##*/}
  echo "$(date '+%Y-%m-%dT%H:%M:%S') ${PROCNAME} (${fname}:${BASH_LINENO[0]}:${FUNCNAME[1]}) $@" 
}

export SERVICE_NAME=$1 # hello_world.service
# CloudWatchLogs設定
export LOG_GROUP_NAME=$2  # /aws/ec2/service-status
export LOG_STREAM_NAME=$3 # status
export AWS_DEFAULT_REGION=ap-northeast-1

function main() {
  log "Start batch program."

  # CloudWatchLogsにPUTするメッセージ
  message=$(systemctl show $SERVICE_NAME | grep "ActiveState=")
  log $message

  # put-log-eventに利用するトークン
  upload_sequence_token=$(aws logs describe-log-streams --log-group-name "$LOG_GROUP_NAME" --query 'logStreams[?logStreamName==`'$LOG_STREAM_NAME'`].[uploadSequenceToken]' --output text)

  # put-log-eventに利用するタイムスタンプ
  time_stamp=$(date +%s%3N)

  # put-log-eventsの実行
  if [ "$upload_sequence_token" != "None" ]
  then
    # トークン有りの場合
    aws logs put-log-events --log-group-name "$LOG_GROUP_NAME" --log-stream-name "$LOG_STREAM_NAME" --log-events timestamp=$time_stamp,message="$message" --sequence-token $upload_sequence_token  --output text
  else
    # トークン無しの場合(初回のput)
    aws logs put-log-events --log-group-name "$LOG_GROUP_NAME" --log-stream-name "$LOG_STREAM_NAME" --log-events timestamp=$time_stamp,message="$message"  --output text
  fi
  log "End batch program."
}

main

このスクリプトに

sudo chmod 755 monitor-by-putting-logs-to-cloudwatch.sh

と実行権限を付ける。cronでスクリプトを定期実行したり、送りたいログをbashの引数として与えて実行すると指定のCloudWatch Logsのロググループへログを送れる。

スクリプトを実行するのに必要なAWSの権限

スクリプト中の describe-log-streamsput-log-events を実行するために logs:DescribeLogStreamslogs:PutLogEvents の権限が必要となる。 logs:PutLogEvents は他のCloudWatchLogsへログを追加できる権限となるため、気になる場合は適宜リソースを制限すること。

IAMポリシー

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogStreams",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}

put-log-eventに利用するトークン

put-log-events は2回目以降のputではトークンが必要となる。そのため、

upload_sequence_token=$(aws logs describe-log-streams --log-group-name "$LOG_GROUP_NAME" --query 'logStreams[?logStreamName==`'$LOG_STREAM_NAME'`].[uploadSequenceToken]' --output text)

でトークンを取得する必要がある。

put-log-eventに必要なタイムスタンプ

put-log-events の使用時には必ずミリ秒まで含めた13桁のUNIXタイムが必要となる。13桁のUNIXタイムは下記のdateコマンドで取得できる。

time_stamp=$(date +%s%3N)

メトリクスフィルターなどのCloudFormation

CloudWatch Alarmの通知先のAWS SNS Topicはすでにあるものとする。
作成しているリソース

  • CloudWatch Logs
    • ロググループ
    • ログストリーム
    • メトリクスフィルター
  • CloudWatch Alarm
    • アラーム
AWSTemplateFormatVersion: 2010-09-09
Description: >-
  alert crontab result, and monitoring crontab

Parameters:
  SNSTopicARN:
    Description: SNS Topic ARN for Notification
    Type: String
  ProjectName:
    Description: Project Name
    Type: String

Resources:
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties: 
      LogGroupName: !Sub /aws/ec2/${ProjectName}-service-status
      RetentionInDays: 1
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-logstream.html
  LogStream:
    Type: AWS::Logs::LogStream
    Properties: 
      LogGroupName: !Ref  LogGroup
      LogStreamName: "service-status"
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-metricfilter.html
# aws logs describe-metric-filters --output yaml
  MetricFilter:
    Type: AWS::Logs::MetricFilter
    Properties: 
      FilterPattern: "ActiveState=active" ## 適宜書き換え
      LogGroupName: !Ref LogGroup
      MetricTransformations: 
      - DefaultValue: 0.0
        MetricName: !Sub ${ProjectName}-filter-active
        MetricNamespace: !Sub ${ProjectName}-service-status
        MetricValue: 1
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html
# aws cloudwatch describe-alarms --alarm-names "active-alarm"  --output yaml
  CloudWatchAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties: 
      ActionsEnabled: true
      AlarmActions:
      - Ref: SNSTopicARN
      AlarmDescription: >-
        Monitor ec2 service status log.
      AlarmName: !Sub ${ProjectName}-active-alarm
      ComparisonOperator: LessThanOrEqualToThreshold
      DatapointsToAlarm: 1
      Dimensions: []
      EvaluationPeriods: 1
      InsufficientDataActions: []
      MetricName: !Sub ${ProjectName}-filter-active
      Namespace: !Sub ${ProjectName}-service-status
      Period: 300
      Statistic: Sum
      Threshold: 0.0
      TreatMissingData: breaching

メトリクスフィルターのフィルターパターン

メトリクスフィルターではフィルターパターンによってログを監視可能なメトリクスに変換している。

公式リファレンス

参考

下記のフィルターパターンの場合、 ActiveState=active を含むログがあるときメトリクスの値を 1 とする。

  MetricFilter:
    Type: AWS::Logs::MetricFilter
    Properties: 
      FilterPattern: "ActiveState=active" ## 適宜書き換え
      LogGroupName: !Ref LogGroup
      MetricTransformations: 
      - DefaultValue: 0.0
        MetricName: !Sub ${ProjectName}-filter-active
        MetricNamespace: !Sub ${ProjectName}-service-status
        MetricValue: 1

ログのWatchDog

CloudFormationの下記の項目で TreatMissingData: breaching と設定すると、ログが定期的に送信されなくなった時アラートを送ることができる。
メトリクスが無い状態をどう扱うか設定しており、この設定では Period: 300 (=5分間) メトリクスが無い場合、 INSUFFICIENT_DATA としてアラートを送信する。

  CloudWatchAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties: 
      Period: 300
      TreatMissingData: breaching

公式リファレンス

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1