Logging in C++ Applications: Best Practices and Tools

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Proper Logging in C++ Matters

Logging is not just about writing messages to a file. In a production environment, it is your primary tool for monitoring, debugging, and auditing. Poorly configured logging can lead to loss of critical data, performance degradation (I/O-bound), or, conversely, to "noisy" disk clogging. In this article, we will cover best practices for logging in C++ that will help you avoid common mistakes and build a reliable log collection system.



1. Choosing a Library: spdlog vs glog vs std::clog

The C++ standard library only offers basic streams std::clog and std::cerr, which are unsuitable for serious projects. Let's consider three popular approaches:



1.1. spdlog — The Modern Standard

spdlog is a header-only library with support for asynchronous logging, file rotation, formatting (à la fmtlib), and multiple sinks (file, console, syslog, Kafka).

Key advantages:

  • High performance (due to asynchronous threads)
  • Flexible configuration of levels and formats
  • Support for structured logging (JSON)
#include <spdlog/spdlog.h>#include <spdlog/sinks/rotating_file_sink.h>

int main() { // Create a rotating file logger (5 files of 10 MB each) auto logger = spdlog::rotating_logger_mt("file_logger", "logs/app.log", 1048576 * 10, 5); logger->set_level(spdlog::level::info); logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%t] %v");

logger->info("Application started"); logger->warn("Low memory: {} MB", free_memory); logger->error("Database connection error: {}", err.what()); return 0;}


1.2. Google glog — A Proven Solution

The glog library from Google is simple to use and has built-in support for conditional logging and stack dumps. The downside is less flexible formatting and lack of asynchronicity.

#include <glog/logging.h>

int main(int argc, char* argv[]) { google::InitGoogleLogging(argv[0]); FLAGS_log_dir = "./logs"; FLAGS_stderrthreshold = google::WARNING; // Duplicate WARNING+ to stderr

LOG(INFO) << "Server started on port " << port; LOG_IF(WARNING, memory_usage > 0.9) << "Memory almost exhausted"; LOG(FATAL) << "Critical error, terminating"; return 0;}


1.3. Custom Logger Using std::clog

Use std::clog only for debugging or very small utilities. It does not support rotation, levels, or multithreading.

#define LOG(level, msg) std::clog << "[" << level << "] " << msg << std::endl;LOG("INFO", "Starting");LOG("ERROR", "Error: " + std::to_string(errno));


2. Best Practices for Configuration and Architecture

Even the best library won't help if the logging architecture is poorly designed. Follow these principles:



2.1. Use Logging Levels

Define 5-6 levels and strictly adhere to them:

  • TRACE — detailed debugging (function entry/exit)
  • DEBUG — debugging information for developers
  • INFO — normal application operation (startup, shutdown)
  • WARN — potential issues (low disk space, high load)
  • ERROR — errors that do not interrupt operation (exceptions)
  • FATAL — critical error after which the application terminates
// In production, set to WARN to avoid cluttering logs with INFO messageslogger->set_level(spdlog::level::warn);


2.2. Structured Logging (JSON)

For

Blogs

Book Recommendations