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