|
|
3.1 Basic Logging and Tracing
通常,用ACE_DEBUG, ACE_ERROR, and ACE_TRACE这三个宏来输出诊断信息
Three macros are commonly used to display diagnostic output from your code: ACE_DEBUG, ACE_ERROR, and ACE_TRACE.
头两个的参数和实现的操作基本相同
The arguments to the first two are the same; their operation is nearly identical, so for our purposes now, we'll treat them the same. They both take a severity indicator as one of the arguments, so you can display any message using either;
然而,ACE_DEBUG通常用来输出自己的调试信息;ACE_ERROR用来输出警告和错误
however, the convention is to use ACE_DEBUG for your own debugging statements and ACE_ERROR for warnings and errors. The use of these macros is the same:
ACE_DEBUG ((severity, formatting-args));ACE_ERROR ((severity, formatting-args));The severity parameter specifies the severity level of your message.
最常用的就是LM_DEBUG和LM_ERROR
The most common levels are LM_DEBUG and LM_ERROR. All the valid severity values are listed in Table 3.1.
The formatting-args parameter is a printf()-like set of format conversion operators and formatting arguments for insertion into the output. The complete set of formatting directives is described in Table 3.2. One might wonder why printf()-like formatting was chosen instead of the more natural—to C++ coders—C++ iostream-style formatting. In some cases, it would have been easier to correctly log certain types of information with type-safe insertion operators. However, an important factor in the logging facility's design is the ability to effectively "no-op" the logging statements at compile time. Note that the ACE_DEBUG and ACE_ERROR invocations require two sets of parentheses. The outer set delimits the single macro argument. This single argument comprises all the arguments, and their enclosing parentheses, needed for a method call. If the preprocessor macro ACE_NDEBUG is defined, the ACE_DEBUG macro will expand to a blank line, ignoring the content of the inner set of parentheses. Achieving this same optimization with insertion operators would have resulted in a rather odd usage:
ACE_DEBUG ((debug_info << "Hi Mom" << endl));
[table=98%]Table 3.1. ACE_Log_Msg Logging Severity Levels
[tr]Severity Level
Meaning
[/tr] | LM_TRACE
| Messages indicating function-calling sequence
| LM_DEBUG
| Debugging information
| LM_INFO
| Messages that contain information normally of use only when debugging a program
| LM_NOTICE
| Conditions that are not error conditions but that may require special handling
| LM_WARNING
| Warning messages
| LM_ERROR
| Error messages
| LM_CRITICAL
| Critical conditions, such as hard device errors
| LM_ALERT
| A condition that should be corrected immediately, such as a corrupted system database
| LM_EMERGENCY
| A panic condition, normally broadcast to all users
| Similarly, many of the formatting tokens, such as %I, would have been awkward to implement and overly verbose to use:
ACE_DEBUG((debug_info<<ACE_Log_Msg::nested_indent<<"Hi Mom"<<endl));One could argue away the compile-time optimization by causing ACE_NDEBUG to put the debug output stream object into a no-op mode. That may be sufficient for some platforms, but for others, such as embedded real-time systems, you really do want the code to simply not exist.
Unlike ACE_DEBUG and ACE_ERROR, which cause output where the macro is placed, ACE_TRACE causes one line of debug information to be printed at the point of the ACE_TRACE statement and another when its enclosing scope is exited. Therefore, placing an ACE_TRACE statement at the beginning of a function or method provides a trace of when that function or method is entered and exited. The ACE_TRACE macro accepts a single character string rather than a set of formatting directives. Because C++ doesn't have a handy way to dump a stack trace, this can be very useful indeed.
Let's take a look at a simple application:
#include "ace/Log_Msg.h"void foo (void);int ACE_TMAIN (int, ACE_TCHAR *[]){ ACE_TRACE(ACE_TEXT ("main")); ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHi Mom\n"))); foo(); ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n"))); return 0;}void foo (void){ ACE_TRACE (ACE_TEXT ("foo")); ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHowdy Pardner\n")));}Our first step is always to include the Log_Msg.h header file. It defines many helpful macros, including ACE_DEBUG and ACE_ERROR, to make your life easier. The full set of output-producing macros is listed in Table 3.3.
You can use ACE_DEBUG to print just about any arbitrary string you want, and the many format directives listed in Table 3.2 can also be modified with printf()-style modifiers for length, precision, and fill adjustments. (See a printf() reference for details on the modifiers.) In the preceding example, we've used %I so that the ACE_DEBUG messages are nicely indented along with the ACE_TRACE messages.
If you compile and execute the preceding code, you should get something like this:
(1024) calling main in file `Simple1.cpp' on line 7 Hi Mom (1024) calling foo in file `Simple1.cpp' on line 18 Howdy Pardner (1024) leaving foo Goodnight(1024) leaving main
[table=98%]Table 3.2. ACE Logging Format Directives
[tr]Code
Argument Type
Displays
[/tr][tr][td]A
[/td][td]ACE_timer_t
[/td][td]Floating-point number; long decimal number if platform doesn't support floating point
[/td][/tr][tr][td]a
[/td][td]—
[/td][td]Aborts the program after displaying output
[/td][/tr][tr][td]c
[/td][td]char
[/td][td]Single character
[/td][/tr][tr][td]C
[/td][td]char*
[/td][td]Character string (narrow characters)
[/td][/tr][tr][td]i,d
[/td][td]int
[/td][td]Decimal number
[/td][/tr][tr][td]I
[/td][td]—
[/td][td]Indents output according to the nesting depth, obtained from ACE_Trace::get_nesting_indent()
[/td][/tr][tr][td]e,E,f,F,g,G
[/td][td]double
[/td][td]Double-precision floating-point number
[/td][/tr][tr][td]l
[/td][td]—
[/td][td]Line number where logging macro appears
[/td][/tr][tr][td]M
[/td][td]—
[/td][td]Text form of the message severity level
[/td][/tr][tr][td]m
[/td][td]—
[/td][td]Message corresponding to errno value, as done by strerror(), for example
[/td][/tr][tr][td]N
[/td][td]—
[/td][td]File name where logging macro appears
[/td][/tr][tr][td]n
[/td][td]—
[/td][td]Program name given to ACE_Log_Msg::open()
[/td][/tr][tr][td]o
[/td][td]int
[/td][td]Octal number
[/td][/tr][tr][td]P
[/td][td]—
[/td][td]Current process ID
[/td][/tr][tr][td]p
[/td][td]ACE_TCHAR*
[/td][td]Specified character string, followed by the appropriate errno message, that is, as done by perror()
[/td][/tr][tr][td]Q
[/td][td]ACE_UINT64
[/td][td]Decimal number
[/td][/tr][tr][td]r
[/td][td]void (*)()
[/td][td]Nothing; calls the specified function
[/td][/tr][tr][td]R
[/td][td]int
[/td][td]Decimal number
[/td][/tr][tr][td]S
[/td][td]int
[/td][td]Signal name of the numbered signal
[/td][/tr][tr][td]s
[/td][td]ACE_TCHAR*
[/td][td]Character string: narrow or wide, according to ACE_TCHAR type
[/td][/tr][tr][td]T
[/td][td]—
[/td][td]Current time as hour:minute:sec.usec
[/td][/tr][tr][td]D
[/td][td]—
[/td][td]Timestamp as month/day/year hour:minute:sec.usec
[/td][/tr][tr][td]t
[/td][td]—
[/td][td]Calling thread's ID (1 if single threaded)
[/td][/tr][tr][td]u
[/td][td]int
[/td][td]Unsigned decimal number
[/td][/tr][tr][td]w
[/td][td]
<span style="font-size: x-small;"><span style="font-family: arial,helvetica,sans-serif;"><span style="font-size: x-small;"><span style="">font-family: times new ro |
|