1 /*----------------------------------------------------------------------------
2 Name: Log.cpp
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Comment: Handling the Client data
6 ----------------------------------------------------------------------------*/
7 #include <util/Log.h>
8 #include <iostream>
9 #include <ctime> //<time.h>
10 #include <cstdlib> //<stdlib.h>
11 #include <util/lexical_cast.h>
12 #include <util/PropertyDef.h>
13
14 using namespace std;
15
16 namespace org { namespace xmlBlaster {
17 namespace util {
18
19 const char* const Log::ESC = "\033[0m";
20 const char* const Log::BOLD = "\033[1m";
21 const char* const Log::RED_BLACK = "\033[31;40m";
22 const char* const Log::GREEN_BLACK = "\033[32;40m";
23 const char* const Log::YELLOW_BLACK = "\033[33;40m";
24 const char* const Log::BLUE_BLACK = "\033[34;40m";
25 const char* const Log::PINK_BLACK = "\033[35;40m";
26 const char* const Log::LTGREEN_BLACK= "\033[36;40m";
27 const char* const Log::WHITE_BLACK = "\033[37;40m";
28 const char* const Log::WHITE_RED = "\033[37;41m";
29 const char* const Log::BLACK_RED = "\033[30;41m";
30 const char* const Log::BLACK_GREEN = "\033[40;42m";
31 const char* const Log::BLACK_PINK = "\033[40;45m";
32 const char* const Log::BLACK_LTGREEN= "\033[40;46m";
33
34
35
36 /**
37 * Initializes logging and Properties
38 */
39 Log::Log(Property& properties, int /*args*/, const char * const /*argc*/[], const string& name)
40 : withXtermColor_(true), properties_(properties), name_(name)
41 {
42 ME = "Log";
43 # ifdef _WIN32
44 withXtermColor_ = false;
45 # endif
46 withXtermColor_ = properties.getBoolProperty("xmlBlaster.withXtermColor", withXtermColor_, true);
47 call_ = true;
48 time_ = true;
49 trace_ = true;
50 dump_ = true;
51 numWarnInvocations = 0;
52 numErrorInvocations = 0;
53 currentLogFormat = "{0} {1} {2}: {3}";
54 logFormatPropertyRead = false;
55 logLevel_ = L_PANIC | L_ERROR | L_WARN | L_INFO;
56
57 timeE = string(LTGREEN_BLACK) + "TIME " + ESC;
58 callE = string(BLACK_LTGREEN) + "CALL " + ESC;
59 traceE = string(WHITE_BLACK ) + "TRACE" + ESC;
60 plainE = string(WHITE_BLACK ) + " " + ESC;
61 infoE = string(GREEN_BLACK ) + "INFO " + ESC;
62 warnE = string(YELLOW_BLACK ) + "WARN " + ESC;
63 errorE = string(RED_BLACK ) + "ERROR" + ESC;
64 panicE = string(BLACK_RED ) + "PANIC" + ESC;
65 exitE = string(GREEN_BLACK ) + "EXIT " + ESC;
66
67 timeX = "TIME ";
68 callX = "CALL ";
69 traceX = "TRACE";
70 plainX = " ";
71 infoX = "INFO ";
72 warnX = "WARN ";
73 errorX = "ERROR";
74 panicX = "PANIC";
75 exitX = "EXIT ";
76 }
77
78
79 Log::~Log() {
80 }
81
82 void Log::exitLow(int val) {
83 // gcc 3.x: The functions abort, exit, _Exit and _exit are recognized and presumed not to return,
84 // but otherwise are not built in.
85 // _exit is not recognized in strict ISO C mode (`-ansi', `-std=c89' or `-std=c99').
86 // _Exit is not recognized in strict C89 mode (`-ansi' or `-std=c89').
87 # if defined(__ICC)
88 ::exit(val);
89 # elif __GNUC__==3
90 ::exit(val);
91 # elif __GNUC__==4
92 ::exit(val);
93 # elif defined(__sun)
94 ::exit(val);
95 # else
96 ::_exit(val);
97 # endif
98 }
99
100 void Log::setWithXtermColor(bool val /* = true */) {
101 withXtermColor_ = val;
102 }
103
104 void Log::setDefaultLogLevel() {
105 logLevel_ = L_PANIC | L_ERROR | L_WARN | L_INFO;
106 setPreLogLevelCheck();
107 }
108
109
110 void Log::setLogLevel(int level) {
111 logLevel_ = level;
112 setPreLogLevelCheck();
113 }
114
115 void Log::setLogLevel(int argc, const char * const args[]) {
116 if ((properties_.findArgument(argc, args, "-?") > 0) ||
117 (properties_.findArgument(argc, args, "-h") > 0)) {
118 std::cout << usage() << std::endl;
119 return;
120 }
121 initialize();
122 }
123
124
125 void Log::removeLogLevel(string logLevel) {
126 int level = logLevelToBit(logLevel);
127 logLevel_ = (logLevel_ & ~level);
128 setPreLogLevelCheck();
129 }
130
131
132 void Log::addLogLevel(string logLevel) {
133 int level = logLevelToBit(logLevel);
134 logLevel_ = (logLevel_ | level);
135 setPreLogLevelCheck();
136 //std::cout << "DEBUG: " << "Adding logLevel '" << logLevel << "' level=" << level << " dump=" << dump_ << std::endl;
137 }
138
139
140 void Log::setPreLogLevelCheck() {
141 call_ = time_ = trace_ = dump_ = false;
142 if (logLevel_ & L_CALL) call_ = true;
143 if (logLevel_ & L_TIME ) time_ = true;
144 if (logLevel_ & L_TRACE) trace_ = true;
145 if (logLevel_ & L_DUMP ) dump_ = true;
146 }
147
148
149 string Log::bitToLogLevel(int level) const {
150 string sb = "";
151 if (level & L_PANIC) sb += "PANIC";
152 if (level & L_ERROR) sb += " | ERROR";
153 if (level & L_WARN ) sb += " | WARN";
154 if (level & L_INFO ) sb += " | INFO";
155 if (level & L_CALL) sb += " | CALL";
156 if (level & L_TIME ) sb += " | TIME";
157 if (level & L_TRACE) sb += " | TRACE";
158 if (level & L_DUMP ) sb += " | DUMP";
159 return sb;
160 }
161
162
163 void Log::panic(const string &instance, const string &text) {
164 if (logLevel_ & L_PANIC) {
165 if (withXtermColor_)
166 log(panicE, L_PANIC, instance, text);
167 else
168 log(panicX, L_PANIC, instance, text);
169 cerr << text << endl;
170 numErrorInvocations++;
171 // displayStatistics();
172 exitLow(1);
173 }
174 }
175
176
177 void Log::exit(const string &instance, const string &text) {
178 if (withXtermColor_)
179 log(exitE, L_EXIT, instance, text);
180 else
181 log(exitX, L_EXIT, instance, text);
182 displayStatistics();
183 exitLow(0);
184 }
185
186
187 void Log::info(const string &instance, const string &text) {
188 if (logLevel_ & L_INFO) {
189 if (withXtermColor_)
190 log(infoE, L_INFO, instance, text);
191 else
192 log(infoX, L_INFO, instance, text);
193 }
194 }
195
196
197 void Log::warn(const string &instance, const string &text) {
198 if(logLevel_ & L_WARN) {
199 numWarnInvocations++;
200 if (withXtermColor_)
201 log(warnE, L_WARN, instance, text);
202 else
203 log(warnX, L_WARN, instance, text);
204 }
205 }
206
207
208 void Log::error(const string &instance, const string &text) {
209 if(logLevel_ & L_PANIC) {
210 numErrorInvocations++;
211 if (withXtermColor_)
212 log(errorE, L_ERROR, instance, text);
213 else
214 log(errorX, L_ERROR, instance, text);
215 }
216 }
217
218
219 void Log::plain(const string &/*instance*/, const string &text) {
220 log("", L_PLAIN, "", text);
221 }
222
223
224 void Log::dump(const string &instance, const string &text) {
225 if((logLevel_ & L_DUMP) != 0) {
226 log("", L_DUMP, instance, text);
227 // log("", L_DUMP, instance, Memory.getStatistic());
228 }
229 }
230
231
232 void Log::trace(const string &instance, const string &text) {
233 if(logLevel_ & L_TRACE) {
234 if (withXtermColor_)
235 log(traceE, L_TRACE, instance, text);
236 else
237 log(traceX, L_TRACE, instance, text);
238 }
239 }
240
241
242 void Log::call(const string &instance, const string &text) {
243 if(logLevel_ & L_CALL) {
244 if (withXtermColor_)
245 log(callE, L_CALL, instance, text);
246 else
247 log(callX, L_CALL, instance, text);
248 }
249 }
250
251
252 void Log::time(const string &instance, const string &text) {
253 if(logLevel_ & L_TIME) {
254 if (withXtermColor_)
255 log(timeE, L_TIME, instance, text);
256 else
257 log(timeX, L_TIME, instance, text);
258 }
259 }
260
261 void Log::log(const string &levelStr, int level, const string &instance,
262 const string &text) {
263 if (logFormatPropertyRead == false) {
264 initialize();
265 }
266
267 string logFormat;
268 if(level & L_DUMP)
269 logFormat = "{3}";
270 else
271 logFormat = currentLogFormat;
272
273 string logEntry = levelStr + " ";
274 if (level & L_TIME) logEntry += getTime() + ": ";
275 if ((level & L_ERROR) || (level & L_WARN) || (level & L_PANIC))
276 cerr << logEntry << instance << " " << text << endl;
277 else
278 cout << logEntry << instance << " " << text << endl;
279 }
280
281 std::string Log::usage() const {
282 std::string text = string("");
283 text += string("\nLogging options:");
284 text += string("\n -trace true Show code trace.");
285 text += string("\n -dump true Dump internal state.");
286 text += string("\n -call true Show important method entries");
287 text += string("\n -time true Display some performance data.");
288 //text += string("\n -logFile <fileName> Log to given file instead to console.");
289 return text;
290 }
291
292
293 void Log::displayStatistics() {
294 // Log.info(ME, Memory.getStatistic());
295 if (withXtermColor_) {
296 if (numErrorInvocations>0) {
297 info(ME, string(BLACK_RED) + "There were " + lexical_cast<std::string>(numErrorInvocations) +
298 " ERRORS and " + lexical_cast<std::string>(numWarnInvocations) + " WARNINGS" + ESC);
299 }
300 else if (numWarnInvocations>0) {
301 info(ME, string(BLACK_PINK) + "There were " + lexical_cast<std::string>(numErrorInvocations) +
302 " ERRORS and " + lexical_cast<std::string>(numWarnInvocations) + " WARNINGS" + ESC);
303 }
304 else {
305 info(ME, string(BLACK_GREEN) + "No errors/warnings were reported" + ESC);
306 }
307 }
308 else {
309 if (numErrorInvocations>0 || numWarnInvocations>0) {
310 info(ME, string("There were ") + lexical_cast<std::string>(numErrorInvocations) + " ERRORS and " + (lexical_cast<std::string>(numWarnInvocations)) + " WARNINGS");
311 }
312 else
313 info(ME, "No errors/warnings were reported");
314 }
315 }
316
317
318 void Log::printStack() {
319 cerr << "sorry, no Stack aviable" << endl;
320 }
321
322
323
324 void Log::initSpecificTrace(const string& trace, const string& traceId)
325 {
326 if (properties_.propertyExists(trace + "[" + name_ + "]")) {
327 if (properties_.getBoolProperty(trace + "[" + name_ + "]", false))
328 addLogLevel(traceId);
329 else removeLogLevel(traceId);
330 return;
331 }
332 if (properties_.propertyExists(trace)) {
333 if (properties_.getBoolProperty(trace, false))
334 addLogLevel(traceId);
335 else removeLogLevel(traceId);
336 }
337 }
338
339
340 void Log::initialize() {
341 setPreLogLevelCheck();
342 logFormatPropertyRead = true;
343 // Given flag -info switches off Log.info messages:
344 initSpecificTrace("info", "INFO");
345 initSpecificTrace("warn", "WARN");
346 initSpecificTrace("error", "ERROR");
347 initSpecificTrace("call", "CALL");
348 initSpecificTrace("time", "TIME");
349 initSpecificTrace("trace", "TRACE");
350 initSpecificTrace("dump", "DUMP");
351
352 if (properties_.getBoolProperty("+call", false))
353 addLogLevel("CALL");
354 if (properties_.getBoolProperty("+time", false))
355 addLogLevel("TIME");
356 if (properties_.getBoolProperty("+trace", false))
357 addLogLevel("TRACE");
358 if (properties_.getBoolProperty("+dump", false))
359 addLogLevel("DUMP");
360
361 // format: {0}:{1}:{2}:{3} <timestamp>:<levelStr>:<instance>:<text>
362 currentLogFormat = properties_.getStringProperty("LogFormat",
363 currentLogFormat);
364
365 //std::cout << "DEBUG: " << "Current logLevel for [" << name_ << "] is " << bitToLogLevel(logLevel_) << std::endl;
366
367 // string tmp = properties_.getStringProperty("LogFormat.Date","MEDIUM");
368 // if (tmp == "SHORT") lookAndFeelDate = java.text.DateFormat.SHORT;
369 // else if (tmp.equals("MEDIUM"))
370 // lookAndFeelDate = java.text.DateFormat.MEDIUM;
371 // else if (tmp.equals("LONG"))
372 // lookAndFeelDate = java.text.DateFormat.LONG;
373 // else if (tmp.equals("FULL"))
374 // lookAndFeelDate = java.text.DateFormat.FULL;
375 // tmp = properties_.getStringProperty("LogFormat.Time","MEDIUM");
376 // if (tmp.equals("SHORT"))
377 // lookAndFeelTime = java.text.DateFormat.SHORT;
378 // else if (tmp.equals("MEDIUM"))
379 // lookAndFeelTime = java.text.DateFormat.MEDIUM;
380 // else if (tmp.equals("LONG"))
381 // lookAndFeelTime = java.text.DateFormat.LONG;
382 // else if (tmp.equals("FULL"))
383 // lookAndFeelTime = java.text.DateFormat.FULL;
384
385 // string la = properties_.getStringProperty("LogFormat.Language","");
386 // string co = properties_.getStringProperty("LogFormat.Country", "");
387 // if (la != null && co != null) country = new Locale(la, co);
388
389 // String fileName = properties_.getProperty("logFile", (String)null);
390 // if (fileName != null)
391 // Log.logToFile(fileName);
392 }
393
394
395 string Log::getTime() {
396 // adapt it here to the correct time format (locales) ?!
397 time_t theTime;
398 ::time(&theTime);
399 string timeStr = ctime(&theTime), ret;
400 // eliminate new lines (if any)
401 string::size_type pos = timeStr.find("\n");
402 if (pos == string::npos) return timeStr;
403 ret.assign(timeStr, 0, pos);
404 return ret;
405 }
406
407 }}} // end of namespace
syntax highlighted by Code2HTML, v. 0.9.1