>_ DevTrendspt

Idioma

Início

Linguagens

Seções

Frontend Backend Mobile DevOps AI / ML GameDev Blockchain Embarcados Segurança
C-plus-plus

Logging C++ Rápido Sem Dores de Cabeça e Dependências Pesadas

Qualquer pessoa que tenha escrito algo mais complexo do que scripts de tutorial em C++ enfrentou a escolha de uma biblioteca de logging. O std::cout padrão é conveniente para utilitários simples de console, mas rapidamente se torna um gargalo devido à E/S lenta e falta de formatação conveniente. Alternativas como Boost.Log ou log4cxx trazem consigo suas dependências, levam muito tempo para compilar e são intimidadoras com suas configurações complexas.

Em 2014, o desenvolvedor Gabriel Melman publicou a biblioteca spdlog. O projeto rapidamente ganhou popularidade na comunidade C++ e agora tem quase 30.000 estrelas no GitHub.

O Que Torna a Biblioteca Popular

O principal motivo do sucesso da biblioteca é o equilíbrio entre desempenho e facilidade de integração. spdlog é distribuída em formato header-only: você apenas copia o diretório include para o seu projeto, inclui o arquivo de cabeçalho e começa a trabalhar. Se você precisa acelerar a compilação da sua aplicação, a biblioteca pode ser pré-compilada via CMake ou instalada através dos gerenciadores de pacotes mais populares (apt, brew, vcpkg, conan).

A formatação de strings é construída sobre a biblioteca fmt, que se tornou a base para std::format no C++20. Isso elimina as correntes complicadas com o operador <<. Alinhamento, saída de números hexadecimais e argumentos posicionais são escritos de forma fácil e clara.

Recursos Úteis para o Desenvolvimento Diário

Combinando Sinks de Log

Na prática, você frequentemente precisa enviar erros para o console com destaque em cores, enquanto escreve informações detalhadas de debug em um arquivo com rotação. No spdlog, essa tarefa é resolvida combinando múltiplos sinks em um único objeto logger:

#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("Сообщение попадет и в консоль, и в файл");
}

Modo Assíncrono para Tarefas de Alta Carga

Em threads de trabalho de servidores de rede ou engines de jogos, escritas diretas em disco atrasam a execução do código. O spdlog pode funcionar de forma assíncrona: uma thread em segundo plano retira mensagens de um buffer circular e as despeja no disco sem desacelerar os cálculos principais.

#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("Запись лога не блокирует текущий поток");
}

Buffer Circular para Rastreamento de Erros

Um recurso interessante da biblioteca é o suporte para backtrace. Suponha que o ambiente de produção tenha o nível de log definido como info e o debug detalhado esteja desabilitado. Quando backtrace é ativado, a biblioteca salva as últimas N mensagens de debug na memória. Quando ocorre uma falha, elas podem ser despejadas instantaneamente no arquivo de log.

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

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

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

Alterando o Nível de Log Sem Recompilar

Os níveis de log podem ser lidos diretamente de variáveis de ambiente ou argumentos de linha de comando na inicialização da aplicação:

#include "spdlog/cfg/env.h"

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

Executar o binário com a flag SPDLOG_LEVEL=debug ./my_app ativa imediatamente a saída de mensagens de debug.

Benchmarks de Desempenho

Um logger síncrono single-threaded processa cerca de 5,7 milhões de chamadas por segundo ao trabalhar com strings curtas (testes do autor em Intel i7-4770). Com 10 threads competindo, a velocidade se mantém em torno de 1,6 milhões de mensagens por segundo.

No modo assíncrono com a política de overflow (overrun), a biblioteca processa mais de 2,6 milhões de operações por segundo. Esses números são alcançados através de alocações mínimas de memória e construção rápida de strings.

Integrações Prontas

A biblioteca é suportada no Linux, Windows, macOS, Android e FreeBSD. O pacote inclui sinks prontos para integração com syslog, Windows Event Log, Android logcat e widgets de texto Qt (QTextEdit). Além disso, a base de código inclui um cronômetro spdlog::stopwatch para medir o tempo de execução de segmentos de código e um utilitário para saída de dados binários em formato hexadecimal.

spdlog resolve o problema de logging sem complexidade desnecessária. Para um utilitário pequeno, basta copiar os arquivos de cabeçalho, e para um serviço grande, o modo assíncrono, rotação de arquivos e filtragem de mensagens em tempo real são úteis. Se você precisa de uma ferramenta rápida e previsível para C++, adicionar spdlog à sua stack deve ser uma prioridade máxima.

Projetos relacionados