bes  Updated for version 3.20.10
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 #if 0
174  char buf[sizeof "YYYY-MM-DDTHH:MM:SSzone"];
175  int status = 0;
176 
177  // From StackOverflow:
178  // This will work too, if your compiler doesn't support %F or %T:
179  // strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%S%Z", gmtime(&now));
180  //
181  // Apologies for the twisted logic - UTC is the default. Override to
182  // local time using BES.LogTimeLocal=yes in bes.conf. jhrg 11/15/17
183  if (!d_use_local_time)
184  status = strftime(buf, sizeof buf, "%FT%T%Z", gmtime(&now));
185  else
186  status = strftime(buf, sizeof buf, "%FT%T%Z", localtime(&now));
187 #endif
188 
189  char buf[sizeof "YYYY-MM-DDTHH:MM:SS zones"];
190  int status = 0;
191  if(d_use_unix_time){
192  (*d_file_buffer) << now;
193  }
194  else {
195  struct tm dat_time;
196  if (!d_use_local_time){
197  gmtime_r(&now, &dat_time);
198  }
199  else{
200  localtime_r(&now, &dat_time);
201  }
202  status = strftime(buf, sizeof buf, "%FT%T %Z", &dat_time);
203  (*d_file_buffer) << buf;
204  }
205 
206 
207 #else
208  const time_t sctime = time(NULL);
209  const struct tm *sttime = localtime(&sctime);
210  char zone_name[10];
211  strftime(zone_name, sizeof(zone_name), "%Z", sttime);
212  char *b = asctime(sttime);
213 
214  (*d_file_buffer) << zone_name << " ";
215  for (register int j = 0; b[j] != '\n'; j++)
216  (*d_file_buffer) << b[j];
217 #endif
218 
219  (*d_file_buffer) << mark << getpid() << mark;
220 
221  d_flushed = 0;
222 }
223 
231 {
232  if (!d_suspended) {
233  if (d_flushed) dump_time();
234  (*d_file_buffer) << s;
235  }
236  return *this;
237 }
238 
243 BESLog& BESLog::operator<<(const string &s)
244 {
245  if (!d_suspended) {
246  if (d_flushed) dump_time();
247  (*d_file_buffer) << s;
248  }
249  return *this;
250 }
251 
257 {
258  if (!d_suspended) {
259  if (d_flushed) dump_time();
260  if (val)
261  (*d_file_buffer) << val;
262  else
263  (*d_file_buffer) << "NULL";
264  }
265  return *this;
266 }
267 
272 BESLog& BESLog::operator<<(const char *val)
273 {
274  if (!d_suspended) {
275  if (d_flushed) {
276  dump_time();
277  }
278  if (val)
279  (*d_file_buffer) << val;
280  else
281  (*d_file_buffer) << "NULL";
282  }
283  return *this;
284 }
285 
291 {
292  if (!d_suspended) {
293  if (d_flushed) dump_time();
294  (*d_file_buffer) << val;
295  }
296  return *this;
297 }
298 
299 BESLog& BESLog::operator<<(unsigned int val)
300 {
301  if (!d_suspended) {
302  if (d_flushed) dump_time();
303  (*d_file_buffer) << val;
304  }
305  return *this;
306 }
307 
308 
314 {
315  if (!d_suspended) {
316  if (d_flushed) dump_time();
317  (*d_file_buffer) << val;
318  }
319  return *this;
320 }
321 
327 {
328  if (!d_suspended) {
329  if (d_flushed) dump_time();
330  (*d_file_buffer) << val;
331  }
332  return *this;
333 }
334 
339 BESLog& BESLog::operator<<(unsigned long val)
340 {
341  if (!d_suspended) {
342  if (d_flushed) dump_time();
343  (*d_file_buffer) << val;
344  }
345  return *this;
346 }
347 
353 {
354  if (!d_suspended) {
355  if (d_flushed) dump_time();
356  (*d_file_buffer) << val;
357  }
358  return *this;
359 }
360 
368 BESLog& BESLog::operator<<(p_ostream_manipulator val)
369 {
370  if (!d_suspended) {
371  (*d_file_buffer) << val;
372  if ((val == (p_ostream_manipulator) endl) || (val == (p_ostream_manipulator) flush)) d_flushed = 1;
373  }
374  return *this;
375 }
376 
377 void BESLog::flush_me(){
378  (*d_file_buffer) << flush;
379  d_flushed = 1;
380 }
381 
388 BESLog& BESLog::operator<<(p_ios_manipulator val)
389 {
390  if (!d_suspended) (*d_file_buffer) << val;
391  return *this;
392 }
393 
401 void BESLog::dump(ostream &strm) const
402 {
403  strm << BESIndent::LMarg << "BESLog::dump - (" << (void *) this << ")" << endl;
404  BESIndent::Indent();
405  strm << BESIndent::LMarg << "log file: " << d_file_name << endl;
406  if (d_file_buffer && *d_file_buffer) {
407  strm << BESIndent::LMarg << "log is valid" << endl;
408  }
409  else {
410  strm << BESIndent::LMarg << "log is NOT valid" << endl;
411  }
412  strm << BESIndent::LMarg << "is verbose: " << d_verbose << endl;
413  strm << BESIndent::LMarg << "is flushed: " << d_flushed << endl;
414  strm << BESIndent::LMarg << "is suspended: " << d_suspended << endl;
415  BESIndent::UnIndent();
416 }
417 
418 BESLog *
419 BESLog::TheLog()
420 {
421  if (d_instance == 0) {
422  d_instance = new BESLog;
423  }
424  return d_instance;
425 }
426 
virtual int get_line()
get the line number where the exception was thrown
Definition: BESError.h:115
virtual std::string get_file()
get the file name where the exception was thrown
Definition: BESError.h:107
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
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:230
~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:401
static std::string lowercase(const std::string &s)
Definition: BESUtil.cc:206
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