{"id":16464031,"url":"https://github.com/filipdutescu/small-better-logger","last_synced_at":"2025-03-23T10:34:36.663Z","repository":{"id":112353151,"uuid":"208133878","full_name":"filipdutescu/small-better-logger","owner":"filipdutescu","description":"A small, better logger library for C++, which features thread-safe loggers.","archived":false,"fork":false,"pushed_at":"2020-07-22T11:01:31.000Z","size":134,"stargazers_count":14,"open_issues_count":1,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-18T07:05:37.918Z","etag":null,"topics":["better","c-plus-plus","cpp","cross-platform","file","free","library","log","logger","logging","logging-library","one","one-file","one-file-library","open-source","opensource","small","thread-safe","threadsafe","wip"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/filipdutescu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-12T19:47:37.000Z","updated_at":"2024-08-07T13:19:37.000Z","dependencies_parsed_at":"2023-05-13T13:15:26.379Z","dependency_job_id":null,"html_url":"https://github.com/filipdutescu/small-better-logger","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filipdutescu%2Fsmall-better-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filipdutescu%2Fsmall-better-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filipdutescu%2Fsmall-better-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/filipdutescu%2Fsmall-better-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/filipdutescu","download_url":"https://codeload.github.com/filipdutescu/small-better-logger/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245090886,"owners_count":20559296,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["better","c-plus-plus","cpp","cross-platform","file","free","library","log","logger","logging","logging-library","one","one-file","one-file-library","open-source","opensource","small","thread-safe","threadsafe","wip"],"created_at":"2024-10-11T11:25:47.542Z","updated_at":"2025-03-23T10:34:36.653Z","avatar_url":"https://github.com/filipdutescu.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"left\"\u003e\r\n  \u003ca href=\"https://github.com/filipdutescu/small-better-logger/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/filipdutescu/small-better-logger\"\u003e\u003c/a\u003e\r\n\u003c/p\u003e\r\n\r\n# Small, Better Logger\r\nA small, better logger library for C++, which features thread-safe loggers.\r\n\r\n## Getting Started\r\nThis section will provide the information needed to include **SBLogger** in your projects, either as source code or as a library.\r\n\u003e ***Note:*** *From now on, I will refer to this library as ***SBLogger***.*\r\n\r\n### Prerequisites\r\nThis library was developed using **C++17** and thus you will have the best experience using a **C++17 (or later)** compiler. For compilers pre **C++17** (**C++11** or **C++14**) or post **C++17** (as of this writing, **C++20**), please refer to [Setting Up](README.md#Setting-Up).\r\n\r\n### Including in Your Projects\r\nAll you need to do if you wish to use **SBLogger** (in a C++ project) is to clone/fork the repo or download the [`SmallBetterLogger.hpp`](SmallBetterLogger/SmallBetterLogger.hpp) file to your project and add it as a header file in your code:\r\n````cpp\r\n...\r\n#include \"SmallBetterLogger.hpp\"\r\n...\r\n````\r\n\r\n***\r\n\r\n### Setting Up\r\n\r\n#### Using Older C++ Standards\r\nThe **SBLogger** library makes use of the predefined [```__cplusplus```](https://en.cppreference.com/w/cpp/preprocessor/replace#Predefined_macros) macro, which provides the compiler version, to auto-detect which code needs to change in order for it to be used in the project it is included in.\r\n\r\nIf you are using a pre **C++17** (**C++11** or **C++14**) compiler which does not support/properly implement the [```__cplusplus```](https://en.cppreference.com/w/cpp/preprocessor/replace#Predefined_macros) macro (such as **MSVC**), you should define the macro ```SBLOGGER_LEGACY```, in order to use this library. If you are using a pre **C++20** compiler that lacks support for the aforementioned [```__cplusplus```](https://en.cppreference.com/w/cpp/preprocessor/replace#Predefined_macros), you should define the ```SBLOGGER_OLD_DATES``` macro, in order to make use of this library.\r\n\r\nPlease define them either before including **SBLogger** or in the first line of the [`SmallBetterLogger.hpp`](SmallBetterLogger/SmallBetterLogger.hpp) file, as shown bellow.\r\n\r\n````cpp\r\n#define SBLOGGER_LEGACY     // Pre C++17 Compiler\r\n#define SBLOGGER_OLD_DATES  // Pre C++20 Compiler\r\n````\r\n\u003e ***Note:*** *For **MSVC** you can fix this problem, by setting up the **`/Zc:__cplusplus`** compiler option. If you do not know how to do this, please refer to the following [Microsoft guide](https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2019#to-set-this-compiler-option-in-visual-studio) for setting it up.*\r\n\r\n***\r\n\r\n#### Cross-Platform Info\r\nIn order for **SBLogger** to work properly outside of **MS Windows**, **SBLogger** automatically detects the OS (based on the criteria found [here](wiki/Setting-Up#Cross-Platform-Info)), defining the following macros:\r\n  * ```#define SBLOGGER_NIX``` - for **Unix/Linux** and **Mac OS X+**\r\n  * ```#define SBLOGGER_OS9``` - for **Mac OS 9 and lower**\r\n\r\n\u003e ***Note:*** *By default, ***MS Windows*** is assumed as the OS for this library.*\r\n\r\nCompilers and platforms tested on:\r\n  * **Windows 10 Home** (both x86 and x64) with **MSVC 2019 (in VS 16.5.0)** using standards **C++14** and **C++17**\r\n  * **Arch Linux** (on x64) with **GCC 9.2.0** using standards **C++11**, **C++14** and **C++17** \r\n\r\n#### Default Log Level\r\nDuring compile time, it is possible to set a default log level for all of the loggers, by defining the **```SBLOGGER_LOG_LEVEL```** and giving it a value ranging between 0 and 6 (the meaning will be explained a bit further in this section). **By default**, the loggers are all given the level of **Trace**. All loggers contain the static method ```void sblogger::SetLoggingLevel(const sblogger::LogLevel\u0026 level)```, which can be set to update the logging level at runtime for all loggers (more about ```LogLevel``` further in this section).\r\n\r\nTo set the desired log level at compile time, either uncomment the line in the [`SmallBetterLogger.hpp`](SmallBetterLogger/SmallBetterLogger.hpp) file which defines the previously mentioned macro as ```SBLOGGER_LEVEL_TRACE```, or define your own before including **SBLogger**:\r\n\r\n````cpp\r\n#define SBLOGGER_LOG_LEVEL SBLOGGER_LEVEL_TRACE // Example found in \"SmallBetterLogger.hpp\"\r\n````\r\nOr using a number rather than another macro:\r\n````cpp\r\n#define SBLOGGER_LOG_LEVEL 0    // Equivalent to the example above\r\n````\r\n\r\nThe values that ```SBLOGGER_LOG_LEVEL``` macro can take values from 0 to 6, each of them having the following meanings, as defined in the [`SmallBetterLogger.hpp`](SmallBetterLogger/SmallBetterLogger.hpp) file:\r\n\r\n````cpp\r\n// Log Levels macros to be used with \"SBLOGGER_LOG_LEVEL\" macro for defining a default level\r\n#define SBLOGGER_LEVEL_TRACE     0\r\n#define SBLOGGER_LEVEL_DEBUG     1\r\n#define SBLOGGER_LEVEL_INFO      2\r\n#define SBLOGGER_LEVEL_WARN      3\r\n#define SBLOGGER_LEVEL_ERROR     4\r\n#define SBLOGGER_LEVEL_CRITICAL  5\r\n#define SBLOGGER_LEVEL_OFF       6\r\n````\r\n\u003e ***Note:*** *Should any other value be provided - concretely, any value lower than 0 or higher than 6, ***SBLogger*** will assume a default level of **```SBLOGGER_LEVEL_TRACE```**.*\r\n\r\nTo change the level of all logs (**for all loggers**, concretely: ```sblogger::StreamLogger```, ```sblogger::FileLogger``` or ```sblogger::DailyLogger```) during runtime, one can use the ```void sblogger::SetLoggingLevel(const sblogger::LogLevel\u0026 level)``` static method, accessible from all of the loggers. It takes as its parameter a value of the ```sblogger::LOG_LEVEL``` enum, which can be one of the following:\r\n\r\n````cpp\r\n// Log level enum. Contains all possible log levels, such as TRACE, ERROR, FATAL etc.\r\nenum class LogLevel\r\n{ \r\n  TRACE /*= 0*/, DEBUG /*= 1*/, INFO /*= 2*/, WARN /*= 3*/, ERROR /*= 4*/, CRITICAL /*= 5*/, OFF /*= 6*/ \r\n};\r\n````\r\n\r\nAs you can see, they mirror the previously defined log level macros. With this, one can now set the logging level during runtime, as follows:\r\n\r\n````cpp\r\n...\r\nsblogger::Logger::SetLoggingLevel(sblogger::LogLevel::WARN);  // Example of setting the level to WARN at runtime\r\n...\r\n````\r\n\r\nThe current logging level can also be found out at runtime, by using the ```const sblogger::LogLevel sblogger::GetLoggingLevel()``` static method, also found in all loggers:\r\n\r\n````cpp\r\n...\r\nauto currentLevel = sblogger::Logger::GetLoggingLevel();  // Example of getting the current level\r\n...\r\n````\r\n\r\n## Usage\r\nAll the code which is related to the **SBLogger** is located in the ```sblogger``` namespace. The loggers are of 3 types: \r\n  * **```sblogger::StreamLogger```** (which writes to the standard streams)\r\n  * **```sblogger::FileLogger```** (which writes to a file) - which also has a specialized derivate,\r\n    * **```sblogger::DailyLogger```** (which writes to a file that changes daily at the specified time) \r\n\r\nThere is also an enum, ```sblogger::StreamType``` which is useful when logging with ```sblogger::StreamLogger```, in order to specify STDOUT, STDERR or STDLOG. The library also defines its own custom errors, which help identify issues a user might run into:\r\n  * ```sblogger::SBLoggerException``` - the default base error from **SBLogger**\r\n  * ```sblogger::NullOrEmptyPathException``` - thrown when the given file path is null or empty\r\n  * ```sblogger::NullOrWhitespaceNameException``` - thrown when the given file name is null or whitespace\r\n  * ```sblogger::InvalidFilePathException``` - thrown when the specified file could not be opened\r\n  * ```sblogger::TimeRangeException``` - thrown when a time related value is out of bounds (e.g.: hours not in [0, 23])\r\n\r\n\u003e ***Note:*** *All those previously mentioned can also be written with lowercase letters (i.e.: ```sblogger::stream_logger```, ```sblogger::stream_type```).*\r\n\r\n### Logging messages\r\nEach of the loggers ensure thread-safety when writing to streams or manipulating them. Any of the following methods enforces compliance with this behaviour.\r\n\r\n### Logger Methods\r\nAll loggers have the following general methods for printing and formatting messages (inherited from ```sblogger::Logger```):\r\n  * ```void Logger::Write(...)``` - write the message ```const std::string\u0026 message``` after replacing all placeholders with the respective parameter value (ex.: ```\"{0}\"``` will be changed to the value of the first parameter after the string)\r\n  * ```void Logger::WriteLine([...])``` - same as ```sblogger::Write(...)```, but appends the newline character (system dependent, define system macros for proper support, check the [Cross-Platform Info](README.md#Cross-Platform-Info))\r\n  * ```void Logger::Trace/Debug/Info/Warn/Error/Critical(...)``` - same as the ```Logger::Write(...)``` method previously mentioned, with the addition that output from the call of one of those methods will only appear if the log level (at the time of the call) is at most the same as the method's (i.e. a message written with ```Logger::Info(...)``` will only appear if the log level is set to **Info**)\r\n  * ```int Logger::Indent()```/```int Dedent()``` - increase/decrease indent by 1\r\n  * ```void Logger::Flush()``` - flushes the stream\r\n\r\n\u003e ***Note:*** *```sblogger::Write``` and ```sblogger::WriteLine``` methods use a logging level of **Trace**.*\r\n\r\n\u003e ***Note:*** *In order to set the logging level, you can do it either at compile or at run time. More information concerning them can be found either in the [Default Log Level](README.md#Default-Log-Level) section or in the [Wiki](https://github.com/filipdutescu/small-better-logger/wiki).*\r\n\r\n**```sblogger::StreamLogger```** contains an additional method:\r\n  * ```void SetStreamType(sblogger::StreamType streamType)``` - change the current stream type to a different ```sblogger::StreamType```\r\n\r\n**```sblogger::FileLogger```** (and thus **```sblogger::DailyLogger```** as well) also contains an additional method:\r\n  * ```void ClearLogs()``` - removes all content from the log file\r\n\r\n***\r\n\r\n### Logger Predefined Macros\r\nFor all the aforementioned methods of logging there are also compile-time ways of outputting messages to streams. There are predefined macros for each method, with the exception of ```sblogger::Indent```, ```sblogger::Dedent``` and ```sblogger::Flush```.\r\n  * ```SBLOGGER_WRITE(x, ...)``` - write the message ```const std::string\u0026 message``` after replacing all placeholders with the respective parameter value (ex.: ```\"{0}\"``` will be changed to the value of the first parameter after the string)\r\n  * ```SBLOGGER_WRITELINE(x, ...)``` - same as ```Write(...)```, but appends the newline character (system dependent, define system macros for proper support, check the [Cross-Platform Info](README.md#Cross-Platform-Info))\r\n  * ```void SBLOGGER_TRACE/SBLOGGER_DEBUG/SBLOGGER_INFO/SBLOGGER_WARN/SBLOGGER_ERROR/SBLOGGER_CRITICAL(x, ...)``` - same as the ```SBLOGGER_WRITE(x, ...)``` method previously mentioned, with the addition that output from the call of one of those methods will only appear if the log level (at the time of the call) is at most the same as the method's (i.e. a message written with ```SBLOGGER_INFO(x, ...)``` will only appear if the log level is set to **Info**)\r\n\r\n\u003e ***Note:*** *The ```x``` found in the macro parameters denotes the message that would be passed in the method calls, shown previously. In the case of the predefined macros it is mandatory to have it.*\r\n\r\n\u003e ***Note:*** *The predefined macros also expose placeholders for the ***file***, ***line*** and ***function*** information. Please check the [Wiki](https://github.com/filipdutescu/small-better-logger/wiki) for more info related to placeholders.*\r\n\r\nAnother important aspect concerning this way of logging is that **those macros are available based on whether or not the ```SBLOGGER_LOG_LEVEL``` macro is defined** (which is defined and initialized by default with the ```SBLOGGER_LEVEL_TRACE``` value).\r\n\r\n\u003e ***Note:*** *For more information regarding available methods and macros, please refer to the [Wiki](https://github.com/filipdutescu/small-better-logger/wiki).*\r\n\r\n***\r\n\r\n### Placeholders\r\n**SBLogger** provides a good amount of placeholders at your disposal, in order to allow easier creation and formatting of logs. They vary from date related placeholders (such as for the current date or time) to colour placeholders (which allow you to add colours for ```sblogger::StreamLogger``` generated output). Below you can find a short summary of the most relevant of those placeholders, with more detail to be found in the [Wiki](https://github.com/filipdutescu/small-better-logger/wiki):\r\n\r\n| Placeholder     | Meaning                                                                      | Other                                                                                    |\r\n|-----------------|------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|\r\n| **{i}**         | Replace with the value of the **i**th parameter from the method call         | If parameter **i** does not exist, the placeholder won't be replaced                     |\r\n| **%[^]tr**      | Replace with the string ```\"Trace\"```                                        | Using ```^``` (```%^tr```) will use the string ```\"TRACE\"```                             |\r\n| **%[^]dbg**     | Replace with the string ```\"Debug\"```                                        | Using ```^``` (```%^dbg```) will use the string ```\"DEBUG\"```                            |\r\n| **%[^]inf**     | Replace with the string ```\"Info\"```                                         | Using ```^``` (```%^inf```) will use the string ```\"INFO\"```                             |\r\n| **%[^]wn**      | Replace with the string ```\"Warn\"```                                         | Using ```^``` (```%^wn```) will use the string ```\"WARN\"```                              |\r\n| **%[^]er**      | Replace with the string ```\"Error\"```                                        | Using ```^``` (```%^er```) will use the string ```\"ERROR\"```                             |\r\n| **%[^]crt**     | Replace with the string ```\"Critical\"```                                     | Using ```^``` (```%^crt```) will use the string ```\"CRITICAL\"```                         |\r\n| **%[^]lvl**     | Replace with the aforementioned string that corresponds to the current level | Using ```^``` (```%^lvl```) will use the uppercase string                                |\r\n| **%src**        | Replace with the name of the current file                                    | Only works using the [predefined macros for logging](README.md#Logger-Predefined-Macros) |\r\n| **%fsrc**       | Replace with the complete path and name of the current file                  | Only works using the [predefined macros for logging](README.md#Logger-Predefined-Macros) |\r\n| **%ln**         | Replace with the current line of the file that the call is made in           | Only works using the [predefined macros for logging](README.md#Logger-Predefined-Macros) |\r\n| **%fnc**        | Replace with the name of the current function (no return type params. etc.)  | Only works using the [predefined macros for logging](README.md#Logger-Predefined-Macros) |\r\n| **Time \u0026 Date** | Same as those from [```strftime```](https://en.cppreference.com/w/cpp/chrono/c/strftime) or [```std::chrono::format```](https://en.cppreference.com/w/cpp/chrono/format) | N/A |\r\n\r\n\u003e ***Note:*** *You can find more about the available placeholders (those being only part of all of the placeholders) by going to the [Wiki](https://github.com/filipdutescu/small-better-logger/wiki).*\r\n\r\n***\r\n\r\n### Usage Examples\r\nThe quickest way to use **SBLogger** is to simply create an instance of it. Then just use the methods available for outputting your logs:\r\n````cpp\r\n...\r\n#include \"SmallBetterLogger.hpp\"\r\n...\r\nint main()\r\n{\r\n  sblogger::StreamLogger logger;\r\n  ...\r\n  logger.WriteLine(\"Hello\");\r\n  logger.Write(\"{0}!\", \"World\");\r\n  ...\r\n}\r\n````\r\nOutput:\r\n````console\r\nHello\r\nWorld!\r\n````\r\n\r\n***\r\n\r\nOr if you wanted to write to a file:\r\n````cpp\r\n...\r\n#include \"SmallBetterLogger.hpp\"\r\n...\r\nint main()\r\n{\r\n  sblogger::FileLogger logger(\"mylog.log\");\r\n  ...\r\n  logger.WriteLine(\"Hello\");\r\n  logger.Write(\"{0}!\", \"World\");\r\n  ...\r\n}\r\n````\r\nOutput:\r\n````console\r\n#In \"mylog.log\"\r\nHello\r\nWorld!\r\n````\r\n\r\n***\r\n\r\nIf you wanted to stylize your logs a bit, a basic way to do this is to use a [format](http://github.com/filipdutescu/small-better-logger/wiki) when instantiating a logger and/or use ```sblogger::Logger::Indent```/```sblogger::Logger::Dedent```, as follows:\r\n````cpp\r\n...\r\n#include \"SmallBetterLogger.hpp\"\r\n...\r\nint main()\r\n{\r\n  sblogger::StreamLogger logger(\"[MyLogFormat]\");\r\n  ...\r\n  logger.Indent();\r\n  logger.WriteLine(\"Hello World,\");\r\n  logger.Dedent();\r\n  logger.Write(\"This is my logger!\");\r\n  logger.WriteLine();\r\n  ...\r\n  logger.SetFormat(\"[%Y-%m-%d %H-%M-%S][%^er]\");\r\n  logger.Error(\"This is an error with a custom format.\\n\");\r\n  ...\r\n}\r\n````\r\nOutput:\r\n````console\r\n    [MyLogFormat] Hello World,\r\n[MyLogFormat] This is my logger!\r\n[2019-11-07 13:37:00][ERROR] This is an error with a custom format.\r\n\r\n````\r\n\r\n\u003e ***Note:*** *You can find more about the supported formats in the [Wiki](https://github.com/filipdutescu/small-better-logger/wiki) and basic usage examples in the [`Source.cpp`](SmallBetterLogger/Source.cpp) file.*\r\n\r\n## Author\r\n  * **Filip-Ioan Dutescu** - [@filipdutescu](https://github.com/filipdutescu)\r\n\r\n## License\r\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) or [`SmallBetterLogger.hpp`](SmallBetterLogger/SmallBetterLogger.hpp) files for details.\r\n\r\n## Acknowledgments\r\n  * [@eugencutic](http://github.com/eugencutic) - Special thanks for code reviews and suggestions\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilipdutescu%2Fsmall-better-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffilipdutescu%2Fsmall-better-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffilipdutescu%2Fsmall-better-logger/lists"}