]>
Commit | Line | Data |
---|---|---|
15b6757b | 1 | ///////////////////////////////////////////////////////////////////////////// |
9715cf42 | 2 | // Name: log.h |
15b6757b FM |
3 | // Purpose: topic overview |
4 | // Author: wxWidgets team | |
5 | // RCS-ID: $Id$ | |
526954c5 | 6 | // Licence: wxWindows licence |
15b6757b FM |
7 | ///////////////////////////////////////////////////////////////////////////// |
8 | ||
880efa2a | 9 | /** |
36c9828f | 10 | |
831e1028 | 11 | @page overview_log Logging Overview |
9715cf42 | 12 | |
831e1028 | 13 | @tableofcontents |
9ad2fe62 | 14 | |
9715cf42 BP |
15 | This is a general overview of logging classes provided by wxWidgets. The word |
16 | logging here has a broad sense, including all of the program output, not only | |
17 | non-interactive messages. The logging facilities included in wxWidgets provide | |
18 | the base wxLog class which defines the standard interface for a @e log target | |
19 | as well as several standard implementations of it and a family of functions to | |
20 | use with them. | |
21 | ||
22 | First of all, no knowledge of wxLog classes is needed to use them. For this, | |
54e280d8 FM |
23 | you should only know about @ref group_funcmacro_log "wxLogXXX() functions". |
24 | All of them have the same syntax as @e printf() or @e vprintf() , i.e. they | |
25 | take the format string as the first argument and respectively a variable number | |
26 | of arguments or a variable argument list pointer. Here are all of them: | |
9715cf42 | 27 | |
54e280d8 | 28 | @li wxLogFatalError() which is like wxLogError(), but also terminates the program |
9715cf42 BP |
29 | with the exit code 3 (using @e abort() standard function). Unlike for all |
30 | the other logging functions, this function can't be overridden by a log | |
31 | target. | |
54e280d8 | 32 | @li wxLogError() is the function to use for error messages, i.e. the messages |
9715cf42 BP |
33 | that must be shown to the user. The default processing is to pop up a |
34 | message box to inform the user about it. | |
54e280d8 | 35 | @li wxLogWarning() for warnings. They are also normally shown to the user, but |
9715cf42 | 36 | don't interrupt the program work. |
54e280d8 | 37 | @li wxLogMessage() is for all normal, informational messages. They also appear in |
9715cf42 | 38 | a message box by default (but it can be changed, see below). |
54e280d8 | 39 | @li wxLogVerbose() is for verbose output. Normally, it is suppressed, but might |
9715cf42 BP |
40 | be activated if the user wishes to know more details about the program |
41 | progress (another, but possibly confusing name for the same function is | |
42 | wxLogInfo). | |
54e280d8 | 43 | @li wxLogStatus() is for status messages. They will go into the status bar of the |
9715cf42 | 44 | active or specified (as the first argument) wxFrame if it has one. |
54e280d8 | 45 | @li wxLogSysError() is mostly used by wxWidgets itself, but might be handy for |
9715cf42 BP |
46 | logging errors after system call (API function) failure. It logs the |
47 | specified message text as well as the last system error code (@e errno or | |
54e280d8 | 48 | Windows' @e GetLastError() depending on the platform) and the corresponding error |
9715cf42 BP |
49 | message. The second form of this function takes the error code explicitly |
50 | as the first argument. | |
54e280d8 FM |
51 | @li wxLogDebug() is @b the right function for debug output. It only does anything |
52 | at all in the debug mode (when the preprocessor symbol @c __WXDEBUG__ is | |
af588446 | 53 | defined) and expands to nothing in release mode (otherwise). |
54e280d8 | 54 | Note that under Windows, you must either run the program under debugger or |
af588446 VZ |
55 | use a 3rd party program such as DebugView |
56 | (http://www.microsoft.com/technet/sysinternals/Miscellaneous/DebugView.mspx) | |
57 | to actually see the debug output. | |
54e280d8 | 58 | @li wxLogTrace() as wxLogDebug() only does something in debug build. The reason for |
9715cf42 BP |
59 | making it a separate function from it is that usually there are a lot of |
60 | trace messages, so it might make sense to separate them from other debug | |
61 | messages which would be flooded in them. Moreover, the second version of | |
62 | this function takes a trace mask as the first argument which allows to | |
63 | further restrict the amount of messages generated. | |
64 | ||
831e1028 BP |
65 | @see @ref group_funcmacro_log "Logging Functions and Macros" |
66 | ||
9715cf42 BP |
67 | The usage of these functions should be fairly straightforward, however it may |
68 | be asked why not use the other logging facilities, such as C standard stdio | |
69 | functions or C++ streams. The short answer is that they're all very good | |
70 | generic mechanisms, but are not really adapted for wxWidgets, while the log | |
71 | classes are. Some of advantages in using wxWidgets log functions are: | |
72 | ||
73 | @li @b Portability: It is a common practice to use @e printf() statements or | |
74 | cout/cerr C++ streams for writing out some (debug or otherwise) | |
75 | information. Although it works just fine under Unix, these messages go | |
76 | strictly nowhere under Windows where the stdout of GUI programs is not | |
77 | assigned to anything. Thus, you might view wxLogMessage() as a simple | |
78 | substitute for @e printf(). | |
79 | You can also redirect the @e wxLogXXX calls to @e cout by just writing: | |
80 | @code | |
81 | wxLog* logger = new wxLogStream(&cout); | |
82 | wxLog::SetActiveTarget(logger); | |
83 | @endcode | |
84 | Finally, there is also a possibility to redirect the output sent to @e cout | |
85 | to a wxTextCtrl by using the wxStreamToTextRedirector class. | |
86 | @li @b Flexibility: The output of wxLog functions can be redirected or | |
87 | suppressed entirely based on their importance, which is either impossible | |
88 | or difficult to do with traditional methods. For example, only error | |
89 | messages, or only error messages and warnings might be logged, filtering | |
90 | out all informational messages. | |
91 | @li @b Completeness: Usually, an error message should be presented to the user | |
92 | when some operation fails. Let's take a quite simple but common case of a | |
93 | file error: suppose that you're writing your data file on disk and there is | |
94 | not enough space. The actual error might have been detected inside | |
95 | wxWidgets code (say, in wxFile::Write), so the calling function doesn't | |
96 | really know the exact reason of the failure, it only knows that the data | |
97 | file couldn't be written to the disk. However, as wxWidgets uses | |
98 | wxLogError() in this situation, the exact error code (and the corresponding | |
99 | error message) will be given to the user together with "high level" message | |
100 | about data file writing error. | |
101 | ||
9ad2fe62 | 102 | |
831e1028 | 103 | |
c602c59b VZ |
104 | @section overview_log_enable Log Messages Selection |
105 | ||
106 | By default, most log messages are enabled. In particular, this means that | |
107 | errors logged by wxWidgets code itself (e.g. when it fails to perform some | |
108 | operation, for instance wxFile::Open() logs an error when it fails to open a | |
109 | file) will be processed and shown to the user. To disable the logging entirely | |
110 | you can use wxLog::EnableLogging() method or, more usually, wxLogNull class | |
111 | which temporarily disables logging and restores it back to the original setting | |
112 | when it is destroyed. | |
113 | ||
114 | To limit logging to important messages only, you may use wxLog::SetLogLevel() | |
115 | with e.g. wxLOG_Warning value -- this will completely disable all logging | |
116 | messages with the severity less than warnings, so wxLogMessage() output won't | |
117 | be shown to the user any more. | |
118 | ||
119 | Moreover, the log level can be set separately for different log components. | |
120 | Before showing how this can be useful, let us explain what log components are: | |
121 | they are simply arbitrary strings identifying the component, or module, which | |
122 | generated the message. They are hierarchical in the sense that "foo/bar/baz" | |
123 | component is supposed to be a child of "foo". And all components are children | |
124 | of the unnamed root component. | |
125 | ||
126 | By default, all messages logged by wxWidgets originate from "wx" component or | |
127 | one of its subcomponents such as "wx/net/ftp", while the messages logged by | |
128 | your own code are assigned empty log component. To change this, you need to | |
129 | define @c wxLOG_COMPONENT to a string uniquely identifying each component, e.g. | |
130 | you could give it the value "MyProgram" by default and re-define it as | |
131 | "MyProgram/DB" in the module working with the database and "MyProgram/DB/Trans" | |
132 | in its part managing the transactions. Then you could use | |
133 | wxLog::SetComponentLevel() in the following ways: | |
c602c59b | 134 | |
831e1028 BP |
135 | @code |
136 | // disable all database error messages, everybody knows databases never | |
137 | // fail anyhow | |
138 | wxLog::SetComponentLevel("MyProgram/DB", wxLOG_FatalError); | |
139 | ||
140 | // but enable tracing for the transactions as somehow our changes don't | |
141 | // get committed sometimes | |
142 | wxLog::SetComponentLevel("MyProgram/DB/Trans", wxLOG_Trace); | |
143 | ||
144 | // also enable tracing messages from wxWidgets dynamic module loading | |
145 | // mechanism | |
146 | wxLog::SetComponentLevel("wx/base/module", wxLOG_Trace); | |
147 | @endcode | |
c602c59b | 148 | |
c602c59b VZ |
149 | Notice that the log level set explicitly for the transactions code overrides |
150 | the log level of the parent component but that all other database code | |
151 | subcomponents inherit its setting by default and so won't generate any log | |
152 | messages at all. | |
153 | ||
831e1028 BP |
154 | |
155 | ||
9ad2fe62 VZ |
156 | @section overview_log_targets Log Targets |
157 | ||
9715cf42 | 158 | After having enumerated all the functions which are normally used to log the |
c602c59b | 159 | messages, and why would you want to use them, we now describe how all this |
9715cf42 BP |
160 | works. |
161 | ||
162 | wxWidgets has the notion of a <em>log target</em>: it is just a class deriving | |
163 | from wxLog. As such, it implements the virtual functions of the base class | |
164 | which are called when a message is logged. Only one log target is @e active at | |
54e280d8 FM |
165 | any moment, this is the one used by @ref group_funcmacro_log "wxLogXXX() functions". |
166 | The normal usage of a log object (i.e. object of a class derived from wxLog) is | |
831e1028 BP |
167 | to install it as the active target with a call to @e SetActiveTarget() and it |
168 | will be used automatically by all subsequent calls to | |
169 | @ref group_funcmacro_log "wxLogXXX() functions". | |
9715cf42 BP |
170 | |
171 | To create a new log target class you only need to derive it from wxLog and | |
af588446 VZ |
172 | override one or several of wxLog::DoLogRecord(), wxLog::DoLogTextAtLevel() and |
173 | wxLog::DoLogText() in it. The first one is the most flexible and allows you to | |
174 | change the formatting of the messages, dynamically filter and redirect them and | |
175 | so on -- all log messages, except for those generated by wxLogFatalError(), | |
176 | pass by this function. wxLog::DoLogTextAtLevel() should be overridden if you | |
177 | simply want to redirect the log messages somewhere else, without changing their | |
178 | formatting. Finally, it is enough to override wxLog::DoLogText() if you only | |
179 | want to redirect the log messages and the destination doesn't depend on the | |
180 | message log level. | |
181 | ||
9715cf42 BP |
182 | There are some predefined classes deriving from wxLog and which might be |
183 | helpful to see how you can create a new log target class and, of course, may | |
184 | also be used without any change. There are: | |
185 | ||
186 | @li wxLogStderr: This class logs messages to a <tt>FILE *</tt>, using stderr by | |
187 | default as its name suggests. | |
188 | @li wxLogStream: This class has the same functionality as wxLogStderr, but uses | |
189 | @e ostream and cerr instead of <tt>FILE *</tt> and stderr. | |
190 | @li wxLogGui: This is the standard log target for wxWidgets applications (it is | |
191 | used by default if you don't do anything) and provides the most reasonable | |
192 | handling of all types of messages for given platform. | |
193 | @li wxLogWindow: This log target provides a "log console" which collects all | |
194 | messages generated by the application and also passes them to the previous | |
195 | active log target. The log window frame has a menu allowing user to clear | |
196 | the log, close it completely or save all messages to file. | |
197 | @li wxLogBuffer: This target collects all the logged messages in an internal | |
198 | buffer allowing to show them later to the user all at once. | |
199 | @li wxLogNull: The last log class is quite particular: it doesn't do anything. | |
200 | The objects of this class may be instantiated to (temporarily) suppress | |
201 | output of @e wxLogXXX() functions. As an example, trying to open a | |
202 | non-existing file will usually provoke an error message, but if for some | |
203 | reasons it is unwanted, just use this construction: | |
204 | @code | |
205 | wxFile file; | |
206 | ||
207 | // wxFile.Open() normally complains if file can't be opened, we don't want it | |
208 | { | |
209 | wxLogNull logNo; | |
210 | if ( !file.Open("bar") ) | |
211 | { | |
212 | // ... process error ourselves ... | |
213 | } | |
214 | } // ~wxLogNull called, old log sink restored | |
215 | ||
216 | wxLogMessage("..."); // ok | |
217 | @endcode | |
218 | ||
831e1028 BP |
219 | @see @ref group_class_logging "Logging Classes" |
220 | ||
9715cf42 BP |
221 | The log targets can also be combined: for example you may wish to redirect the |
222 | messages somewhere else (for example, to a log file) but also process them as | |
223 | normally. For this the wxLogChain, wxLogInterposer, and wxLogInterposerTemp can | |
224 | be used. | |
225 | ||
9ad2fe62 | 226 | |
831e1028 | 227 | |
54e280d8 FM |
228 | @section overview_log_mt Logging in Multi-Threaded Applications |
229 | ||
230 | Starting with wxWidgets 2.9.1, logging functions can be safely called from any | |
231 | thread. Messages logged from threads other than the main one will be buffered | |
232 | until wxLog::Flush() is called in the main thread (which usually happens during | |
233 | idle time, i.e. after processing all pending events) and will be really output | |
234 | only then. Notice that the default GUI logger already only output the messages | |
235 | when it is flushed, so by default messages from the other threads will be shown | |
236 | more or less at the same moment as usual. However if you define a custom log | |
237 | target, messages may be logged out of order, e.g. messages from the main thread | |
238 | with later timestamp may appear before messages with earlier timestamp logged | |
239 | from other threads. wxLog does however guarantee that messages logged by each | |
240 | thread will appear in order in which they were logged. | |
241 | ||
242 | Also notice that wxLog::EnableLogging() and wxLogNull class which uses it only | |
243 | affect the current thread, i.e. logging messages may still be generated by the | |
244 | other threads after a call to @c EnableLogging(false). | |
245 | ||
246 | ||
831e1028 | 247 | |
9ad2fe62 VZ |
248 | @section overview_log_customize Logging Customization |
249 | ||
250 | To completely change the logging behaviour you may define a custom log target. | |
251 | For example, you could define a class inheriting from wxLog which shows all the | |
252 | log messages in some part of your main application window reserved for the | |
253 | message output without interrupting the user work flow with modal message | |
254 | boxes. | |
255 | ||
256 | To use your custom log target you may either call wxLog::SetActiveTarget() with | |
257 | your custom log object or create a wxAppTraits-derived class and override | |
54e280d8 | 258 | wxAppTraits::CreateLogTarget() virtual method in it and also override wxApp::CreateTraits() |
9ad2fe62 VZ |
259 | to return an instance of your custom traits object. Notice that in the latter |
260 | case you should be prepared for logging messages early during the program | |
261 | startup and also during program shutdown so you shouldn't rely on existence of | |
262 | the main application window, for example. You can however safely assume that | |
263 | GUI is (already/still) available when your log target as used as wxWidgets | |
264 | automatically switches to using wxLogStderr if it isn't. | |
265 | ||
54e280d8 FM |
266 | There are several methods which may be overridden in the derived class to |
267 | customize log messages handling: wxLog::DoLogRecord(), wxLog::DoLogTextAtLevel() | |
268 | and wxLog::DoLogText(). | |
269 | ||
270 | The last method is the simplest one: you should override it if you simply | |
271 | want to redirect the log output elsewhere, without taking into account the | |
272 | level of the message. If you do want to handle messages of different levels | |
273 | differently, then you should override wxLog::DoLogTextAtLevel(). | |
274 | ||
4ffdb640 VZ |
275 | Additionally, you can customize the way full log messages are constructed from |
276 | the components (such as time stamp, source file information, logging thread ID | |
277 | and so on). This task is performed by wxLogFormatter class so you need to | |
278 | derive a custom class from it and override its Format() method to build the log | |
279 | messages in desired way. Notice that if you just need to modify (or suppress) | |
280 | the time stamp display, overriding FormatTime() is enough. | |
281 | ||
282 | Finally, if even more control over the output format is needed, then | |
283 | DoLogRecord() can be overridden as it allows to construct custom messages | |
54e280d8 FM |
284 | depending on the log level or even do completely different things depending |
285 | on the message severity (for example, throw away all messages except | |
286 | warnings and errors, show warnings on the screen and forward the error | |
287 | messages to the user's (or programmer's) cell phone -- maybe depending on | |
288 | whether the timestamp tells us if it is day or night in the current time | |
289 | zone). | |
290 | ||
291 | The @e dialog sample illustrates this approach by defining a custom log target | |
9ad2fe62 VZ |
292 | customizing the dialog used by wxLogGui for the single messages. |
293 | ||
232addd1 | 294 | |
831e1028 | 295 | @section overview_log_tracemasks Using Trace Masks |
232addd1 | 296 | |
54e280d8 FM |
297 | Notice that the use of log trace masks is hardly necessary any longer in |
298 | current wxWidgets version as the same effect can be achieved by using | |
299 | different log components for different log statements of any level. Please | |
300 | see @ref overview_log_enable for more information about the log components. | |
232addd1 | 301 | |
54e280d8 FM |
302 | The functions below allow some limited customization of wxLog behaviour |
303 | without writing a new log target class (which, aside from being a matter of | |
304 | several minutes, allows you to do anything you want). | |
305 | The verbose messages are the trace messages which are not disabled in the | |
306 | release mode and are generated by wxLogVerbose(). | |
307 | They are not normally shown to the user because they present little interest, | |
308 | but may be activated, for example, in order to help the user find some program | |
309 | problem. | |
310 | ||
311 | As for the (real) trace messages, their handling depends on the currently | |
312 | enabled trace masks: if wxLog::AddTraceMask() was called for the mask of the given | |
313 | message, it will be logged, otherwise nothing happens. | |
314 | ||
315 | For example, | |
316 | @code | |
317 | wxLogTrace( wxTRACE_OleCalls, "IFoo::Bar() called" ); | |
318 | @endcode | |
319 | ||
320 | will log the message if it was preceded by: | |
321 | ||
322 | @code | |
695d5232 | 323 | wxLog::AddTraceMask( wxTRACE_OleCalls ); |
54e280d8 FM |
324 | @endcode |
325 | ||
326 | The standard trace masks are given in wxLogTrace() documentation. | |
327 | ||
9715cf42 | 328 | */ |