FileLog 테이블 엔진

FileLog 테이블 엔진

FileLog 엔진은 애플리케이션 로그 파일을 레코드 스트림처럼 처리할 수 있게 해줘요. 로그 파일을 구독하고, 구독한 로그 파일에 새 레코드가 추가되면 이를 처리하는 데 사용합니다.

출처: 문서

본문

이 엔진은 애플리케이션 로그 파일을 레코드의 스트림으로 처리할 수 있게 합니다. FileLog를 사용하면:

  • 로그 파일을 구독할 수 있어요.
  • 구독한 로그 파일에 새 레코드가 추가되면 이를 처리할 수 있어요.

테이블 생성 (Creating a table)

CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
    ...
) ENGINE = FileLog('path_to_logs', 'format_name') SETTINGS
    [poll_timeout_ms = 0,]
    [poll_max_batch_size = 0,]
    [max_block_size = 0,]
    [max_threads = 0,]
    [poll_directory_watch_events_backoff_init = 500,]
    [poll_directory_watch_events_backoff_max = 32000,]
    [poll_directory_watch_events_backoff_factor = 2,]
    [handle_error_mode = 'default']

엔진 인자:

  • path_to_logs – 구독할 로그 파일의 경로. 로그 파일이 있는 디렉토리의 경로 또는 단일 로그 파일의 경로일 수 있어요. ClickHouse는 user_files 디렉토리 안의 경로만 허용합니다.
  • format_name — 레코드 형식. FileLog는 파일의 각 줄을 별도의 레코드로 처리하므로 모든 데이터 형식이 이에 적합한 것은 아닙니다.

선택적 매개변수:

  • poll_timeout_ms - 로그 파일에서 단일 poll에 대한 타임아웃. 기본값: stream_poll_timeout_ms.
  • poll_max_batch_size — 단일 poll에서 poll할 최대 레코드 수. 기본값: max_block_size.
  • max_block_size — poll을 위한 최대 배치 크기(레코드 수). 기본값: max_insert_block_size.
  • max_threads — 파일을 파싱할 최대 스레드 수. 기본값은 0이며, 이는 숫자가 max(1, physical_cpu_cores / 4)가 된다는 뜻입니다.
  • poll_directory_watch_events_backoff_init — 디렉토리 감시 스레드의 초기 sleep 값. 기본값: 500.
  • poll_directory_watch_events_backoff_max — 디렉토리 감시 스레드의 최대 sleep 값. 기본값: 32000.
  • poll_directory_watch_events_backoff_factor — 백오프 속도. 기본적으로 지수. 기본값: 2.
  • handle_error_mode — FileLog 엔진의 오류 처리 방법. 가능한 값: default(메시지를 파싱하는 데 실패하면 예외가 발생), stream(예외 메시지와 원시 메시지가 가상 컬럼 _error_raw_message에 저장됨).

설명 (Description)

전달된 레코드는 자동으로 추적되므로 로그 파일의 각 레코드는 한 번만 집계됩니다.

SELECT는 각 레코드를 한 번만 읽을 수 있으므로 레코드를 읽는 데 특별히 유용하지는 않아요(디버깅 제외). 매터리얼라이즈드 뷰를 사용하여 실시간 스레드를 만드는 것이 더 실용적입니다. 이를 위해:

  1. 엔진을 사용하여 FileLog 테이블을 만들고 이를 데이터 스트림으로 간주합니다.
  2. 원하는 구조를 가진 테이블을 만듭니다.
  3. 엔진의 데이터를 변환하여 이전에 만든 테이블에 넣는 매터리얼라이즈드 뷰를 만듭니다.

MATERIALIZED VIEW가 엔진에 조인하면 배경에서 데이터 수집을 시작합니다. 이렇게 하면 로그 파일의 레코드를 지속적으로 수신하고 SELECT를 사용하여 필요한 형식으로 변환할 수 있어요.

하나의 FileLog 테이블에는 원하는 만큼 많은 매터리얼라이즈드 뷰를 가질 수 있습니다. 뷰는 테이블에서 직접 데이터를 읽지 않고 새 레코드(블록 단위)를 받으므로, 서로 다른 상세 수준(그룹화 - 집계 포함 및 미포함)의 여러 테이블에 쓸 수 있어요.

