Mercurial > hg > orthanc
comparison Core/Logging.cpp @ 4014:27628b0f6ada
merging logging code for plugins and files
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 08 Jun 2020 17:03:25 +0200 |
parents | f0ee3f1db775 |
children | c783f4f29390 |
comparison
equal
deleted
inserted
replaced
4013:1e9f6d706237 | 4014:27628b0f6ada |
---|---|
94 | 94 |
95 namespace Orthanc | 95 namespace Orthanc |
96 { | 96 { |
97 namespace Logging | 97 namespace Logging |
98 { | 98 { |
99 void InitializePluginContext(void* pluginContext) | |
100 { | |
101 } | |
102 | |
99 void Initialize() | 103 void Initialize() |
100 { | 104 { |
101 } | 105 } |
102 | 106 |
103 void Finalize() | 107 void Finalize() |
148 * output to the emscripten html5 api (depending on the | 152 * output to the emscripten html5 api (depending on the |
149 * definition of __EMSCRIPTEN__) | 153 * definition of __EMSCRIPTEN__) |
150 *********************************************************/ | 154 *********************************************************/ |
151 | 155 |
152 #include <stdio.h> | 156 #include <stdio.h> |
153 #include <boost/lexical_cast.hpp> | |
154 | 157 |
155 #ifdef __EMSCRIPTEN__ | 158 #ifdef __EMSCRIPTEN__ |
156 # include <emscripten/html5.h> | 159 # include <emscripten/html5.h> |
157 #endif | 160 #endif |
158 | 161 |
181 | 184 |
182 static void TraceLogFunc(const char* msg) | 185 static void TraceLogFunc(const char* msg) |
183 { | 186 { |
184 emscripten_console_log(msg); | 187 emscripten_console_log(msg); |
185 } | 188 } |
186 #else | 189 #else /* __EMSCRIPTEN__ not #defined */ |
187 // __EMSCRIPTEN__ not #defined | |
188 static void ErrorLogFunc(const char* msg) | 190 static void ErrorLogFunc(const char* msg) |
189 { | 191 { |
190 fprintf(stderr, "E: %s\n", msg); | 192 fprintf(stderr, "E: %s\n", msg); |
191 } | 193 } |
192 | 194 |
202 | 204 |
203 static void TraceLogFunc(const char*) | 205 static void TraceLogFunc(const char*) |
204 { | 206 { |
205 fprintf(stdout, "T: %s\n", msg); | 207 fprintf(stdout, "T: %s\n", msg); |
206 } | 208 } |
207 #endif | 209 #endif /* __EMSCRIPTEN__ */ |
208 // __EMSCRIPTEN__ | |
209 | 210 |
210 InternalLogger::InternalLogger(LogLevel level, | 211 InternalLogger::InternalLogger(LogLevel level, |
211 const char* file /* ignored */, | 212 const char* file /* ignored */, |
212 int line /* ignored */) : | 213 int line /* ignored */) : |
213 level_(level) | 214 level_(level) |
251 globalErrorLogFunc(s.c_str()); | 252 globalErrorLogFunc(s.c_str()); |
252 } | 253 } |
253 } | 254 } |
254 } | 255 } |
255 | 256 |
257 void InitializePluginContext(void* pluginContext) | |
258 { | |
259 } | |
260 | |
256 void Initialize() | 261 void Initialize() |
257 { | 262 { |
258 } | 263 } |
259 | 264 |
260 void Finalize() | 265 void Finalize() |
298 } | 303 } |
299 } | 304 } |
300 } | 305 } |
301 | 306 |
302 | 307 |
303 #elif ORTHANC_ENABLE_LOGGING_PLUGIN == 1 | 308 #else |
304 | 309 |
305 /********************************************************* | 310 /********************************************************* |
306 * Logger compatible with the Orthanc plugin SDK | 311 * Logger compatible with the Orthanc plugin SDK, or that |
312 * mimics behavior from Google Log. | |
307 *********************************************************/ | 313 *********************************************************/ |
308 | 314 |
309 #include <cassert> | 315 #include <cassert> |
310 | 316 |
311 namespace | 317 namespace |
333 const void* params); | 339 const void* params); |
334 } OrthancPluginContext; | 340 } OrthancPluginContext; |
335 } | 341 } |
336 | 342 |
337 | 343 |
338 #include <boost/lexical_cast.hpp> | |
339 #include <sstream> | |
340 | |
341 namespace Orthanc | |
342 { | |
343 namespace Logging | |
344 { | |
345 static OrthancPluginContext* context_ = NULL; | |
346 | |
347 void Initialize(void* context) | |
348 { | |
349 assert(sizeof(_OrthancPluginService) == sizeof(int32_t)); | |
350 context_ = reinterpret_cast<OrthancPluginContext*>(context); | |
351 } | |
352 | |
353 InternalLogger::InternalLogger(LogLevel level, | |
354 const char* file /* ignored */, | |
355 int line /* ignored */) : | |
356 level_(level) | |
357 { | |
358 } | |
359 | |
360 InternalLogger::~InternalLogger() | |
361 { | |
362 std::string message = messageStream_.str(); | |
363 if (context_ != NULL) | |
364 { | |
365 switch (level_) | |
366 { | |
367 case LogLevel_ERROR: | |
368 context_->InvokeService(context_, _OrthancPluginService_LogError, message.c_str()); | |
369 break; | |
370 | |
371 case LogLevel_WARNING: | |
372 context_->InvokeService(context_, _OrthancPluginService_LogWarning, message.c_str()); | |
373 break; | |
374 | |
375 case LogLevel_INFO: | |
376 context_->InvokeService(context_, _OrthancPluginService_LogInfo, message.c_str()); | |
377 break; | |
378 | |
379 case LogLevel_TRACE: | |
380 // Not used by plugins | |
381 break; | |
382 | |
383 default: | |
384 { | |
385 std::string s = ("Unknown log level (" + boost::lexical_cast<std::string>(level_) + | |
386 ") for message: " + message); | |
387 context_->InvokeService(context_, _OrthancPluginService_LogInfo, s.c_str()); | |
388 break; | |
389 } | |
390 } | |
391 } | |
392 } | |
393 } | |
394 } | |
395 | |
396 | |
397 #else /* ORTHANC_ENABLE_LOGGING_PLUGIN == 0 && | |
398 ORTHANC_ENABLE_LOGGING_STDIO == 0 && | |
399 ORTHANC_ENABLE_LOGGING == 1 */ | |
400 | |
401 /********************************************************* | |
402 * Internal logger of Orthanc, that mimics some | |
403 * behavior from Google Log. | |
404 *********************************************************/ | |
405 | |
406 #include "Compatibility.h" | |
407 #include "Enumerations.h" | 344 #include "Enumerations.h" |
408 #include "Toolbox.h" | 345 #include "SystemToolbox.h" |
409 | |
410 #if ORTHANC_SANDBOXED == 1 | |
411 # include <stdio.h> | |
412 #else | |
413 # include "SystemToolbox.h" | |
414 #endif | |
415 | 346 |
416 #include <fstream> | 347 #include <fstream> |
417 #include <boost/filesystem.hpp> | 348 #include <boost/filesystem.hpp> |
418 #include <boost/thread.hpp> | 349 #include <boost/thread.hpp> |
419 #include <boost/date_time/posix_time/posix_time.hpp> | 350 #include <boost/date_time/posix_time/posix_time.hpp> |
420 | 351 |
421 | 352 |
422 namespace | 353 namespace |
423 { | 354 { |
424 struct LoggingContext | 355 struct LoggingStreamsContext |
425 { | 356 { |
426 bool infoEnabled_; | |
427 bool traceEnabled_; | |
428 std::string targetFile_; | 357 std::string targetFile_; |
429 std::string targetFolder_; | 358 std::string targetFolder_; |
430 | 359 |
431 std::ostream* error_; | 360 std::ostream* error_; |
432 std::ostream* warning_; | 361 std::ostream* warning_; |
433 std::ostream* info_; | 362 std::ostream* info_; |
434 | 363 |
435 std::unique_ptr<std::ofstream> file_; | 364 std::unique_ptr<std::ofstream> file_; |
436 | 365 |
437 LoggingContext() : | 366 LoggingStreamsContext() : |
438 infoEnabled_(false), | |
439 traceEnabled_(false), | |
440 error_(&std::cerr), | 367 error_(&std::cerr), |
441 warning_(&std::cerr), | 368 warning_(&std::cerr), |
442 info_(&std::cerr) | 369 info_(&std::cerr) |
443 { | 370 { |
444 } | 371 } |
445 }; | 372 }; |
446 } | 373 } |
447 | 374 |
448 | 375 |
449 | 376 |
450 static std::unique_ptr<LoggingContext> loggingContext_; | 377 static std::unique_ptr<LoggingStreamsContext> loggingStreamsContext_; |
451 static boost::mutex loggingMutex_; | 378 static boost::mutex loggingStreamsMutex_; |
452 | 379 static Orthanc::Logging::NullStream nullStream_; |
380 static OrthancPluginContext* pluginContext_ = NULL; | |
381 static bool infoEnabled_ = false; | |
382 static bool traceEnabled_ = false; | |
453 | 383 |
454 | 384 |
455 namespace Orthanc | 385 namespace Orthanc |
456 { | 386 { |
457 namespace Logging | 387 namespace Logging |
513 | 443 |
514 file.reset(new std::ofstream(log.string().c_str())); | 444 file.reset(new std::ofstream(log.string().c_str())); |
515 } | 445 } |
516 | 446 |
517 | 447 |
448 // "loggingStreamsMutex_" must be locked | |
518 static void CheckFile(std::unique_ptr<std::ofstream>& f) | 449 static void CheckFile(std::unique_ptr<std::ofstream>& f) |
519 { | 450 { |
520 if (loggingContext_->file_.get() == NULL || | 451 if (loggingStreamsContext_->file_.get() == NULL || |
521 !loggingContext_->file_->is_open()) | 452 !loggingStreamsContext_->file_->is_open()) |
522 { | 453 { |
523 throw OrthancException(ErrorCode_CannotWriteFile); | 454 throw OrthancException(ErrorCode_CannotWriteFile); |
524 } | 455 } |
525 } | 456 } |
526 | 457 |
591 prefix = (std::string(date) + path.filename().string() + ":" + | 522 prefix = (std::string(date) + path.filename().string() + ":" + |
592 boost::lexical_cast<std::string>(line) + "] "); | 523 boost::lexical_cast<std::string>(line) + "] "); |
593 } | 524 } |
594 | 525 |
595 | 526 |
527 void InitializePluginContext(void* pluginContext) | |
528 { | |
529 assert(sizeof(_OrthancPluginService) == sizeof(int32_t)); | |
530 | |
531 boost::mutex::scoped_lock lock(loggingStreamsMutex_); | |
532 loggingStreamsContext_.reset(NULL); | |
533 pluginContext_ = reinterpret_cast<OrthancPluginContext*>(pluginContext); | |
534 } | |
535 | |
536 | |
596 void Initialize() | 537 void Initialize() |
597 { | 538 { |
598 boost::mutex::scoped_lock lock(loggingMutex_); | 539 boost::mutex::scoped_lock lock(loggingStreamsMutex_); |
599 loggingContext_.reset(new LoggingContext); | 540 loggingStreamsContext_.reset(new LoggingStreamsContext); |
600 } | 541 } |
601 | 542 |
602 void Finalize() | 543 void Finalize() |
603 { | 544 { |
604 boost::mutex::scoped_lock lock(loggingMutex_); | 545 boost::mutex::scoped_lock lock(loggingStreamsMutex_); |
605 loggingContext_.reset(NULL); | 546 loggingStreamsContext_.reset(NULL); |
606 } | 547 } |
607 | 548 |
608 void Reset() | 549 void Reset() |
609 { | 550 { |
610 // Recover the old logging context | 551 // Recover the old logging context |
611 std::unique_ptr<LoggingContext> old; | 552 std::unique_ptr<LoggingStreamsContext> old; |
612 | 553 |
613 { | 554 { |
614 boost::mutex::scoped_lock lock(loggingMutex_); | 555 boost::mutex::scoped_lock lock(loggingStreamsMutex_); |
615 if (loggingContext_.get() == NULL) | 556 if (loggingStreamsContext_.get() == NULL) |
616 { | 557 { |
617 return; | 558 return; |
618 } | 559 } |
619 else | 560 else |
620 { | 561 { |
621 #if __cplusplus < 201103L | 562 #if __cplusplus < 201103L |
622 old.reset(loggingContext_.release()); | 563 old.reset(loggingStreamsContext_.release()); |
623 #else | 564 #else |
624 old = std::move(loggingContext_); | 565 old = std::move(loggingStreamsContext_); |
625 #endif | 566 #endif |
626 | 567 |
627 // Create a new logging context, | 568 // Create a new logging context, |
628 loggingContext_.reset(new LoggingContext); | 569 loggingStreamsContext_.reset(new LoggingStreamsContext); |
629 } | 570 } |
630 } | 571 } |
631 | 572 |
632 EnableInfoLevel(old->infoEnabled_); | |
633 EnableTraceLevel(old->traceEnabled_); | |
634 | |
635 if (!old->targetFolder_.empty()) | 573 if (!old->targetFolder_.empty()) |
636 { | 574 { |
637 SetTargetFolder(old->targetFolder_); | 575 SetTargetFolder(old->targetFolder_); |
638 } | 576 } |
639 else if (!old->targetFile_.empty()) | 577 else if (!old->targetFile_.empty()) |
643 } | 581 } |
644 | 582 |
645 | 583 |
646 void EnableInfoLevel(bool enabled) | 584 void EnableInfoLevel(bool enabled) |
647 { | 585 { |
648 boost::mutex::scoped_lock lock(loggingMutex_); | 586 infoEnabled_ = enabled; |
649 assert(loggingContext_.get() != NULL); | |
650 | |
651 loggingContext_->infoEnabled_ = enabled; | |
652 | 587 |
653 if (!enabled) | 588 if (!enabled) |
654 { | 589 { |
655 // Also disable the "TRACE" level when info-level debugging is disabled | 590 // Also disable the "TRACE" level when info-level debugging is disabled |
656 loggingContext_->traceEnabled_ = false; | 591 traceEnabled_ = false; |
657 } | 592 } |
658 } | 593 } |
659 | 594 |
660 bool IsInfoLevelEnabled() | 595 bool IsInfoLevelEnabled() |
661 { | 596 { |
662 boost::mutex::scoped_lock lock(loggingMutex_); | 597 return infoEnabled_; |
663 assert(loggingContext_.get() != NULL); | |
664 | |
665 return loggingContext_->infoEnabled_; | |
666 } | 598 } |
667 | 599 |
668 void EnableTraceLevel(bool enabled) | 600 void EnableTraceLevel(bool enabled) |
669 { | 601 { |
670 boost::mutex::scoped_lock lock(loggingMutex_); | 602 traceEnabled_ = enabled; |
671 assert(loggingContext_.get() != NULL); | |
672 | |
673 loggingContext_->traceEnabled_ = enabled; | |
674 | 603 |
675 if (enabled) | 604 if (enabled) |
676 { | 605 { |
677 // Also enable the "INFO" level when trace-level debugging is enabled | 606 // Also enable the "INFO" level when trace-level debugging is enabled |
678 loggingContext_->infoEnabled_ = true; | 607 infoEnabled_ = true; |
679 } | 608 } |
680 } | 609 } |
681 | 610 |
682 bool IsTraceLevelEnabled() | 611 bool IsTraceLevelEnabled() |
683 { | 612 { |
684 boost::mutex::scoped_lock lock(loggingMutex_); | 613 return traceEnabled_; |
685 assert(loggingContext_.get() != NULL); | |
686 | |
687 return loggingContext_->traceEnabled_; | |
688 } | 614 } |
689 | 615 |
690 | 616 |
691 void SetTargetFolder(const std::string& path) | 617 void SetTargetFolder(const std::string& path) |
692 { | 618 { |
693 boost::mutex::scoped_lock lock(loggingMutex_); | 619 boost::mutex::scoped_lock lock(loggingStreamsMutex_); |
694 assert(loggingContext_.get() != NULL); | 620 if (loggingStreamsContext_.get() != NULL) |
695 | 621 { |
696 PrepareLogFolder(loggingContext_->file_, "" /* no suffix */, path); | 622 PrepareLogFolder(loggingStreamsContext_->file_, "" /* no suffix */, path); |
697 CheckFile(loggingContext_->file_); | 623 CheckFile(loggingStreamsContext_->file_); |
698 | 624 |
699 loggingContext_->targetFile_.clear(); | 625 loggingStreamsContext_->targetFile_.clear(); |
700 loggingContext_->targetFolder_ = path; | 626 loggingStreamsContext_->targetFolder_ = path; |
701 loggingContext_->warning_ = loggingContext_->file_.get(); | 627 loggingStreamsContext_->warning_ = loggingStreamsContext_->file_.get(); |
702 loggingContext_->error_ = loggingContext_->file_.get(); | 628 loggingStreamsContext_->error_ = loggingStreamsContext_->file_.get(); |
703 loggingContext_->info_ = loggingContext_->file_.get(); | 629 loggingStreamsContext_->info_ = loggingStreamsContext_->file_.get(); |
630 } | |
704 } | 631 } |
705 | 632 |
706 | 633 |
707 void SetTargetFile(const std::string& path) | 634 void SetTargetFile(const std::string& path) |
708 { | 635 { |
709 boost::mutex::scoped_lock lock(loggingMutex_); | 636 boost::mutex::scoped_lock lock(loggingStreamsMutex_); |
710 assert(loggingContext_.get() != NULL); | 637 |
711 | 638 if (loggingStreamsContext_.get() != NULL) |
712 loggingContext_->file_.reset(new std::ofstream(path.c_str(), std::fstream::app)); | 639 { |
713 CheckFile(loggingContext_->file_); | 640 loggingStreamsContext_->file_.reset(new std::ofstream(path.c_str(), std::fstream::app)); |
714 | 641 CheckFile(loggingStreamsContext_->file_); |
715 loggingContext_->targetFile_ = path; | 642 |
716 loggingContext_->targetFolder_.clear(); | 643 loggingStreamsContext_->targetFile_ = path; |
717 loggingContext_->warning_ = loggingContext_->file_.get(); | 644 loggingStreamsContext_->targetFolder_.clear(); |
718 loggingContext_->error_ = loggingContext_->file_.get(); | 645 loggingStreamsContext_->warning_ = loggingStreamsContext_->file_.get(); |
719 loggingContext_->info_ = loggingContext_->file_.get(); | 646 loggingStreamsContext_->error_ = loggingStreamsContext_->file_.get(); |
647 loggingStreamsContext_->info_ = loggingStreamsContext_->file_.get(); | |
648 } | |
720 } | 649 } |
721 | 650 |
722 | 651 |
723 InternalLogger::InternalLogger(LogLevel level, | 652 InternalLogger::InternalLogger(LogLevel level, |
724 const char* file, | 653 const char* file, |
725 int line) : | 654 int line) : |
726 lock_(loggingMutex_, boost::defer_lock_t()), | 655 lock_(loggingStreamsMutex_, boost::defer_lock_t()), |
727 stream_(&null_) // By default, logging to "/dev/null" is simulated | 656 level_(level), |
728 { | 657 stream_(&nullStream_) // By default, logging to "/dev/null" is simulated |
729 lock_.lock(); | 658 { |
730 | 659 if (pluginContext_ != NULL) |
731 if (loggingContext_.get() == NULL) | 660 { |
732 { | 661 // We are logging using the Orthanc plugin SDK |
733 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n"); | 662 |
734 return; | 663 if (level == LogLevel_TRACE) |
735 } | |
736 | |
737 try | |
738 { | |
739 if ((level == LogLevel_INFO && !loggingContext_->infoEnabled_) || | |
740 (level == LogLevel_TRACE && !loggingContext_->traceEnabled_)) | |
741 { | 664 { |
742 // This logging level is disabled, directly exit and unlock | 665 // No trace level in plugins, directly exit as the stream is |
743 // the mutex to speed-up things. The stream is set to "/dev/null" | 666 // set to "/dev/null" |
744 lock_.unlock(); | |
745 return; | 667 return; |
746 } | 668 } |
747 | 669 else |
748 // Compute the prefix of the line, temporary release the lock as | 670 { |
749 // this is a time-consuming operation | 671 pluginStream_.reset(new std::stringstream); |
750 lock_.unlock(); | 672 stream_ = pluginStream_.get(); |
673 } | |
674 } | |
675 else | |
676 { | |
677 // We are logging in a standalone application, not inside an Orthanc plugin | |
678 | |
679 if ((level == LogLevel_INFO && !infoEnabled_) || | |
680 (level == LogLevel_TRACE && !traceEnabled_)) | |
681 { | |
682 // This logging level is disabled, directly exit as the | |
683 // stream is set to "/dev/null" | |
684 return; | |
685 } | |
686 | |
751 std::string prefix; | 687 std::string prefix; |
752 GetLinePrefix(prefix, level, file, line); | 688 GetLinePrefix(prefix, level, file, line); |
753 | 689 |
754 // The prefix is computed, we now re-lock the mutex to access | |
755 // the stream objects. Pay attention that "loggingContext_", | |
756 // "infoEnabled_" or "traceEnabled_" might have changed while | |
757 // the mutex was unlocked. | |
758 lock_.lock(); | |
759 | |
760 if (loggingContext_.get() == NULL) | |
761 { | 690 { |
762 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n"); | 691 // We lock the global mutex. The mutex is locked until the |
763 return; | 692 // destructor is called: No change in the output can be done. |
693 lock_.lock(); | |
694 | |
695 if (loggingStreamsContext_.get() == NULL) | |
696 { | |
697 fprintf(stderr, "ERROR: Trying to log a message after the finalization of the logging engine\n"); | |
698 lock_.unlock(); | |
699 return; | |
700 } | |
701 | |
702 switch (level) | |
703 { | |
704 case LogLevel_ERROR: | |
705 stream_ = loggingStreamsContext_->error_; | |
706 break; | |
707 | |
708 case LogLevel_WARNING: | |
709 stream_ = loggingStreamsContext_->warning_; | |
710 break; | |
711 | |
712 case LogLevel_INFO: | |
713 case LogLevel_TRACE: | |
714 stream_ = loggingStreamsContext_->info_; | |
715 break; | |
716 | |
717 default: | |
718 throw OrthancException(ErrorCode_InternalError); | |
719 } | |
720 | |
721 if (stream_ == &nullStream_) | |
722 { | |
723 // The logging is disabled for this level, we can release | |
724 // the global mutex. | |
725 lock_.unlock(); | |
726 } | |
727 else | |
728 { | |
729 try | |
730 { | |
731 (*stream_) << prefix; | |
732 } | |
733 catch (...) | |
734 { | |
735 // Something is going really wrong, probably running out of | |
736 // memory. Fallback to a degraded mode. | |
737 stream_ = loggingStreamsContext_->error_; | |
738 (*stream_) << "E???? ??:??:??.?????? ] "; | |
739 } | |
740 } | |
764 } | 741 } |
765 | 742 } |
766 switch (level) | 743 } |
744 | |
745 | |
746 InternalLogger::~InternalLogger() | |
747 { | |
748 if (pluginStream_.get() != NULL) | |
749 { | |
750 // We are logging through the Orthanc SDK | |
751 | |
752 std::string message = pluginStream_->str(); | |
753 | |
754 if (pluginContext_ != NULL) | |
767 { | 755 { |
768 case LogLevel_ERROR: | 756 switch (level_) |
769 stream_ = loggingContext_->error_; | 757 { |
770 break; | 758 case LogLevel_ERROR: |
771 | 759 pluginContext_->InvokeService(pluginContext_, _OrthancPluginService_LogError, message.c_str()); |
772 case LogLevel_WARNING: | 760 break; |
773 stream_ = loggingContext_->warning_; | 761 |
774 break; | 762 case LogLevel_WARNING: |
775 | 763 printf("[%s]\n", message.c_str()); |
776 case LogLevel_INFO: | 764 |
777 if (loggingContext_->infoEnabled_) | 765 pluginContext_->InvokeService(pluginContext_, _OrthancPluginService_LogWarning, message.c_str()); |
778 { | 766 break; |
779 stream_ = loggingContext_->info_; | 767 |
780 } | 768 case LogLevel_INFO: |
781 | 769 pluginContext_->InvokeService(pluginContext_, _OrthancPluginService_LogInfo, message.c_str()); |
782 break; | 770 break; |
783 | 771 |
784 case LogLevel_TRACE: | 772 default: |
785 if (loggingContext_->traceEnabled_) | 773 break; |
786 { | 774 } |
787 stream_ = loggingContext_->info_; | |
788 } | |
789 | |
790 break; | |
791 | |
792 default: | |
793 throw OrthancException(ErrorCode_InternalError); | |
794 } | 775 } |
795 | 776 } |
796 if (stream_ == &null_) | 777 else if (stream_ != &nullStream_) |
797 { | |
798 // The logging is disabled for this level. The stream is the | |
799 // "null_" member of this object, so we can release the global | |
800 // mutex. | |
801 lock_.unlock(); | |
802 } | |
803 | |
804 (*stream_) << prefix; | |
805 } | |
806 catch (...) | |
807 { | |
808 // Something is going really wrong, probably running out of | |
809 // memory. Fallback to a degraded mode. | |
810 stream_ = loggingContext_->error_; | |
811 (*stream_) << "E???? ??:??:??.?????? ] "; | |
812 } | |
813 } | |
814 | |
815 | |
816 InternalLogger::~InternalLogger() | |
817 { | |
818 if (stream_ != &null_) | |
819 { | 778 { |
820 *stream_ << "\n"; | 779 *stream_ << "\n"; |
821 stream_->flush(); | 780 stream_->flush(); |
822 } | 781 } |
823 } | 782 } |
824 | 783 |
825 | 784 |
826 void Flush() | 785 void Flush() |
827 { | 786 { |
828 boost::mutex::scoped_lock lock(loggingMutex_); | 787 if (pluginContext_ != NULL) |
829 | 788 { |
830 if (loggingContext_.get() != NULL && | 789 boost::mutex::scoped_lock lock(loggingStreamsMutex_); |
831 loggingContext_->file_.get() != NULL) | 790 |
832 { | 791 if (loggingStreamsContext_.get() != NULL && |
833 loggingContext_->file_->flush(); | 792 loggingStreamsContext_->file_.get() != NULL) |
834 } | 793 { |
835 } | 794 loggingStreamsContext_->file_->flush(); |
795 } | |
796 } | |
797 } | |
798 | |
836 | 799 |
837 void SetErrorWarnInfoLoggingStreams(std::ostream& errorStream, | 800 void SetErrorWarnInfoLoggingStreams(std::ostream& errorStream, |
838 std::ostream& warningStream, | 801 std::ostream& warningStream, |
839 std::ostream& infoStream) | 802 std::ostream& infoStream) |
840 { | 803 { |
841 std::unique_ptr<LoggingContext> old; | 804 boost::mutex::scoped_lock lock(loggingStreamsMutex_); |
842 | 805 |
843 { | 806 loggingStreamsContext_.reset(new LoggingStreamsContext); |
844 boost::mutex::scoped_lock lock(loggingMutex_); | 807 loggingStreamsContext_->error_ = &errorStream; |
845 | 808 loggingStreamsContext_->warning_ = &warningStream; |
846 #if __cplusplus < 201103L | 809 loggingStreamsContext_->info_ = &infoStream; |
847 old.reset(loggingContext_.release()); | |
848 #else | |
849 old = std::move(loggingContext_); | |
850 #endif | |
851 | |
852 loggingContext_.reset(new LoggingContext); | |
853 loggingContext_->error_ = &errorStream; | |
854 loggingContext_->warning_ = &warningStream; | |
855 loggingContext_->info_ = &infoStream; | |
856 } | |
857 | |
858 EnableInfoLevel(old->infoEnabled_); | |
859 EnableTraceLevel(old->traceEnabled_); | |
860 } | 810 } |
861 } | 811 } |
862 } | 812 } |
863 | 813 |
864 | 814 |