Mercurial > hg > orthanc
comparison Core/Logging.cpp @ 2134:ddc75c6c712d
Avoid hard crash if not enough memory
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 09 Nov 2016 12:04:09 +0100 |
parents | bcc575732aef |
children | aa4b8895cd23 |
comparison
equal
deleted
inserted
replaced
2133:15ae532af70e | 2134:ddc75c6c712d |
---|---|
316 { | 316 { |
317 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n"); | 317 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n"); |
318 return; | 318 return; |
319 } | 319 } |
320 | 320 |
321 LogLevel l = StringToLogLevel(level); | 321 try |
322 | 322 { |
323 if ((l == LogLevel_Info && !loggingContext_->infoEnabled_) || | 323 LogLevel l = StringToLogLevel(level); |
324 (l == LogLevel_Trace && !loggingContext_->traceEnabled_)) | 324 |
325 { | 325 if ((l == LogLevel_Info && !loggingContext_->infoEnabled_) || |
326 // This logging level is disabled, directly exit and unlock | 326 (l == LogLevel_Trace && !loggingContext_->traceEnabled_)) |
327 // the mutex to speed-up things. The stream is set to "/dev/null" | 327 { |
328 // This logging level is disabled, directly exit and unlock | |
329 // the mutex to speed-up things. The stream is set to "/dev/null" | |
330 lock_.unlock(); | |
331 return; | |
332 } | |
333 | |
334 // Compute the header of the line, temporary release the lock as | |
335 // this is a time-consuming operation | |
328 lock_.unlock(); | 336 lock_.unlock(); |
329 return; | 337 std::string header; |
330 } | 338 |
331 | 339 { |
332 // Compute the header of the line, temporary release the lock as | 340 boost::filesystem::path path(file); |
333 // this is a time-consuming operation | 341 boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time(); |
334 lock_.unlock(); | 342 boost::posix_time::time_duration duration = now.time_of_day(); |
335 std::string header; | 343 |
336 | 344 /** |
337 { | 345 From Google Log documentation: |
338 boost::filesystem::path path(file); | 346 |
339 boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time(); | 347 "Log lines have this form: |
340 boost::posix_time::time_duration duration = now.time_of_day(); | 348 |
341 | 349 Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... |
342 /** | 350 |
343 From Google Log documentation: | 351 where the fields are defined as follows: |
344 | 352 |
345 "Log lines have this form: | 353 L A single character, representing the log level (eg 'I' for INFO) |
346 | 354 mm The month (zero padded; ie May is '05') |
347 Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... | 355 dd The day (zero padded) |
348 | 356 hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds |
349 where the fields are defined as follows: | 357 threadid The space-padded thread ID as returned by GetTID() (this matches the PID on Linux) |
350 | 358 file The file name |
351 L A single character, representing the log level (eg 'I' for INFO) | 359 line The line number |
352 mm The month (zero padded; ie May is '05') | 360 msg The user-supplied message" |
353 dd The day (zero padded) | 361 |
354 hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds | 362 In this implementation, "threadid" is not printed. |
355 threadid The space-padded thread ID as returned by GetTID() (this matches the PID on Linux) | 363 **/ |
356 file The file name | 364 |
357 line The line number | 365 char date[32]; |
358 msg The user-supplied message" | 366 sprintf(date, "%c%02d%02d %02d:%02d:%02d.%06d ", |
359 | 367 level[0], |
360 In this implementation, "threadid" is not printed. | 368 now.date().month().as_number(), |
361 **/ | 369 now.date().day().as_number(), |
362 | 370 duration.hours(), |
363 char date[32]; | 371 duration.minutes(), |
364 sprintf(date, "%c%02d%02d %02d:%02d:%02d.%06d ", | 372 duration.seconds(), |
365 level[0], | 373 static_cast<int>(duration.fractional_seconds())); |
366 now.date().month().as_number(), | 374 |
367 now.date().day().as_number(), | 375 header = std::string(date) + path.filename().string() + ":" + boost::lexical_cast<std::string>(line) + "] "; |
368 duration.hours(), | 376 } |
369 duration.minutes(), | 377 |
370 duration.seconds(), | 378 |
371 static_cast<int>(duration.fractional_seconds())); | 379 // The header is computed, we now re-lock the mutex to access |
372 | 380 // the stream objects. Pay attention that "loggingContext_", |
373 header = std::string(date) + path.filename().string() + ":" + boost::lexical_cast<std::string>(line) + "] "; | 381 // "infoEnabled_" or "traceEnabled_" might have changed while |
374 } | 382 // the mutex was unlocked. |
375 | 383 lock_.lock(); |
376 | 384 |
377 // The header is computed, we now re-lock the mutex to access | 385 if (loggingContext_.get() == NULL) |
378 // the stream objects. Pay attention that "loggingContext_", | 386 { |
379 // "infoEnabled_" or "traceEnabled_" might have changed while | 387 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n"); |
380 // the mutex was unlocked. | 388 return; |
381 lock_.lock(); | 389 } |
382 | 390 |
383 if (loggingContext_.get() == NULL) | 391 switch (l) |
384 { | 392 { |
385 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n"); | 393 case LogLevel_Error: |
386 return; | 394 stream_ = loggingContext_->error_; |
387 } | 395 break; |
388 | 396 |
389 switch (l) | 397 case LogLevel_Warning: |
390 { | 398 stream_ = loggingContext_->warning_; |
391 case LogLevel_Error: | 399 break; |
392 stream_ = loggingContext_->error_; | 400 |
393 break; | 401 case LogLevel_Info: |
394 | 402 if (loggingContext_->infoEnabled_) |
395 case LogLevel_Warning: | 403 { |
396 stream_ = loggingContext_->warning_; | 404 stream_ = loggingContext_->info_; |
397 break; | 405 } |
398 | 406 |
399 case LogLevel_Info: | 407 break; |
400 if (loggingContext_->infoEnabled_) | 408 |
401 { | 409 case LogLevel_Trace: |
402 stream_ = loggingContext_->info_; | 410 if (loggingContext_->traceEnabled_) |
403 } | 411 { |
404 | 412 stream_ = loggingContext_->info_; |
405 break; | 413 } |
406 | 414 |
407 case LogLevel_Trace: | 415 break; |
408 if (loggingContext_->traceEnabled_) | 416 |
409 { | 417 default: |
410 stream_ = loggingContext_->info_; | 418 throw OrthancException(ErrorCode_InternalError); |
411 } | 419 } |
412 | 420 |
413 break; | 421 if (stream_ == &null_) |
414 | 422 { |
415 default: | 423 // The logging is disabled for this level. The stream is the |
416 throw OrthancException(ErrorCode_InternalError); | 424 // "null_" member of this object, so we can release the global |
417 } | 425 // mutex. |
418 | 426 lock_.unlock(); |
419 if (stream_ == &null_) | 427 } |
420 { | 428 |
421 // The logging is disabled for this level. The stream is the | 429 (*stream_) << header; |
422 // "null_" member of this object, so we can release the global | 430 } |
423 // mutex. | 431 catch (...) |
424 lock_.unlock(); | 432 { |
425 } | 433 // Something is going really wrong, probably running out of |
426 | 434 // memory. Fallback to a degraded mode. |
427 (*stream_) << header; | 435 stream_ = loggingContext_->error_; |
436 (*stream_) << "E???? ??:??:??.?????? ] "; | |
437 } | |
428 } | 438 } |
429 | 439 |
430 | 440 |
431 InternalLogger::~InternalLogger() | 441 InternalLogger::~InternalLogger() |
432 { | 442 { |