1
0

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 1 year has passed since last update.

CloudWatchログアラームの作成が面倒なので、Excelから設定値を読み込んで作成できるようにしてみた。

Last updated at Posted at 2023-02-05

はじめに

こんにちは、山田です。
今回は、CloudWatchログアラームをExcelから作成する方法について記載していきます。
よろしくお願いします。

概要図

概要図は以下の通りです。
image.png
①:Lambdaを用いて、Excelファイルを作成してS3にアップロードします。
②:作成されたExcelファイルをダウンロードします。
③:ダウンロード後、Excelファイルを記入してアップロードします。
④:Lambdaを用いて、Excelファイルを読み込みCloudWatchアラームを作成します。

エクセルファイル作成用Lmabdaのフローチャート・コード

エクセルファイル作成用Lmabdaのフローチャート・コードはそれぞれ以下になります。

フローチャート

フローチャートは以下の通りです。
フローチャート (1).png

コード

実際のコードは以下の通りです。

import openpyxl
import boto3
import os
from openpyxl import Workbook
from openpyxl.worksheet.datavalidation import DataValidation
from openpyxl.styles import PatternFill, Font, Border, Side

s3 = boto3.resource('s3')
s3_client = boto3.client('s3')
sns_client = boto3.client('sns')
cloudwatch_client = boto3.client('cloudwatch')
logs_client = boto3.client('logs')

os.chdir('/tmp')

book = openpyxl.Workbook()
book_x = book.active
book_x.title = 'ログアラーム'
book_y = book.create_sheet('メトリクスフィルター')

book_sheet = ["ログアラーム","メトリクスフィルター"]
for item in book_sheet:
    sheet = book[item]
    for row in range(1,100):
        for col in range(1,6):
            cell = sheet.cell(row = row, column = col)
            cell.font = openpyxl.styles.Font(name='MeiryoUI')
    
    fill = PatternFill(start_color="1F497D", end_color="1F497D", fill_type = "solid")
    font = Font(bold=True, color="FFFFFF")
    for col in range(1,6):
        cell = sheet.cell(row = 1, column = col)
        cell.fill = fill
        cell.font = font
        
    thin = Side(border_style="thin", color="000000")
    for row in range(1,100):
        for col in range(1,6):
            cell = sheet.cell(row = row, column = col)
            cell.border = Border(left=thin, right=thin, top=thin, bottom=thin)
    
    sheet.column_dimensions['I'].hidden = True


def create_logalarmsheet():

    sheet = book['ログアラーム']

    sheet['A1'] = 'No.'
    sheet['B1'] = 'AlarmName'
    sheet['C1'] = 'Description'
    sheet['D1'] = 'MetricsName'
    sheet['E1'] = 'SNS ARN'
    
    sns=[]

    response=sns_client.list_topics()
    count = 0
    for i in range(len(response['Topics'])):
        sns.append(response['Topics'][i]['TopicArn'])
        count+=1
    count = 0
    while 'nextToken' in response:
        response=sns_client.list_topics(nextToken=response['nextToken'])
        for i in range(len(response['Topics'])):
            sns.append(response['Topics'][i]['TopicArn'])
            count+=1

    for i in range(2,100):
        sheet.cell(row=i,column=4).value = '=メトリクスフィルター!E' + str(i)
    
    for i in range(1,100):
        sheet['D'+str(i)].number_format = '#'
    
    for i in range(len(sns)):
        sheet.cell(row=(i+1),column=9).value = sns[i]
        
    dv = DataValidation(type="list", formula1='I1:I'+str(len(sns)), allow_blank=True)
    dv.add(f"E2:E100")

    sheet.add_data_validation(dv)

def create_metricsfiltersheet():

    sheet = book['メトリクスフィルター']

    sheet['A1'] = 'No.'
    sheet['B1'] = 'LogGroupName'
    sheet['C1'] = 'FilterName'
    sheet['D1'] = 'FilterPattern'
    sheet['E1'] = 'MetricsName'

    loggroup = []

    response=logs_client.describe_log_groups()
    count = 0
    for i in range(len(response['logGroups'])):
        loggroup.append(response['logGroups'][i]['logGroupName'])
        count+=1
    count = 0
    while 'nextToken' in response:
        response=logs_client.describe_log_groups(nextToken=response['nextToken'])
        for i in range(len(response['logGroups'])):
            loggroup.append(response['logGroups'][i]['logGroupName'])
            count+=1
    
    for i in range(len(loggroup)):
        sheet.cell(row=(i+1),column=9).value = loggroup[i]
        
    dv = DataValidation(type="list", formula1='I1:I'+str(len(loggroup)), allow_blank=True)
    dv.add(f"B2:B100")
    
    sheet.add_data_validation(dv)

def lambda_handler(event, context):
    create_logalarmsheet()
    create_metricsfiltersheet()
    book.save('エクセル名.xlsx')
    s3_client.upload_file('エクセル名.xlsx','エクセルファイルをアプロードするS3バケット名', 'エクセル名.xlsx')

