bes  Updated for version 3.20.6
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 
39 #include "BESLog.h"
40 #include "TheBESKeys.h"
41 #include "BESInternalFatalError.h"
42 
43 #if HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46 
47 #define ISO8601_TIME_IN_LOGS
48 
49 using namespace std;
50 
51 BESLog *BESLog::d_instance = 0;
52 const string BESLog::mark = string("|&|");
53 
73  d_flushed(1), d_file_buffer(0), d_suspended(0), d_verbose(false), d_use_local_time(false)
74 {
75  d_suspended = 0;
76  bool found = false;
77  try {
78  TheBESKeys::TheKeys()->get_value("BES.LogName", d_file_name, found);
79  }
80  catch (BESInternalFatalError &bife) {
81  cerr << "BESInternalFatalError! Message: " << bife.get_message() << " File: " << bife.get_file() << " Line: " << bife.get_line() << endl;
82  throw bife;
83  }
84  catch (...) {
85  string err ="Caught unknown exception! Unable to determine log file name. BES fatal error!";
86  cerr << err << endl;
87  throw BESInternalFatalError(err, __FILE__, __LINE__);
88  }
89 
90  // By default, use UTC in the logs.
91  found = false;
92  string local_time = "no";
93  try {
94  TheBESKeys::TheKeys()->get_value("BES.LogTimeLocal", local_time, found);
95  if (local_time == "YES" || local_time == "Yes" || local_time == "yes") {
96  d_use_local_time = true;
97  }
98 
99  }
100  catch (...) {
101  string err ="BES Fatal: Unable to read the value of BES.LogTimeUTC";
102  cerr << err << endl;
103  throw BESInternalFatalError(err, __FILE__, __LINE__);
104  }
105 
106  if (d_file_name == "") {
107  string err = "BES Fatal: unable to determine log file name. Please set BES.LogName in your initialization file";
108  cerr << err << endl;
109  throw BESInternalFatalError(err, __FILE__, __LINE__);
110  }
111 
112  d_file_buffer = new ofstream(d_file_name.c_str(), ios::out | ios::app);
113  if (!(*d_file_buffer)) {
114  string err = "BES Fatal; cannot open log file " + d_file_name + ".";
115  cerr << err << endl;
116  throw BESInternalFatalError(err, __FILE__, __LINE__);
117  }
118 
119  found = false;
120  string verbose;
121  TheBESKeys::TheKeys()->get_value("BES.LogVerbose", verbose, found);
122  if (verbose == "YES" || verbose == "Yes" || verbose == "yes") {
123  d_verbose = true;
124  }
125 }
126 
132 {
133  d_file_buffer->close();
134  delete d_file_buffer;
135  d_file_buffer = 0;
136 }
137 
146 {
147 #ifdef ISO8601_TIME_IN_LOGS
148  time_t now;
149  time(&now);
150  char buf[sizeof "YYYY-MM-DDTHH:MM:SSzone"];
151  int status = 0;
152 
153  // From StackOverflow:
154  // This will work too, if your compiler doesn't support %F or %T:
155  // strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%S%Z", gmtime(&now));
156  //
157  // Apologies for the twisted logic - UTC is the default. Override to
158  // local time using BES.LogTimeLocal=yes in bes.conf. jhrg 11/15/17
159  if (!d_use_local_time)
160  status = strftime(buf, sizeof buf, "%FT%T%Z", gmtime(&now));
161  else
162  status = strftime(buf, sizeof buf, "%FT%T%Z", localtime(&now));
163 
164  (*d_file_buffer) << buf;
165 
166 #else
167  const time_t sctime = time(NULL);
168  const struct tm *sttime = localtime(&sctime);
169  char zone_name[10];
170  strftime(zone_name, sizeof(zone_name), "%Z", sttime);
171  char *b = asctime(sttime);
172 
173  (*d_file_buffer) << zone_name << " ";
174  for (register int j = 0; b[j] != '\n'; j++)
175  (*d_file_buffer) << b[j];
176 #endif
177 
178  (*d_file_buffer) << mark << getpid() << mark;
179 
180  d_flushed = 0;
181 }
182 
190 {
191  if (!d_suspended) {
192  if (d_flushed) dump_time();
193  (*d_file_buffer) << s;
194  }
195  return *this;
196 }
197 
202 BESLog& BESLog::operator<<(const string &s)
203 {
204  if (!d_suspended) {
205  if (d_flushed) dump_time();
206  (*d_file_buffer) << s;
207  }
208  return *this;
209 }
210 
216 {
217  if (!d_suspended) {
218  if (d_flushed) dump_time();
219  if (val)
220  (*d_file_buffer) << val;
221  else
222  (*d_file_buffer) << "NULL";
223  }
224  return *this;
225 }
226 
231 BESLog& BESLog::operator<<(const char *val)
232 {
233  if (!d_suspended) {
234  if (d_flushed) {
235  dump_time();
236  }
237  if (val)
238  (*d_file_buffer) << val;
239  else
240  (*d_file_buffer) << "NULL";
241  }
242  return *this;
243 }
244 
250 {
251  if (!d_suspended) {
252  if (d_flushed) dump_time();
253  (*d_file_buffer) << val;
254  }
255  return *this;
256 }
257 
258 BESLog& BESLog::operator<<(unsigned int val)
259 {
260  if (!d_suspended) {
261  if (d_flushed) dump_time();
262  (*d_file_buffer) << val;
263  }
264  return *this;
265 }
266 
267 
273 {
274  if (!d_suspended) {
275  if (d_flushed) dump_time();
276  (*d_file_buffer) << val;
277  }
278  return *this;
279 }
280 
286 {
287  if (!d_suspended) {
288  if (d_flushed) dump_time();
289  (*d_file_buffer) << val;
290  }
291  return *this;
292 }
293 
298 BESLog& BESLog::operator<<(unsigned long val)
299 {
300  if (!d_suspended) {
301  if (d_flushed) dump_time();
302  (*d_file_buffer) << val;
303  }
304  return *this;
305 }
306 
312 {
313  if (!d_suspended) {
314  if (d_flushed) dump_time();
315  (*d_file_buffer) << val;
316  }
317  return *this;
318 }
319 
327 BESLog& BESLog::operator<<(p_ostream_manipulator val)
328 {
329  if (!d_suspended) {
330  (*d_file_buffer) << val;
331  if ((val == (p_ostream_manipulator) endl) || (val == (p_ostream_manipulator) flush)) d_flushed = 1;
332  }
333  return *this;
334 }
335 
336 void BESLog::flush_me(){
337  (*d_file_buffer) << flush;
338  d_flushed = 1;
339 }
340 
347 BESLog& BESLog::operator<<(p_ios_manipulator val)
348 {
349  if (!d_suspended) (*d_file_buffer) << val;
350  return *this;
351 }
352 
360 void BESLog::dump(ostream &strm) const
361 {
362  strm << BESIndent::LMarg << "BESLog::dump - (" << (void *) this << ")" << endl;
363  BESIndent::Indent();
364  strm << BESIndent::LMarg << "log file: " << d_file_name << endl;
365  if (d_file_buffer && *d_file_buffer) {
366  strm << BESIndent::LMarg << "log is valid" << endl;
367  }
368  else {
369  strm << BESIndent::LMarg << "log is NOT valid" << endl;
370  }
371  strm << BESIndent::LMarg << "is verbose: " << d_verbose << endl;
372  strm << BESIndent::LMarg << "is flushed: " << d_flushed << endl;
373  strm << BESIndent::LMarg << "is suspended: " << d_suspended << endl;
374  BESIndent::UnIndent();
375 }
376 
377 BESLog *
378 BESLog::TheLog()
379 {
380  if (d_instance == 0) {
381  d_instance = new BESLog;
382  }
383  return d_instance;
384 }
385 
BESError::get_line
virtual int get_line()
get the line number where the exception was thrown
Definition: BESError.h:115
BESInternalFatalError
exception thrown if an internal error is found and is fatal to the BES
Definition: BESInternalFatalError.h:43
BESLog::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESLog.cc:360
BESError::get_message
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
BESError::get_file
virtual std::string get_file()
get the file name where the exception was thrown
Definition: BESError.h:107
BESLog::operator<<
BESLog & operator<<(std::string &)
Overloaded inserter that writes the specified string.
Definition: BESLog.cc:189
BESLog::~BESLog
~BESLog()
Cleans up the logging mechanism.
Definition: BESLog.cc:131
TheBESKeys::TheKeys
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:62
BESLog::p_ostream_manipulator
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:193
TheBESKeys::get_value
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: TheBESKeys.cc:272
BESLog
Provides a mechanism for applications to log information to an external file.
Definition: BESLog.h:103
BESLog::BESLog
BESLog()
constructor that sets up logging for the application.
Definition: BESLog.cc:72
BESLog::dump_time
void dump_time()
Protected method that dumps the date/time to the log file.
Definition: BESLog.cc:145