Logger C++


I wrote a logger in C++ for C++
https://github.com/Fallet666/logger

And also important information, I'm looking for a job as a C++ developer, please write to me https://t.me/born_in_void if you can help, I'm a student in Moscow)

Logger Library

This project is a simple and flexible logging library in C++. The library supports different logging levels, message formatting, and the ability to write logs to different streams.

Main features

  • Support for different logging levels: DEBUG, INFO, WARN, ERROR.

  • Customizable log formatting.

  • Possibility of logging in multiple streams with protection against data races.

  • Logging to different output streams (std::coutfiles, etc.).

  • Possibility of using a global logger.

Installation

  1. Clone the repository:

    git clone <https://github.com/Fallet666/logger.git>
    
  2. Go to the project directory and build it using CMake:

    cd logger
    mkdir build
    cd build
    cmake ..
    make
    

Basic concepts

  • Logger: The main class for logging. Create an instance of this class to log to a specific thread.

  • Global logger: Singleton instance Loggerwhich can be used by default throughout the project.

Logging functions

The project has several functions for recording logs with different levels of importance. These functions allow flexible management of message output depending on their criticality. Logs are divided into four levels:

  • DEBUG — For debugging information.

  • INFO — For general informational messages.

  • WARN — For warnings.

  • ERROR – For errors that require attention.

Basic functions

LOG_MESSAGE(Logger& logger, LogLevel level, const std::string& message)

Logs a message with the specified level. This function is universal and can be used to log messages of any level.

Example of use:

Logger::Logger log("Logger");
LOG_MESSAGE(log, Logger::DEBUG, "I'm MESSAGE");

Simplified functions for each level

These functions are intended to simplify the invocation of logging at a certain level:

1. logDebug(Logger& logger, const std::string& message)

Logs a message with the level DEBUG.

Example of use:

logDebug(log, "This is a debug message");

2. logInfo(Logger& logger, const std::string& message)

Logs a message with the level INFO.

Example of use:

logInfo(log, "This is an info message");

3. logWarn(Logger& logger, const std::string& message)

Logs a message with the level WARN.

Example of use:

logWarn(log, "This is a warning message");

4. logError(Logger& logger, const std::string& message)

Logs a message with the level ERROR.

Example of use:

logError(log, "This is an error message");

Global logging functions

The project also provides global logging functions that use the globalLogger. These functions allow you to log messages without having to create and manage your own logger instances.

Similar to the basic functions, there are the following global logging functions:

  • logMessageGlobal(LogLevel level, const std::string& message)

  • logDebugGlobal(const std::string& message)

  • logInfoGlobal(const std::string& message)

  • logWarnGlobal(const std::string& message)

  • logErrorGlobal(const std::string& message)

Logging level

You can set the logging level via Cmakethen logs not lower than the specified level will be displayed. For example, if you set the level Warnthen the level logs will be displayed Warn And Error.

Usage in Cmake:

set(DEFAULT_LOG_LEVEL DEBUG)
add_compile_definitions(GLOBAL_LOG_LEVEL=${DEFAULT_LOG_LEVEL})

Note

Each of the logging functions automatically adds information about the file and line from which the log was called, using macros FILE And LINE. This makes it easier to track the source of logs in the code.

Formatting logs

Default formatting:

Format string: “%L: %T [%N]: %M\n”

Example output:

DEBUG: 12:34:56 [MyLogger]: This is a debug message

Advanced formatting

Logs can be customized using a format string. By default, the format string can contain the following components:

  • %L — Logging level (DEBUG, INFO, WARN, ERROR).

  • %T — Log recording time in HH:MM:SS format.

  • %N — The name of the logger.

  • %M — Log message.

  • %t — The identifier of the thread that wrote the log.

  • %S — The name of the file from which the log was called.

  • %# — The line number in the file from which the log was called.

These specifiers can be combined and arranged in any order to customize the log format to suit the needs of the project.

The format string is specified as follows:

Logger::Logger log("custom formating");
log.setFormatString("%L: %T [%N]: %M (%S: %#)\n");

Using colors in logs

The project provides the ability to colorize log output to the console to easily distinguish messages of different levels. Colors are automatically applied if the logger output stream is set to std::cout.

Color scheme:

  • DEBUG — White (\033[37m).

  • INFO — Зеленый (\033[32m).

  • WARN — Желтый (\033[33m).

  • ERROR — Красный (\033[31m).

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

Отключение цвета

Цвета автоматически отключаются, если вы используете другой поток вывода (например, запись логов в файл).

Логирование в многопоточных приложениях

В проекте предусмотрена поддержка многопоточного логирования. Это значит, что несколько потоков могут одновременно записывать логи без риска порчи данных или возникновения гонок.

Синхронизация потоков

Для обеспечения потокобезопасности в классе Logger используется мьютекс (std::mutex). Каждый раз, когда вызывается функция логирования или происходит изменение полей логгера, поток блокируется до завершения операции. Это предотвращает одновременный доступ к общим ресурсам (например, к выходному потоку или настройкам логгера), что гарантирует корректность и целостность данных в логах.

Пример многопоточного логирования

Logger::Logger log("MultiThreadLogger");

std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
    threads.emplace_back([&log, i] { logInfo(log, "Message from thread " + std::to_string(i)); }); } for (auto &t : threads) { t.join(); }

In this example, 10 threads are created, each of which writes a log message with information about its number. Due to the use of a mutex, all messages will be written correctly and without mixing.

Features of multithreaded logging

  • Thread safety: Using a mutex inside a logger ensures that only one operation is performed at a time – either writing a message or changing the logger fields (for example, changing the output stream or log format).

  • Performance: Despite the blocking, the logger is designed to minimize the impact on performance. However, with a large number of logs or high system load, delays are possible.

  • Output to different streams: The logger allows you to use different output streams for different instances, which can be useful for separating logs by category or source.

Logging to different output streams

The project provides a flexible option to configure the output stream for the logger. This means that you can direct logs to any stream that supports the interface. std::ostreamwhether it is standard output (std::cout), files, string streams (std::ostringstream) or even user threads.

Setting the output stream

When creating a logger instance, you can specify where the logs will be written. By default, logs are sent to std::coutbut this behavior can be changed:

Logger::Logger log("FileLogger", std::ofstream("log.txt"));

In this example, logs will be written to the log.txt file.

Change output stream

You can also change the logger output stream while the program is running using the method setOutStream:

Logger::Logger log("Logger");
log.setOutStream(std::cerr);

Example of use with different output streams

std::ofstream file("output.log");
std::ostringstream oss;

Logger::Logger logToFile("FileLogger", file);
Logger::Logger logToStringStream("StringStreamLogger", oss);
Logger::Logger logToConsole("ConsoleLogger");

logInfo(logToFile, "This log goes to a file");
logWarn(logToStringStream, "This log goes to a string stream");
logError(logToConsole, "This log goes to the console");

file.close();

If you have any suggestions for improvement or found any errors, please feel free to create one. issue in the project repository. I am always happy to receive help from the community and would be grateful for your contribution to the development of the project.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *