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