You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

586 lines
22 KiB

  1. pantheios - FAQ
  2. ===============
  3. Updated: 27th December 2010
  4. The FAQ list is under (constant) development. If you post a question on the
  5. Tutorials forum (https://sourceforge.net/forum/forum.php?forum_id=647484)
  6. it will be used to create one.
  7. FAQs:
  8. =====
  9. Q1: "What happens if the Pantheios libraries fail to
  10. initialise?" [2nd October 2006]
  11. A1:
  12. The process will be terminated, via exit() (ExitProcess() on Windows)
  13. From 1.0.1 beta 4 onwards, library initialisation is also accompanied
  14. by invocation of pantheios_onBailOut(), a fallback log function that is
  15. used by the Core (and Front/Back-end(s)) to report on a failure to
  16. initialise Pantheios. The output facilities are operating
  17. system-dependent:
  18. * on UNIX the bail-out message is written to syslog() and to
  19. the console of the calling process (via fprintf()), and to
  20. a local file "logging-bailout.txt" (appending if already
  21. exists)
  22. * on Windows the bail-out message is written to the debugger
  23. (via OutputDebugString()), the console (if any) of the
  24. calling process (via WriteFile()), to a local file
  25. "logging-bailout.txt" (appending if already exists), and to
  26. the Windows Event Log (under the source "logging-bailout").
  27. Note: The Event Log messages will not be correctly formatted
  28. (although their information will be accessible), unless
  29. pantheios.COM is installed: The Windows bail-out
  30. functionality piggy backs on the Event Log message resources
  31. in pantheios.COM (version 1.0.1 beta 3 or later).
  32. Q2: "What if I need more than 32 parameters?"
  33. A2:
  34. You can regenerate the six automatically-generated files as follows:
  35. - edit the scripts/make_hdrs.rb (Ruby) script
  36. - change the NUM_PARAMS constant to the required value
  37. - run the script from the scripts directory. You may have to change
  38. file permissions of the automatically-generated files, if they're
  39. read-only
  40. Q3: "How do I represent a process Id?" [15th November 2007]
  41. A3:
  42. By using the pantheios::processId inserter.
  43. #include <pantheios/inserters/ids.hpp>
  44. int main()
  45. {
  46. pantheios::log_NOTICE("process id=", pantheios::processId);
  47. }
  48. Q4: "What is 'Pure Pantheios'?" [15th November 2007]
  49. A4:
  50. Pantheios is primarily a logging _API_ library. That is, it is explictly
  51. designed to layer over the top of other, feature-rich, logging libraries.
  52. Of course, it comes with several of its own transport mechanisms, known as
  53. back-ends, but they are not part of 'Pure Pantheios'.
  54. Technically speaking, 'Pure Pantheios' consists only of:
  55. - The Application Layer
  56. - The Core
  57. The Application Layer talks only to the Core. The Core talks to a
  58. Front-End and a Back-End, which are, strictly, external to
  59. 'Pure Pantheios'.
  60. The Core talks to the Front-End via the following four functions, declared
  61. in include/pantheios/frontend.h:
  62. - pantheios_fe_init()
  63. initialises the front-end; called at most once per process
  64. - pantheios_fe_uninit()
  65. uninitialises the front-end; called at most once per process
  66. - pantheios_fe_getProcessIdentity()
  67. returns a C-style string that names the current process, e.g.
  68. "logdaemon"; called at most once per process
  69. - pantheios_fe_isSeverityLogged()
  70. returns an integer to indicate whether a log statement of a given
  71. severity level is to be emitted to the Back-End; called each time
  72. a statement is processed
  73. These functions must be implemented by any Front-End linked to the
  74. application/shared object.
  75. The Core talks to the Back-End via the following three functions, declared
  76. in include/pantheios/backend.h:
  77. - pantheios_be_init()
  78. initialises the back-end; called at most once per process
  79. - pantheios_be_uninit()
  80. uninitialises the back-end; called at most once per process
  81. - pantheios_be_logEntry()
  82. called to emit each statement
  83. These functions must be implemented by any Back-End linked to the
  84. application/shared object.
  85. Pantheios comes with a number of stock Front-End and Back-end libraries,
  86. for the convenience of users. Furthermore, a number of Inserter Classes
  87. are provided which supplement the Application Layer, including:
  88. - pantheios::integer - inserts an integer argument
  89. - pantheios::real
  90. - pantheios::pointer
  91. - pantheios::character
  92. - pantheios::args
  93. - pantheios::blob
  94. - pantheios::b64
  95. - pantheios::processId
  96. - pantheios::threadId
  97. Importantly, instances of these Inserters do not perform any conversions
  98. (or allocate memory) unless the given statement they are in is to be
  99. emitted (as determined by pantheios_fe_isSeverityLogged()). This is one of
  100. many ways in which Pantheios provides extremely high-levels of
  101. performance.
  102. Q5: "Is Pantheios thread-safe?" [19th November 2007]
  103. A5:
  104. The short answer is: Yes.
  105. The long answer is:
  106. The Core is thread-safe. The Core initialisation/uninitialisation
  107. functions are reference-counted. On architectures with atomic integer
  108. operations *all* calls to pantheios_init() are thread-safe. On other
  109. architectures *all* calls to pantheios_init() except the first are
  110. thread-safe.
  111. The Application is layer is thread-safe simply because there is no
  112. shared state between threads in any application layer components.
  113. As for the Front-end and Back-ends, the answer is: It depends.
  114. The Front-end functions pantheios_fe_init(), pantheios_fe_uninit() and
  115. pantheios_fe_getProcessIdentity() are called at most once per-process
  116. during the initialisation phase. Therefore, they do not need to be
  117. thread-safe. The Front-end function pantheios_fe_isSeverityLogged() is
  118. called every time a statement is processed, to evaluate whether the
  119. statement should be emitted to the back-end(s). Thus, this function
  120. must be thread-safe.
  121. The Back-end functions pantheios_be_init(), and pantheios_be_uninit()
  122. are called at most once per-process during the initialisation phase.
  123. Therefore, they do not need to be thread-safe. The Back-end function
  124. pantheios_be_logEntry() is called every time a statement is to be
  125. emitted. It must be thread-safe.
  126. All stock Front-end and Back-end implementations are thread-safe.
  127. If you write custom Front-end and/or Back-end, you must ensure that
  128. the functions pantheios_fe_isSeverityLogged() and pantheios_be_logEntry()
  129. are thread-safe. If you do so, your use of Pantheios will be entirely
  130. thread-safe.
  131. Q6: "How do I alter the number of parameters in the Application Layer?" [25th November 2007]
  132. A6:
  133. There are two ways.
  134. First, if you wish to reduce the number of parameters in the Application
  135. Layer - presumably to speed compilation when you don't need the full
  136. range of parameters - then you can simply #define the pre-processor
  137. symbol PANTHEIOS_APPL_PARAMS_LIMIT (introduced in 1.0.1 beta 60) to a
  138. number between 1 and 32.
  139. Second, if you wish to increase the number of parameters available in
  140. functions in the N-ary Function Templates of the Application Layer, you
  141. must re-generate the Application Layer headers using the make_hdrs.rb
  142. Ruby script in the script directory. However, we would advise that if
  143. you are writing application code that needs to pass more than 32
  144. parameters to Pantheios, you are unlikely to be writing transparent
  145. code, one of the design requirements of Pantheios.
  146. Q7: "Why do the back-end(s) have to be specified at link-time?" [3rd January 2008]
  147. A7:
  148. The short answer is: Because Pantheios is initialised automatically,
  149. and before main() is called. (This is actually done by using the Schwarz
  150. counters found in include/pantheios/internal/initialiser.hpp, included by
  151. include/pantheios/pantheios.hpp unless in a DLL context or you #define
  152. PANTHEIOS_NO_AUTO_INIT)
  153. This is done to allow any piece of code in any part of the system to be
  154. able to log any conditions that may be necessary. If the process could not
  155. log before main() started, this might not be possible; indeed, how would
  156. you log a failure in another pre-main sub-system?
  157. The reason why this question comes up a lot is, of course, because users
  158. quite reasonably want to be able to specify logging options, at the start
  159. of main().
  160. The best approach to cater for both requirements is as follows:
  161. 1. Link to be.N
  162. 2. Define the PAN_BE_N_BACKEND_LIST array (see the documentation on be.N)
  163. for an explanation of how this works. Make sure to include an entry
  164. for a back-end that does not need any configuration, e.g. be.syslog.
  165. Then also include an entry for a back-end that provides run-time
  166. customisation, say, be.YourConfigurableBackEnd.
  167. 3. Customise be.YourConfigurableBackEnd inside main(). If the program
  168. does not make it as far as main(), at least you will have had some
  169. logging output go to Syslog, via be.syslog.
  170. NOTE: A future version of Pantheios will include be.loader, which will
  171. allow you to load and configure back-ends at runtime, based on
  172. configuration file(s)
  173. Q8: "I get linker errors with GCC, even though I'm specifying the core,
  174. front-end and back-end libraries. I've used nm, and the core library
  175. says it contains the missing symbols. What gives?" [28th January 2008]
  176. A8:
  177. What's going on here is that GCC's linker reads symbols in a
  178. left-to-right manner. The Pantheios initialisation functions -
  179. pantheios_init(), pantheios_uninit() - must be elicited from the core
  180. library, which is listed first in the libraries list. They then require
  181. symbols from the back-end and front-end libraries, which come next in
  182. the libraries list. They, in turn, require symbols from the core, which
  183. must therefore be listed again, at the end of the libraries list. The
  184. GCC makefiles included in the distribution do this, and can be used as
  185. templates for how to do it in your own projects.
  186. Q9: "Does Pantheios provide a configuration that yields a logged message
  187. containing the containing function, equivalent to:
  188. log(informational, __FUNCTION__, ": my message");
  189. without having to write that (or some wrapper that checks for compiler
  190. support)." [15th March 2008]
  191. A9:
  192. You need to #define PANTHEIOS_TRACE_PREFIX to what you want. By default
  193. it is '__FILE__ "(" PANTHEIOS_STRINGIZE(__LINE__) "): "', which gives the
  194. format '<file>(<line>): '
  195. To include the function, lets says you want it to have the format
  196. '<file>(<line>): <func>: '. To achieve this you'd define it as follows:
  197. #include <pantheios/pantheios.h>
  198. #define PANTHEIOS_TRACE_PREFIX __FILE__ " " PANTHEIOS_STRINGIZE(__LINE__) ": " __FUNCTION__ ": "
  199. #include <pantheios/trace.h>
  200. Note that the definition *must* come before the inclusion of
  201. pantheios/trace.h. Therefore, a safer way of doing this is as follows:
  202. /* File: myPantheiosRootHeader.h */
  203. #include <pantheios/pantheios.h>
  204. #ifdef PANTHEIOS_INCL_PANTHEIOS_H_TRACE
  205. # error pantheios/trace.h must not be included before myPantheiosRootHeader.h
  206. #endif /* PANTHEIOS_INCL_PANTHEIOS_H_TRACE */
  207. #define PANTHEIOS_TRACE_PREFIX __FILE__ " " PANTHEIOS_STRINGIZE(__LINE__) ": " __FUNCTION__ ": "
  208. #include <pantheios/trace.h>
  209. Q10: "Do you hand code the makefiles?" [18th June 2008]
  210. A10:
  211. No, although it sometimes feels a bit like that. I use a proprietary
  212. tool, tmpl2make, that takes a makefile template and a tools
  213. configuration file, and runs a merge over them. The makefile template
  214. language has IFDEF and FOREACH, but it's still a non-trivial effort to
  215. start a new one, which is why I tend to copy them from established
  216. projects (such as Pantheios) to new ones (flecxx, FastFormat).
  217. Q11: "Have you considered CMake?" [18th June 2008]
  218. A11:
  219. Yes, and it's on the roadmap for post 1.0 things to do (along with
  220. project/solution files for XCode, Code::Blocks(), and so on). However,
  221. it will always be the case that the raw makefiles will be available for
  222. maximum portability.
  223. Q12: "Which compilers support implicit linking with Pantheios?" [16th October 2008]
  224. A12:
  225. Borland, Metrowerks CodeWarrior (on Windows), Intel (on Windows) and
  226. Visual C++.
  227. Q13: "How do I link when using compilers that don't support implicit linking?" [16th October 2008]
  228. A13:
  229. You must use explicit linking.
  230. For example, say you're using GCC on UNIX, and wishing to use the
  231. fe.simple front-end and along with the be.fprintf back-end. The
  232. libraries you link to depend on the configuration.
  233. For single-threaded & debug, you need to link to:
  234. pantheios.1.core.gcc40.debug.a
  235. pantheios.1.util.gcc40.debug.a
  236. pantheios.1.fe.simple.gcc40.debug.a
  237. pantheios.1.be.fprintf.gcc40.debug.a
  238. pantheios.1.bec.fprintf.gcc40.debug.a
  239. The command-line will look like:
  240. g++ -Dunix -I$PANTHEIOS_ROOT/include -I$STLSOFT/include \
  241. -L$PANTHEIOS_ROOT/lib \
  242. -lpantheios.1.core.gcc40 \
  243. -lpantheios.1.fe.simple.gcc40 \
  244. -lpantheios.1.be.fprintf.gcc40 \
  245. -lpantheios.1.bec.fprintf.gcc40 \
  246. -lpantheios.1.core.gcc40 \
  247. -lpantheios.1.util.gcc40 \
  248. my_program.cpp
  249. Note the double specification of the pantheios.1.core.gcc40.debug.a
  250. library. This is required with GCC because of the way it handles
  251. library lookup and interpositioning: basically the core depends on
  252. symbols defined in the front-end and back-end(s), and they in turn
  253. depend on some symbols defined in the core, so it has to be specified
  254. before and after them
  255. Q14: "I'm using the Trace API, but it fails to print the function. Why?" [6th May 2009]
  256. A14:
  257. You are using a compiler that does not support the __FUNCTION__ macro. At
  258. the current time (Pantheios 1.0.1-beta 186, STLSoft 1.9.81), the compilers
  259. known to support it are:
  260. * Comeau
  261. * Digital Mars (8.50+)
  262. * GCC (3+)
  263. * Intel C/C++ (7+)
  264. * Metrowerks CodeWarrior (8+)
  265. * Visual C++ (7.0+)
  266. * Watcom C/C++ (OpenWatcom 1.4+)
  267. * SunPro 5.9 (by defining __FUNCTION__ in terms of the compiler-specific
  268. __func__)
  269. Those known to not support it are:
  270. * Borland (all versions 5.5 - 6.1)
  271. * VectorC
  272. If your compiler does not support it, then the only avenue available if
  273. you absolutely must have it, is to #define it in each function, as in:
  274. int main()
  275. {
  276. #define __FUNCTION__ main
  277. PANTHEIOS_TRACE_PRINTF(pantheios::notice, "a string '%s' and a number %d", "<abc>", 42);
  278. . . .
  279. You'll also need to "persuade" the trace macro you wish to use that it can
  280. actually proceed. In the example.cpp.tracing.with_function example, the
  281. PANTHEIOS_TRACE_PREFIX macro is defined as follows:
  282. // From examples/cpp/example.cpp.tracing.with_function/example.cpp.tracing.with_function.cpp
  283. #ifdef STLSOFT_CF_FUNCTION_SYMBOL_SUPPORT
  284. # define PANTHEIOS_TRACE_PREFIX __FILE__ " " PANTHEIOS_STRINGIZE(__LINE__) ": " __FUNCTION__ ": "
  285. #endif /* STLSOFT_CF_FUNCTION_SYMBOL_SUPPORT */
  286. If you're using a compiler that does not support __FUNCTION__, and for
  287. which STLSOFT_CF_FUNCTION_SYMBOL_SUPPORT is not defined, you would remove
  288. the #ifdef and #endif lines.
  289. If you wish to ensure that program remains compatible with compilers that
  290. do support __FUNCTION__, then you would add a guard around the #define, as
  291. in:
  292. int main()
  293. {
  294. #ifndef STLSOFT_CF_FUNCTION_SYMBOL_SUPPORT
  295. # define __FUNCTION__ "main"
  296. #endif /* !STLSOFT_CF_FUNCTION_SYMBOL_SUPPORT */
  297. . . .
  298. Q15: "I have numerous back ends defined, and am trying to pass the
  299. log message to a specific backend for a specific log level, like this:
  300. log_message( int logLevel, int log_BE, const char* message)
  301. {
  302. pantheios::log(pantheios::critical(log_BE), "log this");
  303. }
  304. but change pantheios::critical() to be based on the logLevel, such as
  305. PANTHEIOS_SEV_DEBUG or similar. How is this done?" [21st May 2009]
  306. A15:
  307. Use PANTHEIOS_MAKE_EXTENDED_SEVERITY() to define severity+extended_info
  308. on the fly, as in:
  309. // C example
  310. pantheios_logprintf(
  311. PANTHEIOS_MAKE_EXTENDED_SEVERITY(PANTHEIOS_SEV_NOTICE, 10), "hello");
  312. and:
  313. // C++ example
  314. pantheios::log(
  315. PANTHEIOS_MAKE_EXTENDED_SEVERITY(PANTHEIOS_SEV_NOTICE, 10), "hello");
  316. You can #define your own codebase-specific macro that's more
  317. succinct, e.g:
  318. #define ACME_SEV_X(sev, x) PANTHEIOS_MAKE_EXTENDED_SEVERITY(sev, x)
  319. and use it as:
  320. log_message( int logLevel, int log_BE, const char* message)
  321. {
  322. pantheios::log(ACME_SEV_X(logLevel, log_BE), "log this");
  323. }
  324. Q16: "Currently the logging format is something like:
  325. [Project.5844, 5/20/2009 1:58:37.006 PM; Debug ]: logging message
  326. Is there any way to modify the format of this?" [21st May 2009]
  327. A16:
  328. Yes, in a limited way, via the callback mechanism. Link to a callback
  329. version of a particular back-end library and implement the back-end
  330. callback initialisation function.
  331. This allows you to turn on/off various format prefix fields
  332. [process identity, thread identity, date, time, severity, etc.]
  333. For example, the non-callback version of the be.fprintf back-end is
  334. defined in the bec.fprintf library (e.g.
  335. pantheios.1.bec.fprintf.vc9.lib), whereas the callback version is defined
  336. in the bec.fprintf.WithCallback library (e.g.
  337. pantheios.1.bec.fprintf.WithCallback.vc6.lib).
  338. The callback initialisation function for be.fprintf is
  339. pantheios_be_fprintf_getAppInit(). You implement this function and
  340. customise the behaviour of be.fprintf via the flags member of
  341. pan_be_fprintf_init_t.
  342. Note that the only reordering possible is to put the whole prefix,
  343. en-bloc, to the end (as a suffix). For more sophisticated ordering, the
  344. only option currently available is to write your own back-end, or engage
  345. the services of Synesis Software (http://www.synesis.com.au/contact.html)
  346. to assist you.
  347. Q17: "I'm going through and converting a lot of printf statements to
  348. pantheios::log statements and I'm unsure of how to best retain the pretty
  349. formatting aspects. For types with explicit inserters (real, int, etc.)
  350. it seems I can use the width and fmt parameters to log prettily, but its
  351. unclear how to space strings.
  352. For example how should I translate:
  353. printf("Name: %40s", name.c_str());
  354. " [24th June 2009]
  355. A17:
  356. As of 1.0.1 beta 189, the padding inserter pantheios::pad() can be used
  357. to provide a string of spaces of the necessary size to pad a variable of
  358. arbitrary type, as in:
  359. #include <pantheios/inserters/pad.hpp> // for pantheios::pad
  360. printf("Name: %40s.\n", name.c_str());
  361. pantheios::log_NOTICE("Name: ", PANTHEIOS_LPAD(name, 40), ".");
  362. The inserter is used via the PANTHEIOS_LPAD(), which inserts pad spaces
  363. to the left of the variable, and PANTHEIOS_RPAD(), which inserts pad
  364. spaces to the right.
  365. Q18: "I've written a custom front-end to work with be.N, but the backendId
  366. is always 0 in pantheios_fe_isSeverityLogged(), and nothing gets logged!"
  367. A18:
  368. pantheios_fe_isSeverityLogged() is always called first by the Application
  369. Layer, to determine whether a log statement at the given severity level
  370. will be logged; If not, nothing needs to be converted. In this invocation
  371. the backendId parameter will be 0 (aka PANTHEIOS_BEID_ALL), meaning "does
  372. anything need to be logged?"
  373. Multiplexing back-ends (e.g. be.N) also call pantheios_fe_isSeverityLogged()
  374. to determine whether a specific back-end is interested in the given log
  375. statement (based on its severity level).
  376. So, if you are writing a custom front-end, you must handle both cases: 0
  377. for "any back-ends?", and specific non-0 values (your specific back-end
  378. identifiers) representing your specific back-ends. The scratch test
  379. program test.scratch.be.N.with.custom.fe illustrates how this is to done.
  380. Its definition of pantheios_fe_isSeverityLogged() is as follows:
  381. PANTHEIOS_CALL(int) pantheios_fe_isSeverityLogged(void*, int severity, int beid)
  382. {
  383. switch(beid)
  384. {
  385. // Must handle PANTHEIOS_BEID_ALL, as that's the Application Layer's
  386. // (initial) enquiry as to whether anything should be logged at all
  387. case PANTHEIOS_BEID_ALL:
  388. #if 0
  389. // The inefficient way to do this is to just 'return true'
  390. return true;
  391. #else /* ? 0 */
  392. // The efficient (but complicated) way to do this is to see if
  393. // *any* back-end wants output, in which case we say yes
  394. return severity <= iCeilingMain ||
  395. severity <= iCeilingConsole ||
  396. severity <= iCeilingError;
  397. #endif /* 0 */
  398. // Now handle each specified back-end, which will come from be.N
  399. // multiplexing the output(s)
  400. case WG_LOG_FILE_ID:
  401. return severity <= iCeilingMain;
  402. case WG_LOG_CONSOLE_ID:
  403. return severity <= iCeilingConsole;
  404. case WG_LOG_FILE_ERROR_ID:
  405. return severity <= iCeilingError;
  406. // Don't know about anything else
  407. default:
  408. PANTHEIOS_CONTRACT_ENFORCE_UNEXPECTED_CONDITION_API("unexpected back-end identifier");
  409. return false;
  410. }
  411. }
  412. Q19: "My project requires that I use Microsoft Visual C++'s /Zc:wchar_t-
  413. option, which prevents wchar_t from being a built-in type, instead
  414. being just a typedef to 'unsigned short'. When I try to link with
  415. Pantheios I get link errors, such as:
  416. 1>Zc.wchar_t.test.obj : error LNK2019: unresolved external symbol "public: __thiscall pantheios::args::args(int,unsigned short const * const *,int,unsigned short const *)" (??0args@pantheios@@QAE@HPBQBGHPBG@Z) referenced in function _wmain
  417. 1>Zc.wchar_t.test.obj : error LNK2019: unresolved external symbol "public: unsigned short const * __thiscall pantheios::args::data(void)const " (?data@args@pantheios@@QBEPBGXZ) referenced in function "unsigned short const * __cdecl pantheios::shims::c_str_data_w(class pantheios::args const &)" (?c_str_data_w@shims@pantheios@@YAPBGABVargs@2@@Z)
  418. 1>Zc.wchar_t.test.obj : error LNK2019: unresolved external symbol "public: unsigned short const * __thiscall pantheios::integer::data(void)const " (?data@integer@pantheios@@QBEPBGXZ) referenced in function "unsigned short const * __cdecl pantheios::shims::c_str_data_w(class pantheios::integer const &)" (?c_str_data_w@shims@pantheios@@YAPBGABVinteger@2@@Z)
  419. How can I get Pantheios to define wchar_t in the same way without
  420. hacking the makefile?
  421. "
  422. A19:
  423. You have to link against a version of Pantheios compiled with the same
  424. compiler flag. This can be achieved by setting the CUSTOM_DEFS make macro
  425. as follows:
  426. > nmake CUSTOM_DEFS="-Zc:wchar_t-" build
  427. You will then be able to link to your program.
  428. NOTE: You will need to ensure that other code that relies on Pantheios and
  429. that was not compiled with -Zc:wchar_t- will see another, uncustomised,
  430. version, otherwise you'll have the same linking problem, but in reverse.
  431. =============================== End of file ================================