GSI Object Oriented Online Offline (Go4) GO4-6.4.0
Loading...
Searching...
No Matches
TGo4Log.cxx
Go to the documentation of this file.
1// $Id$
2//-----------------------------------------------------------------------
3// The GSI Online Offline Object Oriented (Go4) Project
4// Experiment Data Processing at EE department, GSI
5//-----------------------------------------------------------------------
6// Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7// Planckstr. 1, 64291 Darmstadt, Germany
8// Contact: http://go4.gsi.de
9//-----------------------------------------------------------------------
10// This software can be used under the license agreements as stated
11// in Go4License.txt file which is part of the distribution.
12//-----------------------------------------------------------------------
13
14#include "TGo4Log.h"
15
16#ifndef _MSC_VER
17#include <unistd.h>
18#include <fcntl.h>
19#endif
20
21#include <stdarg.h>
22#include <fstream>
23#include <iostream>
24
25#include "TDatime.h"
26#include "TDataType.h"
27#include "TMutex.h"
28#include "TSystem.h"
29
30
31const char *TGo4Log::fgcLEFT = "GO4-";
32//const char *TGo4Log::fgcRIGHT = " <GO4";
33const char *TGo4Log::fgcRIGHT = " ";
34const char *TGo4Log::fgcDEBUG = "d";
35const char *TGo4Log::fgcINFO = "*";
36const char *TGo4Log::fgcWARN = "#";
37const char *TGo4Log::fgcERR = "!";
38const char *TGo4Log::fgcDEFAULTLOG = "go4logfile.txt";
39
40TString TGo4Log::fgsGO4SYS = "";
41
44Bool_t TGo4Log::fgbOutputEnabled = kTRUE;
45Bool_t TGo4Log::fgbLogfileEnabled = kFALSE;
46Bool_t TGo4Log::fgbAutoMode = kFALSE;
47void *TGo4Log::fgxLogfile = nullptr;
48TMutex *TGo4Log::fgxMutex = nullptr;
50
52
53TNamed *TGo4Log::fgSniffer = nullptr;
54
55int TGo4Log::fgStdPipe[2] = {-1, -1};
56int TGo4Log::fgStdSave = -1;
57
58class TLogTimer : public TTimer {
59 public:
60 TLogTimer(Int_t millisec) : TTimer(millisec) {}
61
62 Bool_t Notify() override { TGo4Log::ProcessRedirection(); return kTRUE; }
63};
64
65
67
69{
70 if (!fgxMutex) fgxMutex = new TMutex(kTRUE);
71
72 // initialization at first time we call logger
73 // we use recursive mode for cascading lockguards
74 if (IsLogfileEnabled()) {
75 OpenLogfile(fgcDEFAULTLOG,"--- This is the default Go4 Message logfile ---");
76 LogfileEnable(kFALSE); // after first write disable logfile
77 }
78}
79
84
86{
87 if(!fgxInstance)
88 fgxInstance = new TGo4Log();
89
90 return fgxInstance;
91}
92
94{
95 if (fgStdSave > 0) return;
96
97#ifndef _MSC_VER
98
99 fflush(stdout);
100
101 fgStdSave = dup(STDOUT_FILENO); /* save stdout for display later */
102
103 if(pipe(fgStdPipe) != 0) return; /* make a pipe */
104
105 dup2(fgStdPipe[1], STDOUT_FILENO); /* redirect stdout to the pipe */
106 long flags = fcntl(fgStdPipe[0], F_GETFL);
107 flags |= O_NONBLOCK;
108 fcntl(fgStdPipe[0], F_SETFL, flags);
109
110 if (!fgTimer) {
111 fgTimer = new TLogTimer(200);
112 fgTimer->Start(200);
113 }
114#endif
115}
116
117
119{
120 if (fgStdSave < 0) return;
121
122#ifndef _MSC_VER
123
124 if (kind >= 0) {
125
126 std::cout.flush();
127 fflush(stdout);
128
129 char buffer[20000];
130 memset(buffer, 0, sizeof(buffer));
131 int len = read(fgStdPipe[0], buffer, sizeof(buffer)-1); /* read from pipe into buffer */
132
133 // when nothing to read, than nothing to redirect
134 if (len == 0) return;
135
136 dup2(fgStdSave, STDOUT_FILENO); /* reconnect stdout for realoutput */
137
138 printf("%s", buffer);
139 fflush(stdout);
140
141 if (fgSniffer) fgSniffer->SetTitle(buffer);
142 }
143
144 if (kind <= 0) {
145 dup2(fgStdPipe[1], STDOUT_FILENO); // redirect again
146 }
147
148#endif
149}
150
151void TGo4Log::SetSniffer(TNamed *sniff)
152{
153 fgSniffer = sniff;
154}
155
156const char *TGo4Log::GO4SYS()
157{
158 if (fgsGO4SYS.Length()>0) return fgsGO4SYS.Data();
159 const char *go4sys = gSystem->Getenv("GO4SYS");
160#ifdef COMP_GO4SYS
161 if (!go4sys || (strlen(go4sys) == 0)) go4sys = COMP_GO4SYS;
162#endif
163 if (!go4sys || (strlen(go4sys) == 0)) return "";
164
165 fgsGO4SYS = go4sys;
166 if (fgsGO4SYS.Length() > 0) {
167#ifdef _MSC_VER
168 char lastsymbol = '\\';
169 fgsGO4SYS.ReplaceAll("/","\\"); // while in cygpath we cannot deliver windows-like slashes
170#else
171 char lastsymbol = '/';
172#endif
173 if (fgsGO4SYS[fgsGO4SYS.Length() - 1] != lastsymbol) fgsGO4SYS += lastsymbol;
174 }
175
176 return fgsGO4SYS.Length()>0 ? fgsGO4SYS.Data() : "";
177}
178
180{
181 #ifdef COMP_GO4INC
182 return COMP_GO4INC;
183 #else
184 return "";
185 #endif
186}
187
188
189TString TGo4Log::subGO4SYS(const char *subdir)
190{
191 const char *go4sys = GO4SYS();
192
193 if (!subdir || (strlen(subdir) == 0)) return TString(go4sys);
194
195 TString res = go4sys;
196
197#ifdef _MSC_VER
198 res += TString(subdir).ReplaceAll("/","\\");
199#else
200 res += subdir;
201#endif
202
203 return res;
204}
205
206const char *TGo4Log::Message(Int_t prio, const char *text,...)
207{
208 Instance();
209 //TGo4LockGuard(fxMutex);
210 if(prio>-1 && prio<fgiIgnoreLevel) return nullptr;
211 char txtbuf[fguMESLEN-20];
212 va_list args;
213 va_start(args, text);
214 vsnprintf(txtbuf, fguMESLEN-20, text, args);
215 va_end(args);
216 const char *prefix = fgcINFO;
217 switch(prio) {
218 // info output independent of current ignorelevel
219 case -1: prefix = fgcINFO; break;
220 case 0: prefix = fgcDEBUG; break;
221 case 1: prefix = fgcINFO; break;
222 case 2: prefix = fgcWARN; break;
223 case 3: prefix = fgcERR; break;
224 } // switch()
225
227 // message format for logfile is different:
228 int resf = snprintf(fgcMessagetext, __MESSAGETEXTLENGTH__, "%s %s", prefix, txtbuf);
230
231 (void) resf; // prevent compiler warnings
232 }
233
234 // we compose the full messagetext anyway, for further use outside
235 int res = snprintf(fgcMessagetext, __MESSAGETEXTLENGTH__, "%s%s> %s %s", fgcLEFT, prefix, txtbuf, fgcRIGHT);
236 (void) res; // prevent compiler warnings
237
238 if(fgbOutputEnabled) {
239
240 ProcessRedirection(1); // disable redirection
241
242 std::cout << fgcMessagetext << std::endl;
243
244 std::cout.flush();
245
246 if (fgSniffer) fgSniffer->SetTitle(fgcMessagetext);
247
248 ProcessRedirection(-1); // enable again
249 }
250
251 return fgcMessagetext;
252}
253
254void TGo4Log::Printf(Bool_t _stdout, const char *text)
255{
256 ProcessRedirection(1); // disable redirection
257
258 if (_stdout) {
259 fprintf(stdout, "%s", text);
260 fflush(stdout);
261 } else {
262 fprintf(stderr, "%s", text);
263 fflush(stderr);
264 }
265
266 ProcessRedirection(-1); // enable again
267}
268
269
270void TGo4Log::PrintRate(ULong64_t cnt, double rate)
271{
272 ProcessRedirection(1); // disable redirection
273
274 int width = (rate > 1e4) ? 0 : (rate < 1. ? 3 : 1);
275 fprintf(stdout, "\rCnt = %llu Rate = %5.*f Ev/s", cnt, width, rate);
276 fflush(stdout);
277
278 ProcessRedirection(-1); // enable again
279}
280
281void TGo4Log::Debug(const char *text,...)
282{
283 if(fgiIgnoreLevel>0) return;
284 Instance();
285 //TGo4LockGuard(fxMutex);
286 char txtbuf[fguMESLEN];
287 va_list args;
288 va_start(args, text);
289 vsnprintf(txtbuf, fguMESLEN, text, args);
290 va_end(args);
291 Message(0, "%s", txtbuf);
292}
293
294void TGo4Log::Info(const char *text,...)
295{
296 if(fgiIgnoreLevel>1) return;
297 Instance();
298 //TGo4LockGuard(fxMutex);
299 char txtbuf[fguMESLEN];
300 va_list args;
301 va_start(args, text);
302 vsnprintf(txtbuf, fguMESLEN, text, args);
303 va_end(args);
304 Message(1, "%s", txtbuf);
305}
306
307void TGo4Log::Warn(const char *text,...)
308{
309 if(fgiIgnoreLevel>2) return;
310 Instance();
311 //TGo4LockGuard(fxMutex);
312 char txtbuf[fguMESLEN];
313 va_list args;
314 va_start(args, text);
315 vsnprintf(txtbuf, fguMESLEN, text, args);
316 va_end(args);
317 Message(2, "%s", txtbuf);
318}
319
320void TGo4Log::Error(const char *text,...)
321{
322 Instance();
323 //TGo4LockGuard(fxMutex);
324 char txtbuf[fguMESLEN];
325 va_list args;
326 va_start(args, text);
327 vsnprintf(txtbuf, fguMESLEN, text, args);
328 va_end(args);
329 Message(3, "%s", txtbuf);
330}
331
332void TGo4Log::SetIgnoreLevel(Int_t level)
333{
334 //TGo4LockGuard(fxMutex);
335 fgiIgnoreLevel = level;
336}
337
339{
340 return fgiIgnoreLevel;
341}
342
344{
345 return fgxLogName.Data();
346}
347
349{
350 return fgcDEFAULTLOG;
351}
352
354{
355 fgbOutputEnabled = on;
356}
357
359{
360 return fgbOutputEnabled;
361}
362
364{
366}
367
369{
370 return fgbLogfileEnabled;
371}
372
373void TGo4Log::AutoEnable(Bool_t on)
374{
375 fgbAutoMode = on;
376}
377
379{
380 return fgbAutoMode;
381}
382
383void TGo4Log::OpenLogfile(const char *name, const char *headercomment, Bool_t appendmode)
384{
385 //TGo4LockGuard(fxMutex);
386 try
387 {
388 CloseLogfile();
389 char txtbuf[fguMESLEN];
390 if(!name)
391 // default: encode pid into filename
392 snprintf(txtbuf,fguMESLEN,"go4log-%d.txt", gSystem->GetPid());
393 else
394 snprintf(txtbuf,fguMESLEN,"%s",name);
395
396 std::ofstream* lf = new std::ofstream(txtbuf, appendmode ? std::ios::app : std::ios::out);
397
398 if(lf->fail()) {
399 LogfileEnable(kFALSE);
400 delete lf;
401 std::cerr <<"TGo4Log::OpenLogfile() - Error opening logfile "<< name << std::endl;
402 } else {
403 fgxLogfile = lf;
404 fgxLogName = txtbuf; // remember our last filename
405 }
406 // write headercomment into the first lines:
407 if(headercomment) WriteLogfile(headercomment, kFALSE);
408 } // try
409
410 catch(std::exception& ex) // treat standard library exceptions
411 {
412 std::cerr <<"standard exception "<<ex.what()<<"in TGo4Log::OpenLogfile" << std::endl;
413 }
414 catch(...)
415 {
416 std::cerr <<"!!! Unexpected exception in TGo4Log::OpenLogfile !!!" << std::endl;
417 } // catch
418}
419
420void TGo4Log::WriteLogfile(const char *text, Bool_t withtime)
421{
422 //TGo4LockGuard(fxMutex);
423 if(!text || !fgbLogfileEnabled || !fgxLogfile) return;
424 try {
425 std::ofstream *lf = static_cast<std::ofstream*>(fgxLogfile);
426 if (lf->is_open()) {
427 if(withtime) {
428 TDatime now;
429 *lf << now.AsSQLString() << ": ";
430 }
431 *lf << text << std::endl;
432 }
433 }// try
434 catch(std::exception& ex) // treat standard library exceptions
435 {
436 std::cerr <<"standard exception "<<ex.what()<<"in TGo4Log::WriteLogfile" << std::endl;
437 }
438 catch(...)
439 {
440 std::cerr <<"!!! Unexpected exception in TGo4Log::WriteLogfile !!!" << std::endl;
441 } // catch
442}
443
445{
446 //TGo4LockGuard(fxMutex);
447 if(fgxLogfile)
448 {
449 try
450 {
451 delete (std::ofstream*)fgxLogfile;
452 fgxLogfile = nullptr;
453 }
454 catch(std::exception& ex) // treat standard library exceptions
455 {
456 std::cerr <<"standard exception "<<ex.what()<<"in TGo4Log::CloseLogfile" << std::endl;
457 }
458 catch(...)
459 {
460 std::cerr <<"!!! Unexpected exception in TGo4Log::CloseLogfile !!!" << std::endl;
461 } //
462 }
463}
#define __MESSAGETEXTLENGTH__
Definition TGo4Log.h:22
This class handles all logging messages inside Go4.
Definition TGo4Log.h:50
static const char * fgcDEFAULTLOG
Name of default logfile.
Definition TGo4Log.h:169
static TGo4Log * Instance()
Definition TGo4Log.cxx:85
static TString subGO4SYS(const char *subdir)
Return subdirectory in the GO4SYS.
Definition TGo4Log.cxx:189
static void Warn(const char *text,...) GO4_PRINTF_ARGS
User shortcut for message with prio 2.
Definition TGo4Log.cxx:307
static Bool_t IsAutoEnabled()
get current user boolean
Definition TGo4Log.cxx:378
static void ProcessRedirection(int kind=0)
Definition TGo4Log.cxx:118
static void Info(const char *text,...) GO4_PRINTF_ARGS
User shortcut for message with prio 1.
Definition TGo4Log.cxx:294
static void PrintRate(ULong64_t cnt, double rate)
Printout rate and events count, handle redirection.
Definition TGo4Log.cxx:270
static Bool_t fgbOutputEnabled
General switch on/off log output.
Definition TGo4Log.h:197
static const char * GetLogname()
get name of last opened logfile
Definition TGo4Log.cxx:343
static void WriteLogfile(const char *text, Bool_t withtime=kTRUE)
Write text to current logfile if this is open.
Definition TGo4Log.cxx:420
friend class TLogTimer
Definition TGo4Log.h:182
static const char * Message(Int_t prio, const char *text,...) GO4_PRINTF2_ARGS
Display a message.
Definition TGo4Log.cxx:206
static const char * GO4SYS()
Return GO4SYS environment variable or Go4 top directory during compile (if GO4SYS) not set.
Definition TGo4Log.cxx:156
static const char * fgcINFO
Info message indicator.
Definition TGo4Log.h:160
static char fgcMessagetext[__MESSAGETEXTLENGTH__]
Keeps latest message with all format indicators.
Definition TGo4Log.h:206
static Bool_t IsLogfileEnabled()
get current logfile state
Definition TGo4Log.cxx:368
static void Printf(Bool_t _stdout, const char *text)
Make direct printf without log file or logger.
Definition TGo4Log.cxx:254
static const char * fgcRIGHT
Prompt character right side.
Definition TGo4Log.h:154
static const char * fgcERR
Error message indicator.
Definition TGo4Log.h:166
static void SetIgnoreLevel(Int_t level)
Define threshold for output.
Definition TGo4Log.cxx:332
static const char * fgcWARN
Warning message indicator.
Definition TGo4Log.h:163
static void LogfileEnable(Bool_t on=kTRUE)
switch writing to logfile on or off
Definition TGo4Log.cxx:363
static void SetSniffer(TNamed *sniff)
Definition TGo4Log.cxx:151
static int fgStdPipe[2]
optional object to get all output via SetTitle method
Definition TGo4Log.h:55
static Int_t fgiIgnoreLevel
all Messages with lower level are suppressed
Definition TGo4Log.h:194
static void Debug(const char *text,...) GO4_PRINTF_ARGS
User shortcut for message with prio 0.
Definition TGo4Log.cxx:281
static const char * fgcDEBUG
System debug message indicator.
Definition TGo4Log.h:157
static TString fgxLogName
Name of last logfile set.
Definition TGo4Log.h:212
static const char * GO4INCPATH()
Return include path for this Go4 installation.
Definition TGo4Log.cxx:179
static void AutoEnable(Bool_t on=kTRUE)
set boolean for user action
Definition TGo4Log.cxx:373
static TMutex * fgxMutex
we use own mutex to protect the logging instance
Definition TGo4Log.h:191
static void EnableRedirection()
Definition TGo4Log.cxx:93
static void OutputEnable(Bool_t on=kTRUE)
switch output on or off
Definition TGo4Log.cxx:353
static void Error(const char *text,...) GO4_PRINTF_ARGS
User shortcut for message with prio 3.
Definition TGo4Log.cxx:320
static int fgStdSave
redirected pipe for stdout
Definition TGo4Log.h:219
static Bool_t fgbAutoMode
User boolean to write log on demand or not.
Definition TGo4Log.h:203
static Bool_t IsOutputEnabled()
get current output state
Definition TGo4Log.cxx:358
@ fguMESLEN
Definition TGo4Log.h:172
static TString fgsGO4SYS
Definition TGo4Log.h:214
static TNamed * fgSniffer
value of GO4SYS during run
Definition TGo4Log.h:216
virtual ~TGo4Log()
Definition TGo4Log.cxx:80
static Int_t GetIgnoreLevel()
Get threshold for output.
Definition TGo4Log.cxx:338
static void OpenLogfile(const char *name=nullptr, const char *headercomment=nullptr, Bool_t appendmode=kFALSE)
Open file of name for logmessage output.
Definition TGo4Log.cxx:383
static void * fgxLogfile
optional logfile to store messages with time
Definition TGo4Log.h:209
static void CloseLogfile()
Close logfile if existing.
Definition TGo4Log.cxx:444
TGo4Log()
Definition TGo4Log.cxx:68
static const char * fgcLEFT
Prompt character left side.
Definition TGo4Log.h:151
static const char * GetDefaultLogname()
Return default name of log file.
Definition TGo4Log.cxx:348
static Bool_t fgbLogfileEnabled
General switch on/off log file output.
Definition TGo4Log.h:200
static TGo4Log * fgxInstance
Definition TGo4Log.h:188
static TLogTimer * fgTimer
saved file for stdout
Definition TGo4Log.h:221
TLogTimer(Int_t millisec)
Definition TGo4Log.cxx:60
Bool_t Notify() override
Definition TGo4Log.cxx:62