CloudWatch 알람과 그래프를 함께 Slack 알림

2019/7/25 추가



AWS Chatbot 서비스로 CloudWatch 경보를 Slack에 쉽게 알릴 수 있습니다.

개별적으로 통지 내용을 커스터마이즈하고 싶은 경우는 변함없이 Lambda 함수를 작성할 필요가 있기 때문에
그러한 경우에 본 기사의 내용이 참고가 되면 다행입니다.

소개



Amazon CloudWatch에는 AWS 콘솔이 아닌 사용자 지정 대시보드를 생성할 수 있는 기능이 추가되었습니다.
htps : // 아 ws. 아마존. 이 m / jp / 아보 t-a ws / u ts- w / 2018/09 / 아마 존 - c u t ch - ds - abi ty - 와 ld-ku s와 m sh 보아 rds - 우우 츠에서 - ぇ - 아 ws - 안녕하세요 /

구현 예로서 GetMetricWidgetImage API 및 SES를 사용하여 CloudWatch 알람과 함께
그래프 이미지를 메일 통지하는 방법이 공식 Blog에서 소개되고 있습니다.

Reduce Time to Resolution with Amazon CloudWatch Snapshot Graphs and Alerts | Amazon Web Services
htps : // 아 ws. 아마존. 이 m / jp / b ぉ gs / ゔ ぉ ps / Rezuse-chime-To Reso Chion-U-Th-Amazon-C-Udo-tch-s p-sh-tg 등의 phs- an d-a rts /

Slack으로 화상도 통지할 수 있으면. . . 라고 생각해, 상기를 참고로 만들어 보았습니다.

거친 구성





Lambda는 python3.6에서 구현되지만 기본 구성은 메일 알림 버전과 거의 다르지 않습니다.
CloudWatch에서 알람을 감지하면 SNS에 알립니다.
Lambda 함수가 SNS 트리거로 시작됩니다. GetMetricWidgetImage API에서 대상 알람
그래프를 가져오고 Slack API의 files.upload 메서드에서 알람 정보와 그래프를 Post합니다.

결과 이미지



알람이 발생하면 다음과 같이 대상 메트릭의 그래프가 업로드됩니다.


주석을 삽입할 수 있으므로 임계값을 초과한 상태를 쉽게 확인할 수 있다고 생각합니다.
Slack Bot을 사용하고 있기 때문에, 후술하는 Lambda 함수의 설정에는 Bot 유저의 Token과
알림 대상 채널 ID가 필요합니다.
비공개 채널의 경우 Bot 사용자를 invitate하십시오.

OK 상태에 대한 알람을 정의한 경우 임계값 아래로 떨어진 경우에도 알립니다.
다음은 GetMetricWidgetImage API에서 얻은 이미지입니다.


Lambda 함수



병아리 코드 일지 모르지만 용서하십시오
환경 변수 CHANNEL에 채널 ID를, TOKEN에 Bot 사용자의 Token을 설정해야합니다.

lambda_function.py
import base64
import boto3
import json
import logging
import os
import requests

from botocore.exceptions import ClientError

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def get_params(title, message):
    token = os.environ['TOKEN']
    channel = os.environ['CHANNEL']
    reason = message['NewStateReason']
    slack_params = {
        'token': token, 
        'channels': channel,
        'initial_comment': reason,
        'title': title
    }
    return slack_params

def get_properties(alarm_state):
    if alarm_state == "ALARM":
        properties = { 'color': '#ff6961', 'label': 'Trouble threshold start' }
    elif alarm_state == "OK":
        properties = { 'color': '#009933', 'label': 'Trouble threshold end' }
    return properties

