RmpLogger.cpp
Go to the documentation of this file.
00001 /*
00002   COPYRIGHT (c) 2014 SEGWAY Inc.
00003 
00004   Software License Agreement:
00005 
00006   The software supplied herewith by Segway Inc. (the "Company") for its 
00007   RMP Robotic Platforms is intended and supplied to you, the Company's 
00008   customer, for use solely and exclusively with Segway products. The 
00009   software is owned by the Company and/or its supplier, and is protected 
00010   under applicable copyright laws.  All rights are reserved. Any use in 
00011   violation of the foregoing restrictions may subject the user to criminal
00012   sanctions under applicable laws, as well as to civil liability for the 
00013   breach of the terms and conditions of this license. The Company may 
00014   immediately terminate this Agreement upon your use of the software with 
00015   any products that are not Segway products.
00016 
00017   You shall indemnify, defend and hold the Company harmless from any claims, 
00018   demands, liabilities or expenses, including reasonable attorneys fees, incurred 
00019   by the Company as a result of any claim or proceeding against the Company 
00020   arising out of or based upon: 
00021 
00022   (i) The combination, operation or use of the software by you with any hardware, 
00023       products, programs or data not supplied or approved in writing by the Company, 
00024       if such claim or proceeding would have been avoided but for such combination, 
00025       operation or use.
00026 
00027   (ii) The modification of the software by or on behalf of you.
00028 
00029   (iii) Your use of the software.
00030 
00031   THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
00032   WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED
00033   TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00034   PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
00035   IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
00036   CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
00037 */
00038 
00039 #include <RmpLogger.h>
00040 
00041 #include <exception>
00042 #include <vector>
00043 #include <fstream>
00044 
00045 #include <boost/thread/mutex.hpp>
00046 #include <boost/date_time/posix_time/posix_time.hpp>
00047 
00048 namespace segway
00049 {
00050   static boost::mutex s_Mutex;
00051 
00052   std::string GetLogLevelString(LogLevel level);
00053 
00054   struct Logger::Impl
00055   {
00056     static Impl& Instance()
00057     {
00058       static Impl instance;
00059 
00060       return instance;
00061     }
00062     
00063     Impl();
00064 
00065     ~Impl();
00066 
00067     void AddOutputStream(std::ostream& rOutputStream);
00068 
00069     std::vector<std::ostream*> m_OutputStreamList;
00070     LogLevel m_MinLogLevel;
00071   };
00072 
00073   void Logger::SetMinLogLevel(LogLevel level)
00074   {
00075     boost::mutex::scoped_lock scoped_lock(s_Mutex);
00076 
00077     Logger::Impl::Instance().m_MinLogLevel = level;
00078   }
00079 
00080   void Logger::AddOutputStream(std::ostream& rOutputStream)
00081   {
00082     boost::mutex::scoped_lock scoped_lock(s_Mutex);
00083 
00084     Logger::Impl::Instance().AddOutputStream(rOutputStream);
00085   }
00086 
00087   void Logger::AddLogFile(const std::string& rFileName)
00088   {
00089     boost::mutex::scoped_lock scoped_lock(s_Mutex);
00090 
00091     std::ofstream* pFileStream = new std::ofstream();
00092     pFileStream->open(rFileName);
00093 
00094     Logger::Impl::Instance().AddOutputStream(*pFileStream);
00095   }
00096 
00097   void Logger::Log(LogLevel level, const std::string& rMessage)
00098   {
00099     boost::mutex::scoped_lock scoped_lock(s_Mutex);
00100 
00101     if (level >= Impl::Instance().m_MinLogLevel)
00102     {
00103       boost::posix_time::ptime logTime = boost::posix_time::microsec_clock::local_time();
00104       std::string logLevelString = GetLogLevelString(level);
00105       
00106       std::stringstream logMessage;
00107       logMessage << logTime << ", " << logLevelString << ":\t" << rMessage << std::endl; 
00108 
00109       for (size_t i = 0; i < Impl::Instance().m_OutputStreamList.size(); ++i)
00110       {
00111         std::ostream* pOutputStream = Impl::Instance().m_OutputStreamList[i];
00112         
00113         if (pOutputStream != nullptr)
00114         {
00115           *pOutputStream << logMessage.str();
00116           pOutputStream->flush();
00117         }
00118       }
00119     }
00120   }
00121 
00122   Logger::Impl::Impl()
00123     : m_MinLogLevel(DEBUG)
00124   {}
00125 
00126   Logger::Impl::~Impl()
00127   {
00128     for (size_t i = 0; i < m_OutputStreamList.size(); ++i)
00129     {
00130       std::ostream* pOutputStream = m_OutputStreamList[i];
00131       
00132       if (pOutputStream != nullptr)
00133       {
00134         std::ofstream* pOutputFileStream = dynamic_cast<std::ofstream*>(pOutputStream);
00135             
00136         if (pOutputFileStream != nullptr)
00137         {
00138           pOutputFileStream->close();
00139           delete pOutputFileStream;
00140         }
00141       }
00142     }
00143   }
00144 
00145   void Logger::Impl::AddOutputStream(std::ostream& rOutputStream)
00146   {
00147     bool present = false;
00148     
00149     for (size_t i = 0; i < m_OutputStreamList.size(); ++i)
00150     {
00151       if (m_OutputStreamList[i] != nullptr)
00152       {
00153         if (*(m_OutputStreamList[i]) == rOutputStream)
00154         {
00155           present = true;
00156           break;
00157         }
00158       }
00159     }
00160 
00161     if (!present)
00162     {
00163       m_OutputStreamList.push_back(&rOutputStream);
00164     }
00165   }
00166 
00167   std::string GetLogLevelString(LogLevel level)
00168   {
00169     switch (level)
00170     {
00171       case DEBUG:
00172       {
00173         return std::string("DEBUG");
00174       }
00175       case INFO:
00176       {
00177         return std::string("INFO");
00178       }
00179       case WARNING:
00180       {
00181         return std::string("WARNING");
00182       }
00183       case ERROR:
00184       {
00185         return std::string("ERROR");
00186       }
00187       case FATAL:
00188       {
00189         return std::string("FATAL");
00190       }
00191       default:
00192       {
00193         throw std::logic_error("LogLevel cannot be converted to string.");
00194       }
00195     }
00196 
00197     return std::string("Houston, we have a problem!");
00198   }
00199 } // namespace segway
00200 


rmp_base
Author(s):
autogenerated on Wed Aug 26 2015 16:24:39