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