UniSet @VERSION@
База логов (LogDB)

Общее описание работы LogDB

LogDB — расширение UniSet для сбора, хранения и просмотра логов от множества удалённых log-серверов.

Основные возможности:

  • Сбор логов с нескольких удалённых LogServer по TCP
  • Хранение в SQLite с автоматической ротацией
  • REST API для запросов к базе логов
  • WebSocket для просмотра логов в реальном времени
  • Web-интерфейс для интерактивного просмотра
  • Утилиты для конвертации и администрирования

LogDB это сервис, работа которого заключается в подключении к указанным лог-серверам, получении от них логов и сохранении их в БД (sqlite). Помимо этого LogDB выступает в качестве REST сервиса, позволяющего получать логи за указанный период в виде json.

Реализация намеренно простая, т.к. пока неясно нужно ли это и в каком виде. Ожидается что контролируемых логсерверов будет не очень много (максимум несколько десятков) и каждый лог будет генерировать не более 2-5 мегабайт записей. Поэтому sqlite должно хватить.

Конфигурирование LogDB

Для конфигурования необходимо создать секцию вида:

<LogDB name="LogDB" dbfile="logs.db">
<logserver name="main"
ip="localhost"
port="3333"
cmd="-s info,warn,crit"
description="Main server"
logfile="/var/log/uniset-main.log"/>
<logserver name="aux" ip="192.168.1.10" port="3333" cmd="-s warn,crit"/>
</LogDB>

Атрибуты logserver:

  • name — идентификатор лога
  • ip — хост/IP адрес
  • port — порт подключения
  • cmd — команды фильтрации (-s set, -d disable, -a add)
  • description — описание (опционально)
  • logfile — файл для параллельной записи (опционально)

При этом доступно два способа:

  • Первый — это использование секции в общем файле проекта (configure.xml).
  • Второй способ — позволяет создать отдельный xml-файл с одной настроечной секцией и указать его в аргументах командной строки:
    uniset2-logdb --single-confile logdbconf.xml

LogDB: Работа с БД

SQLite — единственный поддерживаемый бэкенд.

Схема таблицы logs:

CREATE TABLE logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
tms INTEGER, -- Unix timestamp
usec INTEGER, -- микросекунды
name TEXT, -- имя log-сервера
text TEXT -- текст сообщения
);

Для оптимизации, запись в БД сделана не по каждому сообщению, а через промежуточный буфер. Т.е. только после того как в буфере скапливается qbufSize сообщений (строк) буфер скидывается в базу.

Помимо этого, встроен механизм "ротации БД". Если задан параметр maxRecords (–prefix-db-max-records), то в БД будет поддерживаться ограниченное количество записей. При этом введён "гистерезис", т.е. фактически удаление старых записей начинается при переполнении БД определяемом коэффициентом переполнения overflowFactor (–prefix-db-overflow-factor). По умолчанию 1.3.

Параметры командной строки для работы с БД:

--logdb-dbfile <path> Путь к файлу БД
--logdb-db-buffer-size <N> Размер буфера перед flush (по умолчанию: 1000)
--logdb-db-max-records <N> Максимум записей в БД (0 = без ограничений)
--logdb-db-overflow-factor <float> Коэффициент переполнения (по умолчанию: 1.3)
--logdb-db-disable Отключить запись в БД
--logdb-db-timestamp-format 'localtime' или 'utc'

LogDB: REST API

LogDB предоставляет возможность получения логов через REST API. Для этого запускается http-сервер. Параметры запуска можно указать при помощи: –prefix-httpserver-host и –prefix-httpserver-port.

А так же –prefix-httpserver-max-queued для указания максимального размера очереди запросов к серверу и –prefix-httpserver-max-threads количество потоков обработки запросов.

REST API доступен по пути: /api/v2/logdb/... (текущая версия v2)

Endpoint Описание
/help Получение списка доступных команд
/list Список доступных логов
/logs?logname&parameters Получение логов 'logname'
/count?logname Получить текущее количество записей
/status Текущее состояние сервиса
/download Загрузить файл БД. По умолчанию выключено

Параметры запроса /logs:

  • logname — имя лога
  • offset=N — начиная с N-ой записи
  • limit=M — количество в ответе
  • from='YYYY-MM-DD' — 'с' указанной даты
  • to='YYYY-MM-DD' — 'по' указанную дату
  • last=XX[m|h|d|M] — за последние XX m-минут, h-часов, d-дней, M-месяцев. По умолчанию: минут

Параметры командной строки для HTTP-сервера:

--logdb-httpserver-host <IP> Адрес прослушивания (по умолчанию: localhost)
--logdb-httpserver-port <PORT> Порт (по умолчанию: 8080)
--logdb-http-max-requests <N> Макс. одновременных HTTP запросов (по умолчанию: 10)
--logdb-httpserver-max-queued <N> Размер очереди запросов
--logdb-httpserver-cors-allow <*> CORS origin (по умолчанию: *)
--logdb-httpserver-logcontrol-enable Включить API управления уровнями
--logdb-httpserver-download-enable Включить скачивание БД

Количество потоков HTTP-сервера рассчитывается автоматически:

http_max_threads = ws-max + http-max-requests + 2 (резерв для мониторинга)
-client

LogDB: Status API

Endpoint /api/v2/logdb/status возвращает текущее состояние сервиса:

{
"uptime_sec": 123.45,
"http_active_requests": 1,
"http_max_requests": 10,
"http_max_threads": 62,
"websockets_active": 2,
"websockets_max": 50,
"logservers": [
{
"name": "main",
"ip": "localhost",
"port": 3333,
"connected": true,
"description": "Main server"
}
],
"db_records": 1500,
"db_buffer_size": 10,
"db_max_records": 200000
}

Поля ответа:

  • uptime_sec — время работы сервиса в секундах
  • http_active_requests — текущее количество HTTP запросов
  • http_max_requests — максимум одновременных HTTP запросов (не WS)
  • http_max_threads — общее количество потоков HTTP-сервера
  • websockets_active — текущее количество WebSocket соединений
  • websockets_max — максимально допустимое количество WebSocket соединений
  • logservers — массив с информацией о log-серверах
  • db_records — общее количество записей в БД
  • db_buffer_size — количество записей в буфере ожидающих записи
  • db_max_records — лимит записей в БД

LogDB: Control API

CONTROL API доступен по пути: /api/v2/logcontrol/... (текущая версия v2)

По умолчанию отключено (см. –logdb-httpserver-logcontrol-enable)

/logcontrol/logname?set=info,warn,crit - Включить уровень логов для logname
/logcontrol/logname?reset - Вернуть логи к настройкам по умолчанию (из конфига)
/logcontrol/logname?get - Получить текущие выставленные настройки

LogDB: Поддержка WebSocket

В LogDB встроена возможность просмотра логов в реальном времени, через websocket.

Список лог-серверов доступен по адресу:

http://host:port/ws/

Прямое подключение к websocket-у доступно по адресу:

ws://host:port/ws/connect/logname?set=info,warn,crit,-level2

Где logname — это имя логсервера от которого мы хотим получать логи (см. Конфигурирование LogDB). set — позволяет установить желаемый уровень логов (не обязательный параметр)

Количество создаваемых websocket-ов можно ограничить при помощи параметра maxWebsockets (–prefix-ws-max).

Управлять уровнем логов можно через API:

http://host:port/ws/logname?set=info,warn,crit,-level2
set=loglevel - Установить loglevel для logname. Разрешение на управление должно быть включено.
'loglevel' - задание в формате команды. Пример: info,warn,+level1,-level2

Параметры командной строки для WebSocket:

