reverted varianttype
[profile/ivi/automotive-message-broker.git] / plugins / common / logger.cpp
1 /*
2 Copyright (C) 2012 Intel Corporation
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #include <iostream>
20 #include <new>
21 #include <cstdlib>
22 #include <stdio.h>
23 #include <pthread.h>
24 #include <unistd.h>
25 #include <signal.h>
26
27
28 #include "logger.h"
29
30 using namespace CUtil;
31
32 // Definition (and initialization) of static attributes
33 Logger* Logger::m_ = 0;
34
35 // Define the function to be called when ctrl-c (SIGINT) signal is sent to process
36 void signal_callback_handler(int signum)
37 {
38     std::cerr << std::endl << " ... Caught signal " << signum << std::endl;
39
40     Logger::getInstance().flush();
41
42     // Terminate program
43     exit(signum);
44 }
45
46
47 #ifdef LOGGER_MULTITHREAD
48 pthread_mutex_t Logger::lock_ = PTHREAD_MUTEX_INITIALIZER;
49 inline void Logger::lock()
50 {
51         pthread_mutex_lock(&lock_);
52 }
53
54 inline void Logger::unlock()
55 {
56         pthread_mutex_unlock(&lock_);
57 }
58 #else
59 void Logger::lock(){}
60 void Logger::unlock(){}
61 #endif
62
63
64
65 /**
66  * \brief Constructor.
67  * It is a private constructor, called only by getInstance() and only the
68  * first time. It is called inside a lock, so lock inside this method
69  * is not required.
70  * It only initializes the initial time. All configuration is done inside the
71  * configure() method.
72  */
73 Logger::Logger() :
74         configured_(false),
75         logFile_(""),
76         logFileName_(""),
77         configuration_(L_nofile_|L_noscreen_),
78         initialTime_usec_(0)
79 {
80         struct timeval initialTime;
81         gettimeofday(&initialTime, NULL);
82         initialTime_usec_ = int64_t(1000000LL*int64_t(initialTime.tv_sec)) + int64_t(initialTime.tv_usec);
83
84 }
85
86 /**
87  * \brief Method to configure the logger. Called by the DEBUG_CONF() macro.
88  * To make implementation easier, the old stream is always closed.
89  * Then, in case, it is open again in append mode.
90  * @param outputFile Name of the file used for logging.
91  * @param configuration Configuration (i.e., log on file and on screen on or off).
92  * @param fileVerbosityLevel Verbosity threshold for file.
93  * @param screenVerbosityLevel Verbosity threshold for screen.
94  */
95 void Logger::configure (const std::string&      outputFile,
96                         const loggerConf        configuration,
97                         const int               fileVerbosityLevel,
98                         const int               screenVerbosityLevel)
99 {
100     Logger::lock();
101
102     logFileName_ = outputFile;
103     fileVerbosityLevel_ = fileVerbosityLevel;
104     screenVerbosityLevel_ = screenVerbosityLevel;
105
106     // Close the old stream, if needed
107     if (configuration_&file_on)
108         out_.close();
109
110     // Compute a new file name, if needed
111     if (outputFile != logFile_){
112         std::ostringstream oss;
113         /*time_t currTime;
114         time(&currTime);
115         struct tm *currTm = localtime(&currTime);*/
116         oss << outputFile << /*"_" <<
117                 (1900 + currTm->tm_year) << "_" <<
118                 currTm->tm_mon << "_" <<
119                 currTm->tm_mday << "_" <<
120                 currTm->tm_hour << "-" <<
121                 currTm->tm_min << "-" <<
122                 currTm->tm_sec << */
123                 ".log";
124         logFile_ = oss.str().c_str();
125     }
126
127     // Open a new stream, if needed
128     if (configuration&file_on)
129         out_.open(logFile_.c_str(), std::ios::app);
130
131     configuration_ = configuration;
132     configured_ = true;
133
134     Logger::unlock();
135
136     // Register signal and signal handler
137     // we need a flush log file at program termination
138     signal(SIGINT, signal_callback_handler);
139     signal(SIGTERM, signal_callback_handler);
140     signal(SIGABRT, signal_callback_handler);
141     signal(SIGKILL, signal_callback_handler);
142
143 }
144
145 /**
146  * \brief Destructor.
147  * It only closes the file, if open, and cleans memory.
148  */
149
150 Logger::~Logger()
151 {
152         Logger::lock();
153         if (configuration_&file_on)
154                 out_.close();
155         delete m_;
156         Logger::unlock();
157
158 }
159
160 /**
161  * \brief Method to get a reference to the object (i.e., Singleton)
162  * It is a static method.
163  * @return Reference to the object.
164  */
165 Logger& Logger::getInstance()
166 {
167         Logger::lock();
168         if (m_ == 0)
169                 m_ = new Logger;
170         Logger::unlock();
171         return *m_;
172 }
173
174
175 /**
176  * \brief Method used to print messages.
177  * Called by the LOGGER() macro.
178  * @param verbosityLevel Priority of the message
179  * @param file Source file where the method has been called (set equal to __FILE__
180  *            by the LOGGER macro)
181  * @param line Source line where the method has been called (set equal to __LINE__
182           by the macro)
183  * @param message Message text
184  */
185 void Logger::print(const unsigned int verbosityLevel,
186                                         const std::string& file,
187                                         const int line,
188                                         const std::string& message)
189 {
190         if (!configured_) {
191                         std::cerr << "ERROR: Logger not configured!" << 
192                                 std::endl;
193                         return;
194         }
195
196         if( ((configuration_&file_on) && (verbosityLevel > fileVerbosityLevel_)) &&
197                 ((configuration_&screen_on) && (verbosityLevel > screenVerbosityLevel_)) )
198                 return;
199
200         struct timeval currentTime;
201         Logger::lock();
202
203         gettimeofday(&currentTime, NULL);
204         int64_t currentTime_usec;
205         currentTime_usec =  int64_t(1000000LL*int64_t(currentTime.tv_sec)) + int64_t(currentTime.tv_usec);
206
207         unsigned int li_tid = (unsigned int)pthread_self();
208
209         if ( (configuration_&file_on) && (verbosityLevel <= fileVerbosityLevel_) )
210                         out_ << double(currentTime_usec - initialTime_usec_)/1000000.0f <<
211                                 " (" << std::hex << li_tid << std::dec << ") " <<
212                                 " [" << file << ":" << line << "] @ " <<
213                                 message << std::endl;
214
215         if ( (configuration_&screen_on) && (verbosityLevel <= screenVerbosityLevel_) )
216                         std::cout <<
217                                 double(currentTime_usec - initialTime_usec_)/1000000.0f <<
218                                 " (" << std::hex << li_tid << std::dec << ") " <<
219                                 logFileName_ << " [" << file << ":" << line << "] @ " <<
220                                 message << std::endl;
221
222
223         Logger::unlock();
224 }
225
226