def get_image(title, message):
    threshold = message['Trigger']['Threshold']
    metrics = [ message['Trigger']['Namespace'], message['Trigger']['MetricName'],
        message['Trigger']['Dimensions'][0]['name'], message['Trigger']['Dimensions'][0]['value'] ]
    alarm_state = message['NewStateValue']

    annotation_properties = get_properties(alarm_state)

    widget_definition = json.dumps(
        {
            "width": 600,
            "height": 400,
            "start": '-PT2H',
            "end": "PT0H",
            "timezone": '+0900',
            "view": "timeSeries",
            "stacked": False,
            "stat": "Average",
            "title": title,
            "metrics": [ metrics ],
            "period": 300,
            "annotations": {
                "horizontal": [
                {
                    "color": annotation_properties['color'],
                    "label": annotation_properties['label'],
                    "value": threshold
                }]
            }
        }
    )

    cloudwatch = boto3.client('cloudwatch')

    try:
        response = cloudwatch.get_metric_widget_image(
            MetricWidget = widget_definition
        )
    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        image = {'file': response['MetricWidgetImage']}
        print("Get Image succeeded:")
        return image

def upload_slack(upload_url, params, files):
    req = requests.post(upload_url, params=params, files=files)
    try:
        req.raise_for_status()
        logger.info("Message posted.")
        return req.text
    except requests.RequestException as e:
        logger.error("Request failed: %s", e)

def lambda_handler(event, context):
    title = event['Records'][0]['Sns']['Subject']
    message = json.loads(event['Records'][0]['Sns']['Message'])
    upload_url = 'https://slack.com/api/files.upload'
    params = get_params(title, message)
    files = get_image(title, message)
    response = upload_slack(upload_url, params, files)
    return response

widget_definition에서 API의 입력 매개 변수를 정의합니다.
전체 구조는 아래 문서를 참조하십시오.

GetMetricWidgetImage: Metric Widget Structure and Syntax
htps : // / cs. 아 ws. 아마존. 코 m / 아마 존 C ぉ 우도 tch / ㅁ st / あぴれふぇ れせ / C ぉ うぁ t ch め t e u 드 t t St 루 c 얽힌. HTML

상기를 바탕으로 boto3 의 get_metric_widget_image 메소드로 그래프를 취득합니다.

Boto 3 Documentation CloudWatch
htps : // 보토 3. 아마조나 ws. 코 m/v1/도쿠멘들 온/아피/ㅁ st/레후 렌세/세 rゔぃせ s/cぉ우도 tch. html #C ぉ 우도 tch. C 엔 t. 게이 t_메 티 c_ 우드 게 t_

2018/9/26 시점에서, 도쿄 리전의 Lambda 실행 환경에 포함되는 boto3에서는
get_metric_widget_image를 사용할 수 없습니다. 어느 쪽이든 업그레이드된다고는 생각합니다만,
현재 배포 패키지 (zip)에 최신 버전의 boto3을 포함시켜야합니다.
또한 통신 라이브러리에 requests를 사용하고 있으므로 여기도 배포 패키지에 포함합니다.

설정 보충



SNS



빈 주제를 만들어 둡니다.

람다



트리거에 SNS를 추가합니다.



트리거 설정에서 대상 SNS Topic을 지정합니다.



반복하지만 환경 변수에 CHANNEL (통지 대상 채널 ID)
TOKEN (Bot 사용자의 Token)을 지정합니다.



실행 역할은 지표 데이터를 검색할 수 있도록 정책을 설정합니다.
타임아웃은 디폴트의 3초에서는 타임 아웃 할 가능성이 있으므로 5초로 해 둡니다.



CloudWatch



대상 CloudWatch 알람의 알림 작업에 생성한 SNS Topic을 지정합니다.


참고 URL



htps : // 기주 b. 코 m / 아 ws - mp ぇ s / 아 ws - c ぉ 우도 t ch s p 쇼 tg 등 phs - r t - xt
htps : //에서 v.ぁsss d. jp / c ぉ d / 아 ws / ぁ mb다 - py 쵸 - 치 ps - 아- ゔ ぇ ts - 그 - t - ct /

이상입니다.
도움이되면 다행입니다.

좋은 웹페이지 즐겨찾기