--logdb-ws-max <N> Максимум соединений (по умолчанию: 50)
--logdb-ws-heartbeat-time <ms> Интервал ping (по умолчанию: 3000)
--logdb-ws-send-time <ms> Интервал отправки (по умолчанию: 500)
--logdb-ws-max-send <N> Сообщений за отправку (по умолчанию: 200)
--logdb-ws-backpressure-timeout <ms> Таймаут backpressure (по умолчанию: 15000)
--logdb-ws-queue-bytes-limit <bytes> Лимит очереди (по умолчанию: 2MB)
--logdb-ws-pong-timeout <ms> Таймаут ожидания PONG (по умолчанию: 10000)
--logdb-ws-max-lifetime <ms> Макс. время жизни соединения, 0=без ограничений

LogDB: Файлы логов

Несмотря на то, что все логи сохраняются в БД, их так же можно писать в файлы. Для этого каждому логу достаточно указать свойство logfile в настройках (см. Конфигурирование LogDB)

LogDB: Технические детали

Вся реализация построена на "однопоточном" eventloop. В нём происходит чтение данных от логсерверов, посылка сообщений в websockets, запись в БД. При этом обработка запросов REST API реализуется отдельными потоками контролируемыми libpoco.

Архитектура:

Log Servers (TCP) → LogDB::Log → signal → addLog() → qbuf (буфер)
flushBuffer()
SQLite DB
REST API / WebSocket
  • Неблокирующий I/O на базе libev
  • HTTP-сервер на Poco с пулом потоков
  • Транзакционная запись в БД (BEGIN/COMMIT)

Параметры для log-серверов:

--logdb-ls-check-connection-sec <N> Интервал проверки соединения (по умолчанию: 5)
--logdb-ls-read-buffer-size <N> Размер буфера чтения (по умолчанию: 10001)

LogDB: Вспомогательные утилиты

uniset2-logdb-adm

Для "обслуживания БД" (создание, конвертирование, ротация) имеется специальная утилита uniset2-logdb-adm. Т.к. logdb при своём запуске подразумевает, что БД уже создана, то для создания БД можно воспользоваться командой:

uniset2-logdb-adm create dbfilename

Для того, чтобы конвертировать (загрузить) отдельные лог-файлы в базу, можно воспользоваться командой:

uniset2-logdb-adm load logfile1 logfile2...logfileN

Более детальное описание параметров см. uniset2-logdb-adm help

uniset2-logdb-conv

Конвертация текстовых логов в SQLite:

uniset2-logdb-conv logs.db main:server.log aux:auxiliary.log

Формат лога: DD/MM/YYYY HH:MM:SS(level): text

uniset2-logdb-ws-reader

WebSocket-клиент для чтения логов:

uniset2-logdb-ws-reader --ws ws://localhost:8080/ws/connect/main

Опции:

  • --recv-buf <size> — размер буфера приёма
  • --pause-after <N> — пауза после N фреймов
  • --pause-ms <ms> — длительность паузы
  • --max-frames <N> — максимум фреймов

Ключевые классы

LogDB

Главный класс, наследует EventLoopServer и Poco::Net::HTTPRequestHandler:

  • Управляет подключениями к удалённым log-серверам
  • Буферизует сообщения и пишет в SQLite
  • Предоставляет REST API и WebSocket
  • Неблокирующий event loop на базе libev

LogDB::Log

Представляет соединение с одним log-сервером:

  • TCP-соединение с автоматическим переподключением
  • Отправка команд фильтрации (-s, -d, -a)
  • Сигналы sigc++ при получении логов
  • Буферизованное чтение

LogDB::LogWebSocket

WebSocket-сессия с браузером:

  • Очередь сообщений с контролем backpressure
  • Heartbeat (ping/pong) с таймаутом
  • Батчинг и троттлинг отправки
  • Ограничение по объёму очереди
  • Автоматическое закрытие при отсутствии pong

Запуск сервиса

Основной сервис:

uniset2-logdb --confile configure.xml --logdb-dbfile logs.db

Или с отдельным конфигурационным файлом:

uniset2-logdb --single-confile logdb-conf.xml

Зависимости

  • SQLite3
  • Poco (PocoFoundation, PocoNet, PocoJSON)
  • libev
  • sigc++-2.0