Как логировать сообщения с временной меткой, включающей микросекунды, в C++?

«Как логировать сообщения с временной меткой, включающей микросекунды, в C++?» — вопрос из категории Linux и ОС, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В современном C++ для логирования с точностью до микросекунд удобно использовать библиотеку <chrono>. Вот практический пример функции логирования:

#include <chrono>
#include <iostream>
#include <iomanip>
#include <ctime>

void log_with_microseconds(const std::string& message) {
    // 1. Получаем текущее время
    auto now = std::chrono::system_clock::now();

    // 2. Преобразуем в time_t для форматирования даты/времени
    std::time_t time_now = std::chrono::system_clock::to_time_t(now);

    // 3. Вычисляем количество микросекунд с начала секунды
    auto since_epoch = now.time_since_epoch();
    auto seconds = std::chrono::duration_cast<std::chrono::seconds>(since_epoch);
    auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(since_epoch - seconds);

    // 4. Форматируем и выводим
    // std::localtime не является потокобезопасным, в production-коде используйте localtime_r
    std::cout << std::put_time(std::localtime(&time_now), "%Y-%m-%d %H:%M:%S.")
              << std::setfill('0') << std::setw(6) << microseconds.count()
              << " - " << message << std::endl;
}

// Пример использования
int main() {
    log_with_microseconds("Запуск приложения");
    // ... какой-то код ...
    log_with_microseconds("Выполнение завершено");
    return 0;
}
// Вывод: 2024-05-15 14:30:25.123456 - Запуск приложения

Ключевые моменты:

  • std::chrono::system_clock предоставляет время, привязанное к системным часам (календарное время).
  • duration_cast используется для преобразования временного интервала в нужные единицы.
  • %Y-%m-%d %H:%M:%S — стандартный формат даты и времени.
  • std::setw(6) гарантирует, что микросекунды будут выведены как 6 цифр (дополнены нулями слева).

Для измерений интервалов (бенчмаркинг) вместо system_clock лучше использовать std::chrono::steady_clock, который монотонен и не подвержен корректировкам системного времени, но он не предназначен для получения календарного времени для логов.