사전 로그
개념

로그

gabury1

로그는 일어난 일을 벌어진 순서대로 하나씩 적어 나간 기록입니다. 프로그램이 도는 동안 무슨 일이 있었는지는 밖에서 들여다볼 수 없습니다. 그래서 벌어질 때마다 하나씩 적어 남깁니다.

상세

가게 주인이 그날 있었던 일을 공책에 한 줄씩 적어 둔다고 해 봅시다. 이미 적은 줄은 지우지 않습니다. 새 일이 생기면 그 아래에 이어 붙입니다.

로그를 로그이게 하는 성질은 둘입니다. 하나는 덧붙이기만 한다는 것입니다. 이미 쌓인 항목은 제자리에서 고쳐 쓰지 않습니다. 새 항목은 언제나 끝에 붙습니다. 다른 하나는 그래서 놓인 순서 자체가 구조가 된다는 것입니다. 몇 번째 항목인지가 언제 일어난 일인지를 말해 줍니다.

항목 하나에는 대개 셋이 들어갑니다. 언제 일어났나, 어디서 났나, 무슨 일이 있었나입니다. 이것을 사람이 읽는 문장으로 적을 수도 있습니다. 기계가 골라 읽도록 필드를 나눠 적을 수도 있습니다. 둘 다 로그입니다.

배경

프로그램은 도는 동안 제 안을 밖에 보여 주지 않습니다. 그리고 끝나는 순간 무엇을 어디까지 했는지가 함께 사라집니다. 뒤늦게 이유를 물어볼 상대가 남지 않는 셈입니다. 그래서 일이 벌어지는 그때그때 밖에다 한 줄씩 적어 두는 자리가 필요했습니다.

운영자는 기계가 뱉어 놓은 메시지 더미에서 문제를 알리는 것과 단순한 상태 알림을 갈라내야 합니다. RFC(Request for Comments) 3164 는 운영체제와 프로세스와 애플리케이션이 점점 더 복잡해졌다고 적습니다. 복잡해질수록 그 더미에서 문제를 골라내는 일이 어려워졌습니다.

그래서 이 잡다한 메시지를 분류하고 기록하는 체계가 고안됐습니다. 운영자가 문제 알림을 더 빨리 구분해 낼 수 있게 하려는 것이었습니다. 장치에서 도는 프로세스가 보내는 메시지를 어디로 보낼지 운영자가 설정할 수 있도록, 유연성도 함께 설계에 넣었습니다. 그런 체계 가운데 하나가 syslog 였습니다. 많은 운영체제에서 널리 받아들여졌습니다. 다만 BSD(Berkeley Software Distribution) syslog 는 널리 쓰였어도 형식이 공식 표준으로 정해진 적이 없었습니다.

갈래

갈리는 자리는 뜻이 아닙니다. 무엇에 쓰려고 적느냐입니다. 같은 덧붙이기 기록을 두고, 사람과 도구가 읽어 진단하는 자리와 장애 뒤에 되살리는 자리와 순서를 고정하는 자리가 갈립니다.

진단과 감사

RFC 5424 는 syslog 메시지 앞머리에 PRI(Priority, 우선순위) 부분을 둡니다. 꺾쇠 괄호로 앞뒤를 묶은 세 자리에서 다섯 자리 문자입니다. 괄호 안에 든 수를 우선순위 값이라고 부릅니다. 이 값 하나가 facility 와 severity 둘을 함께 나타냅니다. 우선순위 값은 facility 번호에 8을 곱한 뒤 severity 값을 더해서 구합니다.

severity 는 0부터 7까지 여덟 단계입니다.

값 이름 뜻
0 Emergency 시스템을 쓸 수 없습니다
1 Alert 즉시 조치를 취해야 합니다
2 Critical 위급한 상태입니다
3 Error 오류 상태입니다
4 Warning 경고 상태입니다
5 Notice 정상이지만 유의할 상태입니다
6 Informational 알림용 메시지입니다
7 Debug 디버그 수준 메시지입니다

