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
54using namespace std;
55
56BESLog *BESLog::d_instance = 0;
57const 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
243BESLog& 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
272BESLog& 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
299BESLog& 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
339BESLog& 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
368BESLog& 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
377void BESLog::flush_me(){
378 (*d_file_buffer) << flush;
379 d_flushed = 1;
380}
381
388BESLog& BESLog::operator<<(p_ios_manipulator val)
389{
390 if (!d_suspended) (*d_file_buffer) << val;
391 return *this;
392}
393
401void 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
418BESLog *
419BESLog::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
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
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
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