From 93c05406d8eddd85707ddcc0eaf2944ec064846c Mon Sep 17 00:00:00 2001 From: mobileben Date: Fri, 8 Sep 2017 21:51:46 -0700 Subject: [PATCH] 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 --- API.markdown | 15 +++++++++++++++ Options.cmake | 12 +++++++++++- src/g3log/g3log.hpp | 11 ++++++++++- src/logcapture.cpp | 31 +++++++++++++++++++++++++++---- 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/API.markdown b/API.markdown index 859b9bd..351ca57 100644 --- a/API.markdown +++ b/API.markdown @@ -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) * [TOWRITE: Windows](#fatal_handling_windows) @@ -159,6 +160,20 @@ int main(int argc, char**argv) { ``` +## 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. + +``` + 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). diff --git a/Options.cmake b/Options.cmake index 124617f..30e0568 100644 --- a/Options.cmake +++ b/Options.cmake @@ -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 diff --git a/src/g3log/g3log.hpp b/src/g3log/g3log.hpp index c5f4d19..011b033 100644 --- a/src/g3log/g3log.hpp +++ b/src/g3log/g3log.hpp @@ -86,7 +86,16 @@ namespace g3 { void setFatalExitHandler(std::function 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 diff --git a/src/logcapture.cpp b/src/logcapture.cpp index 44220dd..9ffc734 100644 --- a/src/logcapture.cpp +++ b/src/logcapture.cpp @@ -9,6 +9,10 @@ #include "g3log/logcapture.hpp" #include "g3log/crashhandler.hpp" +#ifdef G3_DYNAMIC_MAX_MESSAGE_SIZE +#include +#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 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;