blob: 303d893637315b2c5a3314fdb45a038657224967 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pj/types.h>
21#include <pj/log.h>
22#include <pj/string.h>
23#include <pj/os.h>
Benny Prijono9033e312005-11-21 02:08:39 +000024#include <pj/compat/stdarg.h>
25
26#if PJ_LOG_MAX_LEVEL >= 1
27
Benny Prijono8ab968f2007-07-20 08:08:30 +000028#if 0
29PJ_DEF_DATA(int) pj_log_max_level = PJ_LOG_MAX_LEVEL;
30#else
31static int pj_log_max_level = PJ_LOG_MAX_LEVEL;
32#endif
Benny Prijono9033e312005-11-21 02:08:39 +000033static pj_log_func *log_writer = &pj_log_write;
34static unsigned log_decor = PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC |
Benny Prijonod6e362a2008-07-19 17:53:47 +000035 PJ_LOG_HAS_SENDER | PJ_LOG_HAS_NEWLINE |
36 PJ_LOG_HAS_SPACE
37#if defined(PJ_WIN32) && PJ_WIN32!=0
38 | PJ_LOG_HAS_COLOR
39#endif
40 ;
41
42static pj_color_t PJ_LOG_COLOR_0 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
43static pj_color_t PJ_LOG_COLOR_1 = PJ_TERM_COLOR_BRIGHT | PJ_TERM_COLOR_R;
44static pj_color_t PJ_LOG_COLOR_2 = PJ_TERM_COLOR_BRIGHT |
45 PJ_TERM_COLOR_R |
46 PJ_TERM_COLOR_G;
47static pj_color_t PJ_LOG_COLOR_3 = PJ_TERM_COLOR_BRIGHT |
48 PJ_TERM_COLOR_R |
49 PJ_TERM_COLOR_G |
50 PJ_TERM_COLOR_B;
51static pj_color_t PJ_LOG_COLOR_4 = PJ_TERM_COLOR_R |
52 PJ_TERM_COLOR_G |
53 PJ_TERM_COLOR_B;
54static pj_color_t PJ_LOG_COLOR_5 = PJ_TERM_COLOR_R |
55 PJ_TERM_COLOR_G |
56 PJ_TERM_COLOR_B;
57static pj_color_t PJ_LOG_COLOR_6 = PJ_TERM_COLOR_R |
58 PJ_TERM_COLOR_G |
59 PJ_TERM_COLOR_B;
60/* Default terminal color */
61static pj_color_t PJ_LOG_COLOR_77 = PJ_TERM_COLOR_R |
62 PJ_TERM_COLOR_G |
63 PJ_TERM_COLOR_B;
Benny Prijono9033e312005-11-21 02:08:39 +000064
65#if PJ_LOG_USE_STACK_BUFFER==0
66static char log_buffer[PJ_LOG_MAX_SIZE];
67#endif
68
69PJ_DEF(void) pj_log_set_decor(unsigned decor)
70{
71 log_decor = decor;
72}
73
74PJ_DEF(unsigned) pj_log_get_decor(void)
75{
76 return log_decor;
77}
78
Benny Prijonod6e362a2008-07-19 17:53:47 +000079PJ_DEF(void) pj_log_set_color(int level, pj_color_t color)
80{
81 switch (level)
82 {
83 case 0: PJ_LOG_COLOR_0 = color;
84 break;
85 case 1: PJ_LOG_COLOR_1 = color;
86 break;
87 case 2: PJ_LOG_COLOR_2 = color;
88 break;
89 case 3: PJ_LOG_COLOR_3 = color;
90 break;
91 case 4: PJ_LOG_COLOR_4 = color;
92 break;
93 case 5: PJ_LOG_COLOR_5 = color;
94 break;
95 case 6: PJ_LOG_COLOR_6 = color;
96 break;
97 /* Default terminal color */
98 case 77: PJ_LOG_COLOR_77 = color;
99 break;
100 default:
101 /* Do nothing */
102 break;
103 }
104}
105
106PJ_DEF(pj_color_t) pj_log_get_color(int level)
107{
108 switch (level) {
109 case 0:
110 return PJ_LOG_COLOR_0;
111 case 1:
112 return PJ_LOG_COLOR_1;
113 case 2:
114 return PJ_LOG_COLOR_2;
115 case 3:
116 return PJ_LOG_COLOR_3;
117 case 4:
118 return PJ_LOG_COLOR_4;
119 case 5:
120 return PJ_LOG_COLOR_5;
121 case 6:
122 return PJ_LOG_COLOR_6;
123 default:
124 /* Return default terminal color */
125 return PJ_LOG_COLOR_77;
126 }
127}
128
Benny Prijono9033e312005-11-21 02:08:39 +0000129PJ_DEF(void) pj_log_set_level(int level)
130{
Benny Prijono505e82e2007-03-05 21:08:01 +0000131 pj_log_max_level = level;
Benny Prijono9033e312005-11-21 02:08:39 +0000132}
133
Benny Prijono8ab968f2007-07-20 08:08:30 +0000134#if 1
Benny Prijono9033e312005-11-21 02:08:39 +0000135PJ_DEF(int) pj_log_get_level(void)
136{
Benny Prijono505e82e2007-03-05 21:08:01 +0000137 return pj_log_max_level;
Benny Prijono9033e312005-11-21 02:08:39 +0000138}
Benny Prijono505e82e2007-03-05 21:08:01 +0000139#endif
Benny Prijono9033e312005-11-21 02:08:39 +0000140
141PJ_DEF(void) pj_log_set_log_func( pj_log_func *func )
142{
143 log_writer = func;
144}
145
146PJ_DEF(pj_log_func*) pj_log_get_log_func(void)
147{
148 return log_writer;
149}
150
151PJ_DEF(void) pj_log( const char *sender, int level,
152 const char *format, va_list marker)
153{
154 pj_time_val now;
155 pj_parsed_time ptime;
156 char *pre;
157#if PJ_LOG_USE_STACK_BUFFER
158 char log_buffer[PJ_LOG_MAX_SIZE];
159#endif
Benny Prijonoccf95622006-02-07 18:48:01 +0000160 int len, print_len;
Benny Prijono9033e312005-11-21 02:08:39 +0000161
162 PJ_CHECK_STACK();
163
Benny Prijono505e82e2007-03-05 21:08:01 +0000164 if (level > pj_log_max_level)
Benny Prijono9033e312005-11-21 02:08:39 +0000165 return;
166
167 /* Get current date/time. */
168 pj_gettimeofday(&now);
169 pj_time_decode(&now, &ptime);
170
171 pre = log_buffer;
Benny Prijono901a2c32008-07-28 21:15:04 +0000172 if (log_decor & PJ_LOG_HAS_LEVEL_TEXT) {
173 static const char *ltexts[] = { "FATAL:", "ERROR:", " WARN:",
174 " INFO:", "DEBUG:", "TRACE:", "DETRC:"};
175 pj_ansi_strcpy(pre, ltexts[level]);
176 pre += 6;
177 }
Benny Prijono9033e312005-11-21 02:08:39 +0000178 if (log_decor & PJ_LOG_HAS_DAY_NAME) {
179 static const char *wdays[] = { "Sun", "Mon", "Tue", "Wed",
180 "Thu", "Fri", "Sat"};
Benny Prijonoed811d72006-03-10 12:57:12 +0000181 pj_ansi_strcpy(pre, wdays[ptime.wday]);
Benny Prijono9033e312005-11-21 02:08:39 +0000182 pre += 3;
183 }
184 if (log_decor & PJ_LOG_HAS_YEAR) {
185 *pre++ = ' ';
186 pre += pj_utoa(ptime.year, pre);
187 }
188 if (log_decor & PJ_LOG_HAS_MONTH) {
189 *pre++ = '-';
Benny Prijono9cb09a22007-08-30 09:35:10 +0000190 pre += pj_utoa_pad(ptime.mon+1, pre, 2, '0');
Benny Prijono9033e312005-11-21 02:08:39 +0000191 }
192 if (log_decor & PJ_LOG_HAS_DAY_OF_MON) {
Benny Prijonod6e362a2008-07-19 17:53:47 +0000193 *pre++ = '-';
Benny Prijono9033e312005-11-21 02:08:39 +0000194 pre += pj_utoa_pad(ptime.day, pre, 2, '0');
195 }
196 if (log_decor & PJ_LOG_HAS_TIME) {
197 *pre++ = ' ';
198 pre += pj_utoa_pad(ptime.hour, pre, 2, '0');
199 *pre++ = ':';
200 pre += pj_utoa_pad(ptime.min, pre, 2, '0');
201 *pre++ = ':';
202 pre += pj_utoa_pad(ptime.sec, pre, 2, '0');
203 }
204 if (log_decor & PJ_LOG_HAS_MICRO_SEC) {
205 *pre++ = '.';
206 pre += pj_utoa_pad(ptime.msec, pre, 3, '0');
207 }
208 if (log_decor & PJ_LOG_HAS_SENDER) {
Benny Prijono0016d0c2006-08-11 12:42:06 +0000209 enum { SENDER_WIDTH = 14 };
Benny Prijono9033e312005-11-21 02:08:39 +0000210 int sender_len = strlen(sender);
211 *pre++ = ' ';
212 if (sender_len <= SENDER_WIDTH) {
213 while (sender_len < SENDER_WIDTH)
214 *pre++ = ' ', ++sender_len;
215 while (*sender)
216 *pre++ = *sender++;
217 } else {
218 int i;
219 for (i=0; i<SENDER_WIDTH; ++i)
220 *pre++ = *sender++;
221 }
222 }
223
224 if (log_decor != 0 && log_decor != PJ_LOG_HAS_NEWLINE)
225 *pre++ = ' ';
226
Benny Prijonod6e362a2008-07-19 17:53:47 +0000227 if (log_decor & PJ_LOG_HAS_SPACE) {
228 *pre++ = ' ';
229 }
230
Benny Prijono9033e312005-11-21 02:08:39 +0000231 len = pre - log_buffer;
232
233 /* Print the whole message to the string log_buffer. */
Benny Prijonoed811d72006-03-10 12:57:12 +0000234 print_len = pj_ansi_vsnprintf(pre, sizeof(log_buffer)-len, format,
235 marker);
Benny Prijonoccf95622006-02-07 18:48:01 +0000236 if (print_len < 0) {
Benny Prijono6e996dd2006-06-19 12:08:27 +0000237 level = 1;
Benny Prijonoed811d72006-03-10 12:57:12 +0000238 print_len = pj_ansi_snprintf(pre, sizeof(log_buffer)-len,
239 "<logging error: msg too long>");
Benny Prijonoccf95622006-02-07 18:48:01 +0000240 }
241 len = len + print_len;
Benny Prijonoa1e69682007-05-11 15:14:34 +0000242 if (len > 0 && len < (int)sizeof(log_buffer)-2) {
Benny Prijono9cf138e2006-01-19 03:58:29 +0000243 if (log_decor & PJ_LOG_HAS_CR) {
244 log_buffer[len++] = '\r';
245 }
Benny Prijono9033e312005-11-21 02:08:39 +0000246 if (log_decor & PJ_LOG_HAS_NEWLINE) {
247 log_buffer[len++] = '\n';
248 }
Benny Prijono0f3173d2006-10-13 13:48:56 +0000249 log_buffer[len] = '\0';
Benny Prijono9033e312005-11-21 02:08:39 +0000250 } else {
251 len = sizeof(log_buffer)-1;
Benny Prijono9cf138e2006-01-19 03:58:29 +0000252 if (log_decor & PJ_LOG_HAS_CR) {
253 log_buffer[sizeof(log_buffer)-3] = '\r';
254 }
Benny Prijono9033e312005-11-21 02:08:39 +0000255 if (log_decor & PJ_LOG_HAS_NEWLINE) {
256 log_buffer[sizeof(log_buffer)-2] = '\n';
257 }
258 log_buffer[sizeof(log_buffer)-1] = '\0';
259 }
260
261 if (log_writer)
262 (*log_writer)(level, log_buffer, len);
263}
264
Benny Prijono8ab968f2007-07-20 08:08:30 +0000265/*
Benny Prijono9033e312005-11-21 02:08:39 +0000266PJ_DEF(void) pj_log_0(const char *obj, const char *format, ...)
267{
268 va_list arg;
269 va_start(arg, format);
270 pj_log(obj, 0, format, arg);
271 va_end(arg);
272}
Benny Prijono8ab968f2007-07-20 08:08:30 +0000273*/
Benny Prijono9033e312005-11-21 02:08:39 +0000274
275PJ_DEF(void) pj_log_1(const char *obj, const char *format, ...)
276{
277 va_list arg;
278 va_start(arg, format);
279 pj_log(obj, 1, format, arg);
280 va_end(arg);
281}
282#endif /* PJ_LOG_MAX_LEVEL >= 1 */
283
284#if PJ_LOG_MAX_LEVEL >= 2
285PJ_DEF(void) pj_log_2(const char *obj, const char *format, ...)
286{
287 va_list arg;
288 va_start(arg, format);
289 pj_log(obj, 2, format, arg);
290 va_end(arg);
291}
292#endif
293
294#if PJ_LOG_MAX_LEVEL >= 3
295PJ_DEF(void) pj_log_3(const char *obj, const char *format, ...)
296{
297 va_list arg;
298 va_start(arg, format);
299 pj_log(obj, 3, format, arg);
300 va_end(arg);
301}
302#endif
303
304#if PJ_LOG_MAX_LEVEL >= 4
305PJ_DEF(void) pj_log_4(const char *obj, const char *format, ...)
306{
307 va_list arg;
308 va_start(arg, format);
309 pj_log(obj, 4, format, arg);
310 va_end(arg);
311}
312#endif
313
314#if PJ_LOG_MAX_LEVEL >= 5
315PJ_DEF(void) pj_log_5(const char *obj, const char *format, ...)
316{
317 va_list arg;
318 va_start(arg, format);
319 pj_log(obj, 5, format, arg);
320 va_end(arg);
321}
322#endif
323
324#if PJ_LOG_MAX_LEVEL >= 6
325PJ_DEF(void) pj_log_6(const char *obj, const char *format, ...)
326{
327 va_list arg;
328 va_start(arg, format);
329 pj_log(obj, 6, format, arg);
330 va_end(arg);
331}
332#endif
333