실제 서버를 배포하면, 불행하게도 항상 따라오는 게 버그다. 물론 철저한 코딩과 테스트, 경우의 수 계산으로 미연에 방지하는 게 가장 좋겠지만 현실적으로 불가능하니, 차선책으론 에러가 발생했을 때, 문제 해결을 위한 데이터를 최대한 모으는 게 중요하다고 생각했다.
물론 Django에서 아래와 같이 자체적으로 로깅을 지원하긴 하는데, 특히 이용자가 많아질 수록 텍스트로 이루어진 로그는 보기도 불편하고 무엇보다 내가 원하는 특정 상황(=특정 세션)에 대한 부분만 추출하기 너무 까다로웠다. 그렇다고 설정을 만져 Error 이외의 로그를 거르기엔 뭔가 찝찝했다.
그래서 무료로 이용할 수 있는 에러 모니터링 툴에 대해서 찾아보던 중, Sentry에 대해 알게 되었다. 그래서 실제 서비스에 적용해서 사용해 보니, 매우 간편하면서 강력해서 큰 도움이 되었다. 그래서 센트리의 설치나 간단한 활용법에 대해서 공유하고자 한다.
1. 설치하기
간단히 회원가입하고, 바로 프로젝트를 하나 만들면 된다. 프로젝트에서 모니터링을 진행할 프로그램을 지정할 것이다. 자기가 사용하는 언어/프레임워크를 고르면 그에 맞춰서 코드를 만들어 준다. Python -> Django를 고르면 된다. 그러면 아래와 같이 하라는 튜토리얼 페이지가 뜬다.
sentry-sdk 라이브러리를 설치하고 Settings.py에 넣으면 된다. 물론 위 정보는 프로덕션 서버의 설정 파일에 따로 넣는 것을 추천한다. 필요하지 않다면 개발 서버에서는 굳이 에러 트레킹을 할 필요가 없기 때문이다.
그 아래는 0으로 나누기 에러를 발생시키고 테스트 해보는 부분이 있는데, 간단한 테스트이므로 가볍게 한번 해 보면 될 것이다.
2. 활용하기 - 프로젝트
프로젝트 세팅을 마친 후, 화면을 살펴 보자. 왼쪽의 목록에서 여러 가지 메뉴들이 있는데, 차례대로 Projects, Issues, Performance를 살펴볼 예정이다. 우선 Projects 메뉴에 가서, 만든 프로젝트를 눌러 보자.
이 화면은 프로젝트 상세 페이지이다. 내가 돌리고 있는 현재 서버의 상태를 전체적으로 조망할 수 있다.
Crash Free Sessions는 에러 없이 정상적으로 진행된 요청의 비율을 나타낸다. 당연히 이 비율이 높아야 서버가 정상적으로 돌아가고 있다고 간주할 수 있을 것이다. 내 서버는 약 99.9%의 신뢰도를 나타내고 있다. 이 0.1%가 왜 생겼는지는 아래에서 설명하도록 하겠다.
Number of Releases는 이 프로젝트가 가진 릴리즈의 수인데, 쉽게 말해서 웹 서버의 버젼이 몇 개가 있었는지, 즉 몇 번의 변화가 있었는지를 뜻한다. 나는 따로 관련 설정을 안 해서 0이라고 나왔다. 아마 설정을 하면 특정 버젼에선 에러가 많았고 특정 버젼에선 적었다 식으로 모니터링이 가능할 텐데, 굳이 이 기능이 필요할 것 같진 않아서 나는 쓰지 않았으니 관심 있다면 사용해 봐도 될 것이다.
Apdex는 성능 관련 지표인데, 지정된 시간 안에 요청에 대한 응답이 왔는지에 대한 비율이다. 이건 Settings->Perfomance에 가면 해당 값이 있는데, 기본값으론 300ms가 설정되는 것 같다. 성능 트래킹을 원한다면 이 부분도 활용할 수 있을 것이다.
3. 활용하기 - 이슈
Issues 페이지이다. 사실 센트리를 즐겨찾기에 설정해 놨는데, 들어가면 자동으로 이 페이지로 뜬다. 그만큼 사실상 센트리에서 가장 중요한 부분 중 하나이다. 여기서 서버에서 발생한 에러들을 관리할 수 있다. 발생 시간이나 에러 내용, 어떤 URL로 접속했을 때 에러가 발생했는지 등이 적혀 있다. 여러번 발생하는 에러는 아래와 같이 이벤트(=요청 횟수)와 유저를 구분하여 중첩되어 기록된다. 즉, 여러 명의 유저가 이런 문제를 겪은 건지, 아니면 한 명이 똑같은 에러를 여러 번 발생시킨 건지 구분할 수 있다. 이 점이 Sentry가 에러를 보기 편하게 해주는 강점 중 하나라고 생각한다.
참고로, 에러들이 꽤 많이 떠 있는데, 장고 서버를 운영하면서 몇 가지 발생할 수 있는 에러들이 있다.
우선 Invalid HTTP_HOST header: 'www.blockfinex.com'. You may need to add 'www.blockfinex.com'... 등등 HTTP_HOST 에러가 대부분인데, 이건 유저가 아니라 그냥 인터넷 사이트들을 무차별적으로 취약점 스캔하는 봇들이다. 자세히 보면 접근하는 URL도 정상적이지 않다. 아무나 걸려라 하는 식으로 스캔하고 다니는 거라, 에러가 나면서 차단당하는 게 맞다. 해당 에러는 설정을 통해 이 유형의 에러는 무시하도록 할 수 있는데, 혹시 진짜 관찰이 필요한 에러들도 무시될까봐 따로 건들지 않았다.
참고로 settings.py의 ALLOWED_HOST를 설정하지 않거나 *(모든 호스트 허용)으로 해 두면 이 에러는 안 뜰 것이다. 보안에 좋지 않으니 *보다는 실제 사용하는 호스트 이름으로 설정해 두자... 잘 모르겠으면 [{서버의 공인 아이피 주소}, '127.0.0.1', {서버의 도메인 주소}] 정도로만 해 둬도 될 것이다.
그리고, OSError 같은 경우엔 개발 환경에서는 발생하지 않았지만 프로덕션 환경에서는 주기적으로 발생하던 에러인데, 이 에러는 다른 에러들과 다르게 Django의 세션 관련 데이터가 누락되어 있다.
장고와 관련된 정보가 아예 누락되는 걸로 봐선 장고 밖에서 발생하는 에러로 추정되는데, 구글링 결과 장고의 문제는 아니고 wsgi로 사용하는 프레임워크인 uwsgi 관련 버그였다.
stackoverflow.com/questions/59026602/uwsgi-oserror-write-error-during-get-request
쉽게 말해서, 클라이언트와 서버가 요청을 주고받는 중 클라이언트는 어떤 이유로던 통신을 끊었는데, 서버(정확히는 uwsgi)에서는 요청을 계속 처리하고 있어서 생기는 오류이다. 이건 서버 설정을 만지면 해결될 수 있는 오류이다. 사실 이 에러 때문에 서비스에 문제가 생긴 적은 없었던 것 같다...
4. 활용하기 - 이슈 - 에러 상세보기
위에 뜬 에러들 중 하나를 눌러 보면 에러의 상세한 내용을 볼 수 있다. 아래는 실제로 발생한 에러를 캡처한 것이다.
우선 우측 상단의 이벤트, 유저를 통해 1명의 유저에게 이 에러가 12번 발생했다는 것을 알 수 있다. 또한, 해당 유저가 사용했던 브라우저와 운영 체제 역시 확인할 수 있다. 현재 보고 있는 건 가장 최근에 발생한 에러 정보로, 이전에 발생한 에러 정보를 보고 싶다면 events 아래의 숫자를 클릭하면 지금까지 발생한 동일한 에러 리스트가 뜬다. 각각을 클릭하면 각 에러에 대한 정보를 알 수 있다.
또한, users 밑의 숫자(1)을 클릭해도 해당 에러를 겪은 유저들의 목록과 비율이 표시된다.
센트리에서 에러가 발생한 상황의 정보를 수집하여 보여주는데, 우선 실행시킨 코드에서 에러가 발생한 부분을 표시해 준다. 여기는 기존 파이썬에서 보여주는 StackTrace와 같다.
다음으로, breadcrumbs라 해서 사용자가 사이트에서 어떤 행동을 했는지 보여준다. 이 부분이 가장 핵심인데, Django 로거의 info 로그는 물론, 해당 사용자의 요청으로 인해 발생한 추가적인 HTTP 요청(심지어 타 사이트에 대한 API 요청이다)이나 DB 조작도 모두 보여준다. 이 부분을 보안상 가려야 하는 것이 유감일 정도로 상세하게 나온다. '카테고리(CATEGORY)'에서 httplib은 HTTP 요청, query는 DB 쿼리, django는 Django 로거를 나타낸다. 아마 더 많은 종류가 있을 것이다.
그리고, 해당 view는 body에 데이터를 담은 POST 요청을 받아 특정한 동작을 수행하는데, 이 POST 요청에 대한 정보 역시 body의 내용을 포함해 쿠키, 헤더 등 모든 정보가 기록된다. 이외에도, 현재 유저가 django의 auth 시스템을 이용해 로그인 된 상태라면 해당 유저의 정보 역시 기록된다.
Details 옆에 Activity 탭에서는, 해당 에러에 대해 기록을 할 수 있다, 깃헙의 issue와 비슷하다. 아마 여러 명이서 협업을 할 때 담당자를 배정하고, 의견 등을 교환하는 데 사용할 수 있을 것이다. 물론 아래처럼 그냥 개인 메모용으로 써도 된다.
마지막으로, 특정 에러에 대해 Resolve나 Ignore 등으로 체크를 할 수 있다. Resolve는 해결됨, Ignore는 무시이다. 체크할 시 해당 에러에 대해서 빨리 해결하라고 굵은 글씨로 강조하지 않게 된다. 단, 이그노어의 경우엔 이미 발생한 해당 에러에 대해서만 무시이고, 아예 관련 에러를 전체적으로 무시하려면 설정을 만져야 한다.
이외에도 특정 에러 발생시 이메일 등으로 알림을 날리는 기능도 있지만 아마 간단히 활용하는 데는 이 정도만 해도 충분할 것이다.
5. 성능 분석
이건 에러 모니터링과는 크게 관련은 없는 기능인데, 성능 측정엔 도움이 되는 부분이다. Perfomance에 들어가면 볼 수 있다.
서버의 성능과 관련된 각종 지표들을 볼 수 있는 곳이다. 만약 데이터가 표시되지 않는다면 오른쪽 위의 기간을 좀 더 넓게 만져보자. Duration p75는 75%의 요청이 해당 시간보다 빠르게 처리되었다는 뜻이고, throughput은 분당 해당 수치만큼의 요청이 들어왔다는 뜻이고, Failure rate는 말 그대로 에러가 난 비율(HTTP 코드 4XX), apdex는 위에서 설명한 대로 제한 시간 내에 요청이 처리되었는지의 비율이다. 아래에는 관련 그래프들이 나타나 있다.
Failure Rate가 꽤 높다. 대략 5명 중에 한 명이 오류가 난다는 것인데, 사실 정상이다. 왜냐하면 위에서 말한 취약점 스캔 봇들이 상상 이상으로 엄청나게 긁어가기 때문이다. 어떤 요청들이 있었는지 이 성능 페이지에서 바로 확인할 수 있는데, 한번 살펴보자.
php를 사용하지도 않는 사이트인데 관련 URL로 많이 들어온다. 저게 워드프레스 쪽에서 사용되는 관리자 페이지나 설정 파일인데, 아무나 걸려라식 무차별 대입 공격이고 내 서버에는 저런 파일들이 존재하지 않으므로 전부 404 Not Found로 표시되는 것이다. 이게 바로 20%의 failure rate의 정체이다.
위에서 소개한 센트리의 기능들은 극히 일부이다. 일단 무료 버젼에 있는 기능들만 소개한 거고 아마 유료 버젼엔 더 많은 기능들이 있을 것이다. 무료 기능으로도 꽤나 유용하게 사용할 수 있고 무엇보다 설치가 매우 간편하다는게 마음에 들었다. 장고 서버가 있다면 에러 모니터링을 공부해 보는 용도로도 유용할 것 같다.
'프로그래밍 > Django' 카테고리의 다른 글
Django에서 아임포트를 통해 결제 구현하기 - (1) 아임포트 세팅 및 결제 구조 (2) | 2021.05.14 |
---|---|
Django에서 ajax POST로 데이터 받기 (0) | 2020.09.09 |
Django에서 Daum 메일을 통해 메일 전송하기 (0) | 2020.08.25 |
Django 기본 로그인 form 수정해서 한글화하여 쓰기 (0) | 2020.08.06 |