comparison Core/Logging.cpp @ 1490:596927722403

support of --logdir by the internal logger
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 04 Aug 2015 14:04:48 +0200
parents 1389834e130f
children a13581480b1f
comparison
equal deleted inserted replaced
1489:1389834e130f 1490:596927722403
92 /********************************************************* 92 /*********************************************************
93 * Use internal logger, not Google Log 93 * Use internal logger, not Google Log
94 *********************************************************/ 94 *********************************************************/
95 95
96 #include "OrthancException.h" 96 #include "OrthancException.h"
97 97 #include "Toolbox.h"
98
99 #include <fstream>
98 #include <boost/filesystem.hpp> 100 #include <boost/filesystem.hpp>
99 #include <boost/thread.hpp> 101 #include <boost/thread.hpp>
100 102
101 #if BOOST_HAS_DATE_TIME == 1 103 #if BOOST_HAS_DATE_TIME == 1
102 # include <boost/date_time/posix_time/posix_time.hpp> 104 # include <boost/date_time/posix_time/posix_time.hpp>
117 119
118 120
119 static boost::mutex mutex_; 121 static boost::mutex mutex_;
120 static bool infoEnabled_ = false; 122 static bool infoEnabled_ = false;
121 static bool traceEnabled_ = false; 123 static bool traceEnabled_ = false;
122 static std::ostream& error_ = std::cerr; 124
123 static std::ostream& warning_ = std::cerr; 125 static std::ostream* error_ = &std::cerr;
124 static std::ostream& info_ = std::cerr; 126 static std::ostream* warning_ = &std::cerr;
125 static std::ostream& trace_ = std::cerr; 127 static std::ostream* info_ = &std::cerr;
126 static NullStream null_; 128 static NullStream null_;
129
130 static std::auto_ptr<std::ofstream> errorFile_;
131 static std::auto_ptr<std::ofstream> warningFile_;
132 static std::auto_ptr<std::ofstream> infoFile_;
127 133
128 namespace Orthanc 134 namespace Orthanc
129 { 135 {
130 namespace Logging 136 namespace Logging
131 { 137 {
138 static void GetLogPath(boost::filesystem::path& log,
139 boost::filesystem::path& link,
140 const char* level,
141 const std::string& directory)
142 {
143 /**
144 From Google Log documentation:
145
146 Unless otherwise specified, logs will be written to the filename
147 "<program name>.<hostname>.<user name>.log.<severity level>.",
148 followed by the date, time, and pid (you can't prevent the date,
149 time, and pid from being in the filename).
150
151 In this implementation : "hostname" and "username" are not used
152 **/
153
154 boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
155 boost::filesystem::path root(directory);
156 boost::filesystem::path exe(Toolbox::GetPathToExecutable());
157
158 if (!boost::filesystem::exists(root) ||
159 !boost::filesystem::is_directory(root))
160 {
161 throw OrthancException(ErrorCode_CannotWriteFile);
162 }
163
164 char date[64];
165 sprintf(date, "%04d%02d%02d-%02d%02d%02d.%d",
166 static_cast<int>(now.date().year()),
167 now.date().month().as_number(),
168 now.date().day().as_number(),
169 now.time_of_day().hours(),
170 now.time_of_day().minutes(),
171 now.time_of_day().seconds(),
172 Toolbox::GetProcessId());
173
174 std::string programName = exe.filename().replace_extension("").string();
175
176 log = (root / (programName + ".log." +
177 std::string(level) + "." +
178 std::string(date)));
179
180 link = (root / (programName + "." + std::string(level)));
181 }
182
183
184 static void PrepareLogFile(std::ostream*& stream,
185 std::auto_ptr<std::ofstream>& file,
186 const char* level,
187 const std::string& directory)
188 {
189 boost::filesystem::path log, link;
190 GetLogPath(log, link, level, directory);
191
192 printf("[%s]\n", log.string().c_str());
193
194 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
195 boost::filesystem::remove(link);
196 boost::filesystem::create_symlink(log.filename(), link);
197 #endif
198
199 file.reset(new std::ofstream(log.c_str()));
200 stream = file.get();
201 }
202
203
132 void Initialize() 204 void Initialize()
133 { 205 {
134 infoEnabled_ = false; 206 infoEnabled_ = false;
135 traceEnabled_ = false; 207 traceEnabled_ = false;
136 } 208 }
137 209
138 void Finalize() 210 void Finalize()
139 { 211 {
212 errorFile_.reset(NULL);
213 warningFile_.reset(NULL);
214 infoFile_.reset(NULL);
140 } 215 }
141 216
142 void EnableInfoLevel(bool enabled) 217 void EnableInfoLevel(bool enabled)
143 { 218 {
144 boost::mutex::scoped_lock lock(mutex_); 219 boost::mutex::scoped_lock lock(mutex_);
150 boost::mutex::scoped_lock lock(mutex_); 225 boost::mutex::scoped_lock lock(mutex_);
151 traceEnabled_ = enabled; 226 traceEnabled_ = enabled;
152 227
153 if (enabled) 228 if (enabled)
154 { 229 {
155 // Also enable the "INFO" level when trace-level debugging is 230 // Also enable the "INFO" level when trace-level debugging is enabled
156 // enabled
157 infoEnabled_ = true; 231 infoEnabled_ = true;
158 } 232 }
159 } 233 }
160 234
161 void SetTargetFolder(const std::string& path) 235 void SetTargetFolder(const std::string& path)
162 { 236 {
163 boost::mutex::scoped_lock lock(mutex_); 237 boost::mutex::scoped_lock lock(mutex_);
164 // TODO 238 PrepareLogFile(error_, errorFile_, "ERROR", path);
239 PrepareLogFile(warning_, warningFile_, "WARNING", path);
240 PrepareLogFile(info_, infoFile_, "INFO", path);
165 } 241 }
166 242
167 InternalLogger::InternalLogger(const char* level, 243 InternalLogger::InternalLogger(const char* level,
168 const char* file, 244 const char* file,
169 int line) : 245 int line) :
171 { 247 {
172 char c; 248 char c;
173 249
174 if (strcmp(level, "ERROR") == 0) 250 if (strcmp(level, "ERROR") == 0)
175 { 251 {
176 stream_ = &error_; 252 stream_ = error_;
177 c = 'E'; 253 c = 'E';
178 } 254 }
179 else if (strcmp(level, "WARNING") == 0) 255 else if (strcmp(level, "WARNING") == 0)
180 { 256 {
181 stream_ = &warning_; 257 stream_ = warning_;
182 c = 'W'; 258 c = 'W';
183 } 259 }
184 else if (strcmp(level, "INFO") == 0) 260 else if (strcmp(level, "INFO") == 0)
185 { 261 {
186 stream_ = infoEnabled_ ? &info_ : &null_; 262 stream_ = infoEnabled_ ? info_ : &null_;
187 c = 'I'; 263 c = 'I';
188 } 264 }
189 else if (strcmp(level, "TRACE") == 0) 265 else if (strcmp(level, "TRACE") == 0)
190 { 266 {
191 stream_ = traceEnabled_ ? &trace_ : &null_; 267 stream_ = traceEnabled_ ? info_ : &null_;
192 c = 'T'; 268 c = 'T';
193 } 269 }
194 else 270 else
195 { 271 {
196 // Unknown logging level 272 // Unknown logging level
204 boost::posix_time::time_duration duration = now.time_of_day(); 280 boost::posix_time::time_duration duration = now.time_of_day();
205 281
206 /** 282 /**
207 From Google Log documentation: 283 From Google Log documentation:
208 284
209 Log lines have this form: 285 "Log lines have this form:
210 286
211 Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... 287 Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
212 288
213 where the fields are defined as follows: 289 where the fields are defined as follows:
214 290
217 dd The day (zero padded) 293 dd The day (zero padded)
218 hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds 294 hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds
219 threadid The space-padded thread ID as returned by GetTID() (this matches the PID on Linux) 295 threadid The space-padded thread ID as returned by GetTID() (this matches the PID on Linux)
220 file The file name 296 file The file name
221 line The line number 297 line The line number
222 msg The user-supplied message 298 msg The user-supplied message"
299
300 In this implementation, "threadid" is not printed.
223 **/ 301 **/
224 302
225 char date[32]; 303 char date[32];
226 sprintf(date, "%c%02d%02d %02d:%02d:%02d.%06d ", c, 304 sprintf(date, "%c%02d%02d %02d:%02d:%02d.%06d ", c,
227 now.date().month().as_number(), 305 now.date().month().as_number(),