Updated QLA filter to allow for regex matches and client address matches
to control the statements that are logged.
This commit is contained in:
@ -669,9 +669,32 @@ int i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Entry point for the final element int he upstream filter, i.e. the writing
|
||||
* of the data to the client.
|
||||
*
|
||||
* @param instance The "instance" data
|
||||
* @param session The session
|
||||
* @param data The buffer chain to write
|
||||
*/
|
||||
int
|
||||
session_reply(void *instance, void *session, GWBUF *data)
|
||||
{
|
||||
SESSION *the_session = (SESSION *)session;
|
||||
|
||||
return the_session->client->func.write(the_session->client, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the client connection address or name
|
||||
*
|
||||
* @param session The session whose client address to return
|
||||
*/
|
||||
char *
|
||||
session_get_remote(SESSION *session)
|
||||
{
|
||||
if (session && session->client)
|
||||
return session->client->remote;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -149,6 +149,7 @@ SESSION *session_alloc(struct service *, struct dcb *);
|
||||
bool session_free(SESSION *);
|
||||
int session_isvalid(SESSION *);
|
||||
int session_reply(void *inst, void *session, GWBUF *data);
|
||||
char *session_get_remote(SESSION *);
|
||||
void printAllSessions();
|
||||
void printSession(SESSION *);
|
||||
void dprintAllSessions(struct dcb *);
|
||||
|
||||
@ -27,15 +27,25 @@
|
||||
* A single option may be passed to the filter, this is the name of the
|
||||
* file to which the queries are logged. A serial number is appended to this
|
||||
* name in order that each session logs to a different file.
|
||||
*
|
||||
* Date Who Description
|
||||
* 03/06/2014 Mark Riddoch Initial implementation
|
||||
* 11/06/2014 Mark Riddoch Addition of source and match parameters
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <filter.h>
|
||||
#include <modinfo.h>
|
||||
#include <modutil.h>
|
||||
#include <string.h>
|
||||
#include <skygw_utils.h>
|
||||
#include <log_manager.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <regex.h>
|
||||
#include <string.h>
|
||||
|
||||
extern int lm_enabled_logfiles_bitmask;
|
||||
|
||||
MODULE_INFO info = {
|
||||
MODULE_API_FILTER,
|
||||
@ -44,7 +54,7 @@ MODULE_INFO info = {
|
||||
"A simple query logging filter"
|
||||
};
|
||||
|
||||
static char *version_str = "V1.0.0";
|
||||
static char *version_str = "V1.1.0";
|
||||
|
||||
/*
|
||||
* The filter entry points
|
||||
@ -79,8 +89,11 @@ static FILTER_OBJECT MyObject = {
|
||||
* have a nique name.
|
||||
*/
|
||||
typedef struct {
|
||||
int sessions;
|
||||
char *filebase;
|
||||
int sessions; /* The count of sessions */
|
||||
char *filebase; /* The filemane base */
|
||||
char *source; /* The source of the client connection */
|
||||
char *match; /* Optional tet to match against */
|
||||
regex_t re; /* Compiled regex text */
|
||||
} QLA_INSTANCE;
|
||||
|
||||
/**
|
||||
@ -94,7 +107,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
DOWNSTREAM down;
|
||||
char *filename;
|
||||
int fd;
|
||||
FILE *fp;
|
||||
int active;
|
||||
} QLA_SESSION;
|
||||
|
||||
/**
|
||||
@ -143,6 +157,7 @@ static FILTER *
|
||||
createInstance(char **options, FILTER_PARAMETER **params)
|
||||
{
|
||||
QLA_INSTANCE *my_instance;
|
||||
int i;
|
||||
|
||||
if ((my_instance = calloc(1, sizeof(QLA_INSTANCE))) != NULL)
|
||||
{
|
||||
@ -150,7 +165,36 @@ QLA_INSTANCE *my_instance;
|
||||
my_instance->filebase = strdup(options[0]);
|
||||
else
|
||||
my_instance->filebase = strdup("qla");
|
||||
my_instance->source = NULL;
|
||||
my_instance->match = NULL;
|
||||
for (i = 0; params[i]; i++)
|
||||
{
|
||||
if (!strcmp(params[i]->name, "match"))
|
||||
{
|
||||
my_instance->match = strdup(params[i]->value);
|
||||
}
|
||||
else if (!strcmp(params[i]->name, "source"))
|
||||
my_instance->source = strdup(params[i]->value);
|
||||
else if (!filter_standard_parameter(params[i]->name))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"qlafilter: Unexpected parameter '%s'.\n",
|
||||
params[i]->name)));
|
||||
}
|
||||
}
|
||||
my_instance->sessions = 0;
|
||||
if (regcomp(&my_instance->re, my_instance->match, REG_ICASE))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
|
||||
"qlafilter: Invalid regular expression '%s'.\n",
|
||||
my_instance->match)));
|
||||
free(my_instance->match);
|
||||
free(my_instance->source);
|
||||
free(my_instance->filebase);
|
||||
free(my_instance);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return (FILTER *)my_instance;
|
||||
}
|
||||
@ -169,6 +213,7 @@ newSession(FILTER *instance, SESSION *session)
|
||||
{
|
||||
QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance;
|
||||
QLA_SESSION *my_session;
|
||||
char *remote;
|
||||
|
||||
if ((my_session = calloc(1, sizeof(QLA_SESSION))) != NULL)
|
||||
{
|
||||
@ -179,11 +224,18 @@ QLA_SESSION *my_session;
|
||||
free(my_session);
|
||||
return NULL;
|
||||
}
|
||||
my_session->active = 1;
|
||||
if (my_instance->source
|
||||
&& (remote = session_get_remote(session)) != NULL)
|
||||
{
|
||||
if (strcmp(remote, my_instance->source))
|
||||
my_session->active = 0;
|
||||
}
|
||||
sprintf(my_session->filename, "%s.%d", my_instance->filebase,
|
||||
my_instance->sessions);
|
||||
my_instance->sessions++;
|
||||
my_session->fd = open(my_session->filename,
|
||||
O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||
if (my_session->active)
|
||||
my_session->fp = fopen(my_session->filename, "w");
|
||||
}
|
||||
|
||||
return my_session;
|
||||
@ -202,7 +254,8 @@ closeSession(FILTER *instance, void *session)
|
||||
{
|
||||
QLA_SESSION *my_session = (QLA_SESSION *)session;
|
||||
|
||||
close(my_session->fd);
|
||||
if (my_session->active && my_session->fp)
|
||||
fclose(my_session->fp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -250,22 +303,27 @@ QLA_SESSION *my_session = (QLA_SESSION *)session;
|
||||
static int
|
||||
routeQuery(FILTER *instance, void *session, GWBUF *queue)
|
||||
{
|
||||
QLA_INSTANCE *my_instance = (QLA_INSTANCE *)instance;
|
||||
QLA_SESSION *my_session = (QLA_SESSION *)session;
|
||||
char *ptr, t_buf[40];
|
||||
char *ptr;
|
||||
int length;
|
||||
struct tm t;
|
||||
struct timeval tv;
|
||||
|
||||
if (modutil_extract_SQL(queue, &ptr, &length))
|
||||
if (my_session->active && modutil_extract_SQL(queue, &ptr, &length))
|
||||
{
|
||||
if (my_instance->match == NULL ||
|
||||
regexec(&my_instance->re, ptr, 0, NULL, 0) == 0)
|
||||
{
|
||||
gettimeofday(&tv, NULL);
|
||||
localtime_r(&tv.tv_sec, &t);
|
||||
sprintf(t_buf, "%02d:%02d:%02d.%-3d %d/%02d/%d, ",
|
||||
fprintf(my_session->fp,
|
||||
"%02d:%02d:%02d.%-3d %d/%02d/%d, ",
|
||||
t.tm_hour, t.tm_min, t.tm_sec, (int)(tv.tv_usec / 1000),
|
||||
t.tm_mday, t.tm_mon + 1, 1900 + t.tm_year);
|
||||
write(my_session->fd, t_buf, strlen(t_buf));
|
||||
write(my_session->fd, ptr, length);
|
||||
write(my_session->fd, "\n", 1);
|
||||
fwrite(ptr, sizeof(char), length, my_session->fp);
|
||||
fwrite("\n", sizeof(char), 1, my_session->fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass the query downstream */
|
||||
|
||||
Reference in New Issue
Block a user