Amazon CloudWatch Logsの異常検出ができるようになりました。 とはいえ、既存のロググループがたくさんあるとき、ひとつひとつ設定するのは大変です。 というわけで、「既存のロググループの一覧を取得して、CloudWatch Logsの異常検出を設定するCloudFormationテンプレート」を作成するスクリプトを作ってみました。
おすすめの方
- CloudWatch Logsの異常検出をCloudFormationで設定したい方
- CloudWatch Logsの異常検出を既存のロググループになるべく簡単に適用したい方
今回のお試し対象
今回は、ロググループのprefixが「/aws-glue」である3つのロググループで試してみます。
「CloudWatch Logsの異常検出を設定するCloudFormationテンプレート」を作成するスクリプト
次のパラメータをいい感じにすると便利です。(どちらかひとつだけを指定できます)
- logGroupNamePrefix
- logGroupNamePattern
なお事前に次のライブラリをインストールしておきます。
app.py
# pip install pyyaml
# pip install boto3
import yaml
import boto3
logs = boto3.client("logs")
base = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "CloudWatch Logs Anomaly Detector Sample made by Python",
"Resources": {},
}
RESOURCE_NAME_SUFFIX = "LogAnomalyDetector"
RESOURCE_NAME_MAX_LENGTH = 255
OUTPUT_FILE_NAME = "cloudwatch_log_anomaly_detector.yaml"
def main():
log_groups = get_log_groups()
for log_group in log_groups:
resource = make_cloudwatch_logs_anomaly_detector(log_group)
base["Resources"].update(resource)
with open(OUTPUT_FILE_NAME, "w") as f:
yaml.dump(base, f, default_flow_style=False, sort_keys=False)
def get_log_groups():
log_groups = []
options = {
"logGroupNamePrefix": "/aws-glue",
# "logGroupNamePrefix": "/aws/lambda",
# "logGroupNamePattern": ".*",
"logGroupClass": "STANDARD",
# "limit": 5,
}
while True:
resp = logs.describe_log_groups(**options)
log_groups += resp["logGroups"]
if "nextToken" not in resp:
break
options["nextToken"] = resp["nextToken"]
return log_groups
def make_cloudwatch_logs_anomaly_detector(log_group: dict[str, str]):
log_group_name = log_group["logGroupName"]
log_group_arn = log_group["arn"]
return {
convert_resource_name(log_group_name): {
"Type": "AWS::Logs::LogAnomalyDetector",
"Properties": {
"DetectorName": log_group_name,
"AnomalyVisibilityTime": 21,
"EvaluationFrequency": "FIFTEEN_MIN",
"LogGroupArnList": [convert_arn(log_group_arn)],
},
}
}
def convert_resource_name(log_group_name: str):
# https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html
resource_name = (
log_group_name.replace("_", "")
.replace("-", "")
.replace("/", "")
.replace(".", "")
.replace("#", "")
)
return resource_name[: RESOURCE_NAME_MAX_LENGTH - len(RESOURCE_NAME_SUFFIX) - 1] + RESOURCE_NAME_SUFFIX
def convert_arn(arn: str) -> str:
# 末尾の「:*」を削る
return arn[:-2]
if __name__ == "__main__":
main()
スクリプトを実行して、CloudFormationテンプレートを作成する
python app.py
作成されたCloudFormationテンプレート
cloudwatch_log_anomaly_detector.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudWatch Logs Anomaly Detector Sample made by Python
Resources:
awsgluecrawlersLogAnomalyDetector:
Type: AWS::Logs::LogAnomalyDetector
Properties:
DetectorName: /aws-glue/crawlers
AnomalyVisibilityTime: 21
EvaluationFrequency: FIFTEEN_MIN
LogGroupArnList:
- arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws-glue/crawlers
awsgluejobserrorLogAnomalyDetector:
Type: AWS::Logs::LogAnomalyDetector
Properties:
DetectorName: /aws-glue/jobs/error
AnomalyVisibilityTime: 21
EvaluationFrequency: FIFTEEN_MIN
LogGroupArnList:
- arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws-glue/jobs/error
awsgluejobsoutputLogAnomalyDetector:
Type: AWS::Logs::LogAnomalyDetector
Properties:
DetectorName: /aws-glue/jobs/output
AnomalyVisibilityTime: 21
EvaluationFrequency: FIFTEEN_MIN
LogGroupArnList:
- arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws-glue/jobs/output
ロググループのARNが複数指定できるように見えますが、ひとつのみ指定できます。 そのため、ロググループの数だけリソースを作成しています。
The ARN of the log group that is associated with this anomaly detector. You can specify only one log group ARN.
デプロイする
aws cloudformation deploy \
--template-file cloudwatch_log_anomaly_detector.yaml \
--stack-name CloudWatch-Logs-Anomaly-Detector-glue-Sample-Stack \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
CloudWatch Logsの様子を見る
しっかりデプロイされていました。
AWS CLIで異常ディテクターの一覧を取得する
今回デプロイした3つの異常ディテクターがあります。 他の2つは以前にデプロイした異常ディテクターです。
aws logs list-log-anomaly-detectors \
--query 'anomalyDetectors[*].detectorName'
[
"lambda-2-log-anomaly-detector-sample",
"/aws-glue/jobs/output",
"/aws-glue/jobs/error",
"/aws-glue/crawlers",
"lambda-1-log-anomaly-detector-sample"
]