이 등급이 붙어 있어서 읽는 쪽이 먼저 볼 것을 골라낼 수 있습니다.

복구

PostgreSQL 공식 문서는 WAL(Write-Ahead Logging, 쓰기 선행 로그)을 데이터 무결성을 보장하는 표준적인 방법이라고 적습니다. 중심 개념은 하나입니다. 테이블과 인덱스가 놓인 데이터 파일의 변경은 그 변경이 로그로 적힌 뒤에만 기록되어야 합니다. 변경을 기술하는 WAL 레코드가 영구 저장소로 플러시된 다음이라는 뜻입니다.

flowchart TD
    A[변경 발생] --> B[WAL 레코드 적기]
    B --> C[영구 저장소로 플러시]
    C --> D[데이터 파일 변경 기록]

이 절차를 따르면 트랜잭션이 커밋될 때마다 데이터 페이지를 디스크로 플러시할 필요가 없습니다. 장애가 나도 로그로 데이터베이스를 복구할 수 있기 때문입니다. 데이터 페이지에 아직 반영되지 않은 변경은 WAL 레코드에서 다시 실행할 수 있습니다. 문서는 이것을 롤포워드 복구, 다른 이름으로 redo 라고 부릅니다. 그 결과로 디스크 쓰기 횟수가 크게 줄어듭니다. 트랜잭션이 커밋됐음을 보장하는 데 WAL 파일만 플러시하면 되기 때문입니다. WAL 파일은 순차로 쓰입니다. 그래서 WAL 을 동기화하는 비용이 트랜잭션이 바꾼 데이터 파일을 모두 플러시하는 비용보다 훨씬 적습니다.

순서

Kafka 는 토픽 파티션마다 로그를 둡니다. my-topic 이라는 이름의 토픽이 파티션 둘을 가지면 로그는 my-topic-0 과 my-topic-1 두 디렉터리로 이루어집니다. 각 디렉터리에는 그 토픽의 메시지를 담은 데이터 파일이 들어갑니다. 로그 파일의 형식은 로그 엔트리의 나열입니다. 엔트리 하나는 메시지 길이를 담은 4바이트 정수 n 과 뒤따르는 n 바이트의 메시지입니다. 메시지마다 64비트 오프셋이 붙어 유일하게 식별됩니다. 그 오프셋은 그 파티션의 그 토픽으로 지금까지 보낸 모든 메시지 스트림에서 이 메시지가 시작하는 바이트 위치입니다.

flowchart TD
    A[새 메시지] --> B[마지막 파일에 덧붙이기]
    B --> C{설정한 크기 도달}
    C -->|아니오| B
    C -->|예| D[새 파일로 넘어감]

쓰기는 언제나 마지막 파일로 가는 순차 덧붙이기입니다. 그 파일이 설정한 크기에 이르면 새 파일로 넘어갑니다. 시작할 때는 로그 복구 과정이 가장 최근 로그 세그먼트의 모든 메시지를 훑어 각 엔트리가 유효한지 확인합니다. 손상이 발견되면 로그를 마지막 유효 오프셋까지 잘라냅니다.

예시

로그는 만드는 쪽이 누구냐에 따라 손댈 수 있는 정도가 다릅니다. OpenTelemetry 로그 데이터 모델은 세 종류의 로그와 이벤트를 표현하는 것을 목표로 삼는다고 적습니다. 운영체제가 내는 시스템 형식은 형식을 바꿀 수 없습니다. 무엇이 담길지도 손댈 수 없습니다. 다만 그 데이터를 우리가 고칠 수 있는 애플리케이션이 만들어 낸 것이라면 이야기가 다릅니다. 서드파티 애플리케이션이 내는 것은 형식을 손보는 정도의 통제권이 있습니다. 직접 만드는 애플리케이션이 내는 것은 로그를 어떻게 만들지와 무엇을 담을지를 어느 정도 정할 수 있습니다. 아래 셋이 차례로 그 세 자리입니다.

