Быстрое логирование в C++ без боли и тяжелых зависимостей

05 Aug, 2026
29,368
🔱 5,372
👥 474

Каждый, кто писал на C++ что-то сложнее учебных скриптов, сталкивался с выбором библиотеки для логов. Стандартный std::cout удобен в простых консольных утилитах, но быстро становится бутылочным горлышком из-за медленного ввода-вывода и отсутствия удобного форматирования. Альтернативы вроде Boost.Log или log4cxx несут с собой сопутствующие зависимости, долго компилируются и пугают сложной настройкой.

В 2014 году разработчик Габи Мельман опубликовал библиотеку spdlog. Проект быстро набрал популярность в C++ сообществе и сейчас насчитывает почти 30 тысяч звезд на GitHub.

В чем секрет популярности

Главная причина успеха библиотеки — баланс между скоростью работы и простотой интеграции. spdlog распространяется в формате header-only: достаточно скопировать директорию include в проект, подключить заголовочный файл и начать работу. Если нужно ускорить сборку самого приложения, библиотеку можно предварительно скомпилировать через CMake или установить из большинства популярных пакетных менеджеров (apt, brew, vcpkg, conan).

Форматирование строк построено на базе библиотеки fmt, ставшей основой для std::format в C++20. Это избавляет от громоздких цепочек с оператором <<. Выравнивание, вывод чисел в шестнадцатеричном формате и позиционные аргументы пишутся легко и наглядно.

Полезные возможности в ежедневной разработке

Комбинирование приемников логов

На практике часто нужно отправлять ошибки в консоль с цветовой подсветкой, а подробную отладочную информацию писать в файл с ротацией. В spdlog эта задача решается объединением нескольких приемников (sinks) в один объект логгера:

#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/sinks/basic_file_sink.h"

void setup_logging() {
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    console_sink->set_level(spdlog::level::warn);

    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/app.txt", true);
    file_sink->set_level(spdlog::level::trace);

    spdlog::logger logger("multi_sink", {console_sink, file_sink});
    logger.info("Сообщение зафиксировано только в файле");
    logger.warn("Сообщение попадет и в консоль, и в файл");
}

Асинхронный режим для высоконагруженных задач

В рабочих потоках сетевых серверов или игровых движков прямая запись на диск задерживает исполнение кода. spdlog умеет работать асинхронно: фоновый поток забирает сообщения из кольцевого буфера и сбрасывает их на диск, не тормозя основные вычисления.

#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"

void async_example() {
    // Очередь на 8192 элемента и 1 фоновый поток
    spdlog::init_thread_pool(8192, 1); 
    
    auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>(
        "async_logger", "logs/async_log.txt"
    );
    
    async_file->info("Запись лога не блокирует текущий поток");
}

Кольцевой буфер для трассировки ошибок

Интересный инструмент библиотеки — поддержка backtrace. Допустим, в рабочем окружении включен уровень логов info, а подробная отладка отключена. При активированном backtrace библиотека сохраняет последние N debug-сообщений в оперативной памяти. Когда происходит сбой, их можно мгновенно выгрузить в лог-файл.

spdlog::enable_backtrace(32); // Сохраняем последние 32 сообщения в буфер

for (int i = 0; i < 100; ++i) {
    spdlog::debug("Отладочный шаг №{}", i); // Сообщения пока не пишутся в диск
}

// При возникновении ошибки выгружаем накопленный буфер
spdlog::dump_backtrace();

Смена уровня логирования без пересборки

Уровни логов можно считывать прямо из переменных окружения или аргументов командной строки при старте приложения:

#include "spdlog/cfg/env.h"

int main(int argc, char* argv[]) {
    spdlog::cfg::load_env_levels();
    spdlog::info("Приложение успешно запущено");
}

Запуск бинарника с флагом SPDLOG_LEVEL=debug ./my_app сразу активирует вывод отладочных сообщений.

Что по производительности

Синхронный логгер в один поток выдерживает около 5.7 млн вызовов в секунду при работе с короткими строками (тесты авторов на Intel i7-4770). При 10 конкурирующих потоках скорость держится на уровне 1.6 млн сообщений в секунду.

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

Готовые интеграции

Библиотека поддерживается на Linux, Windows, macOS, Android и FreeBSD. В комплект входят готовые приемники для интеграции с системным журналом syslog, Windows Event Log, Android logcat и графическими текстовыми полями Qt (QTextEdit). Дополнительно в коде есть секундомер spdlog::stopwatch для замера времени выполнения фрагментов программы и утилита для вывода бинарных данных в hex-формате.

spdlog решает задачу логирования без лишней сложности. Для небольшого инструмента достаточно скопировать заголовочные файлы, а для крупного сервиса пригодятся асинхронный режим, ротация файлов и фильтрация сообщений на лету. Если вам нужен быстрый и предсказуемый инструмент для C++, добавить spdlog в стек стоит в первую очередь.

🍪 Мы используем файлы cookie и сервис аналитики Яндекс.Метрика, чтобы сайт работал лучше. Продолжая пользоваться devtrends.ru, вы соглашаетесь с обработкой данных согласно Политике конфиденциальности.