From 77b2d1b44a13ccf726109d1881ded79d4d4d45b0 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 7 Mar 2020 16:48:41 +0100 Subject: [PATCH] Add a function for formatting log messages --- src/common/logging.cpp | 28 ++++++++++++++++++++++++++++ src/common/logging.h | 19 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/common/logging.cpp b/src/common/logging.cpp index c1d4122b..f9e776c9 100644 --- a/src/common/logging.cpp +++ b/src/common/logging.cpp @@ -1,6 +1,9 @@ #include "logging.h" +#include +#include #include +#include #include #ifdef __WINE__ @@ -52,3 +55,28 @@ Logger Logger::create_from_environment(std::string prefix) { return Logger(std::move(std::cerr), verbosity_level, prefix); } } + +void Logger::log(const std::string& message) { + const auto current_time = std::chrono::system_clock::now(); + const std::time_t timestamp = + std::chrono::system_clock::to_time_t(current_time); + + // How did C++ manage to get time formatting libraries without a way to + // actually get a timestamp in a threadsafe way? `localtime_r` in C++ is not + // portable but luckily we only have to support GCC anyway. + std::tm tm; + localtime_r(×tamp, &tm); + + std::ostringstream formatted_message; + formatted_message << "[" << std::put_time(&tm, "%T") << "]"; + formatted_message << prefix; + formatted_message << message; + // Flushing a stringstream doesn't do anything, but we need to put a + // linefeed in this string stream rather writing it sprightly to the output + // stream to prevent two messages from being put on the same row + formatted_message << std::endl; + + // No flush. Should technically be necessary, but it decreases throughput by + // a lot and it seems to work fine without. + stream << formatted_message.str(); +} diff --git a/src/common/logging.h b/src/common/logging.h index 00065512..b2534df4 100644 --- a/src/common/logging.h +++ b/src/common/logging.h @@ -76,11 +76,30 @@ class Logger { */ static Logger create_from_environment(std::string prefix = ""); + /** + * Write a message to the log, prefixing it with a timestamp and this + * logger's prefix string. + * + * @param message The message to write. + */ + void log(const std::string& message); + // TODO: Add dedicated logging functions for events and the Wine process's // STDOUT and STDERR private: + /** + * The output stream to write the log messages to. Typically either STDERR + * or a file stream. + */ std::ostream& stream; + /** + * The verbosity level of this logger instance. Based on this certain + * messages may or may not be shown. + */ Verbosity verbosity; + /** + * A prefix that gets prepended before every message. + */ std::string prefix; };