> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-parallel-read-in-order-multi-part.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Этот движок позволяет обрабатывать файлы журнала приложений как поток записей.

# Движок таблицы FileLog

Этот движок позволяет обрабатывать файлы журнала приложений как поток записей.

`FileLog` позволяет:

* Подписываться на файлы журнала.
* Обрабатывать новые записи по мере их добавления в отслеживаемые файлы журнала.

## Создание таблицы

```sql theme={null}
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` - Тайм-аут одного опроса файла журнала. Значение по умолчанию: [stream\_poll\_timeout\_ms](/ru/reference/settings/session-settings/stream#stream_poll_timeout_ms).
* `poll_max_batch_size` — Максимальное количество записей, считываемых за один опрос. Значение по умолчанию: [max\_block\_size](/ru/reference/settings/session-settings/max#max_block_size).
* `max_block_size` — Максимальный размер батча (в записях) для одного опроса. Значение по умолчанию: [max\_insert\_block\_size](/ru/reference/settings/session-settings/max-insert#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 (если не удастся разобрать сообщение, будет сгенерировано исключение), stream (сообщение об исключении и исходное сообщение будут сохранены в виртуальных столбцах `_error` и `_raw_message`).

## Описание

Доставленные записи отслеживаются автоматически, поэтому каждая запись в файле журнала учитывается только один раз.

`SELECT` не слишком полезен для чтения записей (кроме отладки), потому что каждую запись можно прочитать только один раз. Гораздо практичнее создавать потоки в реальном времени с помощью [materialized views](/ru/reference/statements/create/view). Для этого:

1. Используйте движок, чтобы создать таблицу FileLog, и рассматривайте её как поток данных.
2. Создайте таблицу с нужной структурой.
3. Создайте materialized view, которое преобразует данные из движка и помещает их в созданную ранее таблицу.

Когда `MATERIALIZED VIEW` подключается к движку, оно начинает собирать данные в фоновом режиме. Это позволяет непрерывно получать записи из файлов журнала и преобразовывать их в нужный формат с помощью `SELECT`.
Одна таблица FileLog может иметь сколько угодно materialized views; они не читают данные из таблицы напрямую, а получают новые записи (блоками), поэтому вы можете записывать данные в несколько таблиц с разным уровнем детализации (с группировкой — агрегацией — и без неё).

Пример:

```sql theme={null}
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;
```

Чтобы перестать получать данные из потоков или изменить логику преобразования, отсоедините materialized view:

```sql theme={null}
DETACH TABLE consumer;
ATTACH TABLE consumer;
```

Если вы хотите изменить целевую таблицу с помощью `ALTER`, рекомендуем отключить materialized view, чтобы избежать расхождений между целевой таблицей и данными представления.

## Виртуальные столбцы

* `_filename` - Имя файла журнала. Тип данных: `LowCardinality(String)`.
* `_offset` - Смещение в файле журнала. Тип данных: `UInt64`.

Дополнительные виртуальные столбцы при `handle_error_mode='stream'`:

* `_raw_record` - Исходная запись, которую не удалось успешно разобрать. Тип данных: `Nullable(String)`.
* `_error` - Сообщение об исключении, возникшем при неудачном разборе. Тип данных: `Nullable(String)`.

Примечание: виртуальные столбцы `_raw_record` и `_error` заполняются только в случае исключения при разборе; если сообщение было успешно разобрано, они всегда имеют значение `NULL`.

## Долговечность данных

Движок `FileLog` записывает смещение, обработанное для фрагмента, ещё до того, как будет закоммичена вставка, к которой этот фрагмент относится, поэтому при аварийной остановке сервера записанное смещение может оказаться дальше, чем данные, реально попавшие в целевую таблицу. При перезапуске чтение каждого файла журнала возобновляется с того смещения, которое сохранено в его каталоге метаданных, так что эти строки уже никогда не будут прочитаны повторно: они теряются без каких-либо ошибок, а `count()` просто оказывается меньше. Чтобы это проявилось, достаточно обычного сбоя процесса — потеря питания не требуется, поскольку смещение сохраняется в файле метаданных, который переименовывается на своё место в тот момент, когда целевой парт ещё пишется.

Потеря кэша страниц ОС может дополнительно уничтожить данные, уже записанные в целевую таблицу; примеры — потеря питания на уровне устройства и некорректный сброс хоста или ядра. Сами файлы метаданных, хранящие смещения, записываются без fsync — ни самого файла, ни его каталога, — поэтому и они не дают никаких гарантий долговечности.

В отличие от движков для брокеров сообщений, `FileLog` нельзя защитить от этого, предварительно обеспечив долговечность целевой таблицы. Поскольку смещение записывается изнутри конвейера чтения, до завершения вставки, к которой оно относится, параметр `fsync_after_insert = 1` на целевых таблицах `MergeTree` не гарантирует, что вставленный парт станет долговечным до того, как смещение продвинется. Относитесь к чтению через `FileLog` как к дочитыванию локальных файлов по принципу «насколько получится»: если потеря строк недопустима, сохраняйте исходные файлы журналов до тех пор, пока обработанные данные не будут проверены в целевой таблице, чтобы чтение можно было повторить. Удаление и повторное создание таблицы сбрасывает записанные смещения и приводит к повторному чтению файлов с начала.
