1.0.0: Первый выпуск.
Pre-releaseПервый выпуск.
Форматирование строк по образцу {} и лёгкий журнал для микроконтроллеров —
без динамической памяти и без std::string.
log::info(F("пин {} = {}, температура {} °C"), pin, level, 54.25);[12s:104ms] I app: пин 13 = true, температура 54.250 °C
Что умеет
Форматирование по образцу. Одно место вставки {} для любого типа вместо
%d, %lu и %.3f. Тип выводит компилятор, поэтому несовпадение типа или
забытый аргумент перестают быть порчей стека.
Готовые правила вывода — числа, строки в RAM и во флеше, String,
длительности, дата и время, IP-адрес, дампы памяти. Свой тип подключается одной
специализацией formatter<T>.
Необязательное значение opt(условие, префикс, значение) — условие пишется
один раз вместо двух тернарных выражений с пустыми литералами.
Журнал с уровнями, источниками и сменными приёмниками вывода. Библиотека
никуда не пишет сама: порт, сеть, карта памяти — решает приложение.
Уровни задаются раздельно по источникам, так что разговорчивую часть
приложения можно приглушить, не трогая остальные. Проверка идёт до сборки
сообщения, поэтому отброшенный вызов почти ничего не стоит.
Порог FMTLOG_COMPILE_LEVEL убирает вызовы из прошивки целиком — вместе с
образцами и значениями.
Необязательные модули. Цветной вывод (FmtColor.h) и чтение строк из
EEPROM (FmtEeprom.h) подключаются отдельно и не занимают места, пока не нужны.
Сколько это стоит
Все числа получены сборкой, не оценкой. Сравнение с snprintf на сообщениях
вида "msg a={} b={}" с двумя целыми.
Флеш
| постоянная надбавка | каждый вызов | |
|---|---|---|
| AVR (Uno) | 676 Б против 1574 Б у snprintf |
108 Б против 97 Б |
| ESP8266 | 512 Б против 336 Б | 77 Б против 59 Б |
На AVR библиотека экономит флеш примерно до 86 вызовов — дальше немного
дороже. На ESP8266 экономии по флешу нет: printf там слинкован ядром
независимо от кода приложения, и FmtLog добавляется поверх. Разница — около
0.1 % флеша на полсотни вызовов.
Сообщения с дробными на AVR обходятся дороже snprintf примерно на 700 байт:
вывод дробных отдан dtostrf, и он линкуется вдобавок к уже имеющемуся
vfprintf.
Цветной вывод стоит 456 байт и только когда подключён.
Оперативная память
Динамическая память не используется вовсе. Статически — буфер сообщения
(128 байт, на AVR 64) и состояние буфера: 16 байт на ESP, 7 на AVR. Размер
буфера задаётся при сборке через FMTLOG_MESSAGE_SIZE.
Скорость
против snprintf |
|
|---|---|
| целые | в 2.2 раза быстрее |
| с дробным | в 1.25 раза медленнее |
Целые библиотека печатает сама, без разбора образца во время выполнения.
Дробные отдаёт dtostrf — тому же коду, что зовёт printf.
Платформы
| платформа | состояние |
|---|---|
| ESP8266 | проверено сборкой |
| ESP32 | проверено сборкой |
| AVR (Uno, Nano, Mega) | проверено сборкой |
На AVR нет IPAddress — соответствующее правило вывода там не собирается.
<type_traits> ядро AVR не поставляет, нужные признаки типов библиотека
определяет сама.
Установка
Arduino IDE — Library Manager, найти «FmtLog».
PlatformIO — в platformio.ini:
lib_deps = FmtLogЧто проверено
- 51 тест на машине разработчика, плата не нужна:
pio test -e native - 14 сочетаний примеров и плат собираются; предупреждений от библиотеки нет
- замеры размера и скорости — сборкой, а не оценкой
Примеры
| пример | о чём |
|---|---|
Basic |
образец, свой буфер, необязательное значение |
Logging |
уровни, источники, свой приёмник вывода |
Color |
цветной вывод, свои цвета уровней и источников |
CustomType |
подключение своего типа |
Levels |
смена уровня на ходу и отсечение при сборке |
Известные ограничения
- Спецификаторов ширины и точности у
{}нет: число знаков после запятой
задаётся при сборке черезFMTLOG_FLOAT_DECIMALS, общий для всех значений. - Буфер сообщения один на приложение, поэтому журнал не переживёт вызова из
прерывания во время сборки другого сообщения. - Дата и время принимают время эпохи Unix и печатаются как есть: часовой пояс
библиотека не знает, сдвиг задаёт приложение.
Лицензия
MIT