Browse code

core: -e - new cli parameter to enable colorful log messages

- used only when log messages are printed to stderr
- each log level is printed in different color, using term colors (like
$C(xy) variable)

Elena-Ramona Modroiu authored on 01/09/2012 14:16:21
Showing 3 changed files
... ...
@@ -140,3 +140,206 @@ void reset_local_debug_level(void)
140 140
 {
141 141
 	_local_debug_level = UNSET_LOCAL_DEBUG_LEVEL;
142 142
 }
143
+
144
+typedef struct log_level_color {
145
+	char f;
146
+	char b;
147
+} log_level_color_t;
148
+
149
+log_level_color_t _log_level_colors[L_MAX - L_MIN + 1];
150
+
151
+void dprint_init_colors(void)
152
+{
153
+	int i;
154
+
155
+	i = 0;
156
+
157
+	memset(_log_level_colors, 0,
158
+			(L_MAX - L_MIN + 1)*sizeof(log_level_color_t));
159
+
160
+	/* L_ALERT */
161
+	_log_level_colors[i].f = 'R'; /* default */
162
+	_log_level_colors[i].b = 'x'; /* default */
163
+	i++;
164
+
165
+	/* L_BUG */
166
+	_log_level_colors[i].f = 'P'; /* default */
167
+	_log_level_colors[i].b = 'x'; /* default */
168
+	i++;
169
+
170
+	/* L_CRIT2 */
171
+	_log_level_colors[i].f = 'y'; /* default */
172
+	_log_level_colors[i].b = 'x'; /* default */
173
+	i++;
174
+
175
+	/* L_CRIT */
176
+	_log_level_colors[i].f = 'b'; /* default */
177
+	_log_level_colors[i].b = 'x'; /* default */
178
+	i++;
179
+
180
+	/* L_ERR */
181
+	_log_level_colors[i].f = 'r'; /* default */
182
+	_log_level_colors[i].b = 'x'; /* default */
183
+	i++;
184
+
185
+	/* L_WARN */
186
+	_log_level_colors[i].f = 'p'; /* default */
187
+	_log_level_colors[i].b = 'x'; /* default */
188
+	i++;
189
+
190
+	/* L_NOTICE */
191
+	_log_level_colors[i].f = 'g'; /* default */
192
+	_log_level_colors[i].b = 'x'; /* default */
193
+	i++;
194
+
195
+	/* L_INFO */
196
+	_log_level_colors[i].f = 'c'; /* default */
197
+	_log_level_colors[i].b = 'x'; /* default */
198
+	i++;
199
+
200
+	/* L_DBG */
201
+	_log_level_colors[i].f = 'x'; /* default */
202
+	_log_level_colors[i].b = 'x'; /* default */
203
+	i++;
204
+}
205
+
206
+#define TERM_COLOR_SIZE 16
207
+
208
+#define dprint_termc_add(p, end, s) \
209
+        do{ \
210
+                if ((p)+(sizeof(s)-1)<=(end)){ \
211
+                        memcpy((p), s, sizeof(s)-1); \
212
+                        (p)+=sizeof(s)-1; \
213
+                }else{ \
214
+                        /* overflow */ \
215
+                        LM_ERR("dprint_termc_add overflow\n"); \
216
+                        goto error; \
217
+                } \
218
+        } while(0)
219
+
220
+
221
+void dprint_term_color(char f, char b, str *obuf)
222
+{
223
+	static char term_color[TERM_COLOR_SIZE];
224
+	char* p;
225
+	char* end;
226
+
227
+	p = term_color;
228
+	end = p + TERM_COLOR_SIZE;
229
+
230
+	/* excape sequence */
231
+	dprint_termc_add(p, end, "\033[");
232
+
233
+	if(f!='_')
234
+	{
235
+		if (islower((int)f))
236
+		{
237
+			/* normal font */
238
+			dprint_termc_add(p, end, "0;");
239
+		} else {
240
+			/* bold font */
241
+			dprint_termc_add(p, end, "1;");
242
+			f += 32;
243
+		}
244
+	}
245
+
246
+	/* foreground */
247
+	switch(f)
248
+	{
249
+		case 'x':
250
+			dprint_termc_add(p, end, "39;");
251
+		break;
252
+		case 's':
253
+			dprint_termc_add(p, end, "30;");
254
+		break;
255
+		case 'r':
256
+			dprint_termc_add(p, end, "31;");
257
+		break;
258
+		case 'g':
259
+			dprint_termc_add(p, end, "32;");
260
+		break;
261
+		case 'y':
262
+			dprint_termc_add(p, end, "33;");
263
+		break;
264
+		case 'b':
265
+			dprint_termc_add(p, end, "34;");
266
+		break;
267
+		case 'p':
268
+			dprint_termc_add(p, end, "35;");
269
+		break;
270
+		case 'c':
271
+			dprint_termc_add(p, end, "36;");
272
+		break;
273
+		case 'w':
274
+			dprint_termc_add(p, end, "37;");
275
+		break;
276
+		default:
277
+			dprint_termc_add(p, end, "39;");
278
+	}
279
+
280
+	/* background */
281
+	switch(b)
282
+	{
283
+		case 'x':
284
+			dprint_termc_add(p, end, "49");
285
+		break;
286
+		case 's':
287
+			dprint_termc_add(p, end, "40");
288
+		break;
289
+		case 'r':
290
+			dprint_termc_add(p, end, "41");
291
+		break;
292
+		case 'g':
293
+			dprint_termc_add(p, end, "42");
294
+		break;
295
+		case 'y':
296
+			dprint_termc_add(p, end, "43");
297
+		break;
298
+		case 'b':
299
+			dprint_termc_add(p, end, "44");
300
+		break;
301
+		case 'p':
302
+			dprint_termc_add(p, end, "45");
303
+		break;
304
+		case 'c':
305
+			dprint_termc_add(p, end, "46");
306
+		break;
307
+		case 'w':
308
+			dprint_termc_add(p, end, "47");
309
+		break;
310
+		default:
311
+			dprint_termc_add(p, end, "49");
312
+	}
313
+
314
+	/* end */
315
+	dprint_termc_add(p, end, "m");
316
+
317
+	obuf->s = term_color;
318
+	obuf->len = p - term_color;
319
+	return;
320
+
321
+error:
322
+	obuf->s = term_color;
323
+	term_color[0] = '\0';
324
+	obuf->len = 0;
325
+}
326
+
327
+void dprint_color(int level)
328
+{
329
+	str obuf;
330
+
331
+	if(level<L_MIN || level>L_MAX)
332
+		return;
333
+	dprint_term_color(_log_level_colors[level - L_MIN].f,
334
+			_log_level_colors[level - L_MIN].b,
335
+			&obuf);
336
+	fprintf(stderr, "%.*s", obuf.len, obuf.s);
337
+}
338
+
339
+void dprint_color_reset(void)
340
+{
341
+	str obuf;
342
+
343
+	dprint_term_color('x', 'x', &obuf);
344
+	fprintf(stderr, "%.*s", obuf.len, obuf.s);
345
+}
... ...
@@ -81,6 +81,7 @@
81 81
 /*
82 82
  * Log levels
83 83
  */
