Added optional logging of regex filter matching to user defined file and trace log.
This commit is contained in:
@ -32,7 +32,7 @@ The regex filter accepts the options ignorecase or case. These define if the pat
|
||||
|
||||
The Regex filter requires two mandatory parameters to be defined.
|
||||
|
||||
### Match
|
||||
### `match`
|
||||
|
||||
A parameter that can be used to match text in the SQL statement which should be replaced.
|
||||
|
||||
@ -42,7 +42,7 @@ match=TYPE[ ]*=
|
||||
|
||||
If the filter option ignorecase is used all regular expressions are evaluated with the option to ignore the case of the text, therefore a match option of select will match both type, TYPE and any form of the word with upper or lowercase characters.
|
||||
|
||||
### Replace
|
||||
### `replace`
|
||||
|
||||
The replace parameter defines the text that should replace the text in the SQL text which matches the match.
|
||||
|
||||
@ -50,7 +50,7 @@ The replace parameter defines the text that should replace the text in the SQL t
|
||||
replace=ENGINE =
|
||||
```
|
||||
|
||||
### Source
|
||||
### `source`
|
||||
|
||||
The optional source parameter defines an address that is used to match against the address from which the client connection to MaxScale originates. Only sessions that originate from this address will have the match and replacement applied to them.
|
||||
|
||||
@ -58,7 +58,7 @@ The optional source parameter defines an address that is used to match against t
|
||||
source=127.0.0.1
|
||||
```
|
||||
|
||||
### User
|
||||
### `user`
|
||||
|
||||
The optional user parameter defines a user name that is used to match against the user from which the client connection to MaxScale originates. Only sessions that are connected using this username will have the match and replacement applied to them.
|
||||
|
||||
@ -66,6 +66,22 @@ The optional user parameter defines a user name that is used to match against th
|
||||
user=john
|
||||
```
|
||||
|
||||
### `log_file`
|
||||
|
||||
The optional log_file parameter defines a log file in which the filter writes all queries that are not mached and maching queries with their replacement queries. All sessions will log to this file so this should only be used for diagnostic purposes.
|
||||
|
||||
```
|
||||
log_file=/tmp/regexfilter.log
|
||||
```
|
||||
|
||||
### `log_trace`
|
||||
|
||||
The optional log_trace parameter toggles the logging of non-matching and matching queries with their replacements into the trace log file. This is the preferred method of diagnosing the matching of queries since the trace log can be disabled mid-session if such a need rises.
|
||||
|
||||
```
|
||||
log_trace=true
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 - Replace MySQL 5.1 create table syntax with that for later versions
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
#include <string.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "maxconfig.h"
|
||||
|
||||
/** Defined in log_manager.cc */
|
||||
extern int lm_enabled_logfiles_bitmask;
|
||||
extern size_t log_ses_count[];
|
||||
@ -86,6 +88,8 @@ typedef struct {
|
||||
char *match; /* Regular expression to match */
|
||||
char *replace; /* Replacement text */
|
||||
regex_t re; /* Compiled regex text */
|
||||
FILE* logfile;
|
||||
bool log_trace;
|
||||
} REGEX_INSTANCE;
|
||||
|
||||
/**
|
||||
@ -98,6 +102,9 @@ typedef struct {
|
||||
int active; /* Is filter active */
|
||||
} REGEX_SESSION;
|
||||
|
||||
void log_match(REGEX_INSTANCE* inst,char* re, char* old, char* new);
|
||||
void log_nomatch(REGEX_INSTANCE* inst, char* re, char* old);
|
||||
|
||||
/**
|
||||
* Implementation of the mandatory version entry point
|
||||
*
|
||||
@ -146,7 +153,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
|
||||
{
|
||||
REGEX_INSTANCE *my_instance;
|
||||
int i, cflags = REG_ICASE;
|
||||
|
||||
char *logfile = NULL;
|
||||
if ((my_instance = calloc(1, sizeof(REGEX_INSTANCE))) != NULL)
|
||||
{
|
||||
my_instance->match = NULL;
|
||||
@ -162,6 +169,10 @@ int i, cflags = REG_ICASE;
|
||||
my_instance->source = strdup(params[i]->value);
|
||||
else if (!strcmp(params[i]->name, "user"))
|
||||
my_instance->user = strdup(params[i]->value);
|
||||
else if (!strcmp(params[i]->name, "log_trace"))
|
||||
my_instance->log_trace = config_truth_value(params[i]->value);
|
||||
else if (!strcmp(params[i]->name, "log_file"))
|
||||
logfile = strdup(params[i]->value);
|
||||
else if (!filter_standard_parameter(params[i]->name))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
@ -209,6 +220,25 @@ int i, cflags = REG_ICASE;
|
||||
free(my_instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(logfile != NULL)
|
||||
{
|
||||
if((my_instance->logfile = fopen(logfile,"a")) == NULL)
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
|
||||
"regexfilter: Failed to open file '%s'.\n",
|
||||
logfile)));
|
||||
free(my_instance->match);
|
||||
free(my_instance->replace);
|
||||
free(my_instance);
|
||||
free(logfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fprintf(my_instance->logfile,"\nOpened regex filter log\n");
|
||||
fflush(my_instance->logfile);
|
||||
}
|
||||
free(logfile);
|
||||
}
|
||||
return (FILTER *)my_instance;
|
||||
}
|
||||
@ -320,11 +350,15 @@ char *sql, *newsql;
|
||||
{
|
||||
queue = modutil_replace_SQL(queue, newsql);
|
||||
queue = gwbuf_make_contiguous(queue);
|
||||
log_match(my_instance,my_instance->match,sql,newsql);
|
||||
free(newsql);
|
||||
my_session->replacements++;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_nomatch(my_instance,my_instance->match,sql);
|
||||
my_session->no_change++;
|
||||
}
|
||||
free(sql);
|
||||
}
|
||||
|
||||
@ -441,3 +475,43 @@ regmatch_t match[10];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a matching query to either MaxScale's trace log or a separate log file.
|
||||
* The old SQL and the new SQL statements are printed in the log.
|
||||
* @param inst Regex filter instance
|
||||
* @param re Regular expression
|
||||
* @param old Old SQL statement
|
||||
* @param new New SQL statement
|
||||
*/
|
||||
void log_match(REGEX_INSTANCE* inst, char* re, char* old, char* new)
|
||||
{
|
||||
if(inst->logfile)
|
||||
{
|
||||
fprintf(inst->logfile,"Matched %s: [%s] -> [%s]\n",re,old,new);
|
||||
fflush(inst->logfile);
|
||||
}
|
||||
if(inst->log_trace)
|
||||
{
|
||||
LOGIF(LT,(skygw_log_write(LT,"Match %s: [%s] -> [%s]",re,old,new)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a non-matching query to either MaxScale's trace log or a separate log file.
|
||||
* @param inst Regex filter instance
|
||||
* @param re Regular expression
|
||||
* @param old SQL statement
|
||||
*/
|
||||
void log_nomatch(REGEX_INSTANCE* inst, char* re, char* old)
|
||||
{
|
||||
if(inst->logfile)
|
||||
{
|
||||
fprintf(inst->logfile,"No match %s: [%s]\n",re,old);
|
||||
fflush(inst->logfile);
|
||||
}
|
||||
if(inst->log_trace)
|
||||
{
|
||||
LOGIF(LT,(skygw_log_write(LT,"No match %s: [%s]",re,old)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user