syslog 메시지 한 줄

<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - BOM'su root' failed for lonvick on /dev/pts/8

RFC 5424 가 예로 든 메시지입니다. 구조화 데이터가 없는 경우입니다. 버전은 1 이고 facility 는 4, severity 는 2 입니다. 메시지가 만들어진 시각은 2003년 10월 11일 밤 10시 14분 15초 UTC(Coordinated Universal Time, 협정 세계시)에서 다음 초로 3밀리초 들어간 지점입니다. 메시지를 낸 호스트는 자신을 mymachine.example.com 이라고 밝힙니다. APP-NAME 은 su 이고 PROCID 는 알 수 없습니다. MSGID 는 ID47 입니다.

nginx 접근 로그 설정

nginx
access_log logs/access.log combined;

ngx_http_log_module 모듈은 요청 로그를 지정한 형식으로 씁니다. access_log 지시자의 기본값이 logs/access.log combined 입니다. 쓸 수 있는 자리는 http · server · location · location 안의 if · limit_except 입니다. access_log off; 로 끌 수도 있습니다.

nginx
log_format combined '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';

설정에는 미리 정의된 combined 형식이 언제나 들어 있습니다. 한 줄에 무엇이 담기는지가 이 형식에 그대로 적혀 있습니다. 접속한 주소, 사용자 이름, 지역 시각, 요청 줄, 상태 코드, 보낸 본문 바이트 수, 리퍼러, 사용자 에이전트입니다.

파이썬 logging 호출

Python
import logging
logging.warning('Watch out!')  # will print a message to the console
logging.info('I told you so')  # will not print anything

이 줄을 스크립트에 넣고 실행하면 콘솔에 이렇게 찍힙니다.

WARNING:root:Watch out!

info 메시지는 나오지 않습니다. 기본 레벨이 WARNING 이기 때문입니다. 찍힌 메시지에는 레벨 표시와 로깅 호출에 넘긴 사건 설명이 함께 들어 있습니다. 실제 코드에서는 logger = logging.getLogger(__name__) 로 로거를 얻습니다. 그 다음 그 로거의 debug() · info() · warning() · error() · critical() 을 부릅니다.

관련 항목

로그가 놓이거나 저장되는 저장소

표준 출력 · 표준 에러 · 로그 파일 · 접근 로그

로그 수집·보관을 다루는 역할과 정책

컨테이너 런타임 · kubelet · 사이드카 컨테이너 · 노드 수준 로깅 에이전트 · 데몬셋 · 로그 로테이션 · 클러스터 수준 로깅

로그 파일을 이루는 구성 요소

로그 세그먼트 · 오프셋 · 토픽 · 파티션 · 로그 엔트리

로그 항목에 담기는 정보

로그 레벨 · 타임스탬프 · 메시지 · 알림 · 심각도 · facility · 우선순위 값 · PRI · 구조화 데이터 · APP-NAME · PROCID · MSGID · 상태 코드 · 사용자 에이전트

로그 형식에 적용되는 규칙·표준

RFC 5424 · RFC 3164 · OpenTelemetry · 로그 형식 · 구조화 로그

로그 개념을 실제로 채택한 시스템

syslog · 운영체제 · PostgreSQL · Kafka · Kubernetes

로그와 함께 트랜잭션 복구를 이루는 개념

WAL · 테이블 · 인덱스 · 레코드 · 데이터베이스 · 트랜잭션 · 커밋 · 롤포워드 복구 · 체크포인트

로그와 함께 관측성을 이루는 다른 신호

메트릭 · 트레이스 · 스팬 · 분산 추적

로그가 속하는 상위 분류

관측성 · 백엔드 · 인프라

다른 이름: log