doc: added wiki
This commit is contained in:
1 parent
cb65332eb4
commit
d3d3817ae2
1 file changed
+214
+214
@@ -0,0 +1,214 @@
|
|||||||
|
# Описание компонента zh_syslog
|
||||||
|
|
||||||
|
## Общие сведения
|
||||||
|
|
||||||
|
**zh_syslog** — это лёгкий UDP-клиент syslog для ESP-IDF, отправляющий сообщения на удалённый syslog-сервер в формате [RFC 5424](https://datatracker.ietf.org/doc/html/rfc5424).
|
||||||
|
|
||||||
|
Компонент оборачивает стандартный BSD-сокет UDP и предоставляет несколько функций для инициализации, отправки сообщений и освобождения ресурсов.
|
||||||
|
|
||||||
|
## Основные возможности
|
||||||
|
|
||||||
|
1. **Все коды facility (0–23)** — поддержка стандартных значений по RFC 5424, включая `LOCAL0`–`LOCAL7` для локального использования.
|
||||||
|
2. **Все уровни severity (0–7)** — от `ZH_EMERG` до `ZH_DEBUG`.
|
||||||
|
3. **Формат RFC 5424** — автоматический расчёт приоритета `<PRI>` и генерация заголовка сообщения.
|
||||||
|
4. **Отправка по UDP** — сокеты не устанавливают соединения, сообщения доставляются дейтаграммами.
|
||||||
|
5. **Двухуровневая работа с памятью** — короткие сообщения форматируются в стековом буфере, длинные аллоцируются в куче точным размером.
|
||||||
|
6. **Проверка входных аргументов** — валидация IP-адреса, порта и диапазона кодов на этапе вызова.
|
||||||
|
7. **Потокобезопасные `init`/`deinit`** — защита состояния флагом инициализации (см. раздел «Ограничения» для `send`).
|
||||||
|
|
||||||
|
## Внутреннее устройство
|
||||||
|
|
||||||
|
### Структура `zh_syslog_init_config_t`
|
||||||
|
|
||||||
|
Публичная конфигурационная структура, передаваемая в `zh_syslog_init()`.
|
||||||
|
|
||||||
|
| Поле | Тип | Описание |
|
||||||
|
|------|-----|----------|
|
||||||
|
| `syslog_ip` | `char[16]` | IPv4-адрес syslog-сервера в виде строки (макс. 15 символов + `'\0'`) |
|
||||||
|
| `syslog_port` | `uint32_t` | UDP-порт сервера (диапазон 1–65535, по умолчанию 514) |
|
||||||
|
|
||||||
|
Для заполнения значений по умолчанию используется макрос `ZH_SYSLOG_INIT_CONFIG_DEFAULT()` (IP `192.168.0.1`, порт `514`).
|
||||||
|
|
||||||
|
### Внутренние переменные модуля
|
||||||
|
|
||||||
|
Не входят в публичный API и хранятся как `static` в `zh_syslog.c`.
|
||||||
|
|
||||||
|
| Переменная | Тип | Описание |
|
||||||
|
|------------|-----|----------|
|
||||||
|
| `_syslog_server` | `struct sockaddr_in` | Адрес сервера: IPv4, порт в сетевом порядке, семья `AF_INET` |
|
||||||
|
| `_socket` | `volatile int` | Дескриптор UDP-сокета, `-1` когда клиент не инициализирован |
|
||||||
|
| `_is_initialized` | `volatile bool` | Флаг состояния: `true` после успешного `init` |
|
||||||
|
|
||||||
|
Флаг `_is_initialized` используется как простой сторож состояния: `init` отказывает при уже инициализированном клиенте, `deinit` и `send` отказывают при неинициализированном.
|
||||||
|
|
||||||
|
### Управление памятью
|
||||||
|
|
||||||
|
- Короткое сообщение (помещающееся в стековый буфер `char stack_buf[256]`) форматируется прямо в стеке — аллокации в куче не происходит.
|
||||||
|
- Если `snprintf` вернул `len >= 256` (строка обрезана), память выделяется в куче ровно под `len + 1` байт через `heap_caps_calloc(..., MALLOC_CAP_8BIT)`.
|
||||||
|
- Флаг `heap_allocated` отслеживает, нужно ли освобождать буфер: `heap_caps_free()` вызывается владением только для кучного буфера — и при успехе, и при ошибке форматирования.
|
||||||
|
|
||||||
|
## API (интерфейс)
|
||||||
|
|
||||||
|
### Инициализация и освобождение
|
||||||
|
|
||||||
|
| Функция | Описание |
|
||||||
|
|---------|----------|
|
||||||
|
| `zh_syslog_init()` | Создаёт UDP-сокет и настраивает параметры соединения с сервером. |
|
||||||
|
| `zh_syslog_deinit()` | Закрывает сокет и сбрасывает состояние клиента. |
|
||||||
|
|
||||||
|
### Отправка сообщений
|
||||||
|
|
||||||
|
| Функция | Описание |
|
||||||
|
|---------|----------|
|
||||||
|
| `zh_syslog_send()` | Форматирует сообщение по RFC 5424 и отправляет его на настроенный сервер. |
|
||||||
|
|
||||||
|
### Типы и значения
|
||||||
|
|
||||||
|
| Элемент | Описание |
|
||||||
|
|---------|----------|
|
||||||
|
| `zh_syslog_facility_code_t` | Перечисление кодов facility `ZH_KERN`…`ZH_LOCAL7` (0–23). |
|
||||||
|
| `zh_syslog_severity_code_t` | Перечисление уровней severity `ZH_EMERG`…`ZH_DEBUG` (0–7). |
|
||||||
|
| `zh_syslog_init_config_t` | Структура конфигурации (IP и порт сервера). |
|
||||||
|
| `ZH_SYSLOG_INIT_CONFIG_DEFAULT()` | Макрос значений конфигурации по умолчанию. |
|
||||||
|
|
||||||
|
## Потокобезопасность
|
||||||
|
|
||||||
|
1. **Флаг состояния `_is_initialized`** — `volatile bool`, используется как сторож в `init`/`deinit`/`send` для защиты от повторной инициализации и от работы без инициализации.
|
||||||
|
2. **Дескриптор сокета `_socket`** — `volatile int`, обновляется при `init`/`deinit`.
|
||||||
|
|
||||||
|
Мьютексы и критические секции не используются. Проверка флага и последующая работа с сокетом не образуют атомарной операции, поэтому `zh_syslog_send()` **не является потокобезопасной** — подробности в разделе «Ограничения».
|
||||||
|
|
||||||
|
## Алгоритмы
|
||||||
|
|
||||||
|
### Расчёт приоритета
|
||||||
|
|
||||||
|
- Приоритет `<PRI>` считается по формуле RFC 5424: `pri = facility * 8 + severity`.
|
||||||
|
- Значение подставляется в начало сообщения в угловых скобках: `<%d>1 - ...`.
|
||||||
|
|
||||||
|
### Формат сообщения
|
||||||
|
|
||||||
|
Шаблон генерируемого сообщения:
|
||||||
|
|
||||||
|
```
|
||||||
|
<PRI>1 - HOSTNAME APP-NAME - - - MESSAGE
|
||||||
|
```
|
||||||
|
|
||||||
|
Поля `PROCID`, `MSGID` и `STRUCTURED-DATA` не заполняются и заменяются на `-` согласно RFC 5424.
|
||||||
|
|
||||||
|
### Выбор буфера под размер сообщения
|
||||||
|
|
||||||
|
- Сообщение форматируется в стековый буфер `stack_buf[256]` через `snprintf`, который возвращает полную длину строки.
|
||||||
|
- Если возвращённая длина меньше размера буфера — сокету передаётся стековый буфер.
|
||||||
|
- Если длина `>= 256` — выделяется кучный буфер точного размера `len + 1`, сообщение форматируется повторно и отправляется, после чего буфер освобождается.
|
||||||
|
|
||||||
|
## Примеры использования
|
||||||
|
|
||||||
|
### Базовый пример
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "zh_syslog.h"
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
// Сеть (Wi-Fi/Ethernet) должна быть поднята до init
|
||||||
|
zh_syslog_init_config_t config = ZH_SYSLOG_INIT_CONFIG_DEFAULT();
|
||||||
|
strcpy(config.syslog_ip, "192.168.1.100");
|
||||||
|
config.syslog_port = 514;
|
||||||
|
|
||||||
|
if (zh_syslog_init(&config) == ESP_OK)
|
||||||
|
{
|
||||||
|
// Отправка сообщения с приоритетом USER/INFO
|
||||||
|
zh_syslog_send(ZH_USER, ZH_INFO, "esp32_node", "my_app", "Hello syslog");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Освобождение ресурсов
|
||||||
|
zh_syslog_deinit();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Работа с разными уровнями и facility
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "zh_syslog.h"
|
||||||
|
|
||||||
|
void log_events(void)
|
||||||
|
{
|
||||||
|
zh_syslog_init_config_t config = ZH_SYSLOG_INIT_CONFIG_DEFAULT();
|
||||||
|
strcpy(config.syslog_ip, "10.0.0.5");
|
||||||
|
zh_syslog_init(&config);
|
||||||
|
|
||||||
|
// Разные facility и severity для разных событий
|
||||||
|
zh_syslog_send(ZH_KERN, ZH_ERR, "dev1", "fw", "kernel error");
|
||||||
|
zh_syslog_send(ZH_LOCAL0, ZH_WARNING, "dev1", "fw", "sensor timeout");
|
||||||
|
zh_syslog_send(ZH_DAEMON, ZH_DEBUG, "dev1", "fw", "loop tick");
|
||||||
|
|
||||||
|
zh_syslog_deinit();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Отправка длинного сообщения
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "zh_syslog.h"
|
||||||
|
|
||||||
|
void send_long_message(void)
|
||||||
|
{
|
||||||
|
zh_syslog_init_config_t config = ZH_SYSLOG_INIT_CONFIG_DEFAULT();
|
||||||
|
strcpy(config.syslog_ip, "10.0.0.5");
|
||||||
|
zh_syslog_init(&config);
|
||||||
|
|
||||||
|
// Сообщение длиннее стекового буфера уходит через кучу
|
||||||
|
char big[512];
|
||||||
|
memset(big, 'A', sizeof(big) - 1);
|
||||||
|
big[sizeof(big) - 1] = '\0';
|
||||||
|
zh_syslog_send(ZH_USER, ZH_INFO, "dev1", "app", big);
|
||||||
|
|
||||||
|
zh_syslog_deinit();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Логирование
|
||||||
|
|
||||||
|
Компонент использует ESP-IDF логирование с тегом `"zh_syslog"`.
|
||||||
|
|
||||||
|
```c
|
||||||
|
esp_log_level_set("zh_syslog", ESP_LOG_ERROR);
|
||||||
|
```
|
||||||
|
|
||||||
|
Ошибки логируются с указанием файла, строки и имени кода ошибки (`esp_err_to_name`).
|
||||||
|
|
||||||
|
## Ошибки
|
||||||
|
|
||||||
|
| Код | Описание |
|
||||||
|
|-----|----------|
|
||||||
|
| `ESP_OK` | Успех |
|
||||||
|
| `ESP_ERR_INVALID_ARG` | Неверный аргумент: `NULL`-указатель, порт вне диапазона, некорректный IP или код вне диапазона |
|
||||||
|
| `ESP_ERR_INVALID_STATE` | Клиент уже инициализирован (`init`) либо ещё не инициализирован (`deinit`/`send`) |
|
||||||
|
| `ESP_ERR_NO_MEM` | Не удалось выделить память под длинное сообщение |
|
||||||
|
| `ESP_FAIL` | Ошибка создания сокета, форматирования или отправки UDP |
|
||||||
|
|
||||||
|
## Ограничения
|
||||||
|
|
||||||
|
1. **`zh_syslog_send()` не потокобезопасна** — проверка флага и работа с сокетом не атомарны; при конкурентном вызове из нескольких задач нужна внешняя синхронизация.
|
||||||
|
2. **Только IPv4** — адрес сервера задаётся строкой и разбирается через `inet_pton(AF_INET, ...)`, IPv6 не поддерживается.
|
||||||
|
3. **Без гарантии доставки** — UDP не подтверждает доставку, потерю сообщений компонент не отслеживает.
|
||||||
|
4. **Длина IP ограничена 15 символами** — поле `syslog_ip[16]` вмещает только IPv4-строку.
|
||||||
|
5. **Требуется активная сеть** — вызывать `zh_syslog_init()` можно только после установления сетевого соединения.
|
||||||
|
6. **Стек 256 байт на сообщение** — сообщения длиннее буфера приводят к аллокации в куче на каждую отправку.
|
||||||
|
|
||||||
|
## Требования для сборки
|
||||||
|
|
||||||
|
- ESP-IDF версии 5.0 и выше.
|
||||||
|
- FreeRTOS (входит в состав ESP-IDF).
|
||||||
|
- lwIP (стек сокетов, входит в состав ESP-IDF).
|
||||||
|
|
||||||
|
## Установка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ваш_проект/components
|
||||||
|
git clone https://github.com/aZholtikov/zh_syslog
|
||||||
|
```
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "zh_syslog.h"
|
||||||
|
```
|
||||||
Reference in new issue
Block a user