DevOps

CloudWatch Logs와 Slack 통합: 에러 메시지 실시간 전송 설정

MIRACLE LIFE 2024. 12. 25. 15:59

알람이 자주 울리면 처음에는 신경을 쓰다가도 점점 무뎌지기 마련이다. 중요하지 않은 알람이나 즉시 처리할 필요가 없는 알람이 계속 오면, 어느 순간 '또 알람이네' 하고 무심코 넘겨버리게 된다. 문제는 이 과정에서 정말 중요한 알람까지 놓칠 수 있다는 점이다.

 

이런 거짓 알람을 원천적으로 차단하는 것이 가장 좋은 해결책이지만, 현실적으로 모든 알람을 완벽하게 정리하기는 어렵다. 따라서, 알람이 왔을 때 내용을 바로 파악할 수 있도록 구성하는 것이 도움이 될 수 있다.

 

이를 위해 CloudWatch 구독 필터를 설정하고 Lambda를 활용해 Slack으로 오류 메시지를 전송하는 방식을 적용할 수 있다. 이를 통해 오류를 신속하게 파악하고, 즉각 대응이 필요한 크리티컬한 문제인지 빠르게 판단할 수 있다.

 

 

사전 준비 사항.

  • CloudWatch Logs 활성화

1. Slack Webhook API 생성

Slack API를 활용해 원하는 채널로 메시지를 보낼 수 있도록 설정할 수 있다.

먼저, 채널 설정에서 Integrations 탭으로 이동한 후, Add an App을 선택해 Incoming WebHooks를 추가한다.

이 과정에서 메시지를 전송할 수 있는 URL이 제공되며, 이를 이용해 Slack 채널로 메시지를 보낼 수 있다.

 

 

참고. https://jojoldu.tistory.com/552

 


2. Lambda 생성

2-1. 함수 생성

트리거로 CloudWatch Logs를 가진 Lambda 함수를 생성한다.

 

Process CloudWatch log data 블루프린트 선택 시 아래 사진과 같이 트리거를 설정하는 화면이 보인다.

  • 로그 그룹:
    구독 필터를 적용할 로그 그룹을 선택한다.
  • 필터 이름:
    필터의 역할을 잘 파악할 수 있도록 적절한 이름을 입력한다.
  • 필터 패턴:
    필터의 패턴을 지정한다. 패턴과 매칭되는 로그가 발생하는 경우, 해당 람다가 트리거 된다.
    ex. { $.statusCode = %5[0-9]{2}% } <- 500 에러를 감지한다.

 

2-2. 함수 구현

로그 메세지를 포맷팅하여 Slack으로 전송한다.

import * as zlib from "node:zlib";
import * as https from "node:https";

export const handler = async event => {
  try {
    const message = extractLogMessage(event);
    const slackUrl = "slack url";
    await sendToSlack(message, slackUrl);
    return `Successfully processed log event.`;
  } catch (error) {
    console.error("Error processing event:", error);
    throw error;
  }
};

function extractLogMessage(event) {
  const payload = Buffer.from(event.awslogs.data, "base64");
  const parsed = JSON.parse(zlib.gunzipSync(payload).toString("utf8"));
  return parsed.logEvents?.[0]?.message || "No message found";
}

async function sendToSlack(message, slackUrl) {
  const { host, pathname } = new URL(slackUrl);
  const options = {
    hostname: host,
    path: pathname,
    method: "POST",
    headers: { "Content-Type": "application/json" },
  };

  return new Promise((resolve, reject) => {
    const req = https.request(options, res => {
      let responseBody = "";
      res.on("data", chunk => (responseBody += chunk));
      res.on("end", () => resolve(responseBody));
    });

    req.on("error", reject);
    req.write(JSON.stringify({ text: message }));
    req.end();
  });
}

 

여기까지 완료했으면 등록한 필터 패턴과 일치하는 로그가 발생하는 경우 지정한 Slack 채널으로 에러 내용을 포함한 메세지를 받아볼 수 있다.

 

 

참고. 등록한 Lambda 구독 필터는 CloudWatch 로그 그룹의 구독 필터 탭에서 조회/관리 할 수 있다.

 


유용한 도구.
https://app.slack.com/block-kit-builder
Slack 메시지를 커스터마이즈할 때 사용할 수 있다.