Browse Source

Bugfix in logger + test for logger format parsing

Yann Weber 4 years ago
parent
commit
b989e65d33
3 changed files with 136 additions and 99 deletions
  1. 47
    38
      include/logger.h
  2. 26
    41
      src/logger.c
  3. 63
    20
      tests/check_logger.c

+ 47
- 38
include/logger.h View File

@@ -52,6 +52,8 @@
52 52
 /**@ingroup log_facility */
53 53
 #define LOG_MASTER 8
54 54
 
55
+#define PYFCGI_LOGGER_MAX 64
56
+#define PYFCGI_LOGGER_FMT_MAX PYFCGI_LOGGER_MAX
55 57
 #define PYFCGI_LOGGER_FIELD_MAX 24
56 58
 #define PYFCGI_LOGGER_FMT_PARSE_ERRSZ 64
57 59
 
@@ -151,45 +153,7 @@ static const char* PYFCGI_LOGGER_LVLNAME[] = {"Emergency", "Alert", "Critical",
151 153
 
152 154
 static const char* PYFCGI_LOGGER_TYPNAME[] = {"Global", "Access", "Internal",
153 155
                                               "Worker", "Master"};
154
-/**@brief Logger configuration
155
- * @ingroup conf_logger
156
- */
157
-struct pyfcgi_conf_logger_s
158
-{
159
-	/**@brief Or combination of @ref PYFCGI_LOG_SYSLOG or
160
-	 * @ref PYFCGI_LOG_RETRY */
161
-	short flags;
162
-	char *syslog_ident;
163
-	int syslog_facility;
164
-	logmask_t syslog_loglvl;
165
-	logmask_t syslog_logtyp;
166 156
 
167
-	/**@brief PyFCGI internal ident, prefixes all log messages */
168
-	char *ident;
169
-	logmask_t facility;
170
-
171
-	pyfcgi_logger_t *loggers;
172
-	unsigned char logger_sz;
173
-
174
-	char **format;
175
-	unsigned char format_sz;
176
-
177
-	/**@brief Internal pipe to tee(2) the message on loggers */
178
-	int pipes[2];
179
-};
180
-
181
-/**@brief Informations on a logger
182
- * @ingroup conf_logger
183
- */
184
-struct pyfcgi_logger_s
185
-{
186
-	char *filename;
187
-	int fd;
188
-	logmask_t loglvl;
189
-	logmask_t logtyp;
190
-
191
-	size_t fmt_id;
192
-};
193 157
 
194 158
 /**@defgroup conf_logger_format Logline format
195 159
  * @ingroup conf_logger
@@ -263,8 +227,12 @@ struct pyfcgi_logger_fmt_field_s
263 227
  * @ingroup conf_logger_format */
264 228
 struct pyfcgi_logger_format_s
265 229
 {
230
+	/**@brief String copy of the format */
231
+	char *fmt;
266 232
 	/**@brief Stores data about fields */
267 233
 	pyfcgi_logger_fmt_field_t fields[PYFCGI_LOGGER_FIELD_MAX];
234
+	/**@brief field count */
235
+	int nfield;
268 236
 	/**@brief Preallocated buffer for prefix & suffix */
269 237
 	char *buf;
270 238
 	/**@brief Message prefix */
@@ -273,8 +241,49 @@ struct pyfcgi_logger_format_s
273 241
 	char *suffix;
274 242
 };
275 243
 
244
+/**@brief Informations on a logger
245
+ * @ingroup conf_logger
246
+ */
247
+struct pyfcgi_logger_s
248
+{
249
+	char *filename;
250
+	int fd;
251
+	logmask_t loglvl;
252
+	logmask_t logtyp;
253
+
254
+	size_t fmt_id;
255
+};
256
+
257
+/**@brief Logger configuration
258
+ * @ingroup conf_logger
259
+ */
260
+struct pyfcgi_conf_logger_s
261
+{
262
+	/**@brief Or combination of @ref PYFCGI_LOG_SYSLOG or
263
+	 * @ref PYFCGI_LOG_RETRY */
264
+	short flags;
265
+	char *syslog_ident;
266
+	int syslog_facility;
267
+	logmask_t syslog_loglvl;
268
+	logmask_t syslog_logtyp;
269
+
270
+	/**@brief PyFCGI internal ident, prefixes all log messages */
271
+	char *ident;
272
+	logmask_t facility;
273
+
274
+	pyfcgi_logger_t loggers[PYFCGI_LOGGER_MAX];
275
+	unsigned char logger_sz;
276
+
277
+	pyfcgi_logger_format_t formats[PYFCGI_LOGGER_MAX];
278
+	//char **format;
279
+	unsigned char format_sz;
280
+
281
+	/**@brief Internal pipe to tee(2) the message on loggers */
282
+	int pipes[2];
283
+};
276 284
 #include "conf.h"
277 285
 
286
+/**@brief Initiliaze logger conf */
278 287
 int pyfcgi_logger_init();
279 288
 
280 289
 /**@brief Add a new logger

+ 26
- 41
src/logger.c View File

@@ -20,7 +20,7 @@ int pyfcgi_logger_add(const char *filename, logmask_t loglvl, logmask_t logtyp,
20 20
 
21 21
 	conf = &PyFCGI_conf.logs;
22 22
 
23
-	if(conf->logger_sz == 255)
23
+	if(conf->logger_sz >= PYFCGI_LOGGER_MAX)
24 24
 	{
25 25
 		pyfcgi_log(LOG_ERR, "Maximum of 255 logger reached, unable to add this one...");
26 26
 		return PYFCGI_ERR;
@@ -64,41 +64,22 @@ err:
64 64
 
65 65
 int pyfcgi_logger_format_add(const char* format, size_t* idx)
66 66
 {
67
-	char *fmt;
68 67
 	size_t i;
69
-	//void *tmp;
70 68
 	pyfcgi_conf_logger_t *conf;
71 69
 
72 70
 	conf = &PyFCGI_conf.logs;
73 71
 
74 72
 	for(i=0; i<conf->format_sz; i++)
75 73
 	{
76
-		if(!strcmp(format, conf->format[i])) { break; }
74
+		if(!strcmp(format, conf->formats[i].fmt)) { break; }
77 75
 	}
78 76
 	if(idx) { *idx = i; }
79 77
 	if( i<conf->format_sz )
80 78
 	{
81 79
 		return 0;
82 80
 	}
83
-	if( !(fmt = strdup(format)) )
84
-	{
85
-		pyfcgi_log(LOG_ALERT, "Fails to strdup new format : %s",
86
-			   strerror(errno));
87
-		return PYFCGI_FATAL;
88
-	}
89
-	/*
90 81
 	conf->format_sz++;
91
-	if( !(tmp = realloc(conf->format,
92
-	                    sizeof(char*) * conf->format_sz)) )
93
-	{
94
-		conf->format_sz--;
95
-		pyfcgi_log(LOG_ALERT, "Fails to realloc logger format array : %s",
96
-			   strerror(errno));
97
-		return PYFCGI_FATAL;
98
-	}
99
-	conf->format[i] = fmt;
100
-	*/
101
-	return 0;
82
+	return pyfcgi_logger_parse_format(format, &(conf->formats[i]));
102 83
 }
