From c52de9e1cf9a6fbf05b834ca17326f649f92778f Mon Sep 17 00:00:00 2001 From: Kjell Hedstrom Date: Sat, 28 May 2022 20:52:43 -0600 Subject: [PATCH] updating for mkdocs generation --- API.markdown | 369 ---------------------------------- CONTRIBUTING.md | 2 +- docs/.ciignore | 1 - docs/API.md | 162 +++------------ docs/API_custom_formatting.md | 66 ++++++ docs/building.md | 235 ++++++++++++++++++++++ docs/contributing.md | 15 ++ docs/g3log.md | 214 ++++++++++++++++++++ docs/index.md | 128 ++++++++++-- index.md | 2 +- mkdocs.yml | 19 +- 11 files changed, 676 insertions(+), 537 deletions(-) delete mode 100644 API.markdown delete mode 100644 docs/.ciignore create mode 100644 docs/API_custom_formatting.md create mode 100644 docs/building.md create mode 100644 docs/contributing.md create mode 100644 docs/g3log.md diff --git a/API.markdown b/API.markdown deleted file mode 100644 index 0bd25434c..000000000 --- a/API.markdown +++ /dev/null @@ -1,369 +0,0 @@ -# API description -Most of the API that you need for using g3log is described in this readme. For more API documentation and examples please continue to read the [API readme](API.markdown). Examples of what you will find here are: - -* Logging API: LOG calls -* Contract API: CHECK calls -* Logging levels - * disable/enabled levels at runtime - * custom logging levels -* Sink [creation](#sink_creation) and utilization -* Custom [log formatting](#log_formatting) - * Overriding the Default File Sink's file header - * Overriding the Default FileSink's log formatting - * Adding thread ID to the log formatting - * Override log formatting in a default and custom sinks - * Override the log formatting in the default sink -* LOG [flushing](#log_flushing) -* G3log and G3Sinks [usage example](#g3log-and-sink-usage-code-example) -* Support for [dynamic message sizing](#dynamic_message_sizing) -* Fatal handling - * [Linux/*nix](#fatal_handling_linux) - * [Custom fatal handling - override defaults](#fatal_custom_handling) - * [Pre fatal hook](#fatal_pre_hook) - * [Disable fatal handling](#fatal_handling_disabled) - * [PID1 Fatal Signal Recommendations](#PID1) - * [Windows](#fatal_handling_windows) -* Build Options - - -## Logging API: LOG calls -LOG calls can follow streaming ```LOG(INFO) << "some text" ``` or printf-like syntax ```LOGF(WARNING, "some number %d", 123); ``` - -Conditional logging is made with ```LOG_IF(INFO, ) << " some text" ``` or ```LOGF_IF(WARNING, ) << " some text".``` Only if the expressions evaluates to ```true``` will the logging take place. - -Example: -```LOG_IF(INFO, 1 != 200) << " some text";``` or ```LOG_IF(FATAL, SomeFunctionCall()) << " some text";``` - -*A call using FATAL logging level, such as the ```LOG_IF(FATAL,...)``` example above, will after logging the message at ```FATAL```level also kill the process. It is essentially the same as a ```CHECK() << ...``` with the difference that the ```CHECK() << ...``` for streaming or (*) ```CHECKF(, ...);``` for printf-style. - - -If the `````` evaluates to false then the the message for the failed contract will be logged in FIFO order with previously made messages. The process will then shut down after the message is sent to the sinks and the sinks have dealt with the fatal contract message. - - -(\* * ```CHECK_F(, ...);``` was the the previous API for printf-like CHECK. It is still kept for backwards compatability but is exactly the same as ```CHECKF``` *) - - -## Logging levels - The default logging levels are ```DEBUG```, ```INFO```, ```WARNING``` and ```FATAL``` (see FATAL usage [above](#fatal_logging)). The logging levels are defined in [loglevels.hpp](src/g3log/loglevels.hpp). - - For some windows framework there is a clash with the ```DEBUG``` logging level. One of the CMake [Build options](#build_options) can be used to then change offending default level from ```DEBUG``` TO ```DBUG```. - - **CMake option: (default OFF) ** ```cmake -DCHANGE_G3LOG_DEBUG_TO_DBUG=ON ..``` - - ### disable/enabled levels at runtime - Logging levels can be disabled at runtime. The logic for this happens in - [loglevels.hpp](src/g3log/loglevels.hpp), [loglevels.cpp](src/loglevels.cpp) and [g3log.hpp](src/g3log/g3log.hpp). - - There is a cmake option to enable the dynamic enable/disable of levels. - When the option is enabled there will be a slight runtime overhead for each ```LOG``` call when the enable/disable status is checked. For most intent and purposes this runtime overhead is negligable. - - There is **no** runtime overhead for internally checking if a level is enabled//disabled if the cmake option is turned off. If the dynamic logging cmake option is turned off then all logging levels are enabled. - -**CMake option: (default OFF)** ```cmake -DUSE_DYNAMIC_LOGGING_LEVELS=ON ..``` - - - ### custom logging levels - Custom logging levels can be created and used. When defining a custom logging level you set the value for it as well as the text for it. You can re-use values for other levels such as *INFO*, *WARNING* etc or have your own values. Any value with equal or higher value than the *FATAL* value will be considered a *FATAL* logging level. - - **To keep in mind when adding your own custom levels.** -1. If the cmake option `G3_DYNAMIC_LOGGING` is enabled then you must use `g3::only_change_at_initialization::addLogLevel(...)` to give g3log a record of your logging level and if it is an enabled or disbled logging level. -1. If the cmake `G3_DYNAMIC_LOGGING` is turned OFF, then giving g3log a record of your logging level with 'addLogLevel(...) is **not needed** since no `"disbled/enabled"` check will happen - all logging levels will be considered enabled. - - Example: - ```cpp - // In CustomLoggingLevels.hpp - #include - - // all values with a + 1 higher than their closest equivalet - // they could really have the same value as well. - - const LEVELS FYI {DEBUG.value + 1, {"For Your Information"}}; - const LEVELS CUSTOM {INFO.value + 1, {"CUSTOM"}}; - const LEVELS SEVERE {WARNING.value +1, {"SEVERE"}}; - const LEVELS DEADLY {FATAL.value + 1, {"DEADLY"}}; - ``` - -More examples can be viwed in the [unit tests](https://github.com/KjellKod/g3log/blob/master/test_unit/test_io.cpp). - - - -## Sink creation and utilization -The default sink for g3log is the one as used in g2log. It is a simple file sink with a limited API. The details for the default file sink can be found in [filesink.hpp](src/g3log/filesink.hpp), [filesink.cpp](src/filesink.cpp), [filesinkhelper.ipp](src/filesinkhelper.ipp) - -More sinks can be found at [g3sinks](http://www.github.com/KjellKod/g3sinks) (log rotate, log rotate with filtering on levels) - -A logging sink is not required to be a subclass of a specific type. The only requirement of a logging sink is that it can receive a logging message of - - -### Using the default sink -Sink creation is defined in [logworker.hpp](src/g3log/logworker.hpp) and used in [logworker.cpp](src/logworker.cpp). For in-depth knowlege regarding sink implementation details you can look at [sinkhandle.hpp](src/g3log/sinkhandle.hpp) and [sinkwrapper.hpp](src/g3log/sinkwrapper.hpp) -```cpp - std::unique_ptr addDefaultLogger( - const std::string& log_prefix - , const std::string& log_directory - , const std::string& default_id = "g3log"); -``` - -With the default id left as is (i.e. "g3log") a creation of the logger in the unit test "test_filechange" would look like this -```cpp - const std::string directory = "./"; - const std::string name = "(ReplaceLogFile)"; - auto worker = g3::LogWorker::createLogWorker(); - auto handle = worker->addDefaultLogger(name, directory); -``` -The resulting filename would be something like: -``` - ./(ReplaceLogFile).g3log.20160217-001406.log -``` - - -## Custom LOG formatting -### Overriding the Default File Sink's file header -The default file header can be customized in the default file sink in calling -```cpp - FileSink::overrideLogHeader(std::string); -``` - - -### Overriding the Default FileSink's log formatting -The default log formatting is defined in `LogMessage.hpp` -```cpp - static std::string DefaultLogDetailsToString(const LogMessage& msg); -``` - -### Adding thread ID to the log formatting -An "all details" log formatting function is also defined - this one also adds the "calling thread's ID" -```cpp - static std::string FullLogDetailsToString(const LogMessage& msg); -``` - -### Override log formatting in default and custom sinks -The default log formatting look can be overriden by any sink. -If the sink receiving function calls `toString()` then the default log formatting will be used. -If the sink receiving function calls `toString(&XFunc)` then the `XFunc`will be used instead (see `LogMessage.h/cpp` for code details if it is not clear). (`XFunc` is a place holder for *your* formatting function of choice). - -The API for the function-ptr to pass in is -```cpp -std::string (*) (const LogMessage&) -``` -or for short as defined in `LogMessage.h` -```cpp -using LogDetailsFunc = std::string (*) (const LogMessage&); -``` - -### Override the log formatting in the default sink -For convenience the *Default* sink has a function -for doing exactly this -```cpp - void overrideLogDetails(LogMessage::LogDetailsFunc func); -``` - - -Example code for replacing the default log formatting for "full details" formatting (it adds thread ID) - -```cpp - auto worker = g3::LogWorker::createLogWorker(); - auto handle= worker->addDefaultLogger(argv[0], path_to_log_file); - g3::initializeLogging(worker.get()); - handle->call(&g3::FileSink::overrideLogDetails, &LogMessage::FullLogDetailsToString); -``` - -See [test_message.cpp](test_unit/test_message.cpp) for details and testing - - -Example code for overloading the formatting of a custom sink. The log formatting function will be passed into the -`LogMessage::toString(...)` this will override the default log formatting - -Example -```cpp -namespace { - std::string MyCustomFormatting(const LogMessage& msg) { - ... how you want it ... - } - } - - void MyCustomSink::ReceiveLogEntry(LogMessageMover message) { - std::string formatted = message.get().toString(&MyCustomFormatting) << std::flush; - } -... -... - auto worker = g3::LogWorker::createLogWorker(); - auto sinkHandle = worker->addSink(std::make_unique(), - &MyCustomSink::ReceiveLogMessage); - // ReceiveLogMessage(...) will used the custom formatting function "MyCustomFormatting(...) - -``` - - - - - -## LOG flushing -The default file sink will flush each log entry as it comes in. For different flushing policies please take a look at g3sinks [logrotate and LogRotateWithFilters](https://github.com/KjellKod/g3sinks/tree/master/sink_logrotate). - -At shutdown all enqueued logs will be flushed to the sink. -At a discovered fatal event (SIGSEGV et.al) all enqueued logs will be flushed to the sink. - -A programmatically triggered abrupt process exit such as a call to ```exit(0)``` will of course not get the enqueued log entries flushed. Similary a bug that does not trigger a fatal signal but a process exit will also not get the enqueued log entries flushed. G3log can catch several fatal crashes and it deals well with RAII exits but magic is so far out of its' reach. - -# G3log and Sink Usage Code Example -Example usage where a [logrotate sink (g3sinks)](https://github.com/KjellKod/g3sinks) is added. In the example it is shown how the logrotate API is called. The logrotate limit is changed from the default to instead be 10MB. The limit is changed by calling the sink handler which passes the function call through to the actual logrotate sink object. -```cpp - -// main.cpp -#include -#include -#include -#include - -int main(int argc, char**argv) { - using namespace g3; - std::unique_ptr logworker{ LogWorker::createLogWorker() }; - auto sinkHandle = logworker->addSink(std::make_unique(), - &LogRotate::save); - - // initialize the logger before it can receive LOG calls - initializeLogging(logworker.get()); - - // You can call in a thread safe manner public functions on the logrotate sink - // The call is asynchronously executed on your custom sink. - const int k10MBInBytes = 10 * 1024 * 1024; - std::future received = sinkHandle->call(&LogRotate::setMaxLogSize, k10MBInBytes); - - // Run the main part of the application. This can be anything of course, in this example - // we'll call it "RunApplication". Once this call exits we are in shutdown mode - RunApplication(); - - // If the LogWorker is initialized then at scope exit the g3::shutDownLogging() will be - // called automatically. - // - // This is important since it protects from LOG calls from static or other entities that will go out of - // scope at a later time. - // - // It can also be called manually if for some reason your setup is different then the one highlighted in - // this example - g3::shutDownLogging(); -} -``` - - -## Dynamic Message Sizing -The default build uses a fixed size buffer for formatting messages. The size of this buffer is 2048 bytes. If an incoming message results in a formatted message that is greater than 2048 bytes, it will be bound to 2048 bytes and will have the string ```[...truncated...]``` appended to the end of the bound message. There are cases where one would like to dynamically change the size at runtime. For example, when debugging payloads for a server, it may be desirable to handle larger message sizes in order to examine the whole payload. Rather than forcing the developer to rebuild the server, dynamic message sizing could be used along with a config file which defines the message size at runtime. - -This feature supported as a CMake option: - -**CMake option: (default OFF)** ```cmake -DUSE_G3_DYNAMIC_MAX_MESSAGE_SIZE=ON ..``` - -The following is an example of changing the size for the message. - -```cpp - g3::only_change_at_initialization::setMaxMessageSize(10000); -``` - - -## Fatal handling -The default behaviour for G3log is to catch several fatal events before they force the process to exit. After catching a fatal event a stack dump is generated and all log entries, up to the point of the stack dump are together with the dump flushed to the sink(s). - - - ### Linux/*nix - The default fatal handling on Linux deals with fatal signals. At the time of writing these signals were ```SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM```. The Linux fatal handling is handled in [crashhandler.hpp](src/g3log/crashhandler.hpp) and [crashhandler_unix.cpp](src/crashhandler_unix.cpp) - - - - A signal that commonly is associated with voluntarily process exit is ```SIGINT``` (ctrl + c) G3log does not deal with it. - - The fatal signals can be [disabled](#fatal_handling_disabled) or [changed/added ](#fatal_signalhandler_override). - - An example of a Linux stackdump as shown in the output from the fatal example g3log-FATAL-sigsegv. - ``` - ***** FATAL SIGNAL RECEIVED ******* - "Received fatal signal: SIGSEGV(11) PID: 6571 - - ***** SIGNAL SIGSEGV(11) - - ******* STACKDUMP ******* - stack dump [1] ./g3log-FATAL-sigsegv() [0x42a500] - stack dump [2] /lib/x86_64-linux-gnu/libpthread.so.0+0x10340 [0x7f83636d5340] - - stack dump [3] ./g3log-FATAL-sigsegv : example_fatal::tryToKillWithAccessingIllegalPointer(std::unique_ptr, std::allocator >, std::default_delete, std::allocator > > >)+0x119 [0x4107b9] - stack dump [4] ./g3log-FATAL-sigsegvmain+0xdec [0x40e51c] - stack dump [5] /lib/x86_64-linux-gnu/libc.so.6__libc_start_main+0xf5 [0x7f8363321ec5] - stack dump [6] ./g3log-FATAL-sigsegv() [0x40ffa2] - - Exiting after fatal event (FATAL_SIGNAL). Fatal type: SIGSEGV - Log content flushed sucessfully to sink - - " - g3log g3FileSink shutdown at: 16:33:18 - - ``` - - ### Custom fatal handling - override defaults - By default the fatal signals are defined in [src/g3log.cpp](src/g3log.cpp) as - ``` - SIGABRT - SIGFPE - SIGILL - SIGSEGV - SIGTERM - ``` - If you want to define your own set of fatal signals, override the default ones, then this can be done as shown in [src/g3log/crashhandler.hpp](src/g3log/crashhandler.hpp) - ```cpp - // Example when SIGTERM is skipped due to ZMQ usage - g3::overrideSetupSignals({ {SIGABRT, "SIGABRT"}, - {SIGFPE, "SIGFPE"}, - {SIGILL, "SIGILL"}, - {SIGSEGV, "SIGSEGV"}}); - ``` - - ### Pre fatal hook - You can define a custom call back function that will be called before the fatal signal handling re-emits the `fatal` signal. See [src/g3log/g3log.hpp](src/g3log/g3log.hpp) for details. - ``` - // Example of how to enforce important shutdown cleanup even in the event of a fatal crash: - g3::setFatalPreLoggingHook([]{ cleanup(); }); - ``` - - ### Disable fatal handling - Fatal signal handling can be disabled with a CMake option: `ENABLE_FATAL_SIGNALHANDLING`. See [Options.cmake](Options.cmake) for more details - - - ### PID1 Fatal Signal Recommendations - If you are using g3log on a PID1 process then you absolutely should provide your own signal handling (ref: [issue 269](https://github.com/KjellKod/g3log/issues/269)) as g3log re-emits the fatal signal after it has restored the previous signal handler for that signal. PID1 processed do *not* shutdown the process for a normal fatal signal so the choice to exit the PID1 process after such a signal must be taken by the coder - not by g3log. - -### Windows - Windows fatal handling also deals with fatal signals just like Linux. In addition to fatal signals it also deals with unhandled exceptions, vectored exceptions. Windows fatal handling is handled in [crashhandler.hpp](src/g3log/crashhandler.hpp), [crashhandler_windows.cpp](src/crashhandler_windows.cpp), [stacktrace_windows.hpp](src/g3log/stacktrace_windows.hpp), [stacktrace_windows.cpp](src/stacktrace_windows.cpp) - - An example of a Windows stackdump as shown in the output from the fatal example g3log-FATAL-sigsegv. - - - - - - - - ## Build Options - The build options are defined in the file [Options.cmake](Options.cmake) - - build options are generated and saved to a header file. This avoid having to set the define options in the client source code - - - -# Say Thanks -This logger is available for free and all of its source code is public domain. -Writing API documentation is probably the most boring task for a developer. -Did it help you? Could it be better? Please suggest changes, send me feedback or even better: open a pull request. - -You could also contribute by saying thanks with a a donation. It would go a long way not only to show your support but also to boost continued development of this logger and its API documentation - -[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/g3log/25) - -* $5 for a cup of coffee -* $10 for pizza -* $25 for a lunch or two -* $100 for a date night with my wife (which buys family credit for evening coding) - -Cheers -Kjell diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7b942608b..383487915 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,4 +10,4 @@ this will improve things for the community going forward. # Community Driven: -g3log is community driven. Be respectful. Nobody is getting paid and being polite and helpful will get you further than having an attitude. +G3log is community driven. Be respectful. G3log is developed and maintained without financial support, being helpful and polite will move your request and input along faster. \ No newline at end of file diff --git a/docs/.ciignore b/docs/.ciignore deleted file mode 100644 index 8b1378917..000000000 --- a/docs/.ciignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/docs/API.md b/docs/API.md index 9cf86e258..14a64e146 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,30 +1,5 @@ # API description -Please read this document to understand how to use the g3log API to integrate it with your code. -Examples of what you will find here are: - -* Logging API: LOG calls -* Contract API: CHECK calls -* Logging levels - * disable/enabled levels at runtime - * custom logging levels -* Sink [creation](#sink_creation) and utilization -* Custom [log formatting](#log_formatting) - * Overriding the Default File Sink's file header - * Overriding the Default FileSink's log formatting - * Adding thread ID to the log formatting - * Override log formatting in a default and custom sinks - * Override the log formatting in the default sink -* LOG [flushing](#log_flushing) -* G3log and G3Sinks [usage example](#g3log-and-sink-usage-code-example) -* Support for [dynamic message sizing](#dynamic_message_sizing) -* Fatal handling - * [Linux/*nix](#fatal_handling_linux) - * [Custom fatal handling - override defaults](#fatal_custom_handling) - * [Pre fatal hook](#fatal_pre_hook) - * [Disable fatal handling](#fatal_handling_disabled) - * [PID1 Fatal Signal Recommendations](#PID1) - * [Windows](#fatal_handling_windows) -* Build Options +Most of the API that you need for using g3log is described in this readme. For more API documentation and examples please continue to read the [API readme](API.md). Examples of what you will find here are: ## Logging API: LOG calls @@ -48,7 +23,7 @@ If the `````` evaluates to false then the the message for th ## Logging levels - The default logging levels are ```DEBUG```, ```INFO```, ```WARNING``` and ```FATAL``` (see FATAL usage [above](#fatal_logging)). The logging levels are defined in [loglevels.hpp](src/g3log/loglevels.hpp). + The default logging levels are ```DEBUG```, ```INFO```, ```WARNING``` and ```FATAL``` (see FATAL usage [above](#fatal_logging)). The logging levels are defined in [loglevels.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/loglevels.hpp). For some windows framework there is a clash with the ```DEBUG``` logging level. One of the CMake [Build options](#build_options) can be used to then change offending default level from ```DEBUG``` TO ```DBUG```. @@ -56,7 +31,7 @@ If the `````` evaluates to false then the the message for th ### disable/enabled levels at runtime Logging levels can be disabled at runtime. The logic for this happens in - [loglevels.hpp](src/g3log/loglevels.hpp), [loglevels.cpp](src/loglevels.cpp) and [g3log.hpp](src/g3log/g3log.hpp). + [loglevels.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/loglevels.hpp), [loglevels.cpp](https://github.com/KjellKod/g3log/tree/master/src/loglevels.cpp) and [g3log.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/g3log.hpp). There is a cmake option to enable the dynamic enable/disable of levels. When the option is enabled there will be a slight runtime overhead for each ```LOG``` call when the enable/disable status is checked. For most intent and purposes this runtime overhead is negligable. @@ -92,7 +67,7 @@ More examples can be viwed in the [unit tests](https://github.com/KjellKod/g3log ## Sink creation and utilization -The default sink for g3log is the one as used in g2log. It is a simple file sink with a limited API. The details for the default file sink can be found in [filesink.hpp](src/g3log/filesink.hpp), [filesink.cpp](src/filesink.cpp), [filesinkhelper.ipp](src/filesinkhelper.ipp) +The default sink for g3log is the one as used in g2log. It is a simple file sink with a limited API. The details for the default file sink can be found in [filesink.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/filesink.hpp), [filesink.cpp](https://github.com/KjellKod/g3log/tree/master/src/filesink.cpp), [filesinkhelper.ipp](https://github.com/KjellKod/g3log/tree/master/src/filesinkhelper.ipp) More sinks can be found at [g3sinks](http://www.github.com/KjellKod/g3sinks) (log rotate, log rotate with filtering on levels) @@ -100,7 +75,7 @@ A logging sink is not required to be a subclass of a specific type. The only req ### Using the default sink -Sink creation is defined in [logworker.hpp](src/g3log/logworker.hpp) and used in [logworker.cpp](src/logworker.cpp). For in-depth knowlege regarding sink implementation details you can look at [sinkhandle.hpp](src/g3log/sinkhandle.hpp) and [sinkwrapper.hpp](src/g3log/sinkwrapper.hpp) +Sink creation is defined in [logworker.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/logworker.hpp) and used in [logworker.cpp](https://github.com/KjellKod/g3log/tree/master/src/logworker.cpp). For in-depth knowlege regarding sink implementation details you can look at [sinkhandle.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/sinkhandle.hpp) and [sinkwrapper.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/sinkwrapper.hpp) ```cpp std::unique_ptr addDefaultLogger( const std::string& log_prefix @@ -120,28 +95,7 @@ The resulting filename would be something like: ./(ReplaceLogFile).g3log.20160217-001406.log ``` - -## Custom LOG formatting -### Overriding the Default File Sink's file header -The default file header can be customized in the default file sink in calling -```cpp - FileSink::overrideLogHeader(std::string); -``` - - -### Overriding the Default FileSink's log formatting -The default log formatting is defined in `LogMessage.hpp` -```cpp - static std::string DefaultLogDetailsToString(const LogMessage& msg); -``` - -### Adding thread ID to the log formatting -An "all details" log formatting function is also defined - this one also adds the "calling thread's ID" -```cpp - static std::string FullLogDetailsToString(const LogMessage& msg); -``` - -### Override log formatting in default and custom sinks +## Designate the sink function's log entry receving function The default log formatting look can be overriden by any sink. If the sink receiving function calls `toString()` then the default log formatting will be used. If the sink receiving function calls `toString(&XFunc)` then the `XFunc`will be used instead (see `LogMessage.h/cpp` for code details if it is not clear). (`XFunc` is a place holder for *your* formatting function of choice). @@ -155,51 +109,8 @@ or for short as defined in `LogMessage.h` using LogDetailsFunc = std::string (*) (const LogMessage&); ``` -### Override the log formatting in the default sink -For convenience the *Default* sink has a function -for doing exactly this -```cpp - void overrideLogDetails(LogMessage::LogDetailsFunc func); -``` - - -Example code for replacing the default log formatting for "full details" formatting (it adds thread ID) - -```cpp - auto worker = g3::LogWorker::createLogWorker(); - auto handle= worker->addDefaultLogger(argv[0], path_to_log_file); - g3::initializeLogging(worker.get()); - handle->call(&g3::FileSink::overrideLogDetails, &LogMessage::FullLogDetailsToString); -``` - -See [test_message.cpp](test_unit/test_message.cpp) for details and testing - - -Example code for overloading the formatting of a custom sink. The log formatting function will be passed into the -`LogMessage::toString(...)` this will override the default log formatting - -Example -```cpp -namespace { - std::string MyCustomFormatting(const LogMessage& msg) { - ... how you want it ... - } - } - - void MyCustomSink::ReceiveLogEntry(LogMessageMover message) { - std::string formatted = message.get().toString(&MyCustomFormatting) << std::flush; - } -... -... - auto worker = g3::LogWorker::createLogWorker(); - auto sinkHandle = worker->addSink(std::make_unique(), - &MyCustomSink::ReceiveLogMessage); - // ReceiveLogMessage(...) will used the custom formatting function "MyCustomFormatting(...) - -``` - - - +## Log format customization +Please see[API_custom_formatting.md](API_custom_formatting.md) ## LOG flushing @@ -210,7 +121,7 @@ At a discovered fatal event (SIGSEGV et.al) all enqueued logs will be flushed to A programmatically triggered abrupt process exit such as a call to ```exit(0)``` will of course not get the enqueued log entries flushed. Similary a bug that does not trigger a fatal signal but a process exit will also not get the enqueued log entries flushed. G3log can catch several fatal crashes and it deals well with RAII exits but magic is so far out of its' reach. -# G3log and Sink Usage Code Example +## G3log and Sink Usage Code Example Example usage where a [logrotate sink (g3sinks)](https://github.com/KjellKod/g3sinks) is added. In the example it is shown how the logrotate API is called. The logrotate limit is changed from the default to instead be 10MB. The limit is changed by calling the sink handler which passes the function call through to the actual logrotate sink object. ```cpp @@ -269,8 +180,8 @@ The following is an example of changing the size for the message. The default behaviour for G3log is to catch several fatal events before they force the process to exit. After catching a fatal event a stack dump is generated and all log entries, up to the point of the stack dump are together with the dump flushed to the sink(s). - ### Linux/*nix - The default fatal handling on Linux deals with fatal signals. At the time of writing these signals were ```SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM```. The Linux fatal handling is handled in [crashhandler.hpp](src/g3log/crashhandler.hpp) and [crashhandler_unix.cpp](src/crashhandler_unix.cpp) +### Linux/*nix + The default fatal handling on Linux deals with fatal signals. At the time of writing these signals were ```SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM```. The Linux fatal handling is handled in [crashhandler.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/crashhandler.hpp) and [crashhandler_unix.cpp](https://github.com/KjellKod/g3log/tree/master/src/crashhandler_unix.cpp) @@ -302,8 +213,8 @@ The default behaviour for G3log is to catch several fatal events before they for ``` - ### Custom fatal handling - override defaults - By default the fatal signals are defined in [src/g3log.cpp](src/g3log.cpp) as +### Custom fatal handling - override defaults + By default the fatal signals are defined in [https://github.com/KjellKod/g3log/tree/master/src/g3log.cpp](https://github.com/KjellKod/g3log/tree/master/src/g3log.cpp) as ``` SIGABRT SIGFPE @@ -311,7 +222,7 @@ The default behaviour for G3log is to catch several fatal events before they for SIGSEGV SIGTERM ``` - If you want to define your own set of fatal signals, override the default ones, then this can be done as shown in [src/g3log/crashhandler.hpp](src/g3log/crashhandler.hpp) + If you want to define your own set of fatal signals, override the default ones, then this can be done as shown in [src/g3log/crashhandler.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/crashhandler.hpp) ```cpp // Example when SIGTERM is skipped due to ZMQ usage g3::overrideSetupSignals({ {SIGABRT, "SIGABRT"}, @@ -320,51 +231,24 @@ The default behaviour for G3log is to catch several fatal events before they for {SIGSEGV, "SIGSEGV"}}); ``` - ### Pre fatal hook - You can define a custom call back function that will be called before the fatal signal handling re-emits the `fatal` signal. See [src/g3log/g3log.hpp](src/g3log/g3log.hpp) for details. +### Pre fatal hook + You can define a custom call back function that will be called before the fatal signal handling re-emits the `fatal` signal. See [src/g3log/g3log.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/g3log.hpp) for details. ``` // Example of how to enforce important shutdown cleanup even in the event of a fatal crash: g3::setFatalPreLoggingHook([]{ cleanup(); }); ``` - ### Disable fatal handling - Fatal signal handling can be disabled with a CMake option: `ENABLE_FATAL_SIGNALHANDLING`. See [Options.cmake](Options.cmake) for more details +### Disable fatal handling + Fatal signal handling can be disabled with a CMake option: `ENABLE_FATAL_SIGNALHANDLING`. See [Options.cmake](https://github.com/KjellKod/g3log/Options.cmake) for more details - ### PID1 Fatal Signal Recommendations + +### PID1 Fatal Signal Recommendations If you are using g3log on a PID1 process then you absolutely should provide your own signal handling (ref: [issue 269](https://github.com/KjellKod/g3log/issues/269)) as g3log re-emits the fatal signal after it has restored the previous signal handler for that signal. PID1 processed do *not* shutdown the process for a normal fatal signal so the choice to exit the PID1 process after such a signal must be taken by the coder - not by g3log. -### Windows - Windows fatal handling also deals with fatal signals just like Linux. In addition to fatal signals it also deals with unhandled exceptions, vectored exceptions. Windows fatal handling is handled in [crashhandler.hpp](src/g3log/crashhandler.hpp), [crashhandler_windows.cpp](src/crashhandler_windows.cpp), [stacktrace_windows.hpp](src/g3log/stacktrace_windows.hpp), [stacktrace_windows.cpp](src/stacktrace_windows.cpp) +## Windows + Windows fatal handling also deals with fatal signals just like Linux. In addition to fatal signals it also deals with unhandled exceptions, vectored exceptions. Windows fatal handling is handled in [crashhandler.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/crashhandler.hpp), [crashhandler_windows.cpp](https://github.com/KjellKod/g3log/tree/master/src/crashhandler_windows.cpp), [stacktrace_windows.hpp](https://github.com/KjellKod/g3log/tree/master/src/g3log/stacktrace_windows.hpp), [stacktrace_windows.cpp](https://github.com/KjellKod/g3log/tree/master/src/stacktrace_windows.cpp) An example of a Windows stackdump as shown in the output from the fatal example g3log-FATAL-sigsegv. - - - - - - - ## Build Options - The build options are defined in the file [Options.cmake](Options.cmake) - - build options are generated and saved to a header file. This avoid having to set the define options in the client source code - - - -# Say Thanks -This logger is available for free and all of its source code is public domain. -Writing API documentation is probably the most boring task for a developer. -Did it help you? Could it be better? Please suggest changes, send me feedback or even better: open a pull request. - -You could also contribute by saying thanks with a a donation. It would go a long way not only to show your support but also to boost continued development of this logger and its API documentation - -[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/g3log/25) - -* $5 for a cup of coffee -* $10 for pizza -* $25 for a lunch or two -* $100 for a date night with my wife (which buys family credit for evening coding) - -Cheers -Kjell +[introduction](index.md) | [detailed information](g3log.md) | [Configure & Build](building.md) | [**API description**](API.md) | [Custom log formatting](API_custom_formatting.md) \ No newline at end of file diff --git a/docs/API_custom_formatting.md b/docs/API_custom_formatting.md new file mode 100644 index 000000000..d132c7ff1 --- /dev/null +++ b/docs/API_custom_formatting.md @@ -0,0 +1,66 @@ +# Custom LOG formatting +### Overriding the Default File Sink's file header +The default file header can be customized in the default file sink in calling +```cpp + FileSink::overrideLogHeader(std::string); +``` + + +### Overriding the Default FileSink's log formatting +The default log formatting is defined in `LogMessage.hpp` +```cpp + static std::string DefaultLogDetailsToString(const LogMessage& msg); +``` + +### Adding thread ID to the log formatting +An "all details" log formatting function is also defined - this one also adds the "calling thread's ID" +```cpp + static std::string FullLogDetailsToString(const LogMessage& msg); +``` + +### Override default sink log formatting +For convenience the *Default* sink has a function +for doing exactly this +```cpp + void overrideLogDetails(LogMessage::LogDetailsFunc func); +``` + + +Example code for replacing the default log formatting for "full details" formatting (it adds thread ID) + +```cpp + auto worker = g3::LogWorker::createLogWorker(); + auto handle= worker->addDefaultLogger(argv[0], path_to_log_file); + g3::initializeLogging(worker.get()); + handle->call(&g3::FileSink::overrideLogDetails, &LogMessage::FullLogDetailsToString); +``` + +See [test_message.cpp](https://github.com/KjellKod/g3log/tree/master/test_unit/test_message.cpp) for details and testing + + +Example code for overloading the formatting of a custom sink. The log formatting function will be passed into the +`LogMessage::toString(...)` this will override the default log formatting + +Example +```cpp +namespace { + std::string MyCustomFormatting(const LogMessage& msg) { + ... how you want it ... + } + } + + void MyCustomSink::ReceiveLogEntry(LogMessageMover message) { + std::string formatted = message.get().toString(&MyCustomFormatting) << std::flush; + } +... +... + auto worker = g3::LogWorker::createLogWorker(); + auto sinkHandle = worker->addSink(std::make_unique(), + &MyCustomSink::ReceiveLogMessage); + // ReceiveLogMessage(...) will used the custom formatting function "MyCustomFormatting(...) + +``` + + +[introduction](index.md) | [detailed information](g3log.md) | [Configure & Build](building.md) | [API description](API.md) | [**Custom log formatting**](API_custom_formatting.md) + diff --git a/docs/building.md b/docs/building.md new file mode 100644 index 000000000..28beec97f --- /dev/null +++ b/docs/building.md @@ -0,0 +1,235 @@ +# Configure, build, package, install and test g3log + +## Example Project with g3log +An example project integration of g3log, both statially and dynamically built can be found at [g3log_example_integration](https://github.com/KjellKod/g3log_example_integration/blob/master/README.md) + + +## Building it standalone to try out is as easy as: +``` +git clone https://github.com/KjellKod/g3log +cd g3log +mkdir build +cd build +``` + +## Prerequisites +Assume you have got your shiny C++14 compiler installed, you also need these tools to build g3log from source: +- CMake (*Required*) + + g3log uses CMake as a one-stop solution for configuring, building, installing, packaging and testing on Windows, Linux and OSX. + +- Git (*Optional but Recommended*) + + When building g3log it uses git to calculate the software version from the commit history of this repository. If you don't want that, or your setup does not have access to git, or you download g3log source archive from the GitHub Releases page so that you do not have the commit history downloaded, you can instead pass in the version as part of the CMake build arguments. See this [_issue_](https://github.com/KjellKod/g3log/issues/311#issuecomment-488829282) for more information. + ``` + cmake -DVERSION=1.3.2 .. + ``` + +## Configuration Options +g3log provides following CMake options (and default values): +``` +$ cmake -LAH # List non-advanced cached variables. See `cmake --help` for more details. + +... + +// Fatal (fatal-crashes/contract) examples +ADD_FATAL_EXAMPLE:BOOL=ON + +// g3log performance test +ADD_G3LOG_BENCH_PERFORMANCE:BOOL=OFF + +// g3log unit tests +ADD_G3LOG_UNIT_TEST:BOOL=OFF + +// Use DBUG logging level instead of DEBUG. +// By default DEBUG is the debugging level +CHANGE_G3LOG_DEBUG_TO_DBUG:BOOL=OFF + +// Specifies the build type on single-configuration generators. +// Possible values are empty, Debug, Release, RelWithDebInfo, MinSizeRel, … +CMAKE_BUILD_TYPE:STRING= + +// Install path prefix, prepended onto install directories. +// This variable defaults to /usr/local on UNIX +// and c:/Program Files/${PROJECT_NAME} on Windows. +CMAKE_INSTALL_PREFIX:PATH= + +// The prefix used in the built package. +// On Linux, if this option is not set: +// 1) If CMAKE_INSTALL_PREFIX is given, then it will be +// set with the value of CMAKE_INSTALL_PREFIX by g3log. +// 2) Otherwise, it will be set as /usr/local by g3log. +CPACK_PACKAGING_INSTALL_PREFIX:PATH= + +// Enable Visual Studio break point when receiving a fatal exception. +// In __DEBUG mode only +DEBUG_BREAK_AT_FATAL_SIGNAL:BOOL=OFF + +// Vectored exception / crash handling with improved stack trace +ENABLE_FATAL_SIGNALHANDLING:BOOL=ON + +// Vectored exception / crash handling with improved stack trace +ENABLE_VECTORED_EXCEPTIONHANDLING:BOOL=ON + +// iOS version of library. +G3_IOS_LIB:BOOL=OFF + +// Log full filename +G3_LOG_FULL_FILENAME:BOOL=OFF + +// Build shared library +G3_SHARED_LIB:BOOL=ON + +// Build shared runtime library MSVC +G3_SHARED_RUNTIME:BOOL=ON + +// Turn ON/OFF log levels. +// An disabled level will not push logs of that level to the sink. +// By default dynamic logging is disabled +USE_DYNAMIC_LOGGING_LEVELS:BOOL=OFF + +// Use dynamic memory for message buffer during log capturing +USE_G3_DYNAMIC_MAX_MESSAGE_SIZE:BOOL=OFF + +... +``` +For additional option context and comments please also see [Options.cmake](https://github.com/KjellKod/g3log/blob/master/Options.cmake) + +If you want to leave everything as it was, then you should: +``` +cmake .. +``` +You may also specify one or more of those options listed above from the command line. +For example, on Windows: +``` +cmake .. -G "Visual Studio 15 2017" + -DG3_SHARED_LIB=OFF + -DCMAKE_INSTALL_PREFIX=C:/g3log + -DADD_G3LOG_UNIT_TEST=ON + -DADD_FATAL_EXAMPLE=OFF +``` +will use a Visual Studio 2017 solution generator, build g3log as a static library, headers and libraries will be installed to `C:\g3log` when installed from source, enable unit testing, but do not build fatal example. + +MinGW users on Windows may find they should use a different generator: +``` +cmake .. -G "MinGW Makefiles" +``` + +By default, headers and libraries will be installed to `/usr/local` on Linux when installed from build tree via `make install`. You may overwrite it by: +``` +cmake .. -DCMAKE_INSTALL_PREFIX=/usr +``` +This will install g3log to `/usr` instead of `/usr/local`. + +Linux/OSX package maintainers may be interested in the `CPACK_PACKAGING_INSTALL_PREFIX`. For example: +``` +cmake .. -DCPACK_PACKAGING_INSTALL_PREFIX=/usr/local +``` + +## Build Commands +Once the configuration is done, you may build g3log with: +``` +# Suppose you are still in the `build` directory. I won't repeat it anymore! +cmake --build . --config Release +``` +You may also build it with a system-specific way. + +On Linux, OSX and MinGW: +``` +make +``` +On Windows: +``` +msbuild g3log.sln /p:Configuration=Release +``` +Windows users can also open the generated Visual Studio solution file and build it happily. + +## Installation +Install from source in a CMake way: +``` +cmake --build . --target install +``` +Linux users may also use: +``` +sudo make install +``` +You may also create a package first and install g3log with it. See the next section. + +## Packaging +A CMake way: +``` +cmake --build . --config Release --target package +``` +or +``` +cpack -C Release +``` +if the whole library has been built in the previous step. +It will generate a ZIP package on Windows, and a DEB package on Linux. + +Linux users may also use a Linux way: +``` +make package +``` + +If you want to use a different package generator, you should specify a `-G` option. + +On Windows: +``` +cpack -C Release -G NSIS;7Z +``` +this will create a installable NSIS package and a 7z package. + +*Note:* To use the NSIS generator, you should install [```NSIS```](https://nsis.sourceforge.io/Download) first. + +On Linux: +``` +cpack -C Release -G TGZ +``` +this will create a .tar.gz archive for you. + +Once done, you may install or uncompress the package file to the target machine. For example, on Debian or Ubuntu: +``` +sudo dpkg -i g3log--Linux.deb +``` +will install the g3log library to `CPACK_PACKAGING_INSTALL_PREFIX`. + +## Testing + +By default, tests will not be built. To enable unit testing, you should turn on `ADD_G3LOG_UNIT_TEST`. + +Suppose the build process has completed, then you can run the tests with: +``` +ctest -C Release +``` +or: +``` +make test +``` +for Linux users. +or for a detailed gtest output of all the tests: +``` +cd build; +../scripts/runAllTests.sh +``` + +## CMake module + +g3log comes with a CMake module. Once installed, it can be found under `${CMAKE_INSTALL_PREFIX}/lib/cmake/g3log`. Users can use g3log in a CMake-based project this way: + +``` +find_package(g3log CONFIG REQUIRED) +target_link_libraries(main PRIVATE g3log) +``` + +To make sure that CMake can find g3log, you also need to tell CMake where to search for it: +``` +cmake .. -DCMAKE_PREFIX_PATH= +``` + +## Build Options + The build options are defined in the file [Options.cmake](https://github.com/KjellKod/g3log/blob/master/Build.cmake) + + build options are generated and saved to a header file. This avoid having to set the define options in the client source code + +[introduction](index.md) | [detailed information](g3log.md) | [**Configure & Build**](building.md) | [API description](API.md) | [Custom log formatting](API_custom_formatting.md) \ No newline at end of file diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 000000000..438a10169 --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,15 @@ + +# Information for contributing to g3log + +## License +[LICENSE](https://github.com/KjellKod/g3log/blob/master/LICENSE) + + +## Contributing +[CONTRIBUTING.md](https://github.com/KjellKod/g3log/blob/master/CONTRIBUTING.md) + +### Code of conduct +[CODE_OF_CONDUCT.md](https://github.com/KjellKod/g3log/blob/master/CODE_OF_CONDUCT.md) + +### Pull request template +[PULL_REQUEST_TEMPLATE.md](https://github.com/KjellKod/g3log/blob/master/PULL_REQUEST_TEMPLATE.md) \ No newline at end of file diff --git a/docs/g3log.md b/docs/g3log.md new file mode 100644 index 000000000..107da0cf7 --- /dev/null +++ b/docs/g3log.md @@ -0,0 +1,214 @@ +# How to use G3log +G3log is an asynchronous logger with dynamic sinks + + +## Example USAGE +#### Optional to use either streaming or printf-like syntax +``` +LOG(INFO) << "streaming API is as easy as ABC or " << 123; + +LOGF(WARNING, "Printf-style syntax is also %s", "available"); +``` + +## What G3Log is + +* ***G3log*** is the acting name for the third version of g2log and it stands for **g3log with dynamic sinks** +* G3log is an asynchronous, "crash-safe" logger. You can read more about it here [[g2log version]]( +http://www.codeproject.com/Articles/288827/g2log-An-efficient-asynchronous-logger-using-Cplus) +* You can choose to use the default log receiver which saves all LOG calls to file, **or** you can choose to use your own custom made log receiver(s), **or** both, **or** as many sinks as you need. + + + +#### Conditional logging + int less = 1; int more = 2 + LOG_IF(INFO, (lessDesign-by-Contract +*CHECK(false)* will trigger a "fatal" message. It will be logged, and then the +application will exit. + +``` +CHECK(less != more); // not FATAL +CHECK(less > more) << "CHECK(false) triggers a FATAL message"; +``` + + + + +### Detailed API documentation +Please look at [API.md](API.md) for detailed API documentation + + +## Benefits you get when using G3log +1. Easy to use, clean syntax and a blazing fast logger. + +2. All the slow log I/O disk access is done in a background thread. This ensures that the LOG caller can immediately continue with other tasks and do not have to wait for the LOG call to finish. + +3. G3log provides logging, Design-by-Contract [#CHECK], and flush of log to file at + shutdown. Buffered logs will be written to the sink before the application shuts down. + +4. It is thread safe, so using it from multiple threads is completely fine. + +5. It is *CRASH SAFE*. It will save the made logs to the sink before it shuts down. +The logger will catch certain fatal events *(Linux/OSX: signals, Windows: fatal OS exceptions and signals)* , so if your application crashes due to, say a segmentation fault, *SIGSEGV*, it will log and save the crash and all previously buffered log entries before exiting. + + +6. It is cross platform. Tested and used by me or by clients on OSX, Windows, Ubuntu, CentOS + +7. G3log and G2log are used worldwide in commercial products as well as hobby projects. G2log was introduced in early 2011 and is now retired. + +8. The code is given for free as public domain. This gives the option to change, use, and do whatever with it, no strings attached. + +9. *[g3log](https://github.com/KjellKod/g3log)* : is made to facilitate easy adding of custom log receivers. Its tested on at least the following platforms with **Linux**(Clang/gcc), **Windows** (mingw, visual studio) and **OSX**. My recommendation is to go with g3log if you have full C++14 support (C++11 support up to version: https://github.com/KjellKod/g3log/releases/tag/1.3.1). + + +## G3log with sinks +[Sinks](http://en.wikipedia.org/wiki/Sink_(computing)) are receivers of LOG calls. G3log comes with a default sink (*the same as G3log uses*) that can be used to save log to file. A sink can be of *any* class type without restrictions as long as it can either receive a LOG message as a *std::string* **or** as a *g3::LogMessageMover*. + +The *std::string* comes pre-formatted. The *g3::LogMessageMover* is a wrapped struct that contains the raw data for custom handling in your own sink. + +A sink is *owned* by the G3log and is added to the logger inside a ```std::unique_ptr```. The sink can be called though its public API through a *handler* which will asynchronously forward the call to the receiving sink. + +It is crazy simple to create a custom sink. This example show what is needed to make a custom sink that is using custom log formatting but only using that +for adding color to the default log formatting. The sink forwards the colored log to cout + + +```cpp +// in file Customsink.hpp +#pragma once +#include +#include +#include + +struct CustomSink { + +// Linux xterm color +// http://stackoverflow.com/questions/2616906/how-do-i-output-coloured-text-to-a-linux-terminal + enum FG_Color {YELLOW = 33, RED = 31, GREEN=32, WHITE = 97}; + + FG_Color GetColor(const LEVELS level) const { + if (level.value == WARNING.value) { return YELLOW; } + if (level.value == DEBUG.value) { return GREEN; } + if (g3::internal::wasFatal(level)) { return RED; } + + return WHITE; + } + + void ReceiveLogMessage(g3::LogMessageMover logEntry) { + auto level = logEntry.get()._level; + auto color = GetColor(level); + + std::cout << "\033[" << color << "m" + << logEntry.get().toString() << "\033[m" << std::endl; + } +}; + +// in main.cpp, main() function + +auto sinkHandle = logworker->addSink(std::make_unique(), + &CustomSink::ReceiveLogMessage); + +``` + +## Adding and Removing Sinks +You can safely remove and add sinks during the running of your program. + +**Keep in mind** + +- *Initialization of the logger should happen before you have started any other threads that may call the logger.* +- *Destruction of the logger (RAII concept) should happen AFTER shutdown of other threads that are calling the logger.* + +**Adding Sinks** +```cpp + auto sinkHandle1 = logworker->addSink(std::make_unique(), + &CustomSink::ReceiveLogMessage); + auto sinkHandle2 = logworker->addDefaultLogger(argv[0], + path_to_log_file); + logworker->removeSink(std::move(sinkHandle1)); // this will in a thread-safe manner remove the sinkHandle1 + logworker->removeAllSinks(); // this will in a thread-safe manner remove any sinks. +``` + + +**More sinks** can be found in the repository **[github.com/KjellKod/g3sinks](https://github.com/KjellKod/g3sinks)**. + + +## Code Examples +Example usage where a custom sink is added. A function is called though the sink handler to the actual sink object. +```cpp +// main.cpp +#include +#include +#include + +#include "CustomSink.h" + +int main(int argc, char**argv) { + using namespace g3; + std::unique_ptr logworker{ LogWorker::createLogWorker() }; + auto sinkHandle = logworker->addSink(std::make_unique(), + &CustomSink::ReceiveLogMessage); + + // initialize the logger before it can receive LOG calls + initializeLogging(logworker.get()); + LOG(WARNING) << "This log call, may or may not happend before" + << "the sinkHandle->call below"; + + + // You can call in a thread safe manner public functions on your sink + // The call is asynchronously executed on your custom sink. + std::future received = sinkHandle->call(&CustomSink::Foo, + param1, param2); + + // If the LogWorker is initialized then at scope exit the g3::internal::shutDownLogging() will be called. + // This is important since it protects from LOG calls from static or other entities that will go out of + // scope at a later time. + // + // It can also be called manually: + g3::internal::shutDownLogging(); +} + + +// some_file.cpp : To show how easy it is to get the logger to work +// in other parts of your software + +#include + +void SomeFunction() { + ... + LOG(INFO) << "Hello World"; +} +``` + +Example usage where a the default file logger is used **and** a custom sink is added +```cpp +// main.cpp +#include +#include +#include + +#include "CustomSink.h" + +int main(int argc, char**argv) { + using namespace g3; + auto worker = LogWorker::createLogWorker(); + auto defaultHandler = worker->addDefaultLogger(argv[0], + path_to_log_file); + + // logger is initialized + g3::initializeLogging(worker.get()); + + LOG(DEBUG) << "Make log call, then add another sink"; + + worker->addSink(std::make_unique(), + &CustomSink::ReceiveLogMessage); + + ... +} +``` + +[introduction](index.md) | [**detailed information**](g3log.md) | [Configure & Build](building.md) | [API description](API.md) | [Custom log formatting](API_custom_formatting.md) \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 16099fd62..a8221aaf2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,40 +1,130 @@ -## Sample. +# Welcome to g3log -One more, finally. Or not? :) +G3log is an asynchronous logger with three main features. -Now: +1. Intuitive `LOG(...)` API +2. `Design-by-contract` `CHECK(...)` functionality +3. Fatal crash handling for graceful shutdown of the logged process without loosing any log details up to the point of the crash. +The super quick introduction to g3log can be seen in the steps 1 - 9 below. + +For more in-depth information please see the full usage description in [g3log.md](g3log.md). The internal API for more advanced integration with g3log can be accessed in [API.md](API.md) + +## 1. Easy usage in files +Avoid deep dependency injection complexity and instead get access to the logger as easy as +``` +#include +``` + + +## 2. Access to streaming and print_f log call syntax +Both streaming syntax `LOG` and print_f `LOGF` syntax are available. + +``` +LOGF(INFO, "Hi log %d", 123); +LOG(INF) << "Hi log " << 123; + +``` + +## 3. Conditional logging + +``` +LOG_IF(INFO, (1 < 2)) << "If true this message will be logged"; +LOGF_IF(INFO, (1 < 2), "If true, then this %s will be logged", "message"); +``` + +## 4. Design-by-contract framework +``` +CHECK(less != more); // not fatal +CHECK_F(less > more, "CHECK(false) will trigger a fatal message") +``` + +## 5. Handling of fatal +By default g3log will capture fatal events such as `LOG(FATAL)`, `CHECK(false)` and otherwise fatal signals such as: ``` -$ some + SIGABRT + SIGFPE + SIGILL + SIGSEGV + SIGTERM +``` + +When a fatal event happens the not-yet written log activity will be flushed to the logging sinks. Only when all logging activity up to the point of the fatal event has happend, will g3log allow the fatal event to proceed and exit the process. + +If `object` symbols are available the fatal handler will attempt to push the stacktrace up to the fatal reason to the logging sink. + +#### 5b. Overriding and customization of fatal event handling +For overriding fatal error handling to use your own, or to add code `hooks` that you want to execute please see the [API.md](API.md) doc. + +## 6. Default and Custom logging levels +The default logging levels are `DEBUG`, `INFO`, `WARNING` and `FATAL`. You can define your own logging levels or completely replace the logging levels. Ref: [API.md](API.md) + + +### 7. Log filtering +Log filtering is handled in g3log if dynamic logging levels are enabled +in the configuration. See the [API.md](API.md) for information. Log filtering can also be handled through the sink as can be seen in [github/Kjellod/g3sinks](https://github.com/KjellKod/g3sinks) + + +## 8. 3rd party and custom logging sinks +The default logging sink has no external 3rd party dependencies. For more logging sinks please see [github/Kjellod/g3sinks](https://github.com/KjellKod/g3sinks) + +- log rotate +- log to syslog +- log to colored terminal output +- log rotate with filter + +See the [API.md](API.md) for more information about the simple steps to creating your own logging sink. + + +## 9. Log instantiation +With the default application name left as is (i.e. "g3log") a creation of the logger could look something like this: + +```cpp + const std::string directory = "./"; + const std::string name = "TestLogFile"; + auto worker = g3::LogWorker::createLogWorker(); + auto handle = worker->addDefaultLogger(name, directory); +``` +The resulting filename would be something like: +``` + ./TestLogFile.g3log.20160217-001406.log ``` -Look what she said: +## Performance +G3log aims to keep all background logging to sinks with as little log overhead as possible to the logging sink and with as small "worst case latency" as possible. For this reason g3log is a good logger for many systems that deal with critical tasks. Depending on platform the average logging overhead will differ. On my 2010 laptop the average call, when doing extreme performance testing, will be about ~2 us. -> This is it! +The worst case latency is kept stable with no extreme peaks, in spite of any sudden extreme pressure. I have a blog post regarding comparing worst case latency for g3log and other loggers which might be of interest. +You can find it here: https://kjellkod.wordpress.com/2015/06/30/the-worlds-fastest-logger-vs-g3log/ -### Subtitle -And now this: +## Continuos Integration +The g3log repository is evaluating both github actions and CircleCI for executing test coverage, installation and document generation. For windows the repo is still relying on appveyor. In case you want to look into change any of these setups the following files are the ones of interest. +``` +1. appveyor --> g3log/appveyor.yml +2. circleCI --> g3log/.circleci/config.yml +3. github actions --> g3log/.github/workflows/*.yml -- One -- Two -- Three +``` -#### As well -#### As this +## Feedback +If you like this logger (or not) it would be nice with some feedback. That way I can improve g3log and it is always nice to hear when and how someone is using it. -### Another + If you have ANY questions or problems please do not hesitate in contacting me at + `Hedstrom @ Kjellod. cc` -[a link](https://aws.com) +# Say Thanks +This logger is available for free and all of its source code is public domain. A great way of saying thanks is to send a donation. It would go a long way not only to show your support but also to boost continued development. -More? +[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/g3log/25) +* $5 for a cup of coffee +* $25 for a late evening coding with takeout -Can we now have `the build`? -NOW! +Cheers +Kjell *(a.k.a. KjellKod)* -Not gonna work, is it? +[**introduction**](index.md) | [detailed information](g3log.md) | [Configure & Build](building.md) | [API description](API.md) | [Custom log formatting](API_custom_formatting.md) diff --git a/index.md b/index.md index 743103b69..1f38a6afa 100644 --- a/index.md +++ b/index.md @@ -1,2 +1,2 @@ -## wrong file! +## wrong file 1 diff --git a/mkdocs.yml b/mkdocs.yml index f7bf1056d..ff7d3be11 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,11 +1,16 @@ -site_name: Test docs -site_description: 'A docs test' +site_name: G3log, an asynchronous "crash-safe" logger site_author: 'Kjell Hedström' docs_dir: docs/ repo_name: 'KjellKod/g3log' repo_url: 'https://github.com/KjellKod/g3log' -nav: - - Home: index.md - - API Guide: API.md -theme: - name: 'material' +theme: + name: material +nav: + - Introduction to G3log: index.md + - G3log usage: g3log.md + - API description: API.md + - API for custom log formatting: API_custom_formatting.md + - Configure, Build, Package, Install and Test: building.md + - License and contribution: contributing.md + +