From 194bf7bb455daa5404c5db6629524562cd3eb9d7 Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 21 Oct 2026 17:56:13 +0200 Subject: [PATCH] Consolidate debug configuration documentation in header --- lib/debug_config.h | 20 ++++--- lib/debug_config_doc.md | 112 ---------------------------------------- lib/platform_compat.h | 2 +- 3 files changed, 15 insertions(+), 119 deletions(-) delete mode 100644 lib/debug_config_doc.md diff --git a/lib/debug_config.h b/lib/debug_config.h index 5a467240..0191f571 100644 --- a/lib/debug_config.h +++ b/lib/debug_config.h @@ -2,6 +2,11 @@ * Управление диагностикой: debug_config_init → уровни категорий и настройки вывода → DEBUG_*. * NONE наследует общий уровень, DISABLED отключает категорию. Имена настроек — category=level. * Открытый файл имеет приоритет над консолью; hook получает сообщения независимо от выбора выхода. + * Уровни: disabled, none, error, warn, info, debug, trace; отдельный уровень категории заменяет общий, не max(). + * Пример: debug_config_init(); debug_set_level(DEBUG_LEVEL_INFO); debug_parse_config("etcp=trace,config=info"). + * DEBUG_* фильтруют до форматирования; прямой debug_output фильтр не проверяет. + * Строка с префиксами ограничена буфером 4096 байт и обрезается; каждый вывод fflush. + * Модуль и смена глобальных настроек/файлов не синхронизированы; параллельный доступ согласует владелец. */ #ifndef DEBUG_CONFIG_H @@ -98,7 +103,8 @@ typedef struct { /* Global debug configuration */ extern debug_config_t g_debug_config; -/* Initialize debug system with default settings */ +/* До использования: ERROR, категории NONE, консоль stdout, timestamp/function/file:line включены. + * Повторный init сбрасывает поля, но не закрывает уже открытый файл; перед ним закрыть файл отдельно. */ void debug_config_init(void); /* Set debug level */ @@ -154,13 +160,13 @@ int debug_should_output(debug_level_t level, debug_category_t category_idx); /* Get current debug level */ debug_level_t debug_get_level(void); -/* Get category name by index */ +/* Заимствованное имя категории; для неизвестного индекса возвращает "UNKNOWN". */ const char* debug_get_category_name(debug_category_t category_idx); -/* Get category by name string */ +/* Поиск без учёта регистра: индекс, ALL для "all", NONE при NULL/неизвестном имени. */ debug_category_t get_category_by_name(const char* name); -/* Get level by name string with error reporting */ +/* Поиск без учёта регистра: NULL → NONE; неизвестное имя логируется и даёт INFO (fallback). */ debug_level_t debug_level_from_name(const char* name); /* Set category level using text names (main API) */ @@ -172,12 +178,14 @@ int debug_apply_category_config(const char* category_name, const char* level_nam /* Apply global debug level from text name */ void debug_apply_global_level(const char* level_name); -/* Format and output debug message (internal use by macros) */ +/* Форматирует сообщение printf-формата с необязательными метками; фильтрацию выполняет вызывающий. + * Время календарное, локальное, hh:mm:ss-миллисекунды.микросекунды; положительный thread_marker выводится отдельно. */ void debug_output(debug_level_t level, debug_category_t category_idx, const char* function, const char* file, int line, const char* format, ...); -/* Log hook — if set, called with every debug message (for JNI/bridge integration) */ +/* Hook вызывается синхронно для форматированного сообщения до записи в выход; NULL снимает hook. + * category/message заимствованы на время вызова, message указывает на стековый буфер; для хранения скопировать. */ typedef void (*debug_log_hook_fn)(int level, const char* category, const char* message); void debug_set_log_hook(debug_log_hook_fn hook); diff --git a/lib/debug_config_doc.md b/lib/debug_config_doc.md deleted file mode 100644 index 8c72b525..00000000 --- a/lib/debug_config_doc.md +++ /dev/null @@ -1,112 +0,0 @@ -# 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. Инициализация - -```c -#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. Макросы логирования - -```c -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()`. Пример из конфиг-файла: - -```ini -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. Вспомогательные утилиты - -```c -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` — вывод в stdout -- `thread_marker` — числовой маркер потока (0 = нет) diff --git a/lib/platform_compat.h b/lib/platform_compat.h index d144c18f..fa65042e 100644 --- a/lib/platform_compat.h +++ b/lib/platform_compat.h @@ -3,7 +3,7 @@ * Также предоставляет криптографический random_bytes, адреса интерфейсов, выбор default route * и классификацию публичных IPv4. Сокетные типы/ошибки и nonblocking API — в socket_compat.h. * Подключать этот заголовок вместо прямых POSIX includes для общего кода. - * Windows: htobe*/be*toh через byteswap, strcasecmp/strncasecmp через _stricmp/_strnicmp, + * Windows: htobe16/32/64 и be16/32/64toh через byteswap, strcasecmp/strncasecmp через _stricmp/_strnicmp, * memmem через inline-поиск (пустой образец возвращает начало), poll через WSAPoll, mkdir через _mkdir. * utun_gettimeofday — календарное Unix-время (не монотонное); Windows игнорирует tz. * Windows pipe — _pipe(4096, _O_BINARY). fcntl: F_GETFL возвращает 0, F_SETFL с O_NONBLOCK включает