본문 바로가기

DevOps

[AWS] 클라우드 와치 로그에서 특정 패턴일 경우 Slack 알람 보내는 방법

반응형

1. 구성

 

구성은 정말 간단하다.

 

CloudWatch 로그 그룹에 애플리케이션 로그들이 쌓이고 있다. →

구독 필터로 특정 패턴을 감지하여 AWS Lambda로 보내준다. →

AWS Lambda에서는 메시지를 전달받은 뒤 가공하여 Slack으로 메시지를 보내준다.

 

 

serverless 프레임워크를 활용한다.

 

serverless.yml

service: SLACK-NOTIFICATION

frameworkVersion: "3"

plugins:
  - serverless-dotenv-plugin

provider:
  name: aws
  profile: XXXXXXX
  timeout: 30
  memorySize: 256
  runtime: nodejs18.x
  stage: prod
  region: ap-northeast-2
  iam:
    role: arn:aws:iam:XXXX:role/XXXXXXXX

functions:
  main:
    handler: handler.main

 

.env 파일에는 Slack token , alert을 보낼 slack channel id가 있다.

 

 

handler.js

'use strict';

import zlib from 'zlib';
import { sendSlackMessage } from "./libs/slack.js"

export async function main(event) {

  // event.awslogs가 있을 경우
  if (event.awslogs && event.awslogs.data) {

    // 1. event로 들어오는 압축된 데이터를 풀어주자.
    const payload = Buffer.from(event.awslogs.data, 'base64');
    const decodedData = JSON.parse(zlib.unzipSync(payload).toString())

    console.log(decodedData);

    const logGroup = decodedData.logGroup;
    const indexes = decodedData.logEvents.keys();
    
    // 2. 여러개의 log가 들어오기 때문에 반복문을 수행해준다.
    for await (const index of indexes) {

      // slack으로 message를 보낸다.
      const result = await sendSlackMessage(process.env.SLACK_CHANNEL, logGroup, decodedData.logEvents[index].message);

      console.log(result.ok);

    }
  }
  
  return { statusCode: 200, body: "ok"};
};

 

1. cloudwatch 구독 필터를 lambda로 보낼 경우 인코딩되어 들어오기에 디코딩을 해줘야 한다.

2. logEvents이기 때문에 이걸 각 logEvent로 반복문을 수행해줘야 한다.

3. slack으로 메시지를 보낸다.

 

 

libs/slack.js

import { WebClient } from '@slack/web-api';

// Initializing
const webClient = new WebClient(process.env.TOKEN);

async function sendSlackMessage(SLACK_CHANNEL, logGroup, logMessage) {
    try {

        const template = {
            "channel": SLACK_CHANNEL,
            "blocks": [
                {
                    "type": "section",
                    "text": {
                        "type": "mrkdwn",
                        "text": '*Error 로그 발생*\\n\\nCloudWatch Log Group : *'+ logGroup + '*\\n'
                    }
                },
                {
                    "type": "divider"
                }
            ],
            "attachments": [
                {
                    "fallback": "Fallback 입니다.",
                    "color": "#eb4034",
                    "blocks": [
                        {
                            "type": "section",
                            "text": {
                                "type": "mrkdwn",
                                "text": logMessage
                            }
                        }
                    ]
                }
            ]
        };
        
        // Call the chat.postMessage method using the WebClient
        const result = await webClient.chat.postMessage(template);

        return result
    } catch (error) {
        console.error(`Error sanding message ! : ${error}`);
        return "error";
    }
}

export { sendSlackMessage };

 

 

 

로컬 테스트

로컬에서 테스트를 하기 위해서는 sample event data를 가지고 invoke 해줘야 한다.

sls invoke local --function main --path data/event.json

 

 

배포

sls deploy

 

 

 

배포한 뒤에 Cloudwatch log 에 들어가 구독 필터를 적용하여 해당 배포한 lambda와 연결해준다. 

 

 

아래는 예시이다.

소스는 제공해드렸으니 필요하다면 slack message template은 보기좋은대로 수정하여 사용하면 된다.

 

 

 

반응형