Excelファイル

実際に生成されるエクセルファイルの以下の通りです。
image.png
image.png

CloudWAtchアラーム作成用Lmabdaのフローチャート・コード

CloudWAtchアラーム作成用Lmabdaのフローチャート・コードは以下の通りです。

フローチャート

フローチャートは以下の通りです。
フローチャート (2).png

コード

実際のコードは以下の通りです。

import openpyxl
import boto3
import os
import time
from io import BytesIO

s3 = boto3.resource('s3')
s3_client = boto3.client('s3')
sns_client = boto3.client('sns')
cloudwatch_client = boto3.client('cloudwatch')
logs_client = boto3.client('logs')

os.chdir('/tmp')

source_bucket_obj = s3.Bucket('S3バケット名')
source_bucket_obj.download_file('エクセル名.xlsx', 'エクセル名.xlsx')
book = openpyxl.load_workbook('エクセル名.xlsx')
def put_logevent():
    
    s3_resp = s3_client.get_object(Bucket='S3バケット名', Key='エクセル名.xlsx')
    wb = openpyxl.load_workbook(BytesIO(s3_resp['Body'].read()),data_only=True)
    sheet = wb["メトリクスフィルター"]
    
    B = []
    D = []
    
    eng=[B,D]
    
    B_column = len(list(sheet.columns)[2])
    for item in eng:
        count = (eng.index(item)+1)*2
        for i in range(2,B_column+1):
            if sheet.cell(row=i, column=count).value is not None:
                item.append(sheet.cell(row=i, column=count).value)


    for i in range(len(B)):
        res = logs_client.describe_log_streams(
          logGroupName=B[i])
        seq_token=res['logStreams'][0]['uploadSequenceToken']
        response = logs_client.put_log_events(
        logGroupName=B[i],
        logStreamName=res['logStreams'][0]['logStreamName'],
        logEvents=[
            {
            'timestamp': int(time.time()) * 1000,
            'message': D[i]
            },
        ],
        sequenceToken = seq_token
        )

def create_metricsfilter():
        
    sheet = book['メトリクスフィルター']

    B = []
    C = []
    D = []
    E = []
    
    eng=[B,C,D,E]

    B_column = len(list(sheet.columns)[1])
    print(B)
    for item in eng:
        count = eng.index(item)+2
        for i in range(2,B_column+1):
            if sheet.cell(row=i, column=count).value is not None:
                item.append(sheet.cell(row=i, column=count).value)
    
    for i in range(len(B)):
        logs_client.put_metric_filter(
        logGroupName=B[i],
        filterName=C[i],
        filterPattern=D[i],
        metricTransformations=[
            {
                'metricName': E[i],
                'metricNamespace': 'Logs',
                'metricValue': '1',
            },
        ]
        )

def create_logalarm():
    
    sheet = book['ログアラーム']
    sheet2 = book['メトリクスフィルター']
    
    for i in range(2,100):
        sheet['D'+str(i)] = sheet2['E'+str(i)].value
    
    B = []
    C = []
    D = []
    E = []
    
    eng=[B,C,D,E]

    B_column = len(list(sheet.columns)[1])
    for item in eng:
        count = eng.index(item)+2
        for i in range(2,B_column+1):
            if sheet.cell(row=i, column=count).value is not None:
                item.append(sheet.cell(row=i, column=count).value)

    for i in range(len(B)):
      response=cloudwatch_client.put_metric_alarm(
      AlarmName=B[i],
      AlarmDescription=C[i],
      ActionsEnabled=True,
      AlarmActions=[
        E[i],
      ],
      MetricName=D[i],
      Namespace='Logs',
      Statistic='Sum',
      Period=300,
      Unit='Seconds',
      Threshold=1,
      EvaluationPeriods=1,
      ComparisonOperator='GreaterThanOrEqualToThreshold'
      )

def lambda_handler(event, context):    
    create_metricsfilter()
    put_logevent()
    time.sleep(5)
    create_logalarm()

動作確認

前提条件は以下の通りです。

・メトリクスが保存されている名前空間は「Logs」
・アラーム通知条件は、5分間の合計値が1以上になった場合

エクセルファイル作成用Lmabdaを実行します。
image.png
エクセルファイルをダウンロードします。
image.png
エクセルを記入します
image.png
image.png
エクセルファイルを同じ名前でアップロードします。
image.png
CloudWAtchアラーム作成用Lmabdaを実行します。
image.png
CloudWatchアラームが作成されていることが確認できれば完了。
image.png

終わりに

今回はログアラームをExcelより作成する方法について記載しました。
まだまだ改良点はあると思うので、これからも改善していきたいと思います。
また、その他のメトリクスに関してもExcelファイルから作成できるようにしていきたいと思います。
最後まで拝読いただきありがとうございます。

1
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?