5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CloudWatchメトリクスを定期的に取得するログ監視システムの構築(2)

Posted at

先月の記事 でCloudWatchのログを定期的に取得してS3に保存するshellscriptを書いたが、EC2上に置いておくとその都度インスタンスを起動しないといけないため、ちょっとイケてない。

そこで、今回はlambdaから実行するバージョンを作ってみる。

##概要(今回学んだこと)

  • lambdaには一時的に利用できる/tmp/ディレクトリがあること。
  • s3のライフサイクル
  • 日付の取得(python)
  • csvファイルの作成(python)

ソースコード

コード全部

##構成

###メイン関数

def lambda_handler(event, context):
    all_metrics_list = [
        {
        'NameSpaceHeader' : 'AWS/',
        'NameSpace' : 'EC2',
        'MetricName':'CPUUtilization',
        'Dimensions':[{"Name" : "InstanceId","Value" : "i-xxxxxxxxxxxxxxxxx"}],
        'Statistics' : 'Average'
        }
    ]

    for target in all_metrics_list:
        #メトリクス取得
        logs = getMetricStatistics(target)

        #CSVへ変換・ソート
        convertCSV(logs['Datapoints'])
        sortCSV()

        #適当なフォルダ名/ファイル名を生成して、s3へアップ
        uploadToS3(generateFileName(target))

    return {
        'statusCode': 200,
        'body': json.dumps('finish lambda')
    }

##各論

###日付の取得

CloudWatchメトリクスはGMTなので、JSTで1日分のログを収集するには15時で切る。(JSTで指定したい)

today = datetime.today()
yesterday = today - timedelta(days=1)
dayBeforeYesterday = today - timedelta(days=2)

folder_title = datetime.strftime(yesterday, '%Y-%m-%d')
endTime = datetime.strftime(yesterday, '%Y-%m-%dT15:00:00Z')
startTime = datetime.strftime(dayBeforeYesterday, '%Y-%m-%dT15:00:00Z')

###メトリクスの取得

メトリクスによっては必要なDimensionが異なる。これが正しくないとNo Dataが返り続ける。

def getMetricStatistics(target_dict):
    cloudwatch = boto3.client('cloudwatch', region_name='ap-northeast-1')

    logs = cloudwatch.get_metric_statistics(Namespace=target_dict["NameSpaceHeader"] + target_dict["NameSpace"],
                                MetricName=target_dict["MetricName"],
                                Dimensions=target_dict["Dimensions"],
                                StartTime=startTime,
                                EndTime=endTime,
                                Period=300,
                                Statistics=[target_dict["Statistics"]]
                                )
    return logs

###csvへの変換とソート
lambdaではtmpディレクトリが用意されている。ここに整形するファイルを置いておく。

def convertCSV(datapoints):
    with open('/tmp/tmp.txt','w') as f:
        if len(datapoints) == 0:
            print("Empty")
            pass
        else:
            csv.register_dialect('dialect1', doublequote=True, quoting=csv.QUOTE_ALL)
            writer = csv.DictWriter(f, fieldnames=datapoints[0].keys(), dialect="dialect1")
            for row in datapoints:
                writer.writerow(row)


def sortCSV():
    with open('/tmp/tmp.txt', 'r') as f:
        reader = csv.reader(f)
        result = sorted(reader, key=operator.itemgetter(0))

    with open('/tmp/tmp.txt', 'w') as f:
        data = csv.writer(f,delimiter=',')
        for row in result:
            data.writerow(row)

withキーワードを使用すると、ファイル操作中にエラー終了してもcloseしてくれるので有能。

#####csvモジュールについて

register_dialect : dialectを登録する。デリミタやクオーテーションの種類などはここで指定して、1つのセットを作り命名する。

DictWriter : 辞書を出力行にマップするオブジェクトを生成する。fieldnamesはファイルに書き込む順番。

書き出す前にwriter.writeheader()でヘッダーをつけられる。今回はいらない。

S3ライフサイクルの設定

Intelligent-TIERINGは、参照頻度に応じてStandardとStandard-IAに割り振ってくれる。30日アクセスされなければStandard-IAへ格納する。

管理タブから設定。S3はオブジェクトのバージョン管理もできるので有効にする場合には、現行のバージョン(LATEST)と以前のバージョンのそれぞれにライフサイクルのルールを設定できる。

公式ドキュメント

おわりに

あとはCloudWatch Events(cron)で定期実行していけば自然にログが貯まる。

ただ、0時ちょうどに実行すると日付が正しくないような気がする?(今後もう少し検討)

##EC2上にスクリプトを置いてログ収集をする以前の方法

CloudWatchメトリクスを定期的に取得するログ監視システムの構築

5
2
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
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?