Add in support for configurable kMaxMessageValue #203 (#208)

* Add in support for configurable kMaxMessageValue #203

* Add in documentation for USE_G3_DYNAMIC_MAX_MESSAGE_SIZE
This commit is contained in:
mobileben 2017-09-08 21:51:46 -07:00 committed by Kjell Hedström
parent 97c6cf45b3
commit 93c05406d8
4 changed files with 63 additions and 6 deletions

View File

@ -9,6 +9,7 @@ Most of the API that you need for using g3log is described in this readme. For m
* Sink [creation](#sink_creation) and utilization
* 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)
* <strike>[TOWRITE: Windows](#fatal_handling_windows)</strike>
@ -159,6 +160,20 @@ int main(int argc, char**argv) {
```
## Dynamic Message Sizing <a name="dynamic_message_sizing"></a>
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.
```
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 <i>catching</i> 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).

View File

@ -17,6 +17,7 @@
# add_definitions(-DDISABLE_FATAL_SIGNALHANDLING)
# add_definitions(-DDISABLE_VECTORED_EXCEPTIONHANDLING)
# add_definitions(-DDEBUG_BREAK_AT_FATAL_SIGNAL)
# add_definitions(-DG3_DYNAMIC_MAX_MESSAGE_SIZE)
@ -40,7 +41,6 @@ ENDIF(USE_DYNAMIC_LOGGING_LEVELS)
# -DCHANGE_G3LOG_DEBUG_TO_DBUG=ON : change the DEBUG logging level to be DBUG to avoid clash with other libraries that might have
# predefined DEBUG for their own purposes
option (CHANGE_G3LOG_DEBUG_TO_DBUG
@ -55,6 +55,16 @@ ELSE()
ENDIF(CHANGE_G3LOG_DEBUG_TO_DBUG)
# -DG3_DYNAMIC_MAX_MESSAGE_SIZE : use dynamic memory for final_message in logcapture.cpp
option (USE_G3_DYNAMIC_MAX_MESSAGE_SIZE
"Use dynamic memory for message buffer during log capturing" OFF)
IF(USE_G3_DYNAMIC_MAX_MESSAGE_SIZE)
LIST(APPEND G3_DEFINITIONS G3_DYNAMIC_MAX_MESSAGE_SIZE)
message( STATUS "-DUSE_G3_DYNAMIC_MAX_MESSAGE_SIZE=ON\t\tDynamic memory used during log capture" )
ELSE()
message( STATUS "-DUSE_G3_DYNAMIC_MAX_MESSAGE_SIZE=OFF" )
ENDIF(USE_G3_DYNAMIC_MAX_MESSAGE_SIZE)
# -DENABLE_FATAL_SIGNALHANDLING=ON : defualt change the
# By default fatal signal handling is enabled. You can disable it with this option

View File

@ -86,7 +86,16 @@ namespace g3 {
void setFatalExitHandler(std::function<void(FatalMessagePtr)> fatal_call);
#ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE
// only_change_at_initialization namespace is for changes to be done only during initialization. More specifically
// items here would be called prior to calling other parts of g3log
namespace only_change_at_initialization {
// Sets the MaxMessageSize to be used when capturing log messages. Currently this value is set to 2KB. Messages
// Longer than this are bound to 2KB with the string "[...truncated...]" at the end. This function allows
// this limit to be changed.
void setMaxMessageSize(size_t max_size);
}
#endif /* G3_DYNAMIC_MAX_MESSAGE_SIZE */
// internal namespace is for completely internal or semi-hidden from the g3 namespace due to that it is unlikely
// that you will use these

View File

@ -9,6 +9,10 @@
#include "g3log/logcapture.hpp"
#include "g3log/crashhandler.hpp"
#ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE
#include <vector>
#endif /* G3_DYNAMIC_MAX_MESSAGE_SIZE */
// For Windows we need force a thread_local install per thread of three
// signals that must have a signal handler instealled per thread-basis
// It is really a royal pain. Seriously Microsoft? Seriously?
@ -19,7 +23,14 @@
#define SIGNAL_HANDLER_VERIFY() do {} while(0)
#endif
#ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE
// MaxMessageSize is message limit used with vsnprintf/vsnprintf_s
static int MaxMessageSize = 2048;
void g3::only_change_at_initialization::setMaxMessageSize(size_t max_size) {
MaxMessageSize = max_size;
}
#endif /* G3_DYNAMIC_MAX_MESSAGE_SIZE */
/** logCapture is a simple struct for capturing log/fatal entries. At destruction the
* captured message is forwarded to background worker.
@ -60,23 +71,35 @@ LogCapture::LogCapture(const char *file, const int line, const char *function, c
* See also for the attribute formatting ref: http://www.codemaestro.com/reviews/18
*/
void LogCapture::capturef(const char *printf_like_message, ...) {
static const int kMaxMessageSize = 2048;
static const std::string kTruncatedWarningText = "[...truncated...]";
#ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE
std::vector<char> finished_message_backing(MaxMessageSize);
char *finished_message = finished_message_backing.data();
auto finished_message_len = MaxMessageSize;
#else
static const int kMaxMessageSize = 2048;
char finished_message[kMaxMessageSize];
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__))
auto finished_message_len = _countof(finished_message);
#else
auto finished_message_len = sizeof(finished_message);
#endif
#endif /* G3_DYNAMIC_MAX_MESSAGE_SIZE*/
va_list arglist;
va_start(arglist, printf_like_message);
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__))
const int nbrcharacters = vsnprintf_s(finished_message, _countof(finished_message), _TRUNCATE, printf_like_message, arglist);
const int nbrcharacters = vsnprintf_s(finished_message, finished_message_len, _TRUNCATE, printf_like_message, arglist);
#else
const int nbrcharacters = vsnprintf(finished_message, sizeof (finished_message), printf_like_message, arglist);
const int nbrcharacters = vsnprintf(finished_message, finished_message_len, printf_like_message, arglist);
#endif
va_end(arglist);
if (nbrcharacters <= 0) {
stream() << "\n\tERROR LOG MSG NOTIFICATION: Failure to parse successfully the message";
stream() << '"' << printf_like_message << '"' << std::endl;
} else if (nbrcharacters > kMaxMessageSize) {
} else if (nbrcharacters > finished_message_len) {
stream() << finished_message << kTruncatedWarningText;
} else {
stream() << finished_message;