Skip to main content
이 엔진을 사용하면 애플리케이션 로그 파일을 레코드 스트림 형태로 처리할 수 있습니다. FileLog를 사용하면 다음 작업을 수행할 수 있습니다:
  • 로그 파일을 구독합니다.
  • 구독한 로그 파일에 새 레코드가 추가될 때 처리합니다.

테이블 생성

엔진 인수:
  • path_to_logs – 구독할 로그 파일의 경로입니다. 로그 파일이 있는 디렉터리 경로일 수도 있고, 단일 로그 파일 경로일 수도 있습니다. 상대 경로는 file 테이블 함수와 마찬가지로 user_files_path 디렉터리를 기준으로 해석됩니다. 다만, 서버의 작업 디렉터리를 기준으로 이미 user_files_path 내부를 가리키는 상대 경로(예를 들어, 공식 Docker 이미지처럼 서버가 데이터 디렉터리에서 실행될 때의 user_files/my_app/app.log)는 그대로 해석됩니다. 경로의 파일 이름에 글롭 패턴(*, ?, {abc,def}, {N..M})을 사용하면 디렉터리에서 패턴과 일치하는 파일만 읽을 수 있습니다. 자세한 내용은 글롭 패턴으로 파일 선택하기를 참조하십시오. ClickHouse는 user_files 디렉터리 내부의 경로만 허용합니다.
  • format_name - 레코드 포맷입니다. FileLog는 파일의 각 줄을 개별 레코드로 처리하므로, 모든 데이터 포맷이 이에 적합한 것은 아닙니다.
선택적 매개변수:
  • poll_timeout_ms - 로그 파일에서 한 번 폴링할 때의 시간 초과 값입니다. 기본값: stream_poll_timeout_ms.
  • poll_max_batch_size — 한 번의 폴링으로 가져올 수 있는 최대 레코드 수입니다. 기본값: max_block_size.
  • max_block_size — 폴링의 최대 배치 크기(레코드 수)입니다. 기본값: max_insert_block_size.
  • max_threads - 파일을 파싱하기 위한 최대 스레드 수입니다. 기본값은 0이며, 이 경우 스레드 수는 max(1, physical_cpu_cores / 4)입니다.
  • poll_directory_watch_events_backoff_init - 디렉터리 감시 스레드의 초기 대기 값입니다. 기본값: 500.
  • poll_directory_watch_events_backoff_max - 디렉터리 감시 스레드의 최대 대기 값입니다. 기본값: 32000.
  • poll_directory_watch_events_backoff_factor - 백오프 속도입니다. 기본적으로 지수적으로 증가합니다. 기본값: 2.
  • handle_error_mode — FileLog 엔진에서 오류를 처리하는 방식입니다. 가능한 값: default(직접 SELECT를 실행할 때 레코드 파싱에 실패하면 예외를 발생시킴. 테이블이 materialized view로 데이터를 스트리밍하는 동안에는 해당 레코드를 건너뛰고 오류를 서버 로그에 기록함), stream(예외 메시지와 원시 레코드를 가상 컬럼 _error 및 _raw_record에 저장함).

설명

전달된 레코드는 자동으로 추적되므로 로그 파일의 각 레코드는 한 번만 계산됩니다. copytruncate 옵션으로 logrotate를 실행한 뒤처럼, 다음에 파일을 읽을 때 파일 크기가 해당 파일에 기록된 오프셋보다 작으면 처음부터 다시 읽습니다. 다음에 파일을 읽기 전에 파일 크기가 해당 오프셋 이상으로 다시 커지면 파일이 잘렸다는 사실을 감지하지 못합니다. 디렉터리 안에서 여러 이름(하드 링크)으로 존재하는 파일은 그중 하나의 이름으로만 읽습니다. 열 수 없는 파일(대상이 삭제된 심볼릭 링크, 서버가 읽을 수 없는 파일, 삭제된 단일 파일 테이블의 파일)은 서버 로그에 오류를 남기고 건너뛰며, 테이블이 로드되어 있는 동안 열 수 있을 때까지 재시도합니다. 이후 누락되었던 파일은 처음부터 읽습니다. 심볼릭 링크는 테이블이 이를 발견한 시점에 대상이 존재하는 경우에만 읽습니다. 레코드를 읽는 용도로는 SELECT가 그다지 유용하지 않습니다(디버깅 시 제외). 각 레코드는 한 번만 읽을 수 있기 때문입니다. 보다 실용적인 방법은 materialized view(materialized views)를 사용해 실시간 스트림을 만드는 것입니다. 이를 위해 다음을 수행하십시오:
  1. 이 엔진을 사용해 FileLog 테이블을 만들고, 이를 데이터 스트림으로 간주합니다.
  2. 원하는 구조의 테이블을 생성합니다.
  3. 엔진의 데이터를 변환해 앞서 생성한 테이블에 저장하는 materialized view를 생성합니다.
MATERIALIZED VIEW를 엔진에 연결하면 백그라운드에서 데이터 수집이 시작됩니다. 이를 통해 로그 파일의 레코드를 지속적으로 수신하고, SELECT를 사용해 필요한 포맷으로 변환할 수 있습니다. 하나의 FileLog 테이블에는 원하는 만큼 materialized view를 둘 수 있습니다. 이들은 테이블에서 데이터를 직접 읽는 대신 새 레코드(블록 단위)를 받습니다. 따라서 상세 수준이 서로 다른 여러 테이블에 쓸 수 있습니다(그룹화/집계 적용 또는 미적용). 예시:
스트림 데이터 수신을 중단하거나 변환 로직을 변경하려면 materialized view를 detach하십시오:
ALTER를 사용해 대상 테이블을 변경하려면, 대상 테이블과 뷰 데이터 간 불일치를 방지하기 위해 materialized view를 비활성화하는 것이 좋습니다.

글롭 패턴으로 파일 선택하기

path_to_logs의 파일 이름에 글롭 패턴이 포함되어 있으면, 테이블은 해당 디렉터리에서 이름이 일치하는 파일을 읽습니다. 이후에 새로 생기는 파일도 마찬가지입니다. 경로의 디렉터리 부분에는 글롭 패턴을 사용할 수 없습니다. 테이블이 읽고 있는 파일은 일치하지 않는 이름으로 변경되더라도 디렉터리에서 제거될 때까지 계속 읽힙니다. 테이블이 분리된 상태이거나 서버가 중지된 동안 생성된 후 일치하지 않는 이름으로 변경된 파일은 읽히지 않습니다. macOS에서는 디렉터리 목록을 비교하는 방식으로 디렉터리를 감시하므로, 테이블이 목록을 조회하기 전에 생성된 후 일치하지 않는 이름으로 변경된 파일도 마찬가지로 읽히지 않습니다. 이는 로그 교체에 필요한 동작입니다. 예를 들어 compress와 delaycompress를 사용하는 logrotate는 디렉터리를 다음과 같은 상태로 유지합니다:
FileLog('/var/lib/clickhouse/user_files/my_app/*.log', 'JSONEachRow')를 기반으로 하는 테이블은 app.log를 읽습니다. 로그 교체 후에도 app.log.1을 계속 읽으므로, 애플리케이션이 로그를 다시 열기 전까지 해당 파일에 기록한 줄도 유실되지 않습니다. 또한 압축된 파일은 읽지 않습니다. 글롭 패턴이 압축된 파일 이름과 일치하지 않도록 하십시오.

가상 컬럼(Virtual columns)

  • _filename - 로그 파일 이름입니다. 데이터 타입: LowCardinality(String).
  • _offset - 로그 파일 내 오프셋입니다. 데이터 타입: UInt64.
handle_error_mode='stream'일 때 추가되는 가상 컬럼:
  • _raw_record - 성공적으로 파싱되지 않은 원시 레코드입니다. 데이터 타입: Nullable(String).
  • _error - 파싱 실패 중 발생한 예외 메시지입니다. 데이터 타입: Nullable(String).
참고: _raw_record 및 _error 가상 컬럼은 파싱 중 예외가 발생한 경우에만 채워지며, 메시지가 성공적으로 파싱된 경우에는 항상 NULL입니다.

데이터 내구성

FileLog 엔진은 청크가 포함된 삽입이 커밋되기 전에 해당 청크를 소비한 오프셋을 먼저 기록하므로, 서버가 비정상 종료되면 기록된 오프셋이 실제로 대상 테이블에 반영된 데이터보다 앞서 있을 수 있습니다. 재시작하면 각 로그 파일은 메타데이터 디렉터리에 기록된 오프셋부터 이어서 읽기 때문에 그 사이의 행들은 다시 읽히지 않습니다. 즉, 아무런 오류 없이 유실되고 count() 값만 줄어듭니다. 전원 손실이 아니라 일반적인 프로세스 장애만으로도 이 문제가 발생하는데, 대상 파트가 아직 기록되는 중에 메타데이터 파일이 제자리로 이름이 변경되면서 오프셋이 기록되기 때문입니다. OS 페이지 캐시가 유실되면 이미 대상 테이블에 기록된 데이터까지 함께 사라질 수 있습니다. 장치 수준의 전원 손실이나 비정상적인 호스트 또는 커널 리셋이 그 예입니다. 오프셋을 담고 있는 메타데이터 파일 자체도 파일이나 해당 디렉터리에 대한 fsync 없이 기록되므로, 그 자체로는 어떠한 내구성도 보장하지 않습니다. 메시지 브로커 엔진과 달리 FileLog에서는 대상을 먼저 내구성 있게 만드는 방식으로 이 문제를 막을 수 없습니다. 오프셋은 읽기 파이프라인 내부에서, 그것이 속한 삽입이 완료되기 전에 기록되므로, 대상 MergeTree 테이블에 fsync_after_insert = 1을 설정하더라도 오프셋이 전진하기 전에 삽입된 파트가 내구성 있게 확정되지는 않습니다. 따라서 FileLog 활용은 로컬 파일에 대한 최선 노력(best-effort) 방식의 테일링으로 간주하십시오. 단 한 행도 유실되어서는 안 되는 환경이라면, 소비된 데이터가 대상에서 검증될 때까지 원본 로그 파일을 보관하여 언제든 다시 활용할 수 있도록 하십시오. SYSTEM RESET FILELOG를 실행하거나 테이블을 삭제하고 다시 생성하면 기록된 오프셋이 폐기되고 파일을 처음부터 다시 읽습니다.