서비스 운용과 로그 관리

동기

현재 Node.js WebServer와 Android 클라이언트로 동작하는 서비스를 관리하고 있는데 이게 문제가 많다. 이렇게 큰 규모의 서비스를 처음 개발하고 운용하다보니 개발 시점에서 편리한 운용을 고려하지 못했다.

사용자가 뭔가 안된다고 할 때 마다 안되는 원인을 찾는것이 힘들기 때문이다. 이렇게 가다가는 서비스 품질향상보다 디버깅과 운영에 모든 시간을 쏟을 것 같다는 생각에 시간을 조금 투자해서 로그관리를 제대로하기로 결심하였다.

로그관리란?

OWASP에서 권장하는 로그관리를 참고해보니 다음의 목적을 가지고 로그를 관리한다고 한다.

  • 감독목적: 사용자의 캐시아이템이나 상태를 변경시키는 행위에 대해 추적을 할 수 있어야 한다.
  • 추적목적: 어떤 행위가 일어났을 때 어디서, 어떻게, 왜 일어났는지를 알아낼 수 있어야 한다.
  • 데이터 무결성: 로그를 변경할 수 없게 만들어서 사용자들의 데이터 무결성을 로그를 통해 입증한다.

마침 내가 로그관리를 해야겠다고 생각한 목적도 다음과 같다.

  • 감독 및 무결성 목적: 수상한 결제 행위 감시. 결제 실패 시 원인 파악 후, 상품을 받지 못하거나 문제가 있는 사용자에게 보상하기 위한 차원
  • 디버깅 목적: 서비스 장애 발생 시 빠른 원인 파악

적용

이 목적을 가지고 내가 할 수 있는 가장 단순한 방법을 찾아보았다. 로그 관리 best practice등으로 검색을 해 보았는데 무슨 거대한 서비스에나 적합할 것 같은 것들이 나온다. 이 중 ELK Stack (ElasticSearch, Logstash, Kibana)이라는 것이 좀 흥미롭다. ElasticSearch가 검색엔진인 줄 알았는데 로그조회용으로도 쓰이나보다.

일단 나는 단일 Node.js app이 API Server역할을 하기 때문에 분산로깅 및 로그 합치기 같은 문제는 신경 쓸 이유가 없다. 로그도 그냥 파일로 관리하면 된다. 문제는 어떤 정보를 로깅해야 나중에 위에 적은 목적에 맞게 확인하기 편하냐는 것이다.

그래서 현재는 아무렇게나 찍고 있는 로그를 다음과 같이 바꾸기로 하였다.

정책

  • 모든 API 호출에 대해 호출시, 결과 반환시 로깅을 한다. 이는 사후 추적과정에서 특정 사용자가 어떤 행위를 하고 있었는지를 알려준다.
  • 모든 Function Error에 대해 function이름을 로깅을 한다.
  • Function Error에 대해 왜 실패했는지, 무엇을 기대하는지를 같이 기록한다.
  • 오류가 발생하면 사용자에게 보여줄 코드와 메세지를 작성한다. 코드를 이용하면 나중에 사용자가 오류가 발생한다고 하면서 출력된 코드를 말하면 정확히 그 부분을 집어내기 편리하다.
  • 로그파일은 커질 수 있으니 매일 새로운 파일에 기입한다.
  • 로그파일은 실수로 덮어 쓸 수 있으니 안전한 장소에 보관한다. 예)/var/log/servicename/serverlog_161212.log
  • error와 일반로그를 합친 combined log와 error만을 따로 기록한 error log 이렇게 따로 관리한다.

로그레벨 정의

로그를 찍다보면 흔히 LogLevel에대해서 많이 이야기한다. 본인도 처음에 이것을 어떻게 구분할 지 헷갈려서 자꾸 보면서 참고 할 수 있게 여기에 적어본다.

 

Info: 사용자가 어떤 행위를 하는지 추적할 수 있도록 한다.  또한 나중에 Warn이나 Error가 났을 때 어떤 상황에서 그 행위가 일어났는지를 알 수 있도록 API, User정보도 같이 찍어둔다.

Warn: 뭔가 잘 안됬을 때 한다. 예를들어 사용자가 로그인을 할 때 암호를 틀리게 입력했다든지. 주기적으로 이 로그를 확인해서 서버에 특이사항이 없는지 점검하는 용도로 쓴다.

Error: 에러는 서버에서 무엇인가가 잘못되었을 때 표시한다. 사용자에게 보여줄 에러가 아니라 서버 설정이나 어플리케이션 단계에서 문제가 있을 때 사용한다. 따라서 이 로그가 찍힌 경우에는 서버 관리자 Email과 연동하여 바로 수정 작업에 들어갈 수 있어야 한다.

로그 포맷

로그는 한줄에 하나씩 출력할 수 있도록 하며 다음과 같은 정보를 가지면 된다.

TimeStamp(LocalTime GMT+9, ISO Formatted), LogLevel, API Address, Method, UserId(Email), Message

사용한 도구

나는 Node.js와 winston moudle을 이용해서 API서버의 로깅하기로 했다.  이제 앞으로 개발하는 코드에 대해서는 철저한 로깅을 통해 운용시의 문제에 빠르게 대응할 수 있을 것으로 기대한다.

 

 

Resources

안정적인-서비스-운영을-위한-서버-모니터링-2 From 드라마엔컴퍼니(앱이름: 리멤버)

https://theagileadmin.com/2010/08/20/logging-for-success/

https://blog.risingstack.com/node-js-logging-tutorial/

https://www.loggly.com/blog/three-node-js-libraries-which-make-sophisticated-logging-simpler/

https://strongloop.com/strongblog/compare-node-js-logging-winston-bunyan/

Leave a Reply