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
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 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
224BESLog& 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
253BESLog& 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
280BESLog& 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
320BESLog& 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
349BESLog& 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
358void BESLog::flush_me(){
359 (*d_file_buffer) << flush;
360 d_flushed = 1;
361}
362
369BESLog& BESLog::operator<<(p_ios_manipulator val)
370{
371 if (!d_suspended) (*d_file_buffer) << val;
372 return *this;
373}
374
382void 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
399BESLog *
400BESLog::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
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:211
~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: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