84
+#define L_MIN		-5
84 85
 #define L_ALERT		-5
85 86
 #define L_BUG		-4
86 87
 #define L_CRIT2		-3  /* like L_CRIT, but adds prefix */
... ...
@@ -90,6 +91,7 @@
90 90
 #define L_NOTICE 	1
91 91
 #define L_INFO   	2
92 92
 #define L_DBG    	3
93
+#define L_MAX    	3
93 94
 
94 95
 /** @brief This is the facility value used to indicate that the caller of the macro
95 96
  * did not override the facility. Value 0 (the defaul) is LOG_KERN on Linux
... ...
@@ -109,6 +111,8 @@ extern int my_pid(void);
109 109
 /** @brief non-zero if logging to stderr instead to the syslog */
110 110
 extern int log_stderr;
111 111
 
112
+extern int log_color;
113
+
112 114
 /** @brief maps log levels to their string name and corresponding syslog level */
113 115
 
114 116
 struct log_level_info {
... ...
@@ -133,6 +137,9 @@ extern volatile int dprint_crit;
133 133
 int str2facility(char *s);
134 134
 int log_facility_fixup(void *handle, str *gname, str *name, void **val);
135 135
 
136
+void dprint_color(int level);
137
+void dprint_color_reset(void);
138
+void dprint_init_colors(void);
136 139
 
137 140
 /** @brief
138 141
  * General logging macros
... ...
@@ -175,10 +182,12 @@ int log_facility_fixup(void *handle, str *gname, str *name, void **val);
175 175
 					DPRINT_CRIT_ENTER; \
176 176
 					if (likely(((level) >= L_ALERT) && ((level) <= L_DBG))){ \
177 177
 						if (unlikely(log_stderr)) { \
178
+							if (unlikely(log_color)) dprint_color(level); \
178 179
 							fprintf(stderr, "%2d(%d) %s: %s" fmt, \
179 180
 									process_no, my_pid(), \
180 181
 									LOG_LEVEL2NAME(level), (prefix), \
181 182
 									__VA_ARGS__); \
183
+							if (unlikely(log_color)) dprint_color_reset(); \
182 184
 						} else { \
183 185
 							syslog(LOG2SYSLOG_LEVEL(level) | \
184 186
 								   (((facility) != DEFAULT_FACILITY) ? \
... ...
@@ -189,9 +198,11 @@ int log_facility_fixup(void *handle, str *gname, str *name, void **val);
189 189
 						} \
190 190
 					} else { \
191 191
 						if (log_stderr) { \
192
+							if (unlikely(log_color)) dprint_color(level); \
192 193
 							fprintf(stderr, "%2d(%d) %s" fmt, \
193 194
 									process_no, my_pid(), \
194 195
 									(prefix),  __VA_ARGS__); \
196
+							if (unlikely(log_color)) dprint_color_reset(); \
195 197
 						} else { \
196 198
 							if ((level)<L_ALERT) \
197 199
 								syslog(LOG2SYSLOG_LEVEL(L_ALERT) | \
... ...
@@ -237,10 +248,12 @@ int log_facility_fixup(void *handle, str *gname, str *name, void **val);
237 237
 					DPRINT_CRIT_ENTER; \
238 238
 					if (likely(((level) >= L_ALERT) && ((level) <= L_DBG))){ \
239 239
 						if (unlikely(log_stderr)) { \
240
+							if (unlikely(log_color)) dprint_color(level); \
240 241
 							fprintf(stderr, "%2d(%d) %s: %s" fmt, \
241 242
 									process_no, my_pid(), \
242 243
 									LOG_LEVEL2NAME(level), \
243 244
 									(prefix) , ## args);\
245
+							if (unlikely(log_color)) dprint_color_reset(); \
244 246
 						} else { \
245 247
 							syslog(LOG2SYSLOG_LEVEL(level) |\
246 248
 								   (((facility) != DEFAULT_FACILITY) ? \
... ...
@@ -251,9 +264,11 @@ int log_facility_fixup(void *handle, str *gname, str *name, void **val);
251 251
 						} \
252 252
 					} else { \
253 253
 						if (log_stderr) { \
254
+							if (unlikely(log_color)) dprint_color(level); \
254 255
 							fprintf(stderr, "%2d(%d) %s" fmt, \
255 256
 										process_no, my_pid(), \
256 257
 										(prefix) , ## args); \
258
+							if (unlikely(log_color)) dprint_color_reset(); \
257 259
 						} else { \
258 260
 							if ((level)<L_ALERT) \
259 261
 								syslog(LOG2SYSLOG_LEVEL(L_ALERT) | \
... ...
@@ -229,7 +229,8 @@ Options:\n\
229 229
     -d           Debugging mode (multiple -d increase the level)\n\
230 230
     -D no        1..do not fork (almost) anyway, 2..do not daemonize creator\n\
231 231
                   3..daemonize (default)\n\
232
-    -E           Log to stderr\n"
232
+    -E           Log to stderr\n\
233
+    -e           Log messages printed in terminal colors (requires -E)\n"
233 234
 #ifdef USE_TCP
234 235
 "    -T           Disable tcp\n\
235 236
     -N           Number of tcp child processes (default: equal to `-n')\n\
... ...
@@ -373,6 +374,7 @@ int sig_flag = 0;              /* last signal received */
373 373
 int dont_fork = 0;
374 374
 int dont_daemonize = 0;
375 375
 int log_stderr = 0;
376
+int log_color = 0;
376 377
 /* set custom app name for syslog printing */
377 378
 char *log_name = 0;
378 379
 pid_t creator_pid = (pid_t) -1;
... ...
@@ -1854,8 +1856,11 @@ int main(int argc, char** argv)
1854 1854
 	dont_fork_cnt=0;
1855 1855
 
1856 1856
 	daemon_status_init();
1857
+
1858
+	dprint_init_colors();
1859
+
1857 1860
 	/* command line options */
1858
-	options=  ":f:cm:M:dVIhEb:l:L:n:vrRDTN:W:w:t:u:g:P:G:SQ:O:a:A:"
1861
+	options=  ":f:cm:M:dVIhEeb:l:L:n:vrRDTN:W:w:t:u:g:P:G:SQ:O:a:A:"
1859 1862
 #ifdef STATS
1860 1863
 		"s:"
1861 1864
 #endif
... ...
@@ -1878,6 +1883,9 @@ int main(int argc, char** argv)
1878 1878
 			case 'E':
1879 1879
 					log_stderr=1;
1880 1880
 					break;
1881
+			case 'e':
1882
+					log_color=1;
1883
+					break;
1881 1884
 			case 'M':
1882 1885
 					pkg_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
1883 1886
 					if (tmp &&(*tmp)){
... ...
@@ -1972,6 +1980,9 @@ int main(int argc, char** argv)
1972 1972
 			case 'E':
1973 1973
 					/* ignore it, was parsed immediately after startup */
1974 1974
 					break;
1975
+			case 'e':
1976
+					/* ignore it, was parsed immediately after startup */
1977
+					break;
1975 1978
 			case 'O':
1976 1979
 					scr_opt_lev=strtol(optarg, &tmp, 10);
1977 1980
 					if (tmp &&(*tmp)){
... ...
@@ -2128,6 +2139,10 @@ try_again:
2128 2128
 					log_stderr=1;	/* use in both getopt switches,
2129 2129
 									   takes priority over config */
2130 2130
 					break;
2131
+			case 'e':
2132
+					log_color=1;	/* use in both getopt switches,
2133
+									   takes priority over config */
2134
+					break;
2131 2135
 			case 'b':
2132 2136
 					maxbuffer=strtol(optarg, &tmp, 10);
2133 2137
 					if (tmp &&(*tmp)){