8.3 KiB
debug_config — Runtime-система отладочного логирования
1. Назначение
Модуль обеспечивает гибкое управление отладочным выводом без перекомпиляции. Позволяет:
- Задавать глобальный уровень логирования (error/warn/info/debug/trace).
- Покатегорийно включать/выключать или переопределять уровень (26 категорий: etcp, crypto, tun, routing, bgp, bbr, …).
- Вести двойной вывод: в консоль (stdout) и/или в файл.
- Настраивать формат сообщений (временные метки с микросекундами, имя функции, файл:строка).
- Парсить конфигурационную строку вида
"etcp=trace,config=info"из конфиг-файла.
Логика вывода: итоговый уровень = max(глобальный уровень, уровень категории). Сообщение печатается, если его уровень ≤ итогового.
2. Как пользоваться
2.1. Инициализация
#include "debug_config.h"
debug_config_init(); // уровень по умолчанию: ERROR, консоль включена
debug_set_level(DEBUG_LEVEL_INFO); // поднять глобальный уровень до INFO
debug_enable_file_output("/tmp/utun.log", 1); // писать в файл (truncate=1)
debug_apply_category_config("etcp", "trace"); // для ETCP-категории — всё
2.2. Макросы логирования
DEBUG_ERROR(DEBUG_CATEGORY_CRYPTO, "Decrypt failed: len=%d", len);
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "Retransmit timeout, seq=%u", seq);
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Socket created on port %d", port);
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "Route added: %s -> %s", dst, gw);
DEBUG_TRACE(DEBUG_CATEGORY_TUN, "Packet recv: %zu bytes", n);
Макросы делают проверку debug_should_output() перед вызовом debug_output(), поэтому дорогой vsnprintf не вызывается, если вывод не нужен.
2.3. Конфигурационная строка
Формат: "категория=уровень,категория=уровень,...". Парсится вызовом debug_parse_config(). Пример из конфиг-файла:
debug = etcp=trace,config=info,crypto=error
Категории: none, uasync, ll_queue, connection, etcp, crypto, memory, timing, config, tun, routing, timers, normalizer, bgp, socket, control, dump, traffic, debug, general, nat, keepalive, etcp_route, bbr, etcp_dump, connectivity, all.
Уровни: disabled, none, error, warn, info, debug, trace.
Важно: старый формат ll_queue:debug (двоеточие) тоже работает через debug_parse_config, но в конфиге рекомендуется =.
2.4. Двойной вывод (консоль + файл)
- По умолчанию вывод в stdout.
debug_enable_file_output(path, truncate)— перенаправляет вывод в файл, консоль отключается.debug_disable_file_output()— закрывает файл.debug_reopen_log()— переоткрывает лог-файл (используется по SIGHUP для ротации).debug_enable_console(1/0)— ручное управление консольным выводом.
2.5. Вспомогательные утилиты
log_dump(DEBUG_LEVEL_TRACE, DEBUG_CATEGORY_DUMP, "payload", data, len); // hex-дамп (до 128 байт)
ip_str_t s = sockaddr_storage_to_str(&addr); // "192.168.1.1:8080" или "[::1]:443"
ip_str_t s = ip_to_str(&addr, AF_INET); // "192.168.1.1" (без порта)
2.6. Нюансы
- Потокобезопасность: модуль не потокобезопасен. Несколько потоков, одновременно вызывающих макросы, могут перемешать вывод (но не упадут). Файловый вывод использует
fflush()после каждой строки. - Буфер: размер строки лога ограничен 4096 байт (
BUFFER_SIZE), длинные сообщения обрезаются. debug_set_output_fileпротивdebug_enable_file_output: первая вызывается один раз (кто первый — того и тапки), вторая позволяет переоткрыть файл.- Флаг
-f(foreground): в foreground-режиме вывод идёт в stdout, в daemon-режиме — в файл.
3. API
| Функция/макрос | Назначение |
|---|---|
debug_config_init() |
Инициализация: глобальный уровень ERROR, консоль включена, метки времени/функций/файлов — да |
debug_set_level(level) |
Задать глобальный уровень (ERROR..TRACE) |
debug_set_category_level(cat, level) |
Задать уровень конкретной категории (0 = использовать глобальный) |
debug_set_category_level_by_name("etcp", "trace") |
То же, но именами строк |
debug_apply_category_config("etcp", "trace") |
Установить уровень категории с логированием результата |
debug_apply_global_level("info") |
Установить глобальный уровень по имени строки |
debug_parse_config("etcp=trace,config=info") |
Разобрать конфигурационную строку |
debug_should_output(level, cat) |
Проверить, нужно ли выводить сообщение данного уровня/категории |
debug_output(level, cat, func, file, line, fmt, ...) |
Форматировать и вывести сообщение (вызывается макросами) |
debug_enable_file_output(path, truncate) |
Включить вывод в файл (консоль отключается) |
debug_disable_file_output() |
Закрыть файл вывода |
debug_reopen_log() |
Переоткрыть лог-файл (для SIGHUP/ротации) |
debug_enable_console(1/0) |
Включить/выключить консольный вывод |
debug_get_level() |
Получить текущий глобальный уровень |
get_category_by_name("etcp") |
Получить ID категории по имени строки |
debug_level_from_name("trace") |
Получить уровень по имени строки |
debug_get_category_name(cat) |
Получить имя категории по ID |
log_dump(level, cat, prefix, data, len) |
Hex-дамп данных (первые 128 байт) в лог |
ip_to_str(addr, family) |
IP-адрес → строка (без порта). Статический буфер |
sockaddr_storage_to_str(addr) |
sockaddr_storage → "ip:port" (IPv6 в скобках). Статический буфер |
DEBUG_ERROR/WARN/INFO/DEBUG/TRACE(cat, fmt, ...) |
Макросы логирования с проверкой debug_should_output() |
DEBUG_OUTPUT(fmt, ...) |
Устаревший макрос совместимости (ERROR, категория ALL) |
Глобальная переменная: g_debug_config (тип debug_config_t) — хранит всё состояние системы логирования.
Структура debug_config_t:
level— глобальный уровень (по умолчанию ERROR)category_levels[26]— уровни по категориям (NONE = использовать глобальный, DISABLED = никогда не выводить)timestamp_enabled/function_name_enabled/file_line_enabled— формат выводаfile_output— FILE* файла (NULL если вывод в консоль)console_enabled— вывод в stdoutthread_marker— числовой маркер потока (0 = нет)