Log

Log는 애플리케이션 실행 시 생성되는 텍스트 기반의 기록이다. 이는 구조화된 형식(예: JSON)이나 비구조화된 텍스트 형식으로 제공될 수 있다.
문제가 발생했을 때 무슨 일이 있었는지 추적할 수 있게 해주며, 시스템의 동작을 이해하는 데 필수적인 정보를 제공한다.

로그 구조를 설계할 때는 다음과 같은 원칙들을 고려해야 한다:

  1. 일관성(Consistency): 모든 로그 항목은 동일한 구조와 형식을 따라야 한다. 이는 로그 파싱과 분석을 용이하게 만든다.
  2. 검색 가능성(Searchability): 주요 필드들은 쉽게 검색하고 필터링할 수 있는 형태여야 한다.
  3. 확장성(Extensibility): 새로운 정보를 추가할 필요가 생겼을 때 기존 구조를 해치지 않고 확장할 수 있어야 한다.
  4. 상세도 조절(Verbosity Control): 로그 레벨을 통해 필요한 상세도를 조절할 수 있어야 한다.

로그 구조를 효과적으로 설계하면 다음과 같은 이점을 얻을 수 있다:

  1. 신속한 문제 해결: 필요한 정보를 빠르게 찾고 분석할 수 있다.
  2. 효율적인 저장과 처리: 구조화된 형식으로 인해 로그 처리와 저장이 효율적이다.
  3. 자동화된 분석: 일관된 구조는 자동화된 로그 분석과 모니터링을 가능하게 한다.
  4. 효과적인 트러블슈팅: 충분한 컨텍스트 정보로 인해 문제의 근본 원인을 더 쉽게 파악할 수 있다.

Log의 목적

  1. 애플리케이션의 에러와 경고 탐지
  2. 문제 발생 시 정확한 원인 파악
  3. 디버깅 정보 제공

Log의 특징

  1. Metric이 제공하지 못하는 세부적인 정보를 확인할 수 있다.
  2. 레거시 시스템이나 패키지 애플리케이션에서는 Log를 중심으로 시스템 상태를 이해하고 문제를 해결하는 경우가 많다.
  3. 시스템의 내부 상태를 파악하는 데 도움을 준다.

로그의 구조

1
2024-01-15 14:30:25.123 +0900 [ERROR] [pid:1234] [tid:5678] [UserService] [TxID:abc123] Failed to authenticate user - {"user_id": "john_doe", "ip": "192.168.1.100", "attempt": 3, "error_code": "AUTH001"}
  1. 타임스탬프(Timestamp): 로그가 생성된 정확한 시점을 나타낸다.
    이는 보통 다음과 같은 형식을 따른다:

    1
    
    2024-01-15 14:30:25.123 +0900
    

    여기서 밀리초까지의 정확도와 시간대 정보를 포함하는 것이 중요하다. 이를 통해 이벤트의 정확한 발생 시점과 순서를 파악할 수 있다.

  2. 로그 레벨(Log Level): 해당 로그 메시지의 중요도나 심각성을 나타낸다:
    각 레벨은 다음과 같은 의미를 가진다:

    [ERROR] 심각한 문제가 발생했음을 나타낸다.
    [WARN] 잠재적인 문제나 주의가 필요한 상황을 알린다.
    [INFO] 일반적인 정보성 메시지를 표시한다.
    [DEBUG] 개발이나 문제 해결에 필요한 상세 정보를 제공한다.
    [TRACE] 가장 상세한 수준의 디버깅 정보를 포함한다.

  3. 프로세스 ID(Process ID)와 스레드 ID(Thread ID): 멀티프로세스 또는 멀티스레드 환경에서 로그의 출처를 식별하는 데 도움을 준다:

    1
    
    [pid:1234] [tid:5678] 실행 중인 프로세스와 스레드를 식별합니다
    
  4. 컨텍스트 정보(Context Information): 로그가 발생한 환경이나 상황에 대한 정보를 제공한다:

    1
    
    [UserService] [TransactionID:abc123] 어떤 서비스나 컴포넌트에서 발생했는지 식별합니다
    
  5. 로그 메시지(Log Message): 실제 이벤트나 상태 변화에 대한 설명을 담고 있다.
    이는 명확하고 구체적이어야 한다:

    1
    
    "User 'john_doe' failed to authenticate: Invalid password provided after 3 attempts"
    
  6. 추가 컨텍스트(Additional Context): 문제 해결에 도움이 될 수 있는 부가적인 정보를 포함한:

    1
    2
    3
    4
    5
    6
    
    {
        "user_id": "john_doe",
        "ip_address": "192.168.1.100",
        "browser": "Chrome/96.0.4664.110",
        "request_id": "req_123456"
    }
    

구조화된 로깅

현대적인 로깅은 구조화된 형식을 사용하여 더 효과적인 분석이 가능하게 한다:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "timestamp": "2024-01-15T14:30:25.123Z",
  "level": "ERROR",
  "service": "user-service",
  "trace_id": "abc123",
  "message": "Failed to authenticate user",
  "context": {
    "user_id": "john_doe",
    "ip_address": "192.168.1.1",
    "attempt_number": 3
  }
}

로그 수집과 관리

효과적인 로그 관리를 위한 주요 고려사항들은 다음과 같다:

  1. 중앙화된 로그 수집: 최근에는 중앙집중식 로깅(Centralized Logging) 방식이 널리 사용되고 있다. 특징:

    1. 로그 수집 파이프라인을 통해 서비스 로컬에서 발생한 애플리케이션 로그를 중앙 저장소에 수집한다.
    2. 사용자는 단일 대시보드를 이용해 다수 서비스에서 발생한 로그를 검색하고 분석할 수 있다.
    3. 서버에 직접 접근하지 않고도 로그를 확인할 수 있다
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    
    # Fluentd 설정 예시
    <source>
      @type tail
      path /var/log/app/*.log
      tag app.logs
      <parse>
        @type json
      </parse>
    </source>
    
    <match app.logs>
      @type elasticsearch
      host elasticsearch.example.com
      port 9200
      index_name app-logs
    </match>
    
  2. 로그 보관 정책:

    • 보관 기간 설정
    • 로그 회전(rotation) 구성
    • 저장 공간 관리
    • 중요도에 따른 보관 정책 차별화

로그 분석과 활용

수집된 로그는 다음과 같은 목적으로 활용될 수 있다:

  1. 문제 해결:

    • 오류의 근본 원인 분석
    • 성능 병목 지점 식별
    • 사용자 경험 문제 파악
  2. 보안 모니터링:

    • 비정상적인 접근 패턴 감지
    • 보안 위협 식별
    • 감사(audit) 기록 유지
  3. 비즈니스 인사이트:

    • 사용자 행동 패턴 분석
    • 기능 사용률 측정
    • 성능 메트릭 추출

로그 관리의 모범 사례

효과적인 로그 관리를 위해 다음과 같은 실천 방안을 고려해야 한다:

  1. 표준화된 로깅 정책 수립:

    • 로그 형식 정의
    • 필수 포함 정보 지정
    • 로그 레벨 사용 기준 설정
  2. 보안 고려사항:

    • 민감한 정보 마스킹
    • 접근 권한 관리
    • 로그 무결성 보장
  3. 성능 최적화:

    • 비동기 로깅 사용
    • 로그 버퍼링 적용
    • 로그 압축 활용

참고 및 출처