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