summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Edward Rudd 2008-10-25 04:25:56 +0000
committerGravatar Edward Rudd 2008-10-25 04:25:56 +0000
commitcaae8dcfed1462cb19c82f99087e6fe2ba3d407c (patch)
treec575ead091166c6674111b4d214e87487f38e991
parent19bbdd68a491721dd4aeff7cacea51148ce3a9b9 (diff)
implemented logging
added better error messages for DB connections fix several segfaults
-rw-r--r--utility/config.c23
-rw-r--r--utility/config.h12
-rw-r--r--utility/database.c24
-rw-r--r--utility/logparse.c61
-rw-r--r--utility/mod_log_sql.conf4
-rw-r--r--utility/shell.c52
-rw-r--r--utility/util.c31
-rw-r--r--utility/util.h2
8 files changed, 132 insertions, 77 deletions
diff --git a/utility/config.c b/utility/config.c
index ccdc6e5..b1e7585 100644
--- a/utility/config.c
+++ b/utility/config.c
@@ -41,12 +41,10 @@ static apr_status_t config_set_loglevel(config_t *cfg, config_opt_t *opt,
41 return APR_EINVAL; 41 return APR_EINVAL;
42 if (!strcasecmp(argv[1], "error")) { 42 if (!strcasecmp(argv[1], "error")) {
43 cfg->loglevel = LOGLEVEL_ERROR; 43 cfg->loglevel = LOGLEVEL_ERROR;
44 } else if (!strcasecmp(argv[1], "warn")) { 44 } else if (!strcasecmp(argv[1], "notice")) {
45 cfg->loglevel = LOGLEVEL_WARN; 45 cfg->loglevel = LOGLEVEL_NOTICE;
46 } else if (!strcasecmp(argv[1], "debug")) { 46 } else if (!strcasecmp(argv[1], "debug")) {
47 cfg->loglevel = LOGLEVEL_DEBUG; 47 cfg->loglevel = LOGLEVEL_DEBUG;
48 } else if (!strcasecmp(argv[1], "quiet")) {
49 cfg->loglevel = LOGLEVEL_QUIET;
50 } else { 48 } else {
51 cfg->loglevel = LOGLEVEL_ERROR; 49 cfg->loglevel = LOGLEVEL_ERROR;
52 } 50 }
@@ -293,6 +291,8 @@ void config_init(apr_pool_t *p)
293 291
294 config_add_option(p, "DryRun", "Don't perform any actual database changes", 292 config_add_option(p, "DryRun", "Don't perform any actual database changes",
295 config_set_flag, (void *)APR_OFFSETOF(config_t, dryrun)); 293 config_set_flag, (void *)APR_OFFSETOF(config_t, dryrun));
294 config_add_option(p, "Dump", "Dump Configuration and quit",
295 config_set_flag, (void *)APR_OFFSETOF(config_t, dump));
296 config_add_option(p, "Config", "Dummy to handle config directive", 296 config_add_option(p, "Config", "Dummy to handle config directive",
297 config_set_dummy, NULL); 297 config_set_dummy, NULL);
298 config_add_option(p, "Summary", "Show the summary before exit?", 298 config_add_option(p, "Summary", "Show the summary before exit?",
@@ -306,7 +306,7 @@ config_t *config_create(apr_pool_t *p)
306 apr_pool_create(&sp, p); 306 apr_pool_create(&sp, p);
307 cfg = apr_pcalloc(sp, sizeof(config_t)); 307 cfg = apr_pcalloc(sp, sizeof(config_t));
308 cfg->pool = sp; 308 cfg->pool = sp;
309 cfg->loglevel = LOGLEVEL_WARN; 309 cfg->loglevel = LOGLEVEL_ERROR;
310 cfg->summary = 1; 310 cfg->summary = 1;
311 cfg->transactions = 1; 311 cfg->transactions = 1;
312 cfg->input_files = apr_array_make(cfg->pool, 10, sizeof(char *)); 312 cfg->input_files = apr_array_make(cfg->pool, 10, sizeof(char *));
@@ -320,15 +320,15 @@ apr_status_t config_check(config_t *cfg)
320{ 320{
321 apr_status_t ret = APR_SUCCESS; 321 apr_status_t ret = APR_SUCCESS;
322 if (!cfg->dbdriver || !cfg->dbparams) { 322 if (!cfg->dbdriver || !cfg->dbparams) {
323 printf("Database configuration is missing\n"); 323 logging_log(cfg, LOGLEVEL_NOISE, "Database configuration is missing\n");
324 ret = APR_EINVAL; 324 ret = APR_EINVAL;
325 } 325 }
326 if (!cfg->table) { 326 if (!cfg->table) {
327 printf("No Log Table defined\n"); 327 logging_log(cfg, LOGLEVEL_NOISE, "No Log Table defined\n");
328 ret = APR_EINVAL; 328 ret = APR_EINVAL;
329 } 329 }
330 if (apr_is_empty_array(cfg->output_fields)) { 330 if (apr_is_empty_array(cfg->output_fields)) {
331 printf("No Output Fields Defined\n"); 331 logging_log(cfg, LOGLEVEL_NOISE, "No Output Fields Defined\n");
332 ret = APR_EINVAL; 332 ret = APR_EINVAL;
333 } 333 }
334 return ret; 334 return ret;
@@ -345,7 +345,7 @@ static int config_merge(void *rec, const char *key, const char *value)
345 value }; 345 value };
346 opt->func(cfg, opt, 2, args); 346 opt->func(cfg, opt, 2, args);
347 } else { 347 } else {
348 printf("Unhandled: %s\n", key); 348 logging_log(cfg, LOGLEVEL_NOISE, "Unhandled: %s\n", key);
349 } 349 }
350 return 1; 350 return 1;
351} 351}
@@ -400,12 +400,13 @@ apr_status_t config_read(config_t *cfg, const char *filename,
400 if (opt) { 400 if (opt) {
401 rv = opt->func(cfg, opt, targc, (const char **)targv); 401 rv = opt->func(cfg, opt, targc, (const char **)targv);
402 if (APR_STATUS_IS_EINVAL(rv)) { 402 if (APR_STATUS_IS_EINVAL(rv)) {
403 printf("Config Error: Invalid Arguments for %s\n\t%s\n", 403 logging_log(cfg, LOGLEVEL_NOISE,
404 "Config Error: Invalid Arguments for %s\n\t%s\n",
404 opt->name, opt->help); 405 opt->name, opt->help);
405 ret = rv; 406 ret = rv;
406 } 407 }
407 } else { 408 } else {
408 printf("Unhandled: %s\n", targv[0]); 409 logging_log(cfg, LOGLEVEL_NOISE, "Unhandled: %s\n", targv[0]);
409 } 410 }
410 } 411 }
411 } while (rv == APR_SUCCESS); 412 } while (rv == APR_SUCCESS);
diff --git a/utility/config.h b/utility/config.h
index 611e9de..763ef5d 100644
--- a/utility/config.h
+++ b/utility/config.h
@@ -7,10 +7,11 @@
7#include "ap_pcre.h" 7#include "ap_pcre.h"
8 8
9typedef enum { 9typedef enum {
10 LOGLEVEL_QUIET = 0, 10 LOGLEVEL_NOISE = 0,
11 LOGLEVEL_ERROR = 1, 11 LOGLEVEL_NONE,
12 LOGLEVEL_WARN = 2, 12 LOGLEVEL_ERROR,
13 LOGLEVEL_DEBUG = 3, 13 LOGLEVEL_NOTICE,
14 LOGLEVEL_DEBUG,
14} loglevel_e; 15} loglevel_e;
15 16
16typedef struct config_dbd_t config_dbd_t; 17typedef struct config_dbd_t config_dbd_t;
@@ -25,6 +26,7 @@ struct config_t {
25 loglevel_e loglevel; 26 loglevel_e loglevel;
26 /** error_log */ 27 /** error_log */
27 apr_file_t *errorlog_fp; 28 apr_file_t *errorlog_fp;
29 apr_file_t *errorlog_fperr;
28 apr_pool_t *errorlog_p; 30 apr_pool_t *errorlog_p;
29 31
30 /** input directory of log files */ 32 /** input directory of log files */
@@ -59,6 +61,8 @@ struct config_t {
59 61
60 /** Dry Run */ 62 /** Dry Run */
61 int dryrun; 63 int dryrun;
64 /** dump configuration only */
65 int dump;
62 66
63 /* Show the summary */ 67 /* Show the summary */
64 int summary; 68 int summary;
diff --git a/utility/database.c b/utility/database.c
index 45022da..c4e4bc9 100644
--- a/utility/database.c
+++ b/utility/database.c
@@ -4,6 +4,7 @@
4#include "apr_strings.h" 4#include "apr_strings.h"
5 5
6#include "util.h" 6#include "util.h"
7#include "mysql/mysql.h"
7 8
8struct config_dbd_t { 9struct config_dbd_t {
9 const apr_dbd_driver_t *driver; 10 const apr_dbd_driver_t *driver;
@@ -27,9 +28,10 @@ apr_status_t database_connect(config_t *cfg)
27 } 28 }
28 rv = apr_dbd_get_driver(cfg->pool, cfg->dbdriver, &(cfg->dbconn->driver)); 29 rv = apr_dbd_get_driver(cfg->pool, cfg->dbdriver, &(cfg->dbconn->driver));
29 if (rv) { 30 if (rv) {
31
30 logging_log(cfg, LOGLEVEL_ERROR, 32 logging_log(cfg, LOGLEVEL_ERROR,
31 "Could not load database driver %s. Error %d", cfg->dbdriver, 33 "Could not load database driver %s. Error %s", cfg->dbdriver,
32 rv); 34 logging_strerror(rv));
33 return rv; 35 return rv;
34 } 36 }
35 37
@@ -37,7 +39,7 @@ apr_status_t database_connect(config_t *cfg)
37 &(cfg->dbconn->dbd)); 39 &(cfg->dbconn->dbd));
38 if (rv) { 40 if (rv) {
39 logging_log(cfg, LOGLEVEL_ERROR, 41 logging_log(cfg, LOGLEVEL_ERROR,
40 "Could not connect to database. Error %d", rv); 42 "Could not connect to database. Error %s", logging_strerror(rv));
41 return rv; 43 return rv;
42 } 44 }
43 45
@@ -55,7 +57,7 @@ static apr_dbd_prepared_t *database_prepare_insert(config_t *cfg, apr_pool_t *p)
55 char *sql; 57 char *sql;
56 int i, f; 58 int i, f;
57 struct iovec *vec; 59 struct iovec *vec;
58 apr_dbd_prepared_t *stmt; 60 apr_dbd_prepared_t *stmt = NULL;
59 int nfs = cfg->output_fields->nelts; 61 int nfs = cfg->output_fields->nelts;
60 config_output_field_t *ofields; 62 config_output_field_t *ofields;
61 63
@@ -87,14 +89,14 @@ static apr_dbd_prepared_t *database_prepare_insert(config_t *cfg, apr_pool_t *p)
87 89
88 sql = apr_pstrcatv(p, vec, i+2, NULL); 90 sql = apr_pstrcatv(p, vec, i+2, NULL);
89 91
90 printf("SQL: %s\n", sql); 92 logging_log(cfg, LOGLEVEL_DEBUG, "Generated SQL: %s", sql);
91 93
92 rv = apr_dbd_prepare(cfg->dbconn->driver, cfg->pool, cfg->dbconn->dbd, sql, 94 rv = apr_dbd_prepare(cfg->dbconn->driver, cfg->pool, cfg->dbconn->dbd, sql,
93 "INSERT", &stmt); 95 "INSERT", &stmt);
94 96
95 if (rv) { 97 if (rv) {
96 printf("DB Error: %s\n", apr_dbd_error(cfg->dbconn->driver, 98 logging_log(cfg, LOGLEVEL_ERROR, "Unable to Prepare SQL insert: %s",
97 cfg->dbconn->dbd, rv)); 99 apr_dbd_error(cfg->dbconn->driver, cfg->dbconn->dbd, rv));
98 return NULL; 100 return NULL;
99 } 101 }
100 return stmt; 102 return stmt;
@@ -109,6 +111,10 @@ apr_status_t database_insert(config_t *cfg, apr_pool_t *p, apr_table_t *data)
109 // Prepare statement 111 // Prepare statement
110 if (!cfg->dbconn->stmt) { 112 if (!cfg->dbconn->stmt) {
111 cfg->dbconn->stmt = database_prepare_insert(cfg, p); 113 cfg->dbconn->stmt = database_prepare_insert(cfg, p);
114 if (!cfg->dbconn->stmt) {
115 logging_log(cfg, LOGLEVEL_NOISE, "Unable to prepare SQL statement");
116 return APR_EINVAL;
117 }
112 cfg->dbconn->args = apr_palloc(cfg->pool, nfs * sizeof(char *)); 118 cfg->dbconn->args = apr_palloc(cfg->pool, nfs * sizeof(char *));
113 } 119 }
114 for (f=0; f<nfs; f++) { 120 for (f=0; f<nfs; f++) {
@@ -117,8 +123,8 @@ apr_status_t database_insert(config_t *cfg, apr_pool_t *p, apr_table_t *data)
117 rv = apr_dbd_pquery(cfg->dbconn->driver, p, cfg->dbconn->dbd, &f, 123 rv = apr_dbd_pquery(cfg->dbconn->driver, p, cfg->dbconn->dbd, &f,
118 cfg->dbconn->stmt, nfs, cfg->dbconn->args); 124 cfg->dbconn->stmt, nfs, cfg->dbconn->args);
119 if (rv) { 125 if (rv) {
120 printf("DB Error: %s\n", apr_dbd_error(cfg->dbconn->driver, 126 logging_log(cfg, LOGLEVEL_ERROR, "Unable to Insert SQL: %s",
121 cfg->dbconn->dbd, rv)); 127 apr_dbd_error(cfg->dbconn->driver, cfg->dbconn->dbd, rv));
122 return rv; 128 return rv;
123 } 129 }
124 return APR_SUCCESS; 130 return APR_SUCCESS;
diff --git a/utility/logparse.c b/utility/logparse.c
index 4b5ab40..f4afb52 100644
--- a/utility/logparse.c
+++ b/utility/logparse.c
@@ -11,7 +11,6 @@
11#include "ap_pcre.h" 11#include "ap_pcre.h"
12#include "database.h" 12#include "database.h"
13 13
14
15apr_hash_t *g_parser_funcs; 14apr_hash_t *g_parser_funcs;
16 15
17static apr_status_t parser_func_regexmatch(apr_pool_t *p, config_t *cfg, 16static apr_status_t parser_func_regexmatch(apr_pool_t *p, config_t *cfg,
@@ -20,23 +19,26 @@ static apr_status_t parser_func_regexmatch(apr_pool_t *p, config_t *cfg,
20 struct { 19 struct {
21 ap_regex_t *rx; 20 ap_regex_t *rx;
22 const char *substr; 21 const char *substr;
23 } *data; 22 }*data;
24 ap_regmatch_t regm[AP_MAX_REG_MATCH]; 23 ap_regmatch_t regm[AP_MAX_REG_MATCH];
25 // Check if a regular expression configured 24 // Check if a regular expression configured
26 if (!field->args[0]) return APR_EINVAL; 25 if (!field->args[0])
26 return APR_EINVAL;
27 if (!field->data) { 27 if (!field->data) {
28 // pre compile the regex 28 // pre compile the regex
29 data = apr_palloc(cfg->pool, sizeof(ap_regex_t)+sizeof(const char *)); 29 data = apr_palloc(cfg->pool, sizeof(ap_regex_t)+sizeof(const char *));
30 data->rx = ap_pregcomp(cfg->pool, field->args[0], 30 data->rx = ap_pregcomp(cfg->pool, field->args[0],
31 AP_REG_EXTENDED|AP_REG_ICASE); 31 AP_REG_EXTENDED|AP_REG_ICASE);
32 if (field->args[1]) { 32 if (field->args[1]) {
33 data->substr = field->args[1]; 33 data->substr = field->args[1];
34 } else { 34 } else {
35 data->substr = "$1"; 35 data->substr = "$1";
36 } 36 }
37 if (!data->rx) return APR_EINVAL; 37 if (!data->rx)
38 return APR_EINVAL;
38 field->data = data; 39 field->data = data;
39 } else data = field->data; 40 } else
41 data = field->data;
40 42
41 if (!ap_regexec(data->rx, value, AP_MAX_REG_MATCH, regm, 0)) { 43 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); 44 *ret = ap_pregsub(p, data->substr, value, AP_MAX_REG_MATCH, regm);
@@ -66,7 +68,7 @@ static apr_status_t parser_func_machineid(apr_pool_t *p, config_t *cfg,
66 config_output_field_t *field, const char *value, const char **ret) 68 config_output_field_t *field, const char *value, const char **ret)
67{ 69{
68 if (cfg->machineid) { 70 if (cfg->machineid) {
69 *ret = apr_pstrdup(p,cfg->machineid); 71 *ret = apr_pstrdup(p, cfg->machineid);
70 } else { 72 } else {
71 *ret = field->def; 73 *ret = field->def;
72 } 74 }
@@ -81,7 +83,7 @@ parser_func_t parser_get_func(const char *name)
81} 83}
82 84
83static void parser_add_func(apr_pool_t *p, const char *const name, 85static void parser_add_func(apr_pool_t *p, const char *const name,
84 parser_func_t func) 86 parser_func_t func)
85{ 87{
86 if (!g_parser_funcs) { 88 if (!g_parser_funcs) {
87 g_parser_funcs = apr_hash_make(p); 89 g_parser_funcs = apr_hash_make(p);
@@ -103,6 +105,7 @@ void parser_find_logs(config_t *cfg)
103 apr_finfo_t finfo; 105 apr_finfo_t finfo;
104 char **newp; 106 char **newp;
105 107
108 logging_log(cfg, LOGLEVEL_NOTICE, "Find Log files");
106 if (!cfg->input_dir) 109 if (!cfg->input_dir)
107 return; 110 return;
108 apr_pool_create(&tp, cfg->pool); 111 apr_pool_create(&tp, cfg->pool);
@@ -113,7 +116,7 @@ void parser_find_logs(config_t *cfg)
113 continue; 116 continue;
114 newp = (char **)apr_array_push(cfg->input_files); 117 newp = (char **)apr_array_push(cfg->input_files);
115 apr_filepath_merge(newp, cfg->input_dir, finfo.name, 118 apr_filepath_merge(newp, cfg->input_dir, finfo.name,
116 APR_FILEPATH_TRUENAME, cfg->pool); 119 APR_FILEPATH_TRUENAME, cfg->pool);
117 } 120 }
118 apr_dir_close(dir); 121 apr_dir_close(dir);
119 } 122 }
@@ -261,11 +264,12 @@ apr_status_t parse_logfile(config_t *cfg, const char *filename)
261 apr_pool_create(&tp, cfg->pool); 264 apr_pool_create(&tp, cfg->pool);
262 apr_pool_create(&targp, tp); 265 apr_pool_create(&targp, tp);
263 266
267 logging_log(cfg, LOGLEVEL_NOTICE, "Begin Parsing Log File '%s'", filename);
268
264 rv = apr_file_open(&file, filename, APR_FOPEN_READ | APR_BUFFERED, 269 rv = apr_file_open(&file, filename, APR_FOPEN_READ | APR_BUFFERED,
265 APR_OS_DEFAULT, tp); 270 APR_OS_DEFAULT, tp);
266 if (rv != APR_SUCCESS) { 271 if (rv != APR_SUCCESS) {
267 logging_log(cfg, LOGLEVEL_ERROR, "Could not open %s",filename); 272 logging_log(cfg, LOGLEVEL_NOISE, "Could not open %s", filename);
268 printf("Could not open %s\n", filename);
269 return rv; 273 return rv;
270 } 274 }
271 275
@@ -280,44 +284,52 @@ apr_status_t parse_logfile(config_t *cfg, const char *filename)
280 apr_pool_clear(targp); 284 apr_pool_clear(targp);
281 tokenize_logline(buff, &targv, targp, 0); 285 tokenize_logline(buff, &targv, targp, 0);
282 targc = 0; 286 targc = 0;
283 while (targv[targc]) targc++; 287 while (targv[targc])
288 targc++;
284 /** @todo Run Line Filters here */ 289 /** @todo Run Line Filters here */
285 rv = parse_processline(targp, cfg, targv, targc); 290 rv = parse_processline(targp, cfg, targv, targc);
286 if (rv != APR_SUCCESS) { 291 if (rv != APR_SUCCESS) {
287 int i; 292 int i;
288 printf("Line %d(%d): %s\n",line, targc, buff); 293 logging_log(cfg, LOGLEVEL_ERROR, "Line %d(%d): %s", line,
294 targc, buff);
289 for (i = 0; targv[i]; i++) { 295 for (i = 0; targv[i]; i++) {
290 printf("Arg (%d): '%s'\n", i, targv[i]); 296 logging_log(cfg, LOGLEVEL_ERROR, "Arg (%d): '%s'", i,
297 targv[i]);
291 } 298 }
292 } 299 }
293 } 300 }
294 } while (rv == APR_SUCCESS); 301 } while (rv == APR_SUCCESS);
295 printf("Total Lines: %d\n", line);
296 apr_file_close(file); 302 apr_file_close(file);
297 apr_pool_destroy(tp); 303 apr_pool_destroy(tp);
304 logging_log(cfg, LOGLEVEL_NOTICE,
305 "Finish Parsing Log File '%s'. Lines: %d", filename, line);
306
298 return APR_SUCCESS; 307 return APR_SUCCESS;
299} 308}
300 309
301apr_status_t parse_processline(apr_pool_t *ptemp, config_t *cfg, char **argv, int argc) 310apr_status_t parse_processline(apr_pool_t *ptemp, config_t *cfg, char **argv,
311 int argc)
302{ 312{
303 config_logformat_t *fmt; 313 config_logformat_t *fmt;
304 config_logformat_field_t *ifields; 314 config_logformat_field_t *ifields;
305 config_output_field_t *ofields; 315 config_output_field_t *ofields;
306 apr_table_t *datain; 316 apr_table_t *datain;
307 apr_table_t *dataout; 317 apr_table_t *dataout;
308 apr_status_t rv = APR_SUCCESS; 318 apr_status_t rv= APR_SUCCESS;
309 int i; 319 int i;
310 320
311 fmt = apr_hash_get(cfg->log_formats, cfg->logformat, APR_HASH_KEY_STRING); 321 fmt = apr_hash_get(cfg->log_formats, cfg->logformat, APR_HASH_KEY_STRING);
312 if (!fmt) return APR_EINVAL; 322 if (!fmt)
313 if (fmt->fields->nelts != argc) return APR_EINVAL; 323 return APR_EINVAL;
324 if (fmt->fields->nelts != argc)
325 return APR_EINVAL;
314 326
315 datain = apr_table_make(ptemp, fmt->fields->nelts); 327 datain = apr_table_make(ptemp, fmt->fields->nelts);
316 dataout = apr_table_make(ptemp, cfg->output_fields->nelts); 328 dataout = apr_table_make(ptemp, cfg->output_fields->nelts);
317 329
318 ifields = (config_logformat_field_t *)fmt->fields->elts; 330 ifields = (config_logformat_field_t *)fmt->fields->elts;
319 for (i=0; i<fmt->fields->nelts; i++) { 331 for (i=0; i<fmt->fields->nelts; i++) {
320 apr_table_setn(datain,ifields[i].name,argv[i]); 332 apr_table_setn(datain, ifields[i].name, argv[i]);
321 } 333 }
322 /** @todo Run Pre Filters here */ 334 /** @todo Run Pre Filters here */
323 335
@@ -332,12 +344,13 @@ apr_status_t parse_processline(apr_pool_t *ptemp, config_t *cfg, char **argv, in
332 continue; 344 continue;
333 } 345 }
334 if (!ofields[i].func) { 346 if (!ofields[i].func) {
335 apr_table_setn(dataout,ofields[i].field, val); 347 apr_table_setn(dataout, ofields[i].field, val);
336 } else { 348 } else {
337 const char *ret = NULL; 349 const char *ret= NULL;
338 rv = ((parser_func_t)ofields[i].func)(ptemp, cfg, &ofields[i], val, 350 rv = ((parser_func_t)ofields[i].func)(ptemp, cfg, &ofields[i], val,
339 &ret); 351 &ret);
340 if (rv) return rv; 352 if (rv)
353 return rv;
341 apr_table_setn(dataout, ofields[i].field, ret); 354 apr_table_setn(dataout, ofields[i].field, ret);
342 } 355 }
343 } 356 }
diff --git a/utility/mod_log_sql.conf b/utility/mod_log_sql.conf
index bd8496c..771f7c7 100644
--- a/utility/mod_log_sql.conf
+++ b/utility/mod_log_sql.conf
@@ -5,8 +5,8 @@ DBDParams "host=localhost;user=root;dbname=apache_log"
5Table access_log 5Table access_log
6MachineID 7of9 6MachineID 7of9
7UseTransactions on 7UseTransactions on
8LogLevel notice 8LogLevel debug
9DryRun on 9DryRun off
10Summary on 10Summary on
11 11
12LogFormatConfig CLF remhost String 12LogFormatConfig CLF remhost String
diff --git a/utility/shell.c b/utility/shell.c
index b289bce..e521916 100644
--- a/utility/shell.c
+++ b/utility/shell.c
@@ -17,9 +17,10 @@ const apr_getopt_option_t _opt_config[] = {
17 {"transaction", 't', 1, "Use a Transaction (yes,no)"}, 17 {"transaction", 't', 1, "Use a Transaction (yes,no)"},
18 {"logformat", 'r', 1, "Use this logformat to parse files"}, 18 {"logformat", 'r', 1, "Use this logformat to parse files"},
19 {"file", 'f', 1, "Parse this single log file (input dir is NOT scanned)"}, 19 {"file", 'f', 1, "Parse this single log file (input dir is NOT scanned)"},
20 {"inputdir", 'd', 1, "Input Directory to look for log files"}, 20 {"inputdir", 'i', 1, "Input Directory to look for log files"},
21 {"config", 'c', 1, "Configuration file to use (default mod_log_sql.conf)"}, 21 {"config", 'c', 1, "Configuration file to use (default mod_log_sql.conf)"},
22 {"dryrun", 'n', 0, "Perform a dry run (do not actually alter the databse)"}, 22 {"dryrun", 'n', 0, "Perform a dry run (do not actually alter the databse)"},
23 {"dump", 'd', 0, "Dump the configuration after parsing and quit"},
23 {"loglevel", 'l', 1, "Log Level (deubg, warn, error)"}, 24 {"loglevel", 'l', 1, "Log Level (deubg, warn, error)"},
24 {"summary", 's', 1, "Summary (yes,no)"}, 25 {"summary", 's', 1, "Summary (yes,no)"},
25 {"help", 'h', 0, "Show Help"}, 26 {"help", 'h', 0, "Show Help"},
@@ -62,7 +63,7 @@ int main(int argc, const char *const argv[])
62 const char *opt_arg; 63 const char *opt_arg;
63 apr_status_t rv; 64 apr_status_t rv;
64 apr_table_t *args; 65 apr_table_t *args;
65 config_t *base; 66 config_t *cfg;
66 67
67 apr_app_initialize(&argc, &argv, NULL); 68 apr_app_initialize(&argc, &argv, NULL);
68 atexit(apr_terminate); 69 atexit(apr_terminate);
@@ -84,7 +85,7 @@ int main(int argc, const char *const argv[])
84 apr_table_setn(args,"config",opt_arg); 85 apr_table_setn(args,"config",opt_arg);
85 break; 86 break;
86 case 'd': 87 case 'd':
87 apr_table_setn(args,"inputdirectory",opt_arg); 88 apr_table_setn(args,"dump","yes");
88 break; 89 break;
89 case 'f': 90 case 'f':
90 apr_table_setn(args,"inputfile",opt_arg); 91 apr_table_setn(args,"inputfile",opt_arg);
@@ -93,6 +94,9 @@ int main(int argc, const char *const argv[])
93 show_help(argv[0], _opt_config, stdout); 94 show_help(argv[0], _opt_config, stdout);
94 exit(1); 95 exit(1);
95 break; 96 break;
97 case 'i':
98 apr_table_setn(args,"inputdirectory",opt_arg);
99 break;
96 case 'l': 100 case 'l':
97 apr_table_setn(args,"loglevel",opt_arg); 101 apr_table_setn(args,"loglevel",opt_arg);
98 break; 102 break;
@@ -128,45 +132,49 @@ int main(int argc, const char *const argv[])
128 parser_init(pool); 132 parser_init(pool);
129 config_init(pool); 133 config_init(pool);
130 database_init(pool); 134 database_init(pool);
131 logging_init(pool);
132 // Process configuration file 135 // Process configuration file
133 base = config_create(pool); 136 cfg = config_create(pool);
134 rv = config_read(base, apr_table_get(args,"Config"), args); 137 rv = config_read(cfg, apr_table_get(args,"Config"), args);
135 apr_pool_destroy(ptemp); 138 apr_pool_destroy(ptemp);
136 139
140 // Initialize Log system AFTER we parse the configuration
141 logging_init(cfg);
142
137 if (APR_STATUS_IS_ENOENT(rv)) { 143 if (APR_STATUS_IS_ENOENT(rv)) {
138 fprintf(stderr,"Could not load configuration file: %s\n",apr_table_get(args,"config")); 144 logging_log(cfg,LOGLEVEL_NOISE,"Could not load configuration file: %s",apr_table_get(args,"config"));
139 } else if (rv) { 145 } else if (rv) {
140 exit(1); 146 exit(1);
141 } 147 }
142 config_dump(base); 148 if (cfg->dump) {
149 config_dump(cfg);
150 exit(0);
151 }
143 152
144 if (config_check(base)) { 153 if (config_check(cfg)) {
145 printf("Please correct the configuration\n"); 154 logging_log(cfg,LOGLEVEL_NOISE, "Please correct the configuration");
146 exit(1); 155 exit(1);
147 } 156 }
148 157
149 // Find files and parse 158 // Find files and parse
150 parser_find_logs(base); 159 parser_find_logs(cfg);
151 if (!base->dryrun) { 160 if (!cfg->dryrun) {
152 if ((rv = database_connect(base))) { 161 if ((rv = database_connect(cfg))) {
153 printf("Error Connecting to Database: %d\n",rv); 162 logging_log(cfg,LOGLEVEL_NOISE, "Error Connecting to Database");
154 exit(1); 163 exit(1);
155 } 164 }
156 } 165 }
157 if (!apr_is_empty_array(base->input_files)) { 166 if (!apr_is_empty_array(cfg->input_files)) {
158 char **filelist; 167 char **filelist;
159 int f, l; 168 int f, l;
160 filelist = (char **)base->input_files->elts; 169 filelist = (char **)cfg->input_files->elts;
161 for (f=0, l=base->input_files->nelts; f < l; f++) { 170 for (f=0, l=cfg->input_files->nelts; f < l; f++) {
162 printf("Scanning %s\n",filelist[f]); 171 parse_logfile(cfg, filelist[f]);
163 parse_logfile(base, filelist[f]);
164 } 172 }
165 } else { 173 } else {
166 printf("No input files\n"); 174 logging_log(cfg,LOGLEVEL_NOISE,"No log files found to parse");
167 } 175 }
168 if (!base->dryrun) { 176 if (!cfg->dryrun) {
169 database_disconnect(base); 177 database_disconnect(cfg);
170 } 178 }
171 /** @todo summary goes here */ 179 /** @todo summary goes here */
172 return 0; 180 return 0;
diff --git a/utility/util.c b/utility/util.c
index cb6898d..99bb046 100644
--- a/utility/util.c
+++ b/utility/util.c
@@ -33,15 +33,31 @@ void line_chomp(char *str)
33 33
34void logging_init(config_t *cfg) 34void logging_init(config_t *cfg)
35{ 35{
36 apr_status_t rv;
37 apr_pool_create(&cfg->errorlog_p, cfg->pool);
38 apr_file_open_stderr(&cfg->errorlog_fperr, cfg->pool);
36 if (cfg->errorlog) { 39 if (cfg->errorlog) {
37 apr_file_open(&cfg->errorlog_fp, cfg->errorlog, 40 rv = apr_file_open(&cfg->errorlog_fp, cfg->errorlog,
38 APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_BUFFERED, 41 APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_APPEND,
39 APR_OS_DEFAULT, 42 APR_OS_DEFAULT,
40 cfg->pool); 43 cfg->pool);
41 apr_pool_create(&cfg->errorlog_p, cfg->pool); 44 if (rv) {
45 printf("Error opening %s\n",cfg->errorlog);
46 cfg->loglevel = LOGLEVEL_NONE;
47 }
48 logging_log(cfg, LOGLEVEL_ERROR, "Log file Opened");
49 } else {
50 cfg->loglevel = LOGLEVEL_NONE;
51 logging_log(cfg, LOGLEVEL_NOISE, "No Log file specified, disabled logging");
42 } 52 }
43} 53}
44 54
55const char *logging_strerror(apr_status_t rv)
56{
57 char buff[256];
58 return apr_strerror(rv, buff, 256);
59}
60
45/** 61/**
46 * @todo implement logging 62 * @todo implement logging
47 */ 63 */
@@ -51,7 +67,7 @@ void logging_log(config_t *cfg, loglevel_e level, const char *fmt, ...)
51 struct iovec vec[2]; 67 struct iovec vec[2];
52 apr_size_t blen; 68 apr_size_t blen;
53 69
54 if (!cfg->errorlog_fp || cfg->loglevel < level) return; 70 if (cfg->loglevel < level) return;
55 71
56 va_start(ap, fmt); 72 va_start(ap, fmt);
57 apr_pool_clear(cfg->errorlog_p); 73 apr_pool_clear(cfg->errorlog_p);
@@ -61,7 +77,12 @@ void logging_log(config_t *cfg, loglevel_e level, const char *fmt, ...)
61 vec[1].iov_base = "\n"; 77 vec[1].iov_base = "\n";
62 vec[1].iov_len = 1; 78 vec[1].iov_len = 1;
63 79
64 apr_file_writev(cfg->errorlog_fp,vec,2,&blen); 80 if (level == LOGLEVEL_NOISE) {
81 apr_file_writev(cfg->errorlog_fperr,vec,2,&blen);
82 }
83 if (cfg->loglevel > LOGLEVEL_NONE) {
84 apr_file_writev(cfg->errorlog_fp,vec,2,&blen);
85 }
65 86
66 va_end(ap); 87 va_end(ap);
67} 88}
diff --git a/utility/util.h b/utility/util.h
index 9e3aed3..c67cf9c 100644
--- a/utility/util.h
+++ b/utility/util.h
@@ -17,4 +17,6 @@ void logging_init(config_t *cfg);
17void logging_log(config_t *cfg, loglevel_e level, const char *fmt, ...) 17void logging_log(config_t *cfg, loglevel_e level, const char *fmt, ...)
18 __attribute__((format(printf, 3, 4))); 18 __attribute__((format(printf, 3, 4)));
19 19
20const char *logging_strerror(apr_status_t rv);
21
20#endif /*UTIL_H_*/ 22#endif /*UTIL_H_*/