diff options
-rw-r--r-- | utility/Makefile.in | 4 | ||||
-rw-r--r-- | utility/ap_pcre.h | 2 | ||||
-rw-r--r-- | utility/config.c | 46 | ||||
-rw-r--r-- | utility/config.h | 9 | ||||
-rw-r--r-- | utility/database.c | 95 | ||||
-rw-r--r-- | utility/database.h | 12 | ||||
-rw-r--r-- | utility/logparse.c | 89 | ||||
-rw-r--r-- | utility/logparse.h | 7 | ||||
-rw-r--r-- | utility/mod_log_sql.conf | 32 | ||||
-rw-r--r-- | utility/shell.c | 10 |
10 files changed, 245 insertions, 61 deletions
diff --git a/utility/Makefile.in b/utility/Makefile.in index 69a746c..eeb26b8 100644 --- a/utility/Makefile.in +++ b/utility/Makefile.in | |||
@@ -18,8 +18,8 @@ STD_DIST = Makefile.in | |||
18 | 18 | ||
19 | DISTFILES = $(STD_DIST) $(EXTRA_DIST) $(SOURCES) $(HEADERS) | 19 | DISTFILES = $(STD_DIST) $(EXTRA_DIST) $(SOURCES) $(HEADERS) |
20 | 20 | ||
21 | SOURCES = shell.c config.c logparse.c ap_pcre.c util.c | 21 | SOURCES = shell.c config.c logparse.c ap_pcre.c util.c database.c |
22 | HEADERS = shell.h config.h logparse.h ap_pcre.h util.h | 22 | HEADERS = shell.h config.h logparse.h ap_pcre.h util.h database.h |
23 | OBJECTS = $(SOURCES:.c=.o) | 23 | OBJECTS = $(SOURCES:.c=.o) |
24 | DEPS = $(SOURCES:.c=.d) | 24 | DEPS = $(SOURCES:.c=.d) |
25 | TARGETS = mod_log_sql | 25 | TARGETS = mod_log_sql |
diff --git a/utility/ap_pcre.h b/utility/ap_pcre.h index a851d29..e817dc2 100644 --- a/utility/ap_pcre.h +++ b/utility/ap_pcre.h | |||
@@ -73,6 +73,8 @@ extern "C" { | |||
73 | #define AP_REG_EXTENDED (0) /** unused */ | 73 | #define AP_REG_EXTENDED (0) /** unused */ |
74 | #define AP_REG_NOSUB (0) /** unused */ | 74 | #define AP_REG_NOSUB (0) /** unused */ |
75 | 75 | ||
76 | #define AP_MAX_REG_MATCH 10 | ||
77 | |||
76 | /* Error values: */ | 78 | /* Error values: */ |
77 | enum { | 79 | enum { |
78 | AP_REG_ASSERT = 1, /** internal error ? */ | 80 | AP_REG_ASSERT = 1, /** internal error ? */ |
diff --git a/utility/config.c b/utility/config.c index 847d474..d3a6ca5 100644 --- a/utility/config.c +++ b/utility/config.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "apr_file_io.h" | 3 | #include "apr_file_io.h" |
4 | #include "apr_strings.h" | 4 | #include "apr_strings.h" |
5 | #include "apr_hash.h" | 5 | #include "apr_hash.h" |
6 | #include "apr_uri.h" | ||
6 | 7 | ||
7 | #include "shell.h" | 8 | #include "shell.h" |
8 | #include "config.h" | 9 | #include "config.h" |
@@ -65,18 +66,6 @@ static apr_status_t config_set_loglevel(config_t *cfg, config_opt_t *opt, | |||
65 | return APR_SUCCESS; | 66 | return APR_SUCCESS; |
66 | } | 67 | } |
67 | 68 | ||
68 | static apr_status_t config_set_dbconnect(config_t *cfg, config_opt_t *opt, | ||
69 | int argc, const char **argv) | ||
70 | { | ||
71 | return APR_SUCCESS; | ||
72 | } | ||
73 | |||
74 | static apr_status_t config_set_dbparam(config_t *cfg, config_opt_t *opt, | ||
75 | int argc, const char **argv) | ||
76 | { | ||
77 | return APR_SUCCESS; | ||
78 | } | ||
79 | |||
80 | static apr_status_t config_set_inputfile(config_t *cfg, config_opt_t *opt, | 69 | static apr_status_t config_set_inputfile(config_t *cfg, config_opt_t *opt, |
81 | int argc, const char **argv) | 70 | int argc, const char **argv) |
82 | { | 71 | { |
@@ -123,12 +112,12 @@ static apr_status_t config_set_output_field(config_t *cfg, config_opt_t *opt, | |||
123 | config_output_field_t *field; | 112 | config_output_field_t *field; |
124 | char *type, *size, *temp; | 113 | char *type, *size, *temp; |
125 | 114 | ||
126 | if (argc < 4) | 115 | if (argc < 5) |
127 | return APR_EINVAL; | 116 | return APR_EINVAL; |
128 | field = (config_output_field_t *)apr_array_push(cfg->output_fields); | 117 | field = (config_output_field_t *)apr_array_push(cfg->output_fields); |
129 | field->field = apr_pstrdup(cfg->pool, argv[1]); | 118 | field->field = apr_pstrdup(cfg->pool, argv[1]); |
130 | field->source = apr_pstrdup(cfg->pool, argv[3]); | 119 | field->source = apr_pstrdup(cfg->pool, argv[4]); |
131 | 120 | field->def = apr_pstrdup(cfg->pool, argv[3]); | |
132 | type = size = apr_pstrdup(cfg->pool, argv[2]); | 121 | type = size = apr_pstrdup(cfg->pool, argv[2]); |
133 | while (*size!='\0' && *size!='(') | 122 | while (*size!='\0' && *size!='(') |
134 | size++; | 123 | size++; |
@@ -156,13 +145,13 @@ static apr_status_t config_set_output_field(config_t *cfg, config_opt_t *opt, | |||
156 | } | 145 | } |
157 | 146 | ||
158 | // Has a function | 147 | // Has a function |
159 | if (argc > 4) { | 148 | if (argc > 5) { |
160 | int i; | 149 | int i; |
161 | field->fname = apr_pstrdup(cfg->pool, argv[4]); | 150 | field->fname = apr_pstrdup(cfg->pool, argv[5]); |
162 | field->func = parser_get_func(field->fname); | 151 | field->func = parser_get_func(field->fname); |
163 | field->args = apr_pcalloc(cfg->pool, sizeof(char *) * (argc-4+1)); | 152 | field->args = apr_pcalloc(cfg->pool, sizeof(char *) * (argc-5+1)); |
164 | for (i=5; i<=argc; i++) { | 153 | for (i=6; i<=argc; i++) { |
165 | field->args[i-5] = apr_pstrdup(cfg->pool, argv[i]); | 154 | field->args[i-6] = apr_pstrdup(cfg->pool, argv[i]); |
166 | } | 155 | } |
167 | } | 156 | } |
168 | 157 | ||
@@ -208,6 +197,9 @@ void config_dump(config_t *cfg) | |||
208 | 197 | ||
209 | printf("InputDir: %s\n", cfg->input_dir); | 198 | printf("InputDir: %s\n", cfg->input_dir); |
210 | 199 | ||
200 | printf("DB Driver: %s\n", cfg->dbdriver); | ||
201 | printf("DB Params: %s\n", cfg->dbparams); | ||
202 | |||
211 | printf("Table: %s\n", cfg->table); | 203 | printf("Table: %s\n", cfg->table); |
212 | printf("Transactions: %d\n", cfg->transactions); | 204 | printf("Transactions: %d\n", cfg->transactions); |
213 | printf("MachineID: %s\n", cfg->machineid); | 205 | printf("MachineID: %s\n", cfg->machineid); |
@@ -231,7 +223,9 @@ void config_dump(config_t *cfg) | |||
231 | printf("Output Fields:\n"); | 223 | printf("Output Fields:\n"); |
232 | fields = (config_output_field_t *)cfg->output_fields->elts; | 224 | fields = (config_output_field_t *)cfg->output_fields->elts; |
233 | for (i=0; i<cfg->output_fields->nelts; i++) { | 225 | for (i=0; i<cfg->output_fields->nelts; i++) { |
234 | printf(">> %s %s(%d): %s", fields[i].field, logsql_field_datatyeName(fields[i].datatype), fields[i].size, fields[i].source); | 226 | printf(">> %s %s(%d) DEFAULT '%s': %s", fields[i].field, |
227 | logsql_field_datatyeName(fields[i].datatype), | ||
228 | fields[i].size, fields[i].def, fields[i].source); | ||
235 | if (fields[i].func) { | 229 | if (fields[i].func) { |
236 | printf(" :: %s(", fields[i].fname); | 230 | printf(" :: %s(", fields[i].fname); |
237 | if (fields[i].args) { | 231 | if (fields[i].args) { |
@@ -280,11 +274,10 @@ void config_init(apr_pool_t *p) | |||
280 | config_add_option(p, "InputFile", "Parse only this file", | 274 | config_add_option(p, "InputFile", "Parse only this file", |
281 | config_set_inputfile, NULL); | 275 | config_set_inputfile, NULL); |
282 | 276 | ||
283 | config_add_option(p, "DBConnect", | 277 | config_add_option(p, "DBDDriver", "DBD Driver to use", |
284 | "DB Connection information type://user:pass@hostname/database", | 278 | config_set_string, (void *)APR_OFFSETOF(config_t, dbdriver)); |
285 | config_set_dbconnect, NULL); | 279 | config_add_option(p, "DBDParams", "DBD Connection Parameters", |
286 | config_add_option(p, "DBParam", "DB Connection Parameter", | 280 | config_set_string, (void *)APR_OFFSETOF(config_t, dbparams)); |
287 | config_set_dbparam, NULL); | ||
288 | config_add_option(p, "Table", "Table to import the log to", | 281 | config_add_option(p, "Table", "Table to import the log to", |
289 | config_set_string, (void *)APR_OFFSETOF(config_t, table)); | 282 | config_set_string, (void *)APR_OFFSETOF(config_t, table)); |
290 | config_add_option(p, "UseTransactions", "Enable Transactions?", | 283 | config_add_option(p, "UseTransactions", "Enable Transactions?", |
@@ -330,7 +323,6 @@ config_t *config_create(apr_pool_t *p) | |||
330 | cfg->summary = 1; | 323 | cfg->summary = 1; |
331 | cfg->transactions = 1; | 324 | cfg->transactions = 1; |
332 | cfg->input_files = apr_array_make(cfg->pool, 10, sizeof(char *)); | 325 | cfg->input_files = apr_array_make(cfg->pool, 10, sizeof(char *)); |
333 | cfg->dbconfig = apr_table_make(cfg->pool, 5); | ||
334 | cfg->log_formats = apr_hash_make(cfg->pool); | 326 | cfg->log_formats = apr_hash_make(cfg->pool); |
335 | cfg->output_fields = apr_array_make(cfg->pool, 10, | 327 | cfg->output_fields = apr_array_make(cfg->pool, 10, |
336 | sizeof(config_output_field_t)); | 328 | sizeof(config_output_field_t)); |
diff --git a/utility/config.h b/utility/config.h index 67f8ea5..0e80856 100644 --- a/utility/config.h +++ b/utility/config.h | |||
@@ -4,7 +4,6 @@ | |||
4 | #include "apr_tables.h" | 4 | #include "apr_tables.h" |
5 | #include "apr_hash.h" | 5 | #include "apr_hash.h" |
6 | #include "apr_file_io.h" | 6 | #include "apr_file_io.h" |
7 | |||
8 | #include "ap_pcre.h" | 7 | #include "ap_pcre.h" |
9 | 8 | ||
10 | typedef enum { | 9 | typedef enum { |
@@ -14,6 +13,7 @@ typedef enum { | |||
14 | LOGLEVEL_DEBUG = 3, | 13 | LOGLEVEL_DEBUG = 3, |
15 | } loglevel_e; | 14 | } loglevel_e; |
16 | 15 | ||
16 | typedef struct config_dbd_t config_dbd_t; | ||
17 | typedef struct config_t config_t; | 17 | typedef struct config_t config_t; |
18 | struct config_t { | 18 | struct config_t { |
19 | /** the structures pool (to ease function arguments) */ | 19 | /** the structures pool (to ease function arguments) */ |
@@ -32,7 +32,10 @@ struct config_t { | |||
32 | apr_array_header_t *input_files; | 32 | apr_array_header_t *input_files; |
33 | 33 | ||
34 | /** db connection configuration */ | 34 | /** db connection configuration */ |
35 | apr_table_t *dbconfig; | 35 | const char *dbdriver; |
36 | const char *dbparams; | ||
37 | config_dbd_t *dbconn; | ||
38 | |||
36 | /** Logging table */ | 39 | /** Logging table */ |
37 | const char *table; | 40 | const char *table; |
38 | /** Use transactons */ | 41 | /** Use transactons */ |
@@ -111,10 +114,12 @@ struct config_output_field_t { | |||
111 | const char *field; | 114 | const char *field; |
112 | logsql_field_datatype datatype; | 115 | logsql_field_datatype datatype; |
113 | apr_size_t size; | 116 | apr_size_t size; |
117 | const char *def; | ||
114 | const char *source; | 118 | const char *source; |
115 | const char *fname; | 119 | const char *fname; |
116 | void *func; | 120 | void *func; |
117 | const char **args; | 121 | const char **args; |
122 | void *data; | ||
118 | }; | 123 | }; |
119 | 124 | ||
120 | #define CHECK_YESNO(c) ((!strcasecmp(c,"on") || !strcasecmp(c,"yes")) ? 1 : 0) | 125 | #define CHECK_YESNO(c) ((!strcasecmp(c,"on") || !strcasecmp(c,"yes")) ? 1 : 0) |
diff --git a/utility/database.c b/utility/database.c index 5fece50..e7650aa 100644 --- a/utility/database.c +++ b/utility/database.c | |||
@@ -1,2 +1,97 @@ | |||
1 | #include "database.h" | 1 | #include "database.h" |
2 | #include "apu.h" | ||
3 | #include "apr_dbd.h" | ||
4 | #include "apr_strings.h" | ||
2 | 5 | ||
6 | struct config_dbd_t { | ||
7 | const apr_dbd_driver_t *driver; | ||
8 | apr_dbd_t *dbd; | ||
9 | apr_dbd_prepared_t *stmt; | ||
10 | const char **args; | ||
11 | }; | ||
12 | |||
13 | void database_init(apr_pool_t *p) | ||
14 | { | ||
15 | apr_dbd_init(p); | ||
16 | } | ||
17 | |||
18 | apr_status_t database_connect(config_t *cfg) | ||
19 | { | ||
20 | apr_status_t rv; | ||
21 | if (!cfg->dbconn) { | ||
22 | cfg->dbconn = apr_palloc(cfg->pool, sizeof(config_dbd_t)); | ||
23 | } | ||
24 | rv = apr_dbd_get_driver(cfg->pool, cfg->dbdriver, &(cfg->dbconn->driver)); | ||
25 | if (rv) | ||
26 | return rv; | ||
27 | |||
28 | rv = apr_dbd_open(cfg->dbconn->driver, cfg->pool, cfg->dbparams, | ||
29 | &(cfg->dbconn->dbd)); | ||
30 | if (rv) | ||
31 | return rv; | ||
32 | |||
33 | return APR_SUCCESS; | ||
34 | } | ||
35 | |||
36 | apr_status_t database_disconnect(config_t *cfg) | ||
37 | { | ||
38 | return apr_dbd_close(cfg->dbconn->driver, cfg->dbconn->dbd); | ||
39 | } | ||
40 | |||
41 | apr_status_t database_insert(config_t *cfg, apr_pool_t *p, apr_table_t *data) | ||
42 | { | ||
43 | apr_status_t rv; | ||
44 | int f, nfs; | ||
45 | config_output_field_t *ofields; | ||
46 | ofields = (config_output_field_t *)cfg->output_fields->elts; | ||
47 | nfs = cfg->output_fields->nelts; | ||
48 | // Prepare statement | ||
49 | if (!cfg->dbconn->stmt) { | ||
50 | char *sql; | ||
51 | int i; | ||
52 | struct iovec *vec; | ||
53 | vec = apr_palloc(p, (nfs*2 + 5) * sizeof(struct iovec)); | ||
54 | sql = apr_palloc(p, (nfs*3)); | ||
55 | vec[0].iov_base = "INSERT INTO "; | ||
56 | vec[0].iov_len = 12; | ||
57 | vec[1].iov_base = (void *)cfg->table; | ||
58 | vec[1].iov_len = strlen(cfg->table); | ||
59 | vec[2].iov_base = " ("; | ||
60 | vec[2].iov_len = 2; | ||
61 | for (i=3, f=0; f<nfs; f++, i+=2) { | ||
62 | vec[i].iov_base = (void *)ofields[f].field; | ||
63 | vec[i].iov_len = strlen(vec[i].iov_base); | ||
64 | vec[i+1].iov_base = ","; | ||
65 | vec[i+1].iov_len = 1; | ||
66 | memcpy(&sql[f*3], "%s,", 3); | ||
67 | } | ||
68 | sql[nfs*3-1] = '\0'; | ||
69 | vec[i-1].iov_base = ") VALUES ("; | ||
70 | vec[i-1].iov_len = 10; | ||
71 | vec[i].iov_base = sql; | ||
72 | vec[i].iov_len = nfs*3-1; | ||
73 | vec[i+1].iov_base = ")"; | ||
74 | vec[i+1].iov_len = 1; | ||
75 | sql = apr_pstrcatv(p, vec, i+2, NULL); | ||
76 | printf("SQL: %s\n", sql); | ||
77 | cfg->dbconn->args = apr_palloc(cfg->pool, nfs * sizeof(char *)); | ||
78 | rv = apr_dbd_prepare(cfg->dbconn->driver, cfg->pool, cfg->dbconn->dbd, | ||
79 | sql, "INSERT", &(cfg->dbconn->stmt)); | ||
80 | if (rv) { | ||
81 | printf("DB Error: %s\n", apr_dbd_error(cfg->dbconn->driver, | ||
82 | cfg->dbconn->dbd, rv)); | ||
83 | return rv; | ||
84 | } | ||
85 | } | ||
86 | for (f=0; f<nfs; f++) { | ||
87 | cfg->dbconn->args[f] = apr_table_get(data, ofields[f].field); | ||
88 | } | ||
89 | rv = apr_dbd_pquery(cfg->dbconn->driver, p, cfg->dbconn->dbd, &f, | ||
90 | cfg->dbconn->stmt, nfs, cfg->dbconn->args); | ||
91 | if (rv) { | ||
92 | printf("DB Error: %s\n", apr_dbd_error(cfg->dbconn->driver, | ||
93 | cfg->dbconn->dbd, rv)); | ||
94 | return rv; | ||
95 | } | ||
96 | return APR_SUCCESS; | ||
97 | } | ||
diff --git a/utility/database.h b/utility/database.h index 9fc4844..fd24994 100644 --- a/utility/database.h +++ b/utility/database.h | |||
@@ -1,4 +1,16 @@ | |||
1 | #ifndef DATABASE_H_ | 1 | #ifndef DATABASE_H_ |
2 | #define DATABASE_H_ | 2 | #define DATABASE_H_ |
3 | 3 | ||
4 | #include "apr_pools.h" | ||
5 | |||
6 | #include "config.h" | ||
7 | |||
8 | void database_init(apr_pool_t *p); | ||
9 | |||
10 | apr_status_t database_connect(config_t *cfg); | ||
11 | |||
12 | apr_status_t database_disconnect(config_t *cfg); | ||
13 | |||
14 | apr_status_t database_insert(config_t *cfg, apr_pool_t *p, apr_table_t *data); | ||
15 | |||
4 | #endif /*DATABASE_H_*/ | 16 | #endif /*DATABASE_H_*/ |
diff --git a/utility/logparse.c b/utility/logparse.c index 4d823ce..e9ca340 100644 --- a/utility/logparse.c +++ b/utility/logparse.c | |||
@@ -2,16 +2,70 @@ | |||
2 | #include "apr_file_info.h" | 2 | #include "apr_file_info.h" |
3 | #include "apr_file_io.h" | 3 | #include "apr_file_io.h" |
4 | #include "apr_strings.h" | 4 | #include "apr_strings.h" |
5 | #include "apr_time.h" | ||
6 | |||
7 | #include "time.h" | ||
8 | #include "stdlib.h" | ||
5 | 9 | ||
6 | #include "util.h" | 10 | #include "util.h" |
11 | #include "ap_pcre.h" | ||
12 | #include "database.h" | ||
13 | |||
7 | 14 | ||
8 | apr_hash_t *g_parser_funcs; | 15 | apr_hash_t *g_parser_funcs; |
9 | 16 | ||
10 | static apr_status_t parser_func_regexmatch(config_t *cfg, const char *data, | 17 | static apr_status_t parser_func_regexmatch(apr_pool_t *p, config_t *cfg, |
11 | int argc, const char **argv) | 18 | config_output_field_t *field, const char *value, char **ret) |
12 | { | 19 | { |
20 | struct { | ||
21 | ap_regex_t *rx; | ||
22 | const char *substr; | ||
23 | } *data; | ||
24 | ap_regmatch_t regm[AP_MAX_REG_MATCH]; | ||
25 | // Check if a regular expression configured | ||
26 | if (!field->args[0]) return APR_EINVAL; | ||
27 | if (!field->data) { | ||
28 | // pre compile the regex | ||
29 | data = apr_palloc(cfg->pool, sizeof(ap_regex_t)+sizeof(const char *)); | ||
30 | data->rx = ap_pregcomp(cfg->pool, field->args[0], | ||
31 | AP_REG_EXTENDED|AP_REG_ICASE); | ||
32 | if (field->args[1]) { | ||
33 | data->substr = field->args[1]; | ||
34 | } else { | ||
35 | data->substr = "$1"; | ||
36 | } | ||
37 | if (!data->rx) return APR_EINVAL; | ||
38 | field->data = data; | ||
39 | } else data = field->data; | ||
40 | |||
41 | if (!ap_regexec(data->rx, value, AP_MAX_REG_MATCH, regm, 0)) { | ||
42 | *ret = ap_pregsub(p, data->substr, value, AP_MAX_REG_MATCH, regm); | ||
43 | } | ||
44 | //printf("We matched %s against %s to %s\n",value, field->args[0], *ret); | ||
13 | return APR_SUCCESS; | 45 | return APR_SUCCESS; |
14 | } | 46 | } |
47 | |||
48 | static apr_status_t parser_func_totimestamp(apr_pool_t *p, config_t *cfg, | ||
49 | config_output_field_t *field, const char *value, char **ret) | ||
50 | { | ||
51 | time_t time; | ||
52 | struct tm ts; | ||
53 | |||
54 | |||
55 | strptime(value, "%d/%b/%Y:%H:%M:%S %z", &ts); | ||
56 | time = mktime(&ts); | ||
57 | |||
58 | *ret = apr_itoa(p, time); | ||
59 | return APR_SUCCESS; | ||
60 | } | ||
61 | |||
62 | static apr_status_t parser_func_machineid(apr_pool_t *p, config_t *cfg, | ||
63 | config_output_field_t *field, const char *value, char **ret) | ||
64 | { | ||
65 | *ret = apr_pstrdup(p,cfg->machineid); | ||
66 | return APR_SUCCESS; | ||
67 | } | ||
68 | |||
15 | parser_func_t parser_get_func(const char *name) | 69 | parser_func_t parser_get_func(const char *name) |
16 | { | 70 | { |
17 | return apr_hash_get(g_parser_funcs, name, APR_HASH_KEY_STRING); | 71 | return apr_hash_get(g_parser_funcs, name, APR_HASH_KEY_STRING); |
@@ -29,6 +83,8 @@ static void parser_add_func(apr_pool_t *p, const char *const name, | |||
29 | void parser_init(apr_pool_t *p) | 83 | void parser_init(apr_pool_t *p) |
30 | { | 84 | { |
31 | parser_add_func(p, "regexmatch", parser_func_regexmatch); | 85 | parser_add_func(p, "regexmatch", parser_func_regexmatch); |
86 | parser_add_func(p, "totimestamp", parser_func_totimestamp); | ||
87 | parser_add_func(p, "machineid", parser_func_machineid); | ||
32 | } | 88 | } |
33 | 89 | ||
34 | void parser_find_logs(config_t *cfg) | 90 | void parser_find_logs(config_t *cfg) |
@@ -212,7 +268,7 @@ apr_status_t parse_logfile(config_t *cfg, const char *filename) | |||
212 | line_chomp(buff); | 268 | line_chomp(buff); |
213 | 269 | ||
214 | apr_pool_clear(targp); | 270 | apr_pool_clear(targp); |
215 | tokenize_logline(buff, &targv, targp, 1); | 271 | tokenize_logline(buff, &targv, targp, 0); |
216 | targc = 0; | 272 | targc = 0; |
217 | while (targv[targc]) targc++; | 273 | while (targv[targc]) targc++; |
218 | /** @todo Run Line Filters here */ | 274 | /** @todo Run Line Filters here */ |
@@ -239,6 +295,7 @@ apr_status_t parse_processline(apr_pool_t *ptemp, config_t *cfg, char **argv, in | |||
239 | config_output_field_t *ofields; | 295 | config_output_field_t *ofields; |
240 | apr_table_t *datain; | 296 | apr_table_t *datain; |
241 | apr_table_t *dataout; | 297 | apr_table_t *dataout; |
298 | apr_status_t rv; | ||
242 | int i; | 299 | int i; |
243 | 300 | ||
244 | fmt = apr_hash_get(cfg->log_formats, cfg->logformat, APR_HASH_KEY_STRING); | 301 | fmt = apr_hash_get(cfg->log_formats, cfg->logformat, APR_HASH_KEY_STRING); |
@@ -257,20 +314,30 @@ apr_status_t parse_processline(apr_pool_t *ptemp, config_t *cfg, char **argv, in | |||
257 | // Convert input fields to output fields | 314 | // Convert input fields to output fields |
258 | ofields = (config_output_field_t *)cfg->output_fields->elts; | 315 | ofields = (config_output_field_t *)cfg->output_fields->elts; |
259 | for (i=0; i<cfg->output_fields->nelts; i++) { | 316 | for (i=0; i<cfg->output_fields->nelts; i++) { |
260 | const char *t; | 317 | const char *val; |
318 | val = apr_table_get(datain, ofields[i].source); | ||
319 | // If we can't find the source field just continue | ||
320 | if (!val && !(ofields[i].source[0]=='\0' && ofields[i].func)) { | ||
321 | apr_table_setn(dataout, ofields[i].field, ofields[i].def); | ||
322 | continue; | ||
323 | } | ||
261 | if (!ofields[i].func) { | 324 | if (!ofields[i].func) { |
262 | t = apr_table_get(datain, ofields[i].source); | 325 | apr_table_setn(dataout,ofields[i].field, val); |
263 | if (!t) { | 326 | //printf("S: %s = %s\n",ofields[i].field, val); |
264 | return APR_EINVAL; | ||
265 | } | ||
266 | apr_table_setn(dataout,ofields[i].field, t); | ||
267 | printf("S: %s = %s\n",ofields[i].source, t); | ||
268 | } else { | 327 | } else { |
269 | printf("S: %s, F: %p\n",ofields[i].source, ofields[i].func); | 328 | char *ret = NULL; |
329 | rv = ((parser_func_t)ofields[i].func)(ptemp, cfg, &ofields[i], val, | ||
330 | &ret); | ||
331 | if (rv) return rv; | ||
332 | apr_table_setn(dataout, ofields[i].field, ret); | ||
333 | //printf("S: %s = %s\n",ofields[i].field, ret); | ||
270 | } | 334 | } |
271 | } | 335 | } |
272 | 336 | ||
273 | /** @todo Run Post Filters here */ | 337 | /** @todo Run Post Filters here */ |
274 | 338 | ||
339 | // Process DB Query | ||
340 | rv = database_insert(cfg, ptemp, dataout); | ||
341 | if (rv) return rv; | ||
275 | return APR_SUCCESS; | 342 | return APR_SUCCESS; |
276 | } | 343 | } |
diff --git a/utility/logparse.h b/utility/logparse.h index ebabf56..53b376b 100644 --- a/utility/logparse.h +++ b/utility/logparse.h | |||
@@ -3,8 +3,8 @@ | |||
3 | 3 | ||
4 | #include "config.h" | 4 | #include "config.h" |
5 | 5 | ||
6 | typedef apr_status_t (*parser_func_t)(config_t *cfg, const char *data, | 6 | typedef apr_status_t (*parser_func_t)(apr_pool_t *p, config_t *cfg, |
7 | int argc, const char **argv); | 7 | config_output_field_t *field, const char *value, char **ret); |
8 | 8 | ||
9 | parser_func_t parser_get_func(const char *name); | 9 | parser_func_t parser_get_func(const char *name); |
10 | 10 | ||
@@ -14,6 +14,7 @@ void parser_find_logs(config_t *cfg); | |||
14 | 14 | ||
15 | apr_status_t parse_logfile(config_t *cfg, const char *filename); | 15 | apr_status_t parse_logfile(config_t *cfg, const char *filename); |
16 | 16 | ||
17 | apr_status_t parse_processline(apr_pool_t *ptemp, config_t *cfg, char **argv, int argc); | 17 | apr_status_t parse_processline(apr_pool_t *ptemp, config_t *cfg, char **argv, |
18 | int argc); | ||
18 | 19 | ||
19 | #endif /*LOGPARSE_H_*/ | 20 | #endif /*LOGPARSE_H_*/ |
diff --git a/utility/mod_log_sql.conf b/utility/mod_log_sql.conf index 72f0205..9730983 100644 --- a/utility/mod_log_sql.conf +++ b/utility/mod_log_sql.conf | |||
@@ -1,8 +1,9 @@ | |||
1 | InputDirectory ./logs | 1 | InputDirectory ./logs |
2 | ErrorLog ./error_log | 2 | ErrorLog ./error_log |
3 | DBConnect mysql://username:host@server/database | 3 | DBDDriver mysql |
4 | DBDParams "host=localhost;user=root;dbname=apache_log" | ||
4 | DBParam socketfile /tmp/mysql.sock | 5 | DBParam socketfile /tmp/mysql.sock |
5 | Table apache_logs | 6 | Table access_log |
6 | MachineID 7of9 | 7 | MachineID 7of9 |
7 | UseTransactions on | 8 | UseTransactions on |
8 | LogLevel notice | 9 | LogLevel notice |
@@ -34,17 +35,18 @@ Linefilter - "BAD" | |||
34 | PreFilter request - "GET \/images" | 35 | PreFilter request - "GET \/images" |
35 | PostFilter request_method "GET" | 36 | PostFilter request_method "GET" |
36 | 37 | ||
37 | # Usage field datatype(size) source [function [param]...] | 38 | # Usage field datatype(size) default source [function [param]...] |
38 | OutputField bytes_sent int bytes_sent | 39 | OutputField bytes_sent int 0 bytes_sent |
39 | OutputField request_protocol varchar(10) request regexmatch "(HTTP\/[\d\.]+)$" | 40 | OutputField request_protocol varchar(10) "" request regexmatch "(HTTP/[\\d\\.]+)$" |
40 | OutputField remote_host varchar(50) remhost | 41 | OutputField remote_host varchar(50) "" remhost |
41 | OutputField request_method varchar(25) request regexmatch "^(\w+)" | 42 | OutputField request_method varchar(25) "" request regexmatch "^(\\w+)" |
42 | OutputField time_stamp int date totimestamp | 43 | OutputField time_stamp int 0 date totimestamp |
43 | OutputField status smallint status | 44 | OutputField status smallint 0 status |
44 | OutputField request_uri varchar(255) request regexmatch "^\w+ (.+) \w+\.[\d\.]+$" | 45 | OutputField request_uri varchar(255) "" request regexmatch "^\\w+ (.+) \\w+/[\\d\\.]+$" |
45 | OutputField remote_user varchar(50) user | 46 | OutputField remote_user varchar(50) "" user |
46 | OutputField remote_logname varchar(50) ident | 47 | OutputField remote_logname varchar(50) "" ident |
47 | OutputField remote_time char(28) date | 48 | OutputField request_time char(28) "" date regexmatch ".+" "[$0]" |
48 | #Only used for Combined log input, if standard CLF input, they are ignored | 49 | #Only used for Combined log input, if standard CLF input, they are ignored |
49 | OutputField agent varchar(255) agent | 50 | OutputField agent varchar(255) "" agent |
50 | OutputField referer varchar(255) referer | 51 | OutputField referer varchar(255) "" referer |
52 | OutputField machine_id varchar(25) "" "" machineid | ||
diff --git a/utility/shell.c b/utility/shell.c index eaa7098..94cca35 100644 --- a/utility/shell.c +++ b/utility/shell.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "shell.h" | 9 | #include "shell.h" |
10 | #include "config.h" | 10 | #include "config.h" |
11 | #include "logparse.h" | 11 | #include "logparse.h" |
12 | #include "database.h" | ||
12 | 13 | ||
13 | const apr_getopt_option_t _opt_config[] = { | 14 | const apr_getopt_option_t _opt_config[] = { |
14 | {"machineid", 'm', 1, "Machine ID for the log file"}, | 15 | {"machineid", 'm', 1, "Machine ID for the log file"}, |
@@ -122,9 +123,11 @@ int main(int argc, const char *const argv[]) | |||
122 | exit(1); | 123 | exit(1); |
123 | } | 124 | } |
124 | 125 | ||
125 | // Process configuration file | 126 | // Initialize sub systems |
126 | parser_init(pool); | 127 | parser_init(pool); |
127 | config_init(pool); | 128 | config_init(pool); |
129 | database_init(pool); | ||
130 | // Process configuration file | ||
128 | base = config_create(pool); | 131 | base = config_create(pool); |
129 | rv = config_read(base, apr_table_get(args,"Config"), args); | 132 | rv = config_read(base, apr_table_get(args,"Config"), args); |
130 | apr_pool_destroy(ptemp); | 133 | apr_pool_destroy(ptemp); |
@@ -138,6 +141,10 @@ int main(int argc, const char *const argv[]) | |||
138 | 141 | ||
139 | // Find files and parse | 142 | // Find files and parse |
140 | parser_find_logs(base); | 143 | parser_find_logs(base); |
144 | if ((rv = database_connect(base))) { | ||
145 | printf("Error Connecting to Database: %d\n",rv); | ||
146 | exit(1); | ||
147 | } | ||
141 | if (!apr_is_empty_array(base->input_files)) { | 148 | if (!apr_is_empty_array(base->input_files)) { |
142 | char **filelist; | 149 | char **filelist; |
143 | int f, l; | 150 | int f, l; |
@@ -149,5 +156,6 @@ int main(int argc, const char *const argv[]) | |||
149 | } else { | 156 | } else { |
150 | printf("No input files\n"); | 157 | printf("No input files\n"); |
151 | } | 158 | } |
159 | database_disconnect(base); | ||
152 | return 0; | 160 | return 0; |
153 | } | 161 | } |