예시:

CREATE TABLE logs (
    timestamp UInt64,
    level String,
    message String
  ) ENGINE = FileLog('user_files/my_app/app.log', 'JSONEachRow');

CREATE TABLE daily (
    day Date,
    level String,
    total UInt64
  ) ENGINE = SummingMergeTree
  PARTITION BY toYYYYMM(day)
  ORDER BY (day, level);

CREATE MATERIALIZED VIEW consumer TO daily
    AS SELECT toDate(toDateTime(timestamp)) AS day, level, count() AS total
    FROM logs GROUP BY day, level;

SELECT level, sum(total) FROM daily GROUP BY level;

스트림 데이터 수신을 중지하거나 변환 로직을 변경하려면 매터리얼라이즈드 뷰를 분리(detach)하세요:

DETACH TABLE consumer;
ATTACH TABLE consumer;

ALTER로 대상 테이블을 변경하려면 대상 테이블과 뷰의 데이터 사이의 불일치를 피하기 위해 매터리얼라이즈드 뷰를 비활성화하는 것을 권장합니다.

가상 컬럼 (Virtual columns)

  • _filename - 로그 파일의 이름. 데이터 타입: LowCardinality(String).
  • _offset - 로그 파일의 오프셋. 데이터 타입: UInt64.

handle_error_mode='stream'일 때의 추가 가상 컬럼:

  • _raw_record - 성공적으로 파싱되지 못한 원시 레코드. 데이터 타입: Nullable(String).
  • _error - 실패한 파싱 중 발생한 예외 메시지. 데이터 타입: Nullable(String).

참고: _raw_record와 _error 가상 컬럼은 파싱 중 예외가 발생한 경우에만 채워지며, 메시지가 성공적으로 파싱되면 항상 NULL입니다.

데이터 내구성 (Data durability)

FileLog 엔진은 해당 청크가 속한 삽입이 커밋되기 전에 청크가 소비한 오프셋을 기록합니다. 따라서 중단된 서버는 대상 테이블에 도달한 데이터보다 앞선 오프셋을 기록한 상태로 남을 수 있어요. 재시작 시 각 로그 파일은 메타데이터 디렉토리에 기록된 오프셋부터 다시 시작하므로 그 행들은 다시 읽히지 않습니다. 그 행들은 오류 없이 사라지고 count()는 단순히 더 작아집니다. 이를 드러내는 데는 일반적인 프로세스 실패로 충분하며, 전원 손실이 필요하지 않습니다. 오프셋이 대상 part가 아직 쓰이는 동안 제자리로 이름이 바뀌는 메타데이터 파일에 기록되기 때문입니다.

OS 페이지 캐시 손실은 대상 테이블에 이미 기록된 데이터를 추가로 버릴 수 있습니다. 예로는 디바이스 수준 전원 손실과 오염된(clean하지 않은) 호스트 또는 커널 리셋이 있어요. 오프셋을 보유한 메타데이터 파일은 파일이나 디렉토리를 fsync하지 않고 기록되므로, 자체적으로도 내구성 보장이 없습니다.

메시지 브로커 엔진과 달리 FileLog는 대상을 먼저 내구성 있게 만들어서 보호할 수 없어요. 오프셋이 대상 삽입이 끝나기 전에 읽기 파이프라인 내부에서 기록되기 때문에, 대상 MergeTree 테이블에서 fsync_after_insert = 1을 설정해도 오프셋이 진행되기 전에 삽입된 part를 내구성 있게 만들지 못합니다. FileLog 소비는 로컬 파일의 best-effort 테일링으로 취급하세요. 행 손실이 없어야 하는 곳에서는 소비된 데이터가 대상에서 검증될 때까지 원본 로그 파일을 보관해서 소비를 반복할 수 있게 하세요. 테이블을 삭제하고 다시 만들면 기록된 오프셋이 버려지고 파일을 처음부터 다시 읽습니다.

더 알아보기 (Learn more)