본문 바로가기
Nest js

[CloudWatch] CloudWatch로 검색 최적화 Json Formatting 하기

by 욧닭 2023. 5. 17.
반응형

들어가며

사내에서 백엔드 프로젝트를 맡아서 하는 중 시연회에서 기능이 안되는 일이 발생했습니다. 로그를 까서 원인을 빠르게 파악 해야 하는데 내 맘대로 로깅을 한탓에 시연회는 망해버렸었죠.. 이때 든 생각이 개발도 개발이지만 프로젝트를 잘 돌아가게 하기 위해선 로깅 프로세스와 에러 트레킹이 좀 많이 중요하다고 생각했습니다. 그래서 로깅에 대해서 간략하게 설명 드릴까 합니다.

로깅의 사전적 의미

데이터 로거(data logger), 데이터 레코더(data recorder)는 시간이 지남에 따라 또는 장소와 상대적으로 내장 기구센서, 또는 외부 기구와 센서를 가지고 데이터를 기록하는 전자 장치이다. 점진적으로, 그러나 완전하게는 아니지만, 이것들은 디지털 프로세서(또는 컴퓨터)에 기반을 두며 이를 디지털 데이터 로거(digital data logger, DDL)로 부른다.[1][2] 이것들은 일반적으로 크기가 작고 배터리로 구동되며 휴대가 간편하며 마이크로프로세서, 데이터 스토리의 내장 메모리, 센서가 장착되어 있다. 일부 데이터 로거는 개인용 컴퓨터와 통신하며 데이터 로거를 활성화하고 수집된 데이터를 보고 분석하기 위한 소프트웨어를 사용하는 반면 다른 로거들은 로컬 인터페이스 장치(키패드, LCD)를 갖추고 있으며 독립적인 장치로 사용이 가능하다.

로깅

예전 spring 으로 legacy 프로젝트를 개발할 땐 하루마다 .txt 파일로 로그를 쌓았었습니다. 그래서 시스템 장애가 난다면 ssh로 원격 접속을 하고 로그 디렉터리를 들어가 vi로 에러 로그를 찾는 그런 행위들을 했었죠

그러나 AWS라는 클라우드 컴퓨팅 서비스가 나오고 Cloud Watch라는 강력한 로깅 서비스가 나온 이후로 .txt로 로그를 쌓는 일은 많이 없어 졌죠.

그래서 AWS를 통해서 로깅을 어떻게 하고 추척은 어떻게 하면 좋을지 설명 같이 알아보죠!

프로세스

일단 전 nest.js 로 백엔드를 구성했고 따로 Logging 클래스를 사용하지 않고 커스텀으로 만들어서 사용 했습니다

logger.ts

import rTracer from 'cls-rtracer';
import { LogLevel, LogMessage } from './dto/log.dto';

export interface LogMessage {
  message: string;
  data?: Record<string, any>;
}

export enum LogLevel {
  INFO = 'INFO',
  ERROR = 'ERROR',
}

export class Logger {
  public static info(logMessage: LogMessage, method: string): void {
    console.log({
      ...(rTracer.id() ? { requestId: rTracer.id() } : {}),
      method,
      message: logMessage.message,
      ...logMessage.data,
      level: LogLevel.INFO,
    });
  }
}

일단 심플합니다!

 

로깅을 하고 싶은 코드로 가서 Logger의 메서드를 호출하는건데요 이때 Logger를 인스턴스화 하여 사용하기엔 너무 많은 곳에서 사용될 것 같아 메모리 낭비의 요소가 생긴다고 판단하여 메서드를 static으로 만들어서 프로젝트 실행시 메모리에 할당하여 사용하는 것으로 구조를 짰습니다.

 

하나씩 뜯어 보겠습니다.

export interface LogMessage {
  message: string;
  data?: Record<string, any>;
}

Logger.info(logMessage: LogMessage, method: string) 를 사용해 로깅을 할 때 매게변수를 달랑 message 하나만 받기에는 로그를 검색할 때 정형화 되어 있지 않아 필터링이 많이 힘들 것이라고 생각 했습니다.

 

그래서 interface 를 통해 message type을 만들었습니다. LogMessage 는 message 를 필수적으로 받고 부가적인 데이터는 Key-Value 형식으로 받도록 하였습니다.

 

export enum LogLevel {
  INFO = 'INFO',
  ERROR = 'ERROR',
}

로깅 메세지에 들어갈 level 부분 관리하기 쉽게 enum 으로 처리 했습니다. 개발 스타일상 전 WARNDEBUG 는 사용하지 않고 구성했습니다.

 

public static info(logMessage: LogMessage, method: string): void {
  console.log({
    ...(rTracer.id() ? { requestId: rTracer.id() } : {}),
    method,
    message: logMessage.message,
    ...logMessage.data,
    level: LogLevel.INFO,
  });
}

마지막으로 info 메서드 부분입니다.

 

info 메서드는 LogMessage 와 어떤 method 에서 로깅을 했는지를 확인 할 수 있게 method 명을 따로 받고 있습니다.

console.log 부분을 보면 로깅을 Object 타입으로 하고 있습니다. Object에 첫번째 키인 requestId는 cls-rtracer 패키지를 사용합니다.

 

https://www.npmjs.com/package/cls-rtracer

 

cls-rtracer

Express & Koa middlewares and Fastify & Hapi plugins for CLS-based request id generation, batteries included. Latest version: 2.6.2, last published: 10 months ago. Start using cls-rtracer in your project by running `npm i cls-rtracer`. There are 88 other p

www.npmjs.com


cls-rtracer는 client가 API 호출시 랜덤 값을 배정해 서버에서 client로 다시 값을 반환 할 때 까지 랜덤 값을 가지고 있습니다. 그 랜덤값은 다음 요청이 서버로 왔을 땐 사라지며 다시 새로운 랜덤 값을 부여 합니다.

그 랜덤한 값을 가져오는 방법이 rTracer.id() 입니다.
rTracer.id() 의 값은 대략적으로 e2a862f0-f3c0-11ed-8b65-d34eb2658dc4 이러한 형태를 지니고 있고 유니크 합니다.

client 의 요청과 응답이 끝날때 까지 해당 값을 서버에서 가지고 있으니 이 값으로 로그 트레킹을 하면 좋을 것 같네요

 

 

그래서 info 메서드에 rTracer.id() 값을 로깅합니다. 이때 스케줄러나 배치 프로그램을 돌릴때엔 client의 요청으로 프로그램이 돌아가는 것이 아니므로 {} <- 빈값 을 추가 합니다.

 

 

 

이러한 방식으로 로깅을 했으면 AWS Cloud Watch를 사용해 검색해봐야 겠죠

 

https://aws.amazon.com/ko/cloudwatch/

 

애플리케이션 및 인프라 모니터링 - Amazon CloudWatch - Amazon Web Services

로깅, 지표, 컨테이너 모니터링 및 추적 기술에 대해 확실하게 이해할 수 있습니다.

aws.amazon.com

 

Cloud Watch는 AWS 의 가상 컴퓨터 EC2, lambda 등 으로 서버를 구성했을때 옵션으로 선택할 수 있습니다. 

선택을 했다면 이제 Cloud Watch를 사용할 수 있는데요. 서론에서 말했다싶히 로깅을 파일로 하는게 아닌 클라우드에 로깅을 하며 filter링도 쉽게 할 수 있으며 관리도 쉬워지게 됩니다.

 

여기서 중요한 Cloud Watch 요금 정책은 해당 사이트에서 확인하면 좋을 것 같습니다! 전 프리티어 쓰고 있어요

 

https://aws.amazon.com/ko/free/?all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc&awsf.Free%20Tier%20Types=*all&awsf.Free%20Tier%20Categories=*all&all-free-tier.q=watch&all-free-tier.q_operator=AND 

 

무료 클라우드 컴퓨팅 서비스 - AWS 프리 티어

Q: AWS 프리 티어란 무엇입니까? AWS 프리 티어는 고객에게 서비스별로 지정된 한도 내에서 무료로 AWS 서비스를 살펴보고 사용해 볼 수 있는 기능을 제공합니다. 프리 티어는 12개월 프리 티어, 상

aws.amazon.com

Logging을 해서 찍은 데이터를 확인해 보겠습니다.

 

깔끔하게 나오는군요

 

이렇게 key - value의 뎁스가 1인게 좋습니다. cloud watch 에서 뎁스가 2이상인 key를 잘 못찾더라구요

이제 cloud watch의 강력한 기능인 검색기능을 살펴보겠습니다.

 

만약 위 로그중 requestId로 client 가 요청한 데이터의 흐름을 보고싶다면 검색창에 다음과 같은 명령어를 입력하면 됩니다.

 

{$.requestId="3c1750d0-f452-11ed-8b65-d34eb2658dc4"}

다음과 같이 검색한다면 쉽게 값이 나올 것입니다!

감사합니다~

반응형

댓글