diff --git a/Documentation/Changelog.md b/Documentation/Changelog.md new file mode 100644 index 000000000..1499526d3 --- /dev/null +++ b/Documentation/Changelog.md @@ -0,0 +1,11 @@ +#Changelog + +These are the changes introduced in MaxScale version 1.0.6 + +* New modules added + * Binlog router + * Firewall filter + * Multi-Master monitor + * RabbitMQ logging filter +* Added option to use high precision timestamps in logging +* Readwritesplit router now returns the master server's response diff --git a/Documentation/Getting-Started/Configuration-Guide.md b/Documentation/Getting-Started/Configuration-Guide.md index 58d533d3d..726d02a25 100644 --- a/Documentation/Getting-Started/Configuration-Guide.md +++ b/Documentation/Getting-Started/Configuration-Guide.md @@ -56,6 +56,16 @@ threads=1 It should be noted that additional threads will be created to execute other internal services within MaxScale. This setting is used to configure the number of threads that will be used to manage the user connections. +### `ms_timestamp` + +Enable or disable the high precision timestamps in logfiles. Enabling this adds millisecond precision to all logfile timestamps. + +``` +# Valid options are: +# ms_timestamp=<0|1> +ms_timestamp=1 +``` + ### `log_messages` Enable or disable logging of status messages. This logfile is enabled by default and contains information about the modules MaxScale is using and details about the configuration. diff --git a/log_manager/log_manager.cc b/log_manager/log_manager.cc index 89f046465..4179f5c49 100644 --- a/log_manager/log_manager.cc +++ b/log_manager/log_manager.cc @@ -51,6 +51,7 @@ static int block_start_index; static int prevval; static simple_mutex_t msg_mutex; #endif +static int highprec = 0; /** * Variable holding the enabled logfiles information. * Used from log users to check enabled logs prior calling @@ -696,9 +697,11 @@ static int logmanager_write_log( else { sesid_str_len = 0; - } - timestamp_len = get_timestamp_len(); - + } + if(highprec) + timestamp_len = get_timestamp_len_hp(); + else + timestamp_len = get_timestamp_len(); cmplen = sesid_str_len > 0 ? sesid_str_len - sizeof(char) : 0; /** Find out how much can be safely written with current block size */ @@ -758,8 +761,10 @@ static int logmanager_write_log( * to wp. * Returned timestamp_len doesn't include terminating null. */ - timestamp_len = snprint_timestamp(wp, timestamp_len); - + if(highprec) + timestamp_len = snprint_timestamp_hp(wp, timestamp_len); + else + timestamp_len = snprint_timestamp(wp, timestamp_len); if (sesid_str_len != 0) { /** @@ -3077,3 +3082,8 @@ void skygw_log_sync_all(void) skygw_message_send(lm->lm_logmes); skygw_message_wait(lm->lm_clientmes); } + +void skygw_set_highp(int val) +{ + highprec = val; +} \ No newline at end of file diff --git a/log_manager/log_manager.h b/log_manager/log_manager.h index f2146d303..10ccdea1c 100644 --- a/log_manager/log_manager.h +++ b/log_manager/log_manager.h @@ -119,7 +119,7 @@ int skygw_log_write_flush(logfile_id_t id, const char* format, ...); int skygw_log_enable(logfile_id_t id); int skygw_log_disable(logfile_id_t id); void skygw_log_sync_all(void); - +void skygw_set_highp(int); EXTERN_C_BLOCK_END const char* get_trace_prefix_default(void); diff --git a/server/core/config.c b/server/core/config.c index 309f5e709..fcf851137 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -1219,6 +1219,10 @@ int i; { gateway.pollsleep = atoi(value); } + else if (strcmp(name, "ms_timestamp") == 0) + { + skygw_set_highp(atoi(value)); + } else { for (i = 0; lognames[i].logname; i++) diff --git a/utils/skygw_utils.cc b/utils/skygw_utils.cc index 00b63b368..20728633b 100644 --- a/utils/skygw_utils.cc +++ b/utils/skygw_utils.cc @@ -27,12 +27,18 @@ #include #include "skygw_debug.h" #include +#include #include "skygw_utils.h" const char* timestamp_formatstr = "%04d-%02d-%02d %02d:%02d:%02d "; /** One for terminating '\0' */ const size_t timestamp_len = (4+1 +2+1 +2+1 +2+1 +2+1 +2+3 +1) * sizeof(char); + +const char* timestamp_formatstr_hp = "%04d-%02d-%02d %02d:%02d:%02d.%03d "; +/** One for terminating '\0' */ +const size_t timestamp_len_hp = (4+1 +2+1 +2+1 +2+1 +2+1 +2+1+3+3 +1) * sizeof(char); + /** Single-linked list for storing test cases */ struct slist_node_st { @@ -667,6 +673,10 @@ size_t get_timestamp_len(void) return timestamp_len; } +size_t get_timestamp_len_hp(void) +{ + return timestamp_len_hp; +} /** * @node Generate and write a timestamp to location passed as argument * by using at most tslen characters. @@ -689,15 +699,16 @@ size_t snprint_timestamp( time_t t; struct tm tm; size_t rval; - + struct timeval tv; if (p_ts == NULL) { rval = 0; goto retblock; } /** Generate timestamp */ - t = time(NULL); - tm = *(localtime(&t)); + + gettimeofday(&tv,NULL); + tm = *(localtime(&tv.tv_sec)); snprintf(p_ts, MIN(tslen,timestamp_len), timestamp_formatstr, @@ -707,7 +718,56 @@ size_t snprint_timestamp( tm.tm_hour, tm.tm_min, tm.tm_sec); + rval = strlen(p_ts)*sizeof(char); +retblock: + return rval; +} + +/** + * @node Generate and write a timestamp to location passed as argument + * by using at most tslen characters. This will use millisecond precision. + * + * Parameters: + * @param p_ts - in, use + * Write position in memory. Must be filled with at least + * zeroes + * + * @return Length of string written to p_ts. Length includes terminating '\0'. + * + * + * @details (write detailed description here) + * + */ +size_t snprint_timestamp_hp( + char* p_ts, + size_t tslen) +{ + time_t t; + struct tm tm; + size_t rval; + struct timeval tv; + int usec; + if (p_ts == NULL) { + rval = 0; + goto retblock; + } + + /** Generate timestamp */ + + gettimeofday(&tv,NULL); + tm = *(localtime(&tv.tv_sec)); + usec = tv.tv_usec/1000; + snprintf(p_ts, + MIN(tslen,timestamp_len_hp), + timestamp_formatstr_hp, + tm.tm_year+1900, + tm.tm_mon+1, + tm.tm_mday, + tm.tm_hour, + tm.tm_min, + tm.tm_sec, + usec); rval = strlen(p_ts)*sizeof(char); retblock: return rval; diff --git a/utils/skygw_utils.h b/utils/skygw_utils.h index cd3793048..6cc8fcfcd 100644 --- a/utils/skygw_utils.h +++ b/utils/skygw_utils.h @@ -125,7 +125,9 @@ skygw_thr_state_t skygw_thread_get_state(skygw_thread_t* thr); pthread_t skygw_thread_gettid(skygw_thread_t* thr); size_t get_timestamp_len(void); +size_t get_timestamp_len_hp(void); size_t snprint_timestamp(char* p_ts, size_t tslen); +size_t snprint_timestamp_hp(char* p_ts, size_t tslen); EXTERN_C_BLOCK_BEGIN