こんにちは。Amazonの犬、サカイです。
Dashボタンは我が家に2つあります。(じゃがりこ、柿の種)
AWSでWindows Serverを使用していて、イベントログ監視をするために、
CloudWatchLogsを使いたいな~、って人は少なく無いと思います。
ただ、SSMエージェント等を使えば今では簡単に実現可能ですね。
それに留まらず、WarningやError系のレベルだったらメール通知なんかもしたいな~、なんて欲張りな人も
いると思います。
そんな欲張りさんな人向けに、優しい方がLambdaで実現方法を共有して下さっています。
cloudwatchlogs -> lambda -> SNSを試してみた
https://qiita.com/sadayuki-matsuno/items/83b70ee97755e534764f
ただ、僕はもっと欲張りさんなので
通知される内容で、特定の文字が入ったメッセージは送信されないようにフィルタしたいな~、と思っちゃいました。
※CloudWatchLogsのメトリクスフィルタで実現出来ない事はないのですが、
省きたい文字列がフィルタパターンの上限に達しちゃったので他には方法は無いかを考えました。
思っちゃったものは仕方ないので、上記のLambdaでのメール送信スクリプトをベースに改良を加えました。
関数を作る
メール送信スクリプトのフローと併せて、どういう事がしたいかをまとめると
- WindowsServer上でError系レベルのイベントログが書き込まれる
- CloudWatchLogsへと転送される
- CloudWatchLogsへと転送されてきたイベントをトリガーにLambdaが発火
- AWSのSNSトピックに登録されているメーリングリスト宛にイベントログ内容なんかを送信
- ただ、特定の文字列がイベントログに入っている場合はメール送信しない!
参考にさせて頂いたメール送信プログラムでは、4番までしか実現されていないため、5番目を実現する関数を作りました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
def lambda_handler(event, context): #参考にさせて頂いたメール送信プログラム本体
data = zlib.decompress(base64.b64decode(event['awslogs']['data']), 16+zlib.MAX_WBITS)
data_json = json.loads(data)
log_json = json.loads(json.dumps(data_json["logEvents"][0], ensure_ascii=False))
#If文にメッセージチェック処理を追加
if data_json["logGroup"] and not (log_message_omit_check(log_json['message'])):
date = datetime.datetime.fromtimestamp(int(str(log_json["timestamp"])[:10])) + datetime.timedelta(hours=9)
sns_body = {}
sns_body["default"] = ""
sns_body["default"] += "Owner : " +data_json["owner"] + "\n"
sns_body["default"] += "LogGroup : " + data_json["logGroup"] + "\n"
sns_body["default"] += "LogStream : " + data_json["logStream"] + "\n"
sns_body["default"] += "SubscriptionFilters : " + ''.join(data_json["subscriptionFilters"]) + "\n"
sns_body["default"] += "Time : " +date.strftime('%Y-%m-%d %H:%M:%S') + "\n"
sns_body["default"] += "Message : " + log_json['message'] + "\n"
topic = 'arn::XXXXXXX' #送りたいメーリングリストを入れる
subject = '監視メール' #メールタイトル
region = 'ap-northeast-1'
response = sns.publish(
TopicArn=topic,
Message=json.dumps(sns_body, ensure_ascii=False),
Subject=subject,
MessageStructure='json'
)
return 'Successfully processed {} records.'.format(len(event['awslogs']))
def log_message_omit_check(log_message): #特定のメッセージは省く関数
omit_message = []
omit_message.append('TEST_ERROR') #省きたいメッセージをシングルクオートの間に書く
omit_message.append('ERROR_TEST') #複数ある場合は2行目以降にアペンドしていく
#省くメッセージが入っていないかチェック
for message in omit_message:
if message in log_message:
return True
return False
|
やっていることは至極簡単で、省きたい文字列を配列に入れ、forで回しているだけです。
後は動作確認をします。
下記コマンドをコマンドプロンプトから実行して、強制的にエラーを出してみましょう!
1
|
eventcreate /T Error /id 909 /d TEST_ERROR
|
メール送信がされなくなったら大成功です。
なお、省きたいメッセージ全てを入れる必要は無く、一部分だけでも一致すればフィルタされます。