XRootD
XrdClLog.cc
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2011-2012 by European Organization for Nuclear Research (CERN)
3 // Author: Lukasz Janyst <ljanyst@cern.ch>
4 //------------------------------------------------------------------------------
5 // XRootD is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // XRootD is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
17 //------------------------------------------------------------------------------
18 
19 #include <iostream>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <iomanip>
23 #include <sstream>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <sys/time.h>
28 #include <ctime>
30 #include "XrdSys/XrdSysE2T.hh"
31 #include "XrdCl/XrdClOptimizers.hh"
32 #include "XrdCl/XrdClLog.hh"
33 
34 namespace XrdCl
35 {
36  //----------------------------------------------------------------------------
37  // Open a file
38  //----------------------------------------------------------------------------
39  bool LogOutFile::Open( const std::string &filename )
40  {
41  int fd = open( filename.c_str(), O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR );
42  if( fd < 0 )
43  {
44  std::cerr << "Unable to open " << filename << " " << XrdSysE2T( errno );
45  std::cerr << std::endl;
46  return false;
47  }
48  pFileDes = fd;
49  return true;
50  }
51 
52  //----------------------------------------------------------------------------
53  // Destructor
54  //----------------------------------------------------------------------------
56  {
57  if( pFileDes != -1 )
58  {
59  close( pFileDes );
60  pFileDes = -1;
61  }
62  }
63 
64  //----------------------------------------------------------------------------
65  // Message handler
66  //----------------------------------------------------------------------------
67  void LogOutFile::Write( const std::string &message )
68  {
69  if( unlikely( pFileDes == -1 ) )
70  {
71  std::cerr << "Log file not opened" << std::endl;
72  return;
73  }
74  int ret = write( pFileDes, message.c_str(), message.length() );
75  if( ret < 0 )
76  {
77  std::cerr << "Unable to write to the log file: " << XrdSysE2T( errno );
78  std::cerr << std::endl;
79  return;
80  }
81  }
82 
83  //----------------------------------------------------------------------------
84  // Message handler
85  //----------------------------------------------------------------------------
86  void LogOutCerr::Write( const std::string &message )
87  {
88  pMutex.Lock();
89  std::cerr << message;
90  pMutex.UnLock();
91  }
92 
93  //----------------------------------------------------------------------------
94  // Print an error message
95  //----------------------------------------------------------------------------
96  void Log::Say( LogLevel level,
97  uint64_t topic,
98  const char *format,
99  va_list list )
100  {
101  //--------------------------------------------------------------------------
102  // Build the user message
103  //--------------------------------------------------------------------------
104  int size = 1024;
105  int ret = 0;
106  char *buffer = 0;
107  while(1)
108  {
109  va_list cp;
110  va_copy( cp, list );
111  buffer = new char[size];
112  ret = vsnprintf( buffer, size, format, cp );
113  va_end( cp );
114 
115  if( ret < 0 )
116  {
117  snprintf( buffer, size, "Error while processing a log message \"%s\" \n", format);
118  pOutput->Write(buffer);
119  delete [] buffer;
120  return;
121  }
122  else if( ret < size )
123  break;
124 
125  size *= 2;
126  delete [] buffer;
127  }
128 
129  //--------------------------------------------------------------------------
130  // Add time and error level
131  //--------------------------------------------------------------------------
132  char now[48];
133  char ts[32];
134  char tz[8];
135  tm tsNow;
136  timeval ttNow;
137 
138  gettimeofday( &ttNow, 0 );
139  localtime_r( &ttNow.tv_sec, &tsNow );
140 
141  strftime( ts, 32, "%Y-%m-%d %H:%M:%S", &tsNow );
142  strftime( tz, 8, "%z", &tsNow );
143  snprintf( now, 48, "%s.%06ld %s", ts, (long int)ttNow.tv_usec, tz );
144 
145  XrdOucTokenizer tok( buffer );
146  char *line = 0;
147  std::ostringstream out;
148  while( (line = tok.GetLine()) )
149  {
150  out << "[" << now << "][" << LogLevelToString( level ) << "]";
151  out << "[" << TopicToString( topic ) << "]";
152  if(pPid) out << "[" << std::setw(5) << pPid << "]";
153  out << " " << line << std::endl;
154  }
155 
156  pOutput->Write( out.str() );
157  delete [] buffer;
158  }
159 
160  //----------------------------------------------------------------------------
161  // Map a topic number to a string
162  //----------------------------------------------------------------------------
163  void Log::SetTopicName( uint64_t topic, std::string name )
164  {
165  uint32_t len = name.length();
166  if( len > pTopicMaxLength )
167  {
168  pTopicMaxLength = len;
169  TopicMap::iterator it;
170  for( it = pTopicMap.begin(); it != pTopicMap.end(); ++it )
171  it->second.append( len-it->second.length(), ' ' );
172  }
173  else
174  name.append( pTopicMaxLength-len, ' ' );
175  pTopicMap[topic] = name;
176  }
177 
178  //----------------------------------------------------------------------------
179  // Convert log level to string
180  //----------------------------------------------------------------------------
181  std::string Log::LogLevelToString( LogLevel level )
182  {
183  switch( level )
184  {
185  case ErrorMsg:
186  return "Error ";
187  case WarningMsg:
188  return "Warning";
189  case InfoMsg:
190  return "Info ";
191  case DebugMsg:
192  return "Debug ";
193  case DumpMsg:
194  return "Dump ";
195  default:
196  return "Unknown Level";
197  }
198  }
199 
200  //----------------------------------------------------------------------------
201  // Convert a string to LogLevel
202  //----------------------------------------------------------------------------
203  bool Log::StringToLogLevel( const std::string &strLevel, LogLevel &level )
204  {
205  if( strLevel == "Error" ) level = ErrorMsg;
206  else if( strLevel == "Warning" ) level = WarningMsg;
207  else if( strLevel == "Info" ) level = InfoMsg;
208  else if( strLevel == "Debug" ) level = DebugMsg;
209  else if( strLevel == "Dump" ) level = DumpMsg;
210  else return false;
211  return true;
212  }
213 
214  //----------------------------------------------------------------------------
215  // Convert a topic number to a string
216  //----------------------------------------------------------------------------
217  std::string Log::TopicToString( uint64_t topic )
218  {
219  TopicMap::iterator it = pTopicMap.find( topic );
220  if( it != pTopicMap.end() )
221  return it->second;
222  std::ostringstream o;
223  o << "0x" << std::setw(pTopicMaxLength-2) << std::setfill( '0' );
224  o << std::setbase(16) << topic;
225  return o.str();
226  }
227 
228  //----------------------------------------------------------------------------
229  // Report an error
230  //----------------------------------------------------------------------------
231  void Log::Error( uint64_t topic, const char *format, ... )
232  {
233  if( unlikely( GetLevel() < ErrorMsg ) )
234  return;
235 
236  if( unlikely( (topic & pMask[ErrorMsg]) == 0 ) )
237  return;
238 
239  va_list argList;
240  va_start( argList, format );
241  Say( ErrorMsg, topic, format, argList );
242  va_end( argList );
243  }
244 
245  //----------------------------------------------------------------------------
246  // Report a warning
247  //----------------------------------------------------------------------------
248  void Log::Warning( uint64_t topic, const char *format, ... )
249  {
250  if( unlikely( GetLevel() < WarningMsg ) )
251  return;
252 
253  if( unlikely( (topic & pMask[WarningMsg]) == 0 ) )
254  return;
255 
256  va_list argList;
257  va_start( argList, format );
258  Say( WarningMsg, topic, format, argList );
259  va_end( argList );
260  }
261 
262  //----------------------------------------------------------------------------
263  // Print an info
264  //----------------------------------------------------------------------------
265  void Log::Info( uint64_t topic, const char *format, ... )
266  {
267  if( likely( GetLevel() < InfoMsg ) )
268  return;
269 
270  if( unlikely( (topic & pMask[InfoMsg]) == 0 ) )
271  return;
272 
273  va_list argList;
274  va_start( argList, format );
275  Say( InfoMsg, topic, format, argList );
276  va_end( argList );
277  }
278 
279  //----------------------------------------------------------------------------
280  // Print a debug message
281  //----------------------------------------------------------------------------
282  void Log::Debug( uint64_t topic, const char *format, ... )
283  {
284  if( likely( GetLevel() < DebugMsg ) )
285  return;
286 
287  if( unlikely( (topic & pMask[DebugMsg]) == 0 ) )
288  return;
289 
290  va_list argList;
291  va_start( argList, format );
292  Say( DebugMsg, topic, format, argList );
293  va_end( argList );
294  }
295 
296  //----------------------------------------------------------------------------
297  // Print a dump message
298  //----------------------------------------------------------------------------
299  void Log::Dump( uint64_t topic, const char *format, ... )
300  {
301  if( likely( GetLevel() < DumpMsg ) )
302  return;
303 
304  if( unlikely( (topic & pMask[DumpMsg]) == 0 ) )
305  return;
306 
307  va_list argList;
308  va_start( argList, format );
309  Say( DumpMsg, topic, format, argList );
310  va_end( argList );
311  }
312 }
#define likely(x)
#define unlikely(x)
int open(const char *path, int oflag,...)
ssize_t write(int fildes, const void *buf, size_t nbyte)
#define close(a)
Definition: XrdPosix.hh:43
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
virtual void Write(const std::string &message)
Definition: XrdClLog.cc:86
virtual void Write(const std::string &message)
Definition: XrdClLog.cc:67
void Close()
Close the log file.
Definition: XrdClLog.cc:55
bool Open(const std::string &fileName)
Open the log file.
Definition: XrdClLog.cc:39
virtual void Write(const std::string &message)=0
LogLevel
Log levels.
Definition: XrdClLog.hh:107
@ InfoMsg
print info
Definition: XrdClLog.hh:111
@ WarningMsg
report warnings
Definition: XrdClLog.hh:110
@ DebugMsg
print debug info
Definition: XrdClLog.hh:112
@ ErrorMsg
report errors
Definition: XrdClLog.hh:109
@ DumpMsg
print details of the request and responses
Definition: XrdClLog.hh:113
void SetTopicName(uint64_t topic, std::string name)
Map a topic number to a string.
Definition: XrdClLog.cc:163
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition: XrdClLog.cc:231
LogLevel GetLevel() const
Get the log level.
Definition: XrdClLog.hh:258
void Warning(uint64_t topic, const char *format,...)
Report a warning.
Definition: XrdClLog.cc:248
void Dump(uint64_t topic, const char *format,...)
Print a dump message.
Definition: XrdClLog.cc:299
void Info(uint64_t topic, const char *format,...)
Print an info.
Definition: XrdClLog.cc:265
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
Definition: XrdClLog.cc:282
void Say(LogLevel level, uint64_t topic, const char *format, va_list list)
Definition: XrdClLog.cc:96