1 mike 1.13 //%/////////////////////////////////////////////////////////////////////////////
2 //
|
3 kumpf 1.18 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
|
5 mike 1.13 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 kumpf 1.18 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
10 mike 1.13 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
|
13 kumpf 1.18 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
14 mike 1.13 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
16 kumpf 1.18 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
19 mike 1.13 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 //==============================================================================
23 //
24 // Author: Mike Brasher (mbrasher@bmc.com)
25 //
|
26 kumpf 1.16 // Modified By: Sushma Fernandes (Hewlett-Packard Company)
27 // sushma_fernandes@hp.com
|
28 david 1.25 // Modified By: Dave Rosckes (IBM)
29 // rosckes@us.ibm.com
|
30 mike 1.13 //
31 //%/////////////////////////////////////////////////////////////////////////////
32
33 #include <iostream>
34 #include <fstream>
|
35 kumpf 1.23 #include <cstring>
|
36 mike 1.13 #include "Logger.h"
37 #include "System.h"
|
38 kumpf 1.16 #include "Destroyer.h"
|
39 humberto 1.30 #include <Pegasus/Common/MessageLoader.h> //l10n
|
40 kumpf 1.16
|
41 mike 1.13 PEGASUS_USING_STD;
42
43 PEGASUS_NAMESPACE_BEGIN
44
45 const Uint32 Logger::TRACE = (1 << 0);
46 const Uint32 Logger::INFORMATION = (1 << 1);
47 const Uint32 Logger::WARNING = (1 << 2);
48 const Uint32 Logger::SEVERE = (1 << 3);
49 const Uint32 Logger::FATAL = (1 << 4);
50
|
51 david 1.26 static char const* LOGLEVEL_LIST[] =
52 {
53 "TRACE",
54 "INFORMATION",
55 "WARNING",
56 "SEVERE",
57 "FATAL"
58 };
59
60
|
61 mike 1.13 LoggerRep* Logger::_rep = 0;
62 String Logger::_homeDirectory = ".";
|
63 kumpf 1.16
|
64 david 1.26 const Uint32 Logger::_NUM_LOGLEVEL = 5;
65
66 // Set separator
67 const char Logger::_SEPARATOR = '@';
68
69 Uint32 Logger::_severityMask;
|
70 kumpf 1.16
|
71 mike 1.13 Uint32 Logger::_writeControlMask = 0xF; // Set all on by default
72
|
73 david 1.26 // Set the return codes
74 const Boolean Logger::_SUCCESS = 1;
75 const Boolean Logger::_FAILURE = 0;
76
|
77 mike 1.13 /* _allocLogFileName. Allocates the name from a name set.
78 Today this is static. However, it should be completely
79 configerable and driven from the config file so that
80 Log organization and names are open.
81 ATTN: rewrite this so that names, choice to do logs and
82 mask for level of severity are all driven from configuration
83 input.
84 */
|
85 kumpf 1.22 static CString _allocLogFileName(
|
86 mike 1.13 const String& homeDirectory,
87 Logger::LogFileType logFileType)
88 {
|
89 mike 1.15 static const char* fileNames[] =
|
90 mike 1.13 {
91 "PegasusTrace.log",
92 "PegasusStandard.log",
93 "PegasusError.log",
94 "PegasusDebug.log"
95 };
96
97 int index = int(logFileType);
98
99 if (index > Logger::NUM_LOGS)
100 index = Logger::ERROR_LOG;
101
102 const char* logFileName = fileNames[index];
103
104 String result;
|
105 kumpf 1.19 result.reserveCapacity(homeDirectory.size() + 1 + strlen(logFileName));
|
106 kumpf 1.20 result.append(homeDirectory);
107 result.append('/');
108 result.append(logFileName);
|
109 kumpf 1.22 return result.getCString();
|
110 mike 1.13 }
111
112 class LoggerRep
113 {
114 public:
115
116 LoggerRep(const String& homeDirectory)
117 {
|
118 david 1.27 #if !defined(PEGASUS_USE_SYSLOGS)
|
119 mike 1.13 // Add test for home directory set.
120
121 // If home directory does not exist, create it.
|
122 kumpf 1.22 CString lgDir = homeDirectory.getCString();
|
123 mike 1.13
124 if (!System::isDirectory(lgDir))
125 System::makeDirectory(lgDir);
126
|
127 karl 1.14 // KS: I put the second test in just in case some trys to create
|
128 mike 1.13 // a completly erronous directory. At least we will get a message
|
129 humberto 1.30 if (!System::isDirectory(lgDir)){
130 //l10n
131 //cerr << "Logging Disabled";
132 MessageLoaderParms parms("Common.Logger.LOGGING_DISABLED",
133 "Logging Disabled");
134
135 cerr << MessageLoader::getMessage(parms);
136 }
|
137 mike 1.13
|
138 kumpf 1.22 CString fileName = _allocLogFileName(homeDirectory, Logger::TRACE_LOG);
|
139 mike 1.13 _logs[Logger::TRACE_LOG].open(fileName, ios::app);
140
141 fileName = _allocLogFileName(homeDirectory, Logger::STANDARD_LOG);
142 _logs[Logger::STANDARD_LOG].open(fileName, ios::app);
143
144 fileName = _allocLogFileName(homeDirectory, Logger::ERROR_LOG);
145 _logs[Logger::ERROR_LOG].open(fileName, ios::app);
146
147 fileName = _allocLogFileName(homeDirectory, Logger::DEBUG_LOG);
148 _logs[Logger::DEBUG_LOG].open(fileName, ios::app);
|
149 kumpf 1.17 #endif
|
150 mike 1.13
151 }
152
153 ostream& logOf(Logger::LogFileType logFileType)
154 {
155 int index = int(logFileType);
156
157 if (index > int(Logger::ERROR_LOG))
158 index = Logger::ERROR_LOG;
159
160 return _logs[index];
161 }
162
163 private:
164
165 ofstream _logs[int(Logger::NUM_LOGS)];
166 };
167
|
168 david 1.26 void Logger::_putInternal(
|
169 mike 1.13 LogFileType logFileType,
170 const String& systemId,
|
171 david 1.26 const Uint32 logComponent, // TODO: Support logComponent mask in future release
172 Uint32 logLevel,
|
173 mike 1.13 const String& formatString,
|
174 chuck 1.29 const String& messageId, // l10n
|
175 mike 1.13 const Formatter::Arg& arg0,
176 const Formatter::Arg& arg1,
177 const Formatter::Arg& arg2,
178 const Formatter::Arg& arg3,
179 const Formatter::Arg& arg4,
180 const Formatter::Arg& arg5,
181 const Formatter::Arg& arg6,
182 const Formatter::Arg& arg7,
183 const Formatter::Arg& arg8,
184 const Formatter::Arg& arg9)
185 {
|
186 david 1.26 // Test for logLevel against severity mask to determine
|
187 mike 1.13 // if we write this log.
|
188 david 1.26 if ((_severityMask & logLevel) != 0)
|
189 mike 1.13 {
190 if (!_rep)
191 _rep = new LoggerRep(_homeDirectory);
192
|
193 chuck 1.29 // Get the logLevel String
194 // This converts bitmap to string based on highest order
195 // bit set
196 // ATTN: KS Fix this more efficiently.
197 static const char* svNames[] =
198 {
|
199 mike 1.13 "TRACE ",
200 "INFO ",
201 "WARNING ",
202 "SEVERE ",
203 "FATAL "
|
204 chuck 1.29 };
205 // NUM_LEVELS = 5
206 int sizeSvNames = sizeof(svNames) / sizeof(svNames[0]) - 1;
207
208 // l10n start
209 // The localized message to be sent to the system log.
210 String localizedMsg;
211
212 // If the caller specified a messageId, then load the localized
213 // message in the locale of the server process.
214 if (messageId != String::EMPTY)
215 {
216 // A message ID was specified. Use the MessageLoader.
217 MessageLoaderParms msgParms(messageId, formatString);
218 msgParms.useProcessLocale = true;
219 msgParms.arg0 = arg0;
220 msgParms.arg1 = arg1;
221 msgParms.arg2 = arg2;
222 msgParms.arg3 = arg3;
223 msgParms.arg4 = arg4;
224 msgParms.arg5 = arg5;
225 chuck 1.29 msgParms.arg6 = arg6;
226 msgParms.arg7 = arg7;
227 msgParms.arg8 = arg8;
228 msgParms.arg9 = arg9;
229
230 localizedMsg = MessageLoader::getMessage(msgParms);
231 }
232 else
233 { // No message ID. Use the Pegasus formatter
234 localizedMsg = Formatter::format(formatString,
235 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
236 }
237 // l10n end
238
|
239 david 1.26 #if defined(PEGASUS_USE_SYSLOGS)
240
|
241 kumpf 1.16 // Open the syslog.
242 // Ignore the systemId and open the log as cimserver
|
243 david 1.26 System::openlog(systemId);
|
244 kumpf 1.16
245 // Log the message
|
246 chuck 1.29 System::syslog(logLevel,(const char*)localizedMsg.getCString());
247 // l10n TODO uncomment this line
248 // System::syslog(logLevel,(const char*)localizedMsg.getCStringUTF8());
249
|
250 kumpf 1.16
251 // Close the syslog.
|
252 david 1.26 System::closelog();
|
253 david 1.25
|
254 david 1.26 #else
|
255 david 1.25
|
256 david 1.26 // Prepend the systemId to the incoming message
257 String messageString(systemId);
258 messageString.append(": ");
|
259 chuck 1.29 messageString.append(localizedMsg); // l10n - TODO need to send as UTF-8
|
260 david 1.25
|
261 kumpf 1.16 const char* tmp = "";
|
262 david 1.26 if (logLevel & Logger::TRACE) tmp = "TRACE ";
263 if (logLevel & Logger::INFORMATION) tmp = "INFO ";
264 if (logLevel & Logger::WARNING) tmp = "WARNING ";
265 if (logLevel & Logger::SEVERE) tmp = "SEVERE ";
266 if (logLevel & Logger::FATAL) tmp = "FATAL ";
|
267 chuck 1.29 _rep->logOf(logFileType) << System::getCurrentASCIITime()
268 << " " << tmp << messageString.getCString() << endl;
269 // l10n - TODO uncomment this
270 // << " " << tmp << messageString.getCStringUTF8() << endl;
|
271 david 1.26
|
272 kumpf 1.16 #endif
|
273 david 1.26 }
274 }
|
275 mike 1.13
|
276 david 1.26 void Logger::put(
277 LogFileType logFileType,
278 const String& systemId,
279 Uint32 logLevel,
280 const String& formatString,
281 const Formatter::Arg& arg0,
282 const Formatter::Arg& arg1,
283 const Formatter::Arg& arg2,
284 const Formatter::Arg& arg3,
285 const Formatter::Arg& arg4,
286 const Formatter::Arg& arg5,
287 const Formatter::Arg& arg6,
288 const Formatter::Arg& arg7,
289 const Formatter::Arg& arg8,
|
290 chuck 1.29 const Formatter::Arg& arg9)
291 {
292 Uint32 logComponent = 0;
293
294 Logger::_putInternal(
295 logFileType,
296 systemId,
297 logComponent,
298 logLevel,
299 formatString,
300 //l10n
301 String::EMPTY,
302 arg0,
303 arg1,
304 arg2,
305 arg3,
306 arg4,
307 arg5,
308 arg6,
309 arg7,
310 arg8,
311 chuck 1.29 arg9);
312 }
313
314 // l10n
315 void Logger::put_l(
316 LogFileType logFileType,
317 const String& systemId,
318 Uint32 logLevel,
319 const String& messageId, // l10n
320 const String& formatString,
321 const Formatter::Arg& arg0,
322 const Formatter::Arg& arg1,
323 const Formatter::Arg& arg2,
324 const Formatter::Arg& arg3,
325 const Formatter::Arg& arg4,
326 const Formatter::Arg& arg5,
327 const Formatter::Arg& arg6,
328 const Formatter::Arg& arg7,
329 const Formatter::Arg& arg8,
330 const Formatter::Arg& arg9)
|
331 david 1.26 {
332 Uint32 logComponent = 0;
333
334 Logger::_putInternal(
335 logFileType,
336 systemId,
337 logComponent,
338 logLevel,
339 formatString,
|
340 chuck 1.29 messageId,
|
341 david 1.26 arg0,
342 arg1,
343 arg2,
344 arg3,
345 arg4,
346 arg5,
347 arg6,
348 arg7,
349 arg8,
|
350 chuck 1.29 arg9);
|
351 david 1.26 }
352
353 void Logger::trace(
354 LogFileType logFileType,
355 const String& systemId,
356 const Uint32 logComponent,
357 const String& formatString,
358 const Formatter::Arg& arg0,
359 const Formatter::Arg& arg1,
360 const Formatter::Arg& arg2,
361 const Formatter::Arg& arg3,
362 const Formatter::Arg& arg4,
363 const Formatter::Arg& arg5,
364 const Formatter::Arg& arg6,
365 const Formatter::Arg& arg7,
366 const Formatter::Arg& arg8,
|
367 chuck 1.29 const Formatter::Arg& arg9)
368 {
369 Uint32 logLevel = Logger::TRACE;
370
371 Logger::_putInternal(
372 logFileType,
373 systemId,
374 logComponent,
375 logLevel,
376 formatString,
377 // l10n
378 String::EMPTY,
379 arg0,
380 arg1,
381 arg2,
382 arg3,
383 arg4,
384 arg5,
385 arg6,
386 arg7,
387 arg8,
388 chuck 1.29 arg9);
389 }
390
391 // l10n
392 void Logger::trace_l(
393 LogFileType logFileType,
394 const String& systemId,
395 const Uint32 logComponent,
396 const String& messageId,
397 const String& formatString,
398 const Formatter::Arg& arg0,
399 const Formatter::Arg& arg1,
400 const Formatter::Arg& arg2,
401 const Formatter::Arg& arg3,
402 const Formatter::Arg& arg4,
403 const Formatter::Arg& arg5,
404 const Formatter::Arg& arg6,
405 const Formatter::Arg& arg7,
406 const Formatter::Arg& arg8,
407 const Formatter::Arg& arg9)
|
408 david 1.26 {
409 Uint32 logLevel = Logger::TRACE;
410
411 Logger::_putInternal(
412 logFileType,
413 systemId,
414 logComponent,
415 logLevel,
416 formatString,
|
417 chuck 1.29 messageId,
|
418 david 1.26 arg0,
419 arg1,
420 arg2,
421 arg3,
422 arg4,
423 arg5,
424 arg6,
425 arg7,
426 arg8,
|
427 chuck 1.29 arg9);
|
428 mike 1.13 }
429
430 void Logger::setHomeDirectory(const String& homeDirectory)
431 {
432 _homeDirectory = homeDirectory;
433 }
|
434 david 1.26
435 ////////////////////////////////////////////////////////////////////////////////
436 // Set logLevel.
437 ////////////////////////////////////////////////////////////////////////////////
438 void Logger::setlogLevelMask( const String logLevelList )
439 {
440 Uint32 position = 0;
441 Uint32 logLevelType;
442 String logLevelName = logLevelList;
443
444 // Check if logLevel has been specified
445 if (logLevelName != String::EMPTY)
446 {
447 // initialise _severityMask
448 _severityMask = 0;
449
450 // Set logLevelType to indicate the level of logging
451 // required by the user.
452 if (String::equalNoCase(logLevelName,"TRACE"))
453 {
454 logLevelType = Logger::TRACE;
455 david 1.26 }
456 else if (String::equalNoCase(logLevelName,"INFORMATION"))
457 {
458 logLevelType = Logger::INFORMATION;
459 }
460 else if (String::equalNoCase(logLevelName,"WARNING"))
461 {
462 logLevelType = Logger::WARNING;
463 }
464 else if (String::equalNoCase(logLevelName,"SEVERE"))
465 {
466 logLevelType = Logger::SEVERE;
467 }
468 else if (String::equalNoCase(logLevelName,"FATAL"))
469 {
470 logLevelType = Logger::FATAL;
471 }
472 // Setting _severityMask. NOTE: When adding new logLevels
473 // it is essential that they are adding in ascending order
474 // based on priority. Once a case statement is true we will
475 // continue to set all following log levels with a higher
476 david 1.26 // priority.
477 switch(logLevelType)
478 {
479 case Logger::TRACE:
480 _severityMask |= Logger::TRACE;
481 case Logger::INFORMATION:
482 _severityMask |= Logger::INFORMATION;
483 case Logger::WARNING:
484 _severityMask |= Logger::WARNING;
485 case Logger::SEVERE:
486 _severityMask |= Logger::SEVERE;
487 case Logger::FATAL:
488 _severityMask |= Logger::FATAL;
489 }
490 }
491 else
492 {
493 // Property logLevel not specified, set default value.
494 _severityMask = ~Logger::TRACE;
495 }
496 return ;
497 david 1.26 }
498
499 Boolean Logger::isValidlogLevel(
500 const String logLevel)
501 {
502 // Validate the logLevel and modify the logLevel argument
503 // to reflect the invalid logLevel
504
505 Uint32 position=0;
506 Uint32 index=0;
507 String logLevelName = String::EMPTY;
508 Boolean validlogLevel=false;
509 Boolean retCode=true;
510
511 logLevelName = logLevel;
512
513 if (logLevelName != String::EMPTY)
514 {
515 // Lookup the index for logLevel name in _logLevel_LIST
516 index = 0;
517 validlogLevel = false;
518 david 1.26
519 while (index < _NUM_LOGLEVEL)
520 {
521 if (String::equalNoCase(logLevelName, LOGLEVEL_LIST[index]))
522 {
523 // Found logLevel, break from the loop
524 validlogLevel = true;
525 break;
526 }
527 else
528 {
529 index++;
530 }
531 }
532 }
533 else
534 {
535 // logLevels is empty, it is a valid value so return true
536 return _SUCCESS;
537 }
538
539 david 1.26 return validlogLevel;
540 }
541
|
542 mike 1.13
543 PEGASUS_NAMESPACE_END
|