SysLog — протокол журналирования сообщений

Продолжая тему ведения журналов событий и отладки, поговорим про Syslog. Это протокол передачи текстовых сообщений, прежде всего логов — сообщений о происходящих событиях, разработанный в 1980 году. Формат этого протокола очень прост и удобен, и практически не изменился за последние 35 лет.

Формат достаточно гибок, и предусматривает отправку как простых текстовых сообщений:

Use the BFG!

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

<13> Feb 5 17:32:18 10.0.0.9 Use the BFG!

Стандарт рассматривает также отправку ещё более сложных сообщений, в том числе со специальными указаниями для дальнейшей пересылки, но суть остаётся прежней — это всё то же текстовое сообщение не длиннее 1 килобайта, отправленное на порт 514 (UDP) / 6514 (UDP) или 601 (TCP) / 6514 (TCP).

Маркер важности

Очень важная фича, которая может помочь syslog-серверу правильно отреагировать на пришедшее сообщение — поместить его в нужную таблицу или запустить оповещение администратора системы, к примеру. Предусмотрены такие метки:

0 — Emergency, авария

1 — Alert, тревога

2 — Critical, критическая ошибка

3 — Error, ошибка

4 — Warning, предупреждение

5 — Notice, уведомление

6 — Info, информация

7 — Debug, отладка

Реализация

Таким образом, со стороны МК требуется лишь подключиться к Syslog-серверу (в случае TCP), нужным образом сформировать сообщение, и отправить его на сервер.

debug_socket.c:

char syslog_buffer[500] = { 0 };

extern struct in_addr ServerIP;

void SyslogSend(char* buf, int buf_len)
{
struct pbuf *p;
p = pbuf_alloc(PBUF_TRANSPORT, buf_len, PBUF_RAM);
if (p == NULL) return;
memcpy(p->payload, buf, buf_len);

struct ip_addr server;
//ServerIP
IP4_ADDR(&server,192,168,1,123);

udp_sendto(UDPSyslogSock, p, &server, 514);
pbuf_free(p);
}

void SyslogTransportInit()
{
UDPSyslogSock = udp_new();
udp_recv(UDPSyslogSock, NULL, NULL);
udp_bind(UDPSyslogSock, IP_ADDR_ANY, 514);
udp_connect(UDPSyslogSock, IP_ADDR_ANY, 514);
}

debug_socket.h:

extern char syslog_buffer[500];
extern int DebugBufLen;
extern char MACString[17];
extern unsigned long int dbg_msg_seq;

#define DEBUG_PRINTF(...) { \
if (fDebugConnected) { \
DebugBufLen += sprintf(&DebugBuffer[DebugBufLen], "
"); \
DebugBufLen += snprintf(&DebugBuffer[DebugBufLen], DEBUG_BUF_LEN - DebugBufLen - 1, __VA_ARGS__);\
} \
unsigned int len = sprintf(syslog_buffer, "%s:%lu:", MACString, dbg_msg_seq++); \
len += sprintf(&syslog_buffer[len], __VA_ARGS__); \
SyslogSend(syslog_buffer, len); \
}

На сервере я обычно использую syslog-ng, он умеет складывать пришедшие сообщения в текстовый файл или в базу данных, а также проставлять сообщениям временнУю метку (Timestamp), что избавляет МК от необходимости знать точное время, да и уменьшает трафик. Впрочем я думаю, это умеют все syslog-серверы.

И у вас всегда остаётся возможность обойтись стандартными средствами: линукс прямо из коробки умеет складывать syslog-сообщения, пришедшие по UDP на порт 514, в /var/log.

Пример применения

Мои устройства имеют отладочную telnet-консоль, и чтение информации с неё было неудобным — нет архива старых сообщений, для отладки требуется одновременная работа двух человек (один воспроизводит глюк, другой записывает лог), ну и просто putty не очень удобен для этого.

Telnet-консоль была сделана как в статье, и мне было достаточно просто переписать этот макрос немного иначе — теперь он вызывает функцию отправки данных в UDP/514. Также я добавляю к сообщению MAC-адрес устройства и номер сообщения (чтобы отследить ситуацию пропажи сообщений). На сервере работает скрипт на питоне, он разрезает сообщение и складывает принятое в БД.

На веб-интерфейсе сервера есть страница просмотра сообщений по приборам, с динамической подгрузкой AJAX-ом новых (в процессе появления) и более старых (при прокрутке списка) сообщений. Все отображаемые сообщения можно копировать для подробного анализа. Также есть разбиение по датам.

Объём записываемых данных достаточно велик — порядка 50 мегабайт/час с одного прибора, поэтому сделаны также средства logrotate: в конце дня данные за день архивируются, а архивы старше недели удаляются, потому что ошибки обычно принимаются в рассмотрение сразу после их появления.

В целом, можно подытожить что Syslog — простой и нетребовательный к ресурсам метод логирования событий, и если есть возможность — все события нужно не складировать на девайсе, а отправлять syslog-ом на компьютер, он большой и умный — разберётся :)

Ссылка на основную публикацию