bes  Updated for version 3.20.13
BESLog.cc
1 // BESLog.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include "config.h"
34 
35 #include <iostream>
36 #include <time.h>
37 #include <string>
38 #include <sstream>
39 
40 #include "BESLog.h"
41 #include "BESDebug.h"
42 #include "BESUtil.h"
43 #include "TheBESKeys.h"
44 #include "BESInternalFatalError.h"
45 
46 #if HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49 
50 #define ISO8601_TIME_IN_LOGS
51 #define MODULE "bes"
52 #define prolog std::string("BESLog::").append(__func__).append("() - ")
53 
54 using namespace std;
55 
56 BESLog *BESLog::d_instance = 0;
57 const string BESLog::mark = string("|&|");
58 
59 
79  d_flushed(1), d_file_buffer(0), d_suspended(0), d_verbose(false), d_use_local_time(false), d_use_unix_time(false)
80 {
81  d_suspended = 0;
82  bool found = false;
83  try {
84  TheBESKeys::TheKeys()->get_value("BES.LogName", d_file_name, found);
85  }
86  catch (BESInternalFatalError &bife) {
87  stringstream msg;
88  msg << prolog << "ERROR - Caught BESInternalFatalError! Will re-throw. Message: " << bife.get_message() << " File: " << bife.get_file() << " Line: " << bife.get_line() << endl;
89  BESDEBUG(MODULE,msg.str());
90  cerr << msg.str();
91  throw bife;
92  }
93  catch (...) {
94  stringstream msg;
95  msg << prolog << "FATAL ERROR: Caught unknown exception! Unable to determine log file name." << endl;
96  BESDEBUG(MODULE,msg.str());
97  cerr << msg.str();
98  throw BESInternalFatalError(msg.str(), __FILE__, __LINE__);
99  }
100 
101  // By default, use UTC in the logs.
102  found = false;
103  string local_time;
104  try {
105  TheBESKeys::TheKeys()->get_value("BES.LogTimeLocal", local_time, found);
106  d_use_local_time = found && (BESUtil::lowercase(local_time) == "yes");
107  BESDEBUG(MODULE, prolog << "d_use_local_time: " << (d_use_local_time?"true":"false") << endl);
108  }
109  catch (...) {
110  stringstream err;
111  err << prolog << "FATAL ERROR: Caught unknown exception. Failed to read the value of BES.LogTimeLocal" << endl;
112  BESDEBUG(MODULE,err.str());
113  cerr << err.str() << endl;
114  throw BESInternalFatalError(err.str(), __FILE__, __LINE__);
115  }
116 
117  if (d_file_name.empty()) {
118  stringstream err;
119  err << prolog << "FATAL ERROR: unable to determine log file name. ";
120  err << "Please set BES.LogName in your initialization file" << endl;
121  BESDEBUG(MODULE,err.str());
122  cerr << err.str() << endl;
123  throw BESInternalFatalError(err.str(), __FILE__, __LINE__);
124  }
125 
126  d_file_buffer = new ofstream(d_file_name.c_str(), ios::out | ios::app);
127  if (!(*d_file_buffer)) {
128  stringstream err;
129  err << prolog << "BES Fatal; cannot open log file " + d_file_name + "." << endl;
130  BESDEBUG(MODULE,err.str());
131  cerr << err.str() << endl;
132  throw BESInternalFatalError(err.str(), __FILE__, __LINE__);
133  }
134 
135  found = false;
136  string s;
137  TheBESKeys::TheKeys()->get_value("BES.LogVerbose", s, found);
138  d_verbose = found && (BESUtil::lowercase(s) == "yes");
139  BESDEBUG(MODULE, prolog << "d_verbose: " << (d_verbose?"true":"false") << endl);
140 
141  found = false;
142  s = "";
143  TheBESKeys::TheKeys()->get_value("BES.LogUnixTime", s, found);
144  d_use_unix_time = found && (BESUtil::lowercase(s)=="true");
145  BESDEBUG(MODULE, prolog << "d_use_unix_time: " << (d_use_unix_time?"true":"false") << endl);
146 
147 }
148 
154 {
155  d_file_buffer->close();
156  delete d_file_buffer;
157  d_file_buffer = 0;
158 }
159 
168 {
169 #ifdef ISO8601_TIME_IN_LOGS
170  time_t now;
171  time(&now);
172 
173  char buf[sizeof "YYYY-MM-DDTHH:MM:SS zones"];
174  if(d_use_unix_time){
175  (*d_file_buffer) << now;
176  }
177  else {
178  struct tm date_time;
179  if (!d_use_local_time){
180  gmtime_r(&now, &date_time);
181  }
182  else{
183  localtime_r(&now, &date_time);
184  }
185  (void)strftime(buf, sizeof buf, "%FT%T %Z", &date_time);
186  (*d_file_buffer) << buf;
187  }
188 #else
189  const time_t sctime = time(NULL);
190  const struct tm *sttime = localtime(&sctime);
191  char zone_name[10];
192  strftime(zone_name, sizeof(zone_name), "%Z", sttime);
193  char *b = asctime(sttime);
194 
195  (*d_file_buffer) << zone_name << " ";
196  for (register int j = 0; b[j] != '\n'; j++)
197  (*d_file_buffer) << b[j];
198 #endif
199 
200  (*d_file_buffer) << mark << getpid() << mark;
201 
202  d_flushed = 0;
203 }
204 
212 {
213  if (!d_suspended) {
214  if (d_flushed) dump_time();
215  (*d_file_buffer) << s;
216  }
217  return *this;
218 }
219 
224 BESLog& BESLog::operator<<(const string &s)
225 {
226  if (!d_suspended) {
227  if (d_flushed) dump_time();
228  (*d_file_buffer) << s;
229  }
230  return *this;
231 }
232 
238 {
239  if (!d_suspended) {
240  if (d_flushed) dump_time();
241  if (val)
242  (*d_file_buffer) << val;
243  else
244  (*d_file_buffer) << "NULL";
245  }
246  return *this;
247 }
248 
253 BESLog& BESLog::operator<<(const char *val)
254 {
255  if (!d_suspended) {
256  if (d_flushed) {
257  dump_time();
258  }
259  if (val)
260  (*d_file_buffer) << val;
261  else
262  (*d_file_buffer) << "NULL";
263  }
264  return *this;
265 }
266 
272 {
273  if (!d_suspended) {
274  if (d_flushed) dump_time();
275  (*d_file_buffer) << val;
276  }
277  return *this;
278 }
279 
280 BESLog& BESLog::operator<<(unsigned int val)
281 {
282  if (!d_suspended) {
283  if (d_flushed) dump_time();
284  (*d_file_buffer) << val;
285  }
286  return *this;
287 }
288 
289 
295 {
296  if (!d_suspended) {
297  if (d_flushed) dump_time();
298  (*d_file_buffer) << val;
299  }
300  return *this;
301 }
302 
308 {
309  if (!d_suspended) {
310  if (d_flushed) dump_time();
311  (*d_file_buffer) << val;
312  }
313  return *this;
314 }
315 
320 BESLog& BESLog::operator<<(unsigned long val)
321 {
322  if (!d_suspended) {
323  if (d_flushed) dump_time();
324  (*d_file_buffer) << val;
325  }
326  return *this;
327 }
328 
334 {
335  if (!d_suspended) {
336  if (d_flushed) dump_time();
337  (*d_file_buffer) << val;
338  }
339  return *this;
340 }
341 
349 BESLog& BESLog::operator<<(p_ostream_manipulator val)
350 {
351  if (!d_suspended) {
352  (*d_file_buffer) << val;
353  if ((val == (p_ostream_manipulator) endl) || (val == (p_ostream_manipulator) flush)) d_flushed = 1;
354  }
355  return *this;
356 }
357 
358 void BESLog::flush_me(){
359  (*d_file_buffer) << flush;
360  d_flushed = 1;
361 }
362 
369 BESLog& BESLog::operator<<(p_ios_manipulator val)
370 {
371  if (!d_suspended) (*d_file_buffer) << val;
372  return *this;
373 }
374 
382 void BESLog::dump(ostream &strm) const
383 {
384  strm << BESIndent::LMarg << "BESLog::dump - (" << (void *) this << ")" << endl;
385  BESIndent::Indent();
386  strm << BESIndent::LMarg << "log file: " << d_file_name << endl;
387  if (d_file_buffer && *d_file_buffer) {
388  strm << BESIndent::LMarg << "log is valid" << endl;
389  }
390  else {
391  strm << BESIndent::LMarg << "log is NOT valid" << endl;
392  }
393  strm << BESIndent::LMarg << "is verbose: " << d_verbose << endl;
394  strm << BESIndent::LMarg << "is flushed: " << d_flushed << endl;
395  strm << BESIndent::LMarg << "is suspended: " << d_suspended << endl;
396  BESIndent::UnIndent();
397 }
398 
399 BESLog *
400 BESLog::TheLog()
401 {
402  if (d_instance == 0) {
403  d_instance = new BESLog;
404  }
405  return d_instance;
406 }
407 
unsigned int get_line() const
get the line number where the exception was thrown
Definition: BESError.h:129
std::string get_file() const
get the file name where the exception was thrown
Definition: BESError.h:120
std::string get_message() const
get the error message for this exception
Definition: BESError.h:111
exception thrown if an internal error is found and is fatal to the BES
Provides a mechanism for applications to log information to an external file.
Definition: BESLog.h:130
void dump_time()
Protected method that dumps the date/time to the log file.
Definition: BESLog.cc:167
BESLog & operator<<(std::string &)
Overloaded inserter that writes the specified string.
Definition: BESLog.cc:211
~BESLog()
Cleans up the logging mechanism.
Definition: BESLog.cc:153
std::ostream &(* p_ostream_manipulator)(std::ostream &)
Defines a data type p_std::ostream_manipulator "pointer to function that takes std::ostream& and retu...
Definition: BESLog.h:222
BESLog()
constructor that sets up logging for the application.
Definition: BESLog.cc:78
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESLog.cc:382
static std::string lowercase(const std::string &s)
Definition: BESUtil.cc:254
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: TheBESKeys.cc:340
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:71