Free Electron
debug.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __platform_debug_h__
8 #define __platform_debug_h__
9 
10 namespace fe
11 {
12 
13 FE_MEM_PORT extern String gs_logPrefix;
14 FE_MEM_PORT extern BWORD gs_bannerPrinted;
15 
16 /**************************************************************************//**
17  @brief Format text into a fe::String
18 *//***************************************************************************/
19 void FE_DL_EXPORT vsPrintf(std::string &target, const char *fmt, va_list ap, int &size);
20 
21 /**
22  Base class for logging system Log objects
23  */
24 class FE_DL_PUBLIC Log
25 {
26  public:
27  Log(void);
28 virtual ~Log(void);
29 
30 virtual void log(const std::string &a_message) =0;
31 virtual void log(const std::string &a_message,
32  std::map<std::string,std::string> &a_attributes)
33  {
34  log(a_message);
35  }
36 
37  void acquire(void)
38  {
39  RecursiveMutex::Guard guard(mutex());
40  m_cnt++;
41  }
42  bool release(void)
43  {
44  RecursiveMutex::Guard guard(mutex());
45  m_cnt--;
46  return (m_cnt > 0);
47  }
48 
49 
50 #if FE_SAFE_COUNTED_MUTEX
51 virtual RecursiveMutex& mutex(void) const
52  { return *ms_pMutex; }
53 
54  private:
55 static FE_DL_PUBLIC I32 ms_mutexCount;
56 static FE_DL_PUBLIC RecursiveMutex* ms_pMutex;
57 #else
58 virtual RecursiveMutex& mutex(void) const
59  { return ms_mutex; }
60  private:
61 static FE_DL_PUBLIC RecursiveMutex ms_mutex;
62 #endif
63 
64  int m_cnt;
65 };
66 
67 FE_DL_PUBLIC void intrusive_ptr_add_ref(Log *a_log);
68 FE_DL_PUBLIC void intrusive_ptr_release(Log *a_log);
69 
70 //typedef boost::intrusive_ptr<Log> t_logptr;
71 typedef Log *t_logptr;
72 
73 class FE_DL_PUBLIC StdoutLog : public Log
74 {
75  public:
76  StdoutLog(void) {}
77 virtual ~StdoutLog(void) {}
78 
79 virtual void log(const std::string &a_message,
80  std::map<std::string,std::string> &a_attributes);
81 virtual void log(const std::string &a_message)
82  {
83  std::cout << a_message.c_str();
84  std::cout.flush();
85  }
86 };
87 
88 class FE_DL_PUBLIC FileLog : public StdoutLog
89 {
90  public:
91  FileLog(void) {}
92 virtual ~FileLog(void) {}
93 
94  using StdoutLog::log;
95 
96 virtual void log(const std::string &a_message,
97  std::map<std::string,std::string> &a_attributes);
98 
99  void setFilename(String a_filename);
100  String filename(void) { return m_filename; }
101 
102  protected:
103  String m_filename;
104  std::ofstream m_ofstream;
105 };
106 
107 class FE_DL_PUBLIC AnnotatedLog : public StdoutLog
108 {
109  public:
110  AnnotatedLog(void): m_newline(true) {}
111 virtual ~AnnotatedLog(void) {}
112 
113  using StdoutLog::log;
114 
115 virtual void log(const std::string &a_message,
116  std::map<std::string,std::string> &a_attributes);
117  protected:
118  void output(std::ostream& stream,const char* source,
119  int size,bool right);
120  bool m_newline;
121 };
122 
123 class FE_DL_PUBLIC PrefaceLog : public AnnotatedLog
124 {
125  public:
126  PrefaceLog(void);
127 virtual ~PrefaceLog(void) {}
128 
129  using AnnotatedLog::log;
130 
131 virtual void log(const std::string &a_message,
132  std::map<std::string,std::string> &a_attributes);
133 
134 virtual String preface(void) { return m_logPreface; }
135 virtual void setPreface(String a_preface) { m_logPreface=a_preface; }
136 
137  protected:
138  BWORD m_annotate;
139  String m_logPreface;
140 };
141 
142 //* NOTE globally shared prefix
143 class FE_DL_PUBLIC PrefixLog : public PrefaceLog
144 {
145  public:
146  PrefixLog(void) {}
147 virtual ~PrefixLog(void) {}
148 
149  using PrefaceLog::log;
150 
151 virtual String preface(void) { return gs_logPrefix; }
152 
153 static String prefix(void) { return gs_logPrefix; }
154  void setPrefix(String a_prefix) { gs_logPrefix=a_prefix; }
155 };
156 
157 class FE_DL_PUBLIC GroupLog : public AnnotatedLog
158 {
159  public:
160  GroupLog(void) {}
161 virtual ~GroupLog(void) {}
162 
163  using AnnotatedLog::log;
164 
165 virtual void log(const std::string &a_message,
166  std::map<std::string,std::string> &a_attributes);
167 };
168 
169 class FE_DL_PUBLIC NullLog : public Log
170 {
171  public:
172  NullLog(void) {}
173 virtual ~NullLog(void) {}
174 
175  using Log::log;
176 
177 virtual void log(const std::string &a_message)
178  {
179  /* NOOP */
180  }
181 };
182 
183 class FE_DL_PUBLIC Win32Log : public Log
184 {
185  public:
186  Win32Log(void) {}
187 virtual ~Win32Log(void) {}
188 
189  using Log::log;
190 
191 virtual void log(const std::string &a_message)
192  {
193 #if FE_OS==FE_WIN32 || FE_OS==FE_WIN64
194  OutputDebugStringA(a_message.c_str());
195 #endif
196  }
197 };
198 
199 class Logger;
200 
201 /**
202 @page logging Logging Guide
203 
204 The logging system has these concepts:
205 - named groups
206 - named Log objects (Log objects output a message somewhere)
207 - group name to log name relationships (bindings)
208 
209 With this structure logging groups can be flexibly configured without any
210 hardcoded enumerations via defines, enums, or whatever.
211 
212 A Static Logger object, named feLogger, is intended to be used for most logging.
213 However, most logging calls will actually go through the feLog* macros.
214 
215 @section basic_logging Basic Logging
216 @code
217 feLog("some logging message text\n");
218 @endcode
219 
220 Note that the trailing newline is not automatic.
221 
222 The group for a basic log message is the MODULE macro, if defined, and is
223 otherwise "default". FE's build system automatically sets MODULE to be
224 the module name (such as "src.platform").
225 
226 @section explicit_logging Logging to an Explicit Group
227 
228 @code
229 feLogGroup("my group", "some logging message text\n");
230 @endcode
231 
232 @section direct_logging Direct Logging
233 
234 @code
235 feLogDirect("some logging message text\n");
236 @endcode
237 
238 Direct logging incurs minimum overhead and processing, and may be independently
239 \#ifdef disabled from normal logging. Direct logging has no group.
240 
241 @section control_logging Controlling Output
242 
243 @subsection naming_logs Setting Up Named Log Objects
244 @code
245 feLogger.setLog("stdout", new StdoutLog());
246 @endcode
247 
248 @subsection binding_groups Binding Groups to Log Objects
249 @code
250 feLogger.bind("src\.platform", "stdout");
251 @endcode
252 
253 
254 Binding can use regular expressions, which is where a lot of the flexibility
255 lies. Here is an example of binding all messages to stdout:
256 @code
257 feLogger.bind(".*", "stdout");
258 @endcode
259 
260 Here is an example of binding all debug messages following a particular
261 naming convention:
262 @code
263 feLogger.bind(".*\.debug", "stdout");
264 @endcode
265 
266 Clearing a binding is done with the clear method:
267 @code
268 feLogger.clear(".*")
269 @endcode
270 
271 @section log_objects Log Objects
272 
273 Log objects take the vsprinted message and a map of attributes. File, line
274 number, etc, all come in as attributes.
275 
276 @section log_defaults Default feLogger bindings
277 As with any binding, these can be cleared and reset, but as a default,
278 feLogger is initialized like this in its constructor:
279 @code
280 m_directLog = new StdoutLog();
281 setLog("stdout", m_directLog);
282 setLog("win32", new Win32Log());
283 bind(".*", "stdout");
284 bind(".*", "win32");
285 @endcode
286 */
287 
288 /**************************************************************************//**
289  @brief C++ portion of logging interface implementation
290 
291 *//***************************************************************************/
292 class FE_DL_PUBLIC Logger
293 {
294  public:
295  Logger(void);
296 virtual ~Logger(void);
297 
298 //virtual void direct(const char *format, ...) const;
299 virtual void log(const String &a_group,
300  std::map<std::string,std::string> &a_attributes,
301  const char *a_format, ...);
302 virtual void bind(const String &a_group, const String &a_logname);
303 virtual void antibind(const String &a_group, const String &a_logname);
304 virtual void clear(const String &a_group);
305 virtual void clearAll(void);
306 virtual void setLog(const String &a_logname, t_logptr a_log);
307 
308 virtual void dump(void);
309 
310 //virtual GroupLogger operator[](const String &a_group) const;
311 
312  private:
313  void wiregroup(const String &a_group);
314  std::map<String, std::vector<String> > m_bindings;
315  std::map<String, std::vector<String> > m_antibindings;
316  std::map<String, t_logptr> m_logs;
317  t_logptr m_directLog;
318 
319  std::map<String, std::vector<t_logptr> > m_bindmap;
320 
321 #if FE_SAFE_COUNTED_MUTEX
322 virtual RecursiveMutex& mutex(void) const
323  { return *ms_pMutex; }
324 
325  private:
326 static FE_DL_PUBLIC I32 ms_mutexCount;
327 static FE_DL_PUBLIC RecursiveMutex* ms_pMutex;
328 #else
329 virtual RecursiveMutex& mutex(void) const
330  { return ms_mutex; }
331  private:
332 static FE_DL_PUBLIC RecursiveMutex ms_mutex;
333 #endif
334 
335 };
336 
337 
338 //extern Logger debugLogger;
339 
340 } /* namespace */
341 
342 // This does not seem to work properly in g++ 3 if it is in a namespace
343 //extern FE_DL_PUBLIC fe::Logger feLogger;
344 
345 #ifndef MODULE
346 #define MODULE ""
347 #endif
348 
349 //#define feLog(...) /* NOOP */
350 //#define feLogGroup(grp, ...) /* NOOP */
351 
352 #if 1
353 #define feLog(...) { \
354  std::stringstream out; \
355  out << __LINE__; \
356  std::map<std::string,std::string> attributes; \
357  attributes["file"] = __FILE__; \
358  attributes["line"] = out.str().c_str(); \
359  attributes["date"] = __DATE__; \
360  attributes["time"] = __TIME__; \
361  attributes["group"] = MODULE; \
362  feLogger()->log(MODULE, attributes, __VA_ARGS__); \
363  }
364 
365 #define feLogGroup(grp, ...) { \
366  std::stringstream out; \
367  out << __LINE__; \
368  std::map<std::string,std::string> attributes; \
369  attributes["file"] = __FILE__; \
370  attributes["line"] = out.str().c_str(); \
371  attributes["date"] = __DATE__; \
372  attributes["time"] = __TIME__; \
373  attributes["group"] = grp; \
374  feLogger()->log(grp, attributes, __VA_ARGS__); \
375  }
376 #else
377 #define feLog(...) { feLogDirect(__VA_ARGS__); }
378 #define feLogGroup(grp,...) { feLogDirect(__VA_ARGS__); }
379 #endif
380 
381 //#define feLogDirect(...) feLogger.direct(__VA_ARGS__)
382 FE_DL_PUBLIC void feLogDirect(const char *format, ...);
383 
384 FE_DL_PUBLIC void feLogError(const char *format, ...);
385 
386 #endif /* __platform_debug_h__ */
C++ portion of logging interface implementation.
Definition: debug.h:292
kernel
Definition: namespace.dox:3
void vsPrintf(std::string &target, const char *fmt, va_list ap, int &size)
Format text into a fe::String.
Definition: debug.cc:252
Automatically reference-counted string container.
Definition: String.h:128
Base class for logging system Log objects.
Definition: debug.h:24