103 84
 
104 85
 int pyfcgi_logger_parse_format(const char* fmt,
@@ -107,31 +88,34 @@ int pyfcgi_logger_parse_format(const char* fmt,
107 88
 	const char *ptr, *str_start;
108 89
 	int err;
109 90
 	char reason_err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
110
-	unsigned char nfield;
111 91
 	pyfcgi_logger_fmt_field_t *cur_field;
112 92
 
113 93
 	memset(fmt_data, 0, sizeof(pyfcgi_logger_format_t));
94
+
95
+	if( !(fmt_data->fmt = strdup(fmt)) )
96
+	{
97
+		pyfcgi_log(LOG_ALERT, "Fails to strdup new format : %s",
98
+			   strerror(errno));
99
+		return PYFCGI_FATAL;
100
+	}
101
+
114 102
 	ptr = fmt;
115
-	nfield = 0;
103
+	fmt_data->nfield = 0;
116 104
 	cur_field = fmt_data->fields;
117 105
 
118 106
 	while(*ptr)
119 107
 	{
120
-		if(nfield >= PYFCGI_LOGGER_FIELD_MAX)
108
+		if(fmt_data->nfield >= PYFCGI_LOGGER_FIELD_MAX)
121 109
 		{
122 110
 			//TODO error truncate !
123
-			break;
111
+			//break; 
112
+			goto parse_err;
124 113
 		}
125 114
 		str_start = ptr;
126
-		while(*ptr && *ptr != '{' && *(ptr+1) != '{')
115
+		cur_field->len = 0;
116
+		while(*ptr && (*ptr != '{' || *(ptr+1) == '{'))
127 117
 		{ // handling const chr fields
128 118
 			//TODO : issue warning/error when unescaped '}' found
129
-			if(!cur_field->type)
130
-			{
131
-				cur_field->type = pyfcgi_logger_field_const;
132
-				cur_field->known_length = 1;
133
-				cur_field->len = 0;
134
-			}
135 119
 			if(*ptr == '{' && *(ptr+1) == '{')
136 120
 			{
137 121
 				cur_field->len++;
@@ -142,6 +126,8 @@ int pyfcgi_logger_parse_format(const char* fmt,
142 126
 		}
143 127
 		if(cur_field->len)
144 128
 		{
129
+			cur_field->known_length = 1;
130
+			cur_field->type = pyfcgi_logger_field_const;
145 131
 			cur_field->val = strndup(str_start, cur_field->len);
146 132
 			if(!cur_field->val)
147 133
 			{
@@ -151,19 +137,20 @@ int pyfcgi_logger_parse_format(const char* fmt,
151 137
 					   strerror(err));
152 138
 				goto exit_err;
153 139
 			}
154
-			nfield++;
155
-			cur_field = &(fmt_data->fields[nfield]); // next_field
156
-			continue; // to check nfield
140
+			fmt_data->nfield++;
141
+			cur_field = &(fmt_data->fields[fmt_data->nfield]); // next_field
142
+			continue; // to check fmt_data->nfield
157 143
 		}
158 144
 		if(*ptr == '{') //should be this or '\0'...
159 145
 		{
160 146
 			ptr++;
161
-			if( (1 == pyfcgi_logger_parse_field(&ptr, fmt, 
162
-			                                    cur_field, 
163
-			                                    reason_err)) )
147
+			if( pyfcgi_logger_parse_field(&ptr, fmt,  cur_field, 
148
+			                              reason_err) )
164 149
 			{
165 150
 				goto parse_err;
166 151
 			}
152
+			fmt_data->nfield++;
153
+			cur_field = &(fmt_data->fields[fmt_data->nfield]); // next_field
167 154
 		}
168 155
 		ptr++;
169 156
 	};
@@ -336,7 +323,6 @@ int pyfcgi_logger_parse_field_dtfmt(const char** ptr, char** format)
336 323
 	}
337 324
 	if(!fmt_len)
338 325
 	{
339
-		(*ptr)++;
340 326
 		fmt_len = sizeof(PYFCGI_LOGGER_TIME_FMT_DEFAULT);
341 327
 		fmt = PYFCGI_LOGGER_TIME_FMT_DEFAULT;
342 328
 	}
@@ -356,7 +342,6 @@ int pyfcgi_logger_parse_field_sz(const char **ptr, size_t *size)
356 342
 	*size = 0;
357 343
 	if(**ptr == '}' || **ptr == ':')
358 344
 	{
359
-		(*ptr)++;
360 345
 		return 0;
361 346
 	}
362 347
 

+ 63
- 20
tests/check_logger.c View File

@@ -15,8 +15,10 @@ START_TEST(test_logger_init)
15 15
 	pyfcgi_logger_init();
16 16
 	ck_assert_ptr_eq(conf->syslog_ident, NULL);
17 17
 	ck_assert_ptr_eq(conf->ident, NULL);
18
-	ck_assert_ptr_eq(conf->format, NULL);
18
+	/*
19
+	ck_assert_ptr_eq(conf->formats, NULL);
19 20
 	ck_assert_ptr_eq(conf->loggers, NULL);
21
+	*/
20 22
 	ck_assert_int_eq(conf->logger_sz, 0);
21 23
 	ck_assert_int_eq(conf->format_sz, 0);
22 24
 	ck_assert_int_eq(conf->flags, 0);
@@ -24,19 +26,20 @@ START_TEST(test_logger_init)
24 26
 }
25 27
 END_TEST
26 28
 
27
-/*
28 29
 START_TEST(test_logger_format_add)
29 30
 {
30 31
 	int ret;
31 32
 	size_t s;
32 33
 	pyfcgi_logger_init();
34
+	const char *fmt = "{datetime} {level} {ident}[{pid}] {msg}";
33 35
 
34
-	ret = pyfcgi_logger_format_add("TEST", NULL);
36
+	ret = pyfcgi_logger_format_add(fmt, &s);
35 37
 	ck_assert_int_eq(conf->format_sz, 1);
36
-	ck_assert_str_eq(conf->format[0], "TEST");
38
+	ck_assert_int_eq(s, 0);
39
+	ck_assert_str_eq(conf->formats[s].fmt, fmt);
40
+
37 41
 }
38 42
 END_TEST
39
-*/
40 43
 
41 44
 /*
42 45
 	TC logger default values
@@ -54,7 +57,7 @@ START_TEST(test_logger_parse_field_dtfmt_default)
54 57
 	ret = pyfcgi_logger_parse_field_dtfmt((const char**)&ptr, &fmt);
55 58
 	ck_assert_int_eq(ret, 0);
56 59
 	ck_assert_str_eq(fmt, PYFCGI_LOGGER_TIME_FMT_DEFAULT);
57
-	ck_assert_ptr_eq(ptr, orig+1);
60
+	ck_assert_ptr_eq(ptr, orig);
58 61
 	free(fmt);
59 62
 }
60 63
 END_TEST
@@ -74,7 +77,7 @@ START_TEST(test_logger_parse_field_sz_default)
74 77
 		ret = pyfcgi_logger_parse_field_sz((const char**)&ptr, &val);
75 78
 		ck_assert_int_eq(ret, 0);
76 79
 		ck_assert_int_eq(val, 0);
77
-		ck_assert_ptr_eq(ptr, (*orig)+1);
80
+		ck_assert_ptr_eq(ptr, (*orig));
78 81
 		orig++;
79 82
 	}
80 83
 }
@@ -122,11 +125,13 @@ START_TEST(test_logger_parse_field_sz)
122 125
 {
123 126
 	int ret, *res;
124 127
 	size_t val;
125
-	char *ptr, **orig;
126
-	char *vals[] = {"42:%F}", "1337:}", "0}", NULL};
127
-	int _res[] = {42,1337,0};
128
+	char *ptr, **orig, **eptr;
129
+	char *vals[] = {"42:%F}", "1337:}", "0}", ":}", NULL};
130
+	int _res[] = {42,1337,0, 0};
131
+	char *_eptr[] = {vals[0]+2, vals[1]+4, vals[2]+1, vals[3]};
128 132
 
129 133
 	orig = vals;
134
+	eptr = _eptr;
130 135
 	res = _res;
131 136
 	while(*orig)
132 137
 	{
@@ -134,9 +139,10 @@ START_TEST(test_logger_parse_field_sz)
134 139
 
135 140
 		ret = pyfcgi_logger_parse_field_sz((const char**)&ptr, &val);
136 141
 		ck_assert_int_eq(val, *res);
137
-		ck_assert_ptr_eq(ptr, (*orig)+snprintf(NULL, 0, "%d", *res));
142
+		ck_assert_ptr_eq(ptr, *eptr);
138 143
 		orig++;
139 144
 		res++;
145
+		eptr++;
140 146
 	}
141 147
 }
142 148
 END_TEST
@@ -174,10 +180,16 @@ START_TEST(test_logger_parse_field_datetime)
174 180
 	pyfcgi_logger_fmt_field_t field;
175 181
 	char *vals[] = {"datetime:42}", "datetime::%s%F}",
176 182
 	                "datetime:42:COUCOU}",
177
-			"dat:32:FOO}", "d::BAR}", NULL};
178
-	int _len[] = {42, PYFCGI_LOG_DTM_LEN, 42, 32, PYFCGI_LOG_DTM_LEN};
183
+			"dat:32:FOO}", "d::BAR}",
184
+			"datetime}{level}", "datetime} {level}",
185
+			"datetime}:{level}",
186
+			NULL};
187
+	int _len[] = {42, PYFCGI_LOG_DTM_LEN, 42, 32, PYFCGI_LOG_DTM_LEN,
188
+	              PYFCGI_LOG_DTM_LEN, PYFCGI_LOG_DTM_LEN, PYFCGI_LOG_DTM_LEN};
179 189
 	char *_fmt[] = {PYFCGI_LOGGER_TIME_FMT_DEFAULT, "%s%F", "COUCOU", "FOO",
180
-	                "BAR"};
190
+	                "BAR", PYFCGI_LOGGER_TIME_FMT_DEFAULT,
191
+			PYFCGI_LOGGER_TIME_FMT_DEFAULT,
192
+			PYFCGI_LOGGER_TIME_FMT_DEFAULT};
181 193
 
182 194
 	memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
183 195
 	
@@ -339,8 +351,9 @@ START_TEST(test_logger_parse_field_msg)
339 351
 	int ret;
340 352
 	char **val, **ptr;
341 353
 	char err[PYFCGI_LOGGER_FMT_PARSE_ERRSZ];
342
-	char *vals[] = {"msg}", "m}", "ms}", NULL};
343 354
 	pyfcgi_logger_fmt_field_t field;
355
+	char *vals[] = {"msg}", "m}", "ms}", NULL};
356
+
344 357
 
345 358
 	val = vals;
346 359
 	memset(&field, 0, sizeof(pyfcgi_logger_fmt_field_t));
@@ -365,6 +378,35 @@ START_TEST(test_logger_parse_field_msg)
365 378
 }
366 379
 END_TEST
367 380
 
381
+START_TEST(test_logger_format_parse1)
382
+{
383
+	int ret, i;
384
+	size_t s;
385
+	pyfcgi_logger_init();
386
+	const char *fmt = "{datetime} {level} {ident}[{pid}] {msg}";
387
+	pyfcgi_logger_field_type_e types[] = {
388
+		pyfcgi_logger_field_datetime, pyfcgi_logger_field_const,
389
+		pyfcgi_logger_field_level, pyfcgi_logger_field_const,
390
+		pyfcgi_logger_field_ident, pyfcgi_logger_field_const,
391
+		pyfcgi_logger_field_pid, pyfcgi_logger_field_const,
392
+		pyfcgi_logger_field_msg};
393
+
394
+
395
+	ret = pyfcgi_logger_format_add(fmt, &s);
396
+	ck_assert_int_eq(ret, 0);
397
+	ck_assert_int_eq(conf->format_sz, 1);
398
+	ck_assert_int_eq(s, 0);
399
+	ck_assert_str_eq(conf->formats[s].fmt, fmt);
400
+	for(i=0; i<9; i++)
401
+	{
402
+dprintf(2, "I=%d\n", i);
403
+		ck_assert_int_eq(conf->formats[s].fields[i].type, types[i]);
404
+	}
405
+	ck_assert_int_eq(conf->formats[s].nfield, 9);
406
+
407
+}
408
+END_TEST
409
+
368 410
 /*
369 411
 	TC logger format parsing error
370 412
 */
@@ -425,11 +467,6 @@ Suite * logger_suite(void)
425 467
 
426 468
 	s = suite_create("Logger");
427 469
 
428
-	tc_init = tcase_create("Initialisation");
429
-	tcase_add_test(tc_init, test_logger_init);
430
-	//tcase_add_test(tc_init, test_logger_format_add);
431
-	suite_add_tcase(s, tc_init);
432
-
433 470
 	tc_field_default = tcase_create("Logger format parsing default values");
434 471
 	tcase_add_test(tc_field_default, test_logger_parse_field_dtfmt_default);
435 472
 	tcase_add_test(tc_field_default, test_logger_parse_field_sz_default);
@@ -444,6 +481,7 @@ Suite * logger_suite(void)
444 481
 	tcase_add_test(tc_field, test_logger_parse_field_pid);
445 482
 	tcase_add_test(tc_field, test_logger_parse_field_ident);
446 483
 	tcase_add_test(tc_field, test_logger_parse_field_msg);
484
+	tcase_add_test(tc_field, test_logger_format_parse1);
447 485
 	suite_add_tcase(s, tc_field);
448 486
 
449 487
 	tc_parse_err = tcase_create("Logger format parsing errors handling");
@@ -451,6 +489,11 @@ Suite * logger_suite(void)
451 489
 	tcase_add_test(tc_parse_err, test_logger_parse_field_parse_err);
452 490
 	suite_add_tcase(s, tc_parse_err);
453 491
 	
492
+	tc_init = tcase_create("Initialisation");
493
+	tcase_add_test(tc_init, test_logger_init);
494
+	tcase_add_test(tc_init, test_logger_format_add);
495
+	suite_add_tcase(s, tc_init);
496
+
454 497
 
455 498
 	return s;
456 499
 }

Loading…
Cancel
Save