StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StUCMAppender.cxx
1 /***************************************************************************
2  StUCMAppender.cpp - class StUCMAppender
3  -------------------
4  begin : 2007
5  copyright : (C) 2007 by Valeri Fine
6  email : fine@bnl.gov
7  ***************************************************************************/
8 #include <cstdlib>
9 #include <cassert>
10 #include "StUCMAppender.h"
11 #include "TSystem.h"
12 #include "TString.h"
13 #include "TObjString.h"
14 
15 #include "StStarLogger/logging/TxEventLog.h"
16 #include "StStarLogger/logging/TxEventLogFactory.h"
17 //#include "StUCMApi/TxEventLog.h"
18 
19 #include <log4cxx/helpers/loglog.h>
20 #include <log4cxx/level.h>
21 #include <log4cxx/helpers/optionconverter.h>
22 #include <log4cxx/patternlayout.h>
23 // #include <data/TxUCMException.h>
24 #include "TObjArray.h"
25 using namespace log4cxx;
26 using namespace log4cxx::helpers;
27 using namespace log4cxx::db;
28 using namespace log4cxx::spi;
29 using namespace TxLogging;
30 
31 static int lockUcm =0;
32 
33 IMPLEMENT_LOG4CXX_OBJECT(StUCMAppender)
34 //_________________________________________________________________________
35 StUCMAppender::StUCMAppender(const char *mode)
36 : connection(0),technology(mode), bufferSize(1),fLastId(0),fIsConnectionOpen(false)
37 {
38  fprintf(stderr,"StUCMAppender::StUCMAppender() %p %s %i\n", this, mode, lockUcm);
39  lockUcm++;
40 }
41 
42 //_________________________________________________________________________
43 StUCMAppender::~StUCMAppender()
44 {
45  // fprintf(stderr,"StUCMAppender::~StUCMAppender()\n" );
46  finalize();
47  if (connection) {
48  delete connection;
49  connection = 0;
50  }
51 }
52 
53 //_________________________________________________________________________
54 void StUCMAppender::setOption(const String& option,
55  const String& value)
56 {
57  if (equalsIgnoreCase(option, _T("buffersize")))
58  {
59  setBufferSize((size_t)OptionConverter::toInt(value, 1));
60  }
61  else if (equalsIgnoreCase(option, _T("password")))
62  {
63  setPassword(value);
64  }
65  else if (equalsIgnoreCase(option, _T("url"))
66  || equalsIgnoreCase(option, _T("dns")))
67  {
68  setURL(value);
69  }
70  else if (equalsIgnoreCase(option, _T("user")))
71  {
72  setUser(value);
73  }
74  else
75  {
76  AppenderSkeleton::setOption(name, value);
77  }
78 }
79 
80 //_________________________________________________________________________
81 void StUCMAppender::append(const spi::LoggingEventPtr& event)
82 {
83  if (!this->closed) {
84  buffer.push_back(event);
85 
86  if (buffer.size() >= bufferSize)
87  flushBuffer();
88  }
89 }
90 
91 //_________________________________________________________________________
92 // String StUCMAppender::getLogStatement(const spi::LoggingEventPtr& event) const
93 String StUCMAppender::getLogStatement(const spi::LoggingEventPtr& event)
94 {
95 #if (STAR_LOG4CXX_VERSION == 9)
96  StringBuffer sbuf;
97  ((StUCMAppender*)this)->getLayout()->format(sbuf, event);
98  return sbuf.str();
99 #else
100  String sbuf;
101  ((StUCMAppender*)this)->getLayout()->format(sbuf,event,pool);
102  return sbuf;
103 #endif
104 }
105 
106 //_________________________________________________________________________
107 /* The default behavior holds a single connection open until the appender is closed (typically when garbage collected). */
108 void StUCMAppender::closeConnection()
109 {
110  if (connection) {
111  // connection->logEnd();
112  delete connection;
113  }
114  connection = 0;
115  fIsConnectionOpen = false;
116 }
117 
118 //_________________________________________________________________________
119 TxEventLog *StUCMAppender::getConnection()
120 {
121  if (!fIsConnectionOpen) {
122 
123  if (!connection) {
124  connection = TxEventLogFactory::create("WEB"); // create ucm collector factory
125 // connection = TxEventLogFactory::create("U"); // create ucm collector factory
126 // connection = TxEventLogFactory::create(technology.c_str()); // create ucm collector factory
127 // connection = TxEventLogFactory::create();
128  if ( getenv("JOBINDEX") && getenv("REQUESTID") ) {
129  const char *JOBINDEX = getenv("JOBINDEX");
130  std::string UCMJOB = getenv("REQUESTID");
131  UCMJOB +=JOBINDEX;
132  // However, what we really need is:
133  // const char *REQUESTID = getenv("REQUESTID");
134  // const char *PROCESSID = getenv("PROCESSID");
135  } else {
136  fprintf(stderr,"StUCMAppender::getConnection() no JOBINDEX/REQUESTID was provided \n");
137 // connection = TxEventLogFactory::create("WEB"); // create ucm collector factory
138 // connection = TxEventLogFactory::create("U"); // create ucm collector factory
139 // connection = TxEventLogFactory::create(technology.c_str()); // create ucm collector factory
140 // connection = TxEventLogFactory::create();
141 // connection = TxEventLogFactory::create("w"); // to access the Web interface
142  }
143  }
144  }
145  return connection;
146 }
147 
148 //_________________________________________________________________________
149 void StUCMAppender::close()
150 {
151  if (!this->closed) {
152  flushBuffer();
153  closeConnection();
154  this->closed = true;
155  }
156 }
157 #if 0
158 //_________________________________________________________________________
159 static void ReplaceVariable(TString &string, const char *var)
160 {
161 // replace the $VAR with its value if any
162  TString spec;
163  const char *varValue = gSystem->Getenv(var);
164  if (!varValue) {
165  // Special cases
166  spec = var;
167  if (spec == "REQUESTID") {
168  spec.Form("%d",gSystem->GetPid());
169  varValue= spec.Data();
170  } else if (spec == "JOBINDEX") {
171  spec.Form("%d",0);
172  varValue= spec.Data();
173  }
174  }
175 
176  if (varValue) {
177  TString fullName = "$"; fullName += var;
178  // fullName.ToUpper();
179  string.ReplaceAll(fullName,varValue);
180  }
181 }
182 #endif
183 //_________________________________________________________________________
184 void StUCMAppender::flushBuffer()
185 {
186  //Do the actual logging
187  std::list<spi::LoggingEventPtr>::iterator i;
188  if ( getConnection()) {
189  for (i = buffer.begin(); i != buffer.end(); i++)
190  {
191  // Job tracking block
192  const LoggingEventPtr& logEvent = *i;
193  const LevelPtr &level = logEvent->getLevel();
194  TxEventLog::Level trackingLevel =TxEventLog::LEVEL_INFO;
195  if (level == LOG4CXX_LEVEL_FATAL) {
196  trackingLevel = TxEventLog::LEVEL_FATAL;
197  } else if (level == LOG4CXX_LEVEL_ERROR) {
198  trackingLevel = TxEventLog::LEVEL_ERROR;
199  } else if (level == LOG4CXX_LEVEL_WARN) {
200  trackingLevel = TxEventLog::LEVEL_WARNING;
201  } else if (level == LOG4CXX_LEVEL_DEBUG) {
202  trackingLevel = TxEventLog::LEVEL_DEBUG;
203  } else {
204  // continue;
205  }
206 
207  // void logUserEvent(Stage stage, Level level, const std::string& userContext,
208  // const std::string& userKey, const std::string& userMsg);
209  String sql = getLogStatement(logEvent);
210  TString userKeys = sql.c_str();
211  TObjArray *pair = userKeys.Tokenize(",");
212  // Parse the statement
213  TIter next(pair);
214  TObjString *nextPair = 0;
215  int keyCounter=0; // to workaround of the ROOT error
216  TString ucmParamters[3];
217  while ( (nextPair = (TObjString *)next()) && (keyCounter<3)) {
218  assert(nextPair);
219  TString nextString = nextPair->String();
220  TObjArray &keyValue = *nextString.Tokenize("=");
221  // expect:
222  // StageID='1',MessageKey='ProgSize',MessageValue='419'
223  // More robust parser should be added later on
224  ucmParamters[keyCounter] = ((TObjString *)keyValue[1])->String().Strip();
225  delete &keyValue;
226  keyCounter++;
227  }
228  String context;
229 #if (STAR_LOG4CXX_VERSION == 9)
230  context = logEvent->getNDC();
231 #else
232  logEvent->getNDC(context);
233 #endif
234  // Map Stage to TxEventLog Stage
235  ucmParamters[0].ReplaceAll("'","");ucmParamters[1].ReplaceAll("'","");ucmParamters[2].ReplaceAll("'","");
236  int ucmStage = ucmParamters[0].Atoi();
237  // assert (ucmStage >=TxEventLog::START && ucmStage <=TxEventLog::END);
238  // log task at once
239  static bool taskDone = false;
240  if (!taskDone) {
241  taskDone = true;
242  const char *taskSize = getenv("SUMS_nProcesses");
243  int nSize = 1;
244  if (taskSize && taskSize[0]) nSize = atoi(taskSize);
245  connection->logTask(nSize);
246  }
247  fprintf(stderr,"%s\n","StUCMAppender::flushBuffer() . . . . . . . . ." );
248 
249  connection->logEvent( ucmParamters[1].Data()
250  , ucmParamters[2].Data()
251  , trackingLevel
252  , TxEventLog::Stage(ucmStage)
253  , context
254  );
255  pair->Delete();
256  delete pair;
257  }
258  buffer.clear();
259  }
260  closeConnection();
261 }
262 #if (STAR_LOG4CXX_VERSION == 10)
263 //_________________________________________________________________________
264 void StUCMAppender::append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p)
265 {
266  append(event);
267 }
268 #endif
269