|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Trace macro declarations. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #ifndef CNTDEBUG_H |
|
20 #define CNTDEBUG_H |
|
21 |
|
22 #include <QDebug> // QDebug |
|
23 #include <QtGlobal> // qDebug() |
|
24 |
|
25 // #define TRACK_MEMORY_LEAKS |
|
26 #define TRACES |
|
27 // #define TRACE2FILE |
|
28 |
|
29 /*! |
|
30 \def CNT_UNUSED(name) |
|
31 \brief Declares a single variable as unused when tracing is disabled. |
|
32 |
|
33 CNT_UNUSED allows variables (usually method parameters) to be declared as used only if |
|
34 tracing is enabled. Without this variables that are included in trace macros, but not otherwise |
|
35 used, would cause unused variable warnings on compilation. If tracing is enabled, CNT_UNUSED |
|
36 has no effect. |
|
37 |
|
38 Consider the following class method where the parameter number is not used at all, except for |
|
39 tracing its value on entry: |
|
40 |
|
41 \code |
|
42 #include <cntdebug.h> |
|
43 |
|
44 void MyClass::myMethod(int number) |
|
45 { |
|
46 CNT_UNUSED(number) |
|
47 CNT_ENTRY("number =" << number) |
|
48 |
|
49 // ...some more code where the parameter number is not used. |
|
50 |
|
51 CNT_EXIT |
|
52 } |
|
53 \endcode |
|
54 |
|
55 Compiling this method with tracing completely disabled at compile time would cause an unused |
|
56 variable warning to be issued unless the CNT_UNUSED macro is used to declare the variable as |
|
57 trace-only. |
|
58 |
|
59 \param name The name of the variable to declare as unused if tracing is disabled. To mark |
|
60 several variables as trace-only, add a separate CNT_UNUSED statement for each. |
|
61 \sa CNT_STATIC_ENTRY_ARGS(args), CNT_ENTRY_ARGS(args). |
|
62 */ |
|
63 |
|
64 /*! |
|
65 \def CNT_STATIC_ENTRY |
|
66 \brief A method entry trace macro for static class methods or global functions. |
|
67 |
|
68 Invoking CNT_STATIC_ENTRY outputs a timestamp followed by the scope in which the macro |
|
69 was invoked and the word "entry". |
|
70 |
|
71 CNT_STATIC_ENTRY is intended to be used as the first line of static class methods or |
|
72 global functions. There is a corresponding exit macro, CNT_EXIT. |
|
73 |
|
74 The following example shows proper usage of the CNT_STATIC_ENTRY macro. Assuming a class |
|
75 has been declared with a static method that is implemented like this: |
|
76 |
|
77 \code |
|
78 #include <cntdebug.h> |
|
79 |
|
80 void MyClass::myStaticMethod() |
|
81 { |
|
82 CNT_STATIC_ENTRY |
|
83 |
|
84 int i = 1; |
|
85 i++; |
|
86 |
|
87 CNT_EXIT |
|
88 } |
|
89 \endcode |
|
90 |
|
91 calling MyClass::myStaticMethod() generates output lines of the following format: |
|
92 |
|
93 \code |
|
94 2009-03-25 11:00:50.171 : static void MyClass::myStaticMethod() entry |
|
95 2009-03-25 11:00:50.171 : static void MyClass::myStaticMethod() exit |
|
96 \endcode |
|
97 |
|
98 \sa CNT_STATIC_ENTRY_ARGS(args), CNT_EXIT. |
|
99 */ |
|
100 |
|
101 /*! |
|
102 \def CNT_STATIC_ENTRY_ARGS(args) |
|
103 \brief A method entry trace macro with arguments for static class methods or global functions. |
|
104 |
|
105 CNT_STATIC_ENTRY_ARGS(args) is similar to CNT_STATIC_ENTRY but it allows arguments to be |
|
106 output on the same line without needing to resort to a separate CNT_LOG_ARGS call. This is |
|
107 especially handy for outputting the parameters of the method call. |
|
108 |
|
109 The following example shows proper usage of the CNT_STATIC_ENTRY_ARGS(args) macro. Assuming |
|
110 a class has been declared with a static method that is implemented like this: |
|
111 |
|
112 \code |
|
113 #include <QString> |
|
114 #include <cntdebug.h> |
|
115 |
|
116 void MyClass::myStaticMethod(const QString &text, int number) |
|
117 { |
|
118 CNT_STATIC_ENTRY_ARGS("text =" << text << "number =" << number); |
|
119 |
|
120 int i = 1; |
|
121 i++; |
|
122 |
|
123 CNT_EXIT |
|
124 } |
|
125 \endcode |
|
126 |
|
127 calling MyClass::myStaticMethod(QString("foo"), 74) generates output lines of the following |
|
128 format: |
|
129 |
|
130 \code |
|
131 2009-03-25 11:00:50.171 : static void MyClass::myStaticMethod(const QString&, int) entry, text = "foo" number = 74 |
|
132 2009-03-25 11:00:50.171 : static void MyClass::myStaticMethod(const QString&, int) exit |
|
133 \endcode |
|
134 |
|
135 \param args Any number of arguments that can be streamed into a QTextStream, joined together |
|
136 by the streaming operator <<. |
|
137 \sa CNT_STATIC_ENTRY. |
|
138 */ |
|
139 |
|
140 /*! |
|
141 \def CNT_ENTRY |
|
142 \brief A method entry trace macro for class methods. |
|
143 |
|
144 Invoking CNT_ENTRY outputs a timestamp followed by the scope in which the macro |
|
145 was invoked, the word "entry" and the this pointer value of the instance invoking the |
|
146 macro. |
|
147 |
|
148 The this pointer value included in the debug output can help make the output more readable, as |
|
149 it allows different instances of the same class to be distinguished from each other. |
|
150 |
|
151 CNT_ENTRY is intended to be used as the first line of class methods. There is a corresponding |
|
152 exit macro, CNT_EXIT. |
|
153 |
|
154 The following example shows proper usage of the CNT_ENTRY macro. Assuming a class has been |
|
155 declared with a non-static method that is implemented like this: |
|
156 |
|
157 \code |
|
158 #include <cntdebug.h> |
|
159 |
|
160 void MyClass::myMethod() |
|
161 { |
|
162 CNT_ENTRY |
|
163 |
|
164 int i = 1; |
|
165 i++; |
|
166 |
|
167 CNT_EXIT |
|
168 } |
|
169 \endcode |
|
170 |
|
171 calling myMethod() on an instance of MyClass generates output lines of the following format: |
|
172 |
|
173 \code |
|
174 2009-03-25 11:00:50.171 : void MyClass::myMethod() this 0x6cdab90 entry |
|
175 2009-03-25 11:00:50.171 : void MyClass::myMethod() exit |
|
176 \endcode |
|
177 |
|
178 \sa CNT_ENTRY_ARGS(args), CNT_EXIT. |
|
179 */ |
|
180 |
|
181 /*! |
|
182 \def CNT_ENTRY_ARGS(args) |
|
183 \brief A method entry trace macro with arguments for class methods. |
|
184 |
|
185 CNT_ENTRY_ARGS(args) is similar to CNT_ENTRY but it allows arguments to be output on the |
|
186 same line without needing to resort to a separate CNT_LOG_ARGS call. This is especially |
|
187 handy for outputting the parameters of the method call. |
|
188 |
|
189 The following example shows proper usage of the CNT_ENTRY_ARGS(args)) macro. Assuming a |
|
190 class has been declared with a non-static method that is implemented like this: |
|
191 |
|
192 \code |
|
193 #include <QString> |
|
194 #include <cntdebug.h> |
|
195 |
|
196 void MyClass::myMethod(const QString &text, int number) |
|
197 { |
|
198 CNT_ENTRY_ARGS("text =" << text << "number =" << number); |
|
199 |
|
200 int i = 1; |
|
201 i++; |
|
202 |
|
203 CNT_EXIT |
|
204 } |
|
205 \endcode |
|
206 |
|
207 calling myMethod(QString("foo"), 74) on an instance of MyClass generates output lines of the |
|
208 following format: |
|
209 |
|
210 \code |
|
211 2009-03-25 11:00:50.171 : void MyClass::myMethod(const QString&, int) this 0x6cdab90 entry, text = "foo" number = 74 |
|
212 2009-03-25 11:00:50.171 : void MyClass::myMethod(const QString&, int) exit |
|
213 \endcode |
|
214 |
|
215 \param args Any number of arguments that can be streamed into a QTextStream, joined together |
|
216 by the streaming operator <<. |
|
217 \sa CNT_ENTRY, CNT_EXIT. |
|
218 */ |
|
219 |
|
220 /*! |
|
221 \def CNT_EXIT |
|
222 \brief A method exit trace macro for class methods or global functions. |
|
223 |
|
224 Invoking CNT_EXIT outputs a timestamp followed by the scope in which the macro |
|
225 was invoked and the word "exit". |
|
226 |
|
227 CNT_EXIT is intended to be used as the last line of class methods and global functions, |
|
228 just before the return statement, if any. There are two corresponding entry macros, |
|
229 CNT_ENTRY and CNT_STATIC_ENTRY, depending on whether the method being traced is a |
|
230 non-static or a static class method. CNT_EXIT makes no distinction between these two types |
|
231 of methods and is to be used for both. |
|
232 |
|
233 See CNT_ENTRY or CNT_STATIC_ENTRY for an example of how to use CNT_EXIT. |
|
234 |
|
235 \sa CNT_EXIT_ARGS(args), CNT_ENTRY, CNT_STATIC_ENTRY. |
|
236 */ |
|
237 |
|
238 /*! |
|
239 \def CNT_EXIT_ARGS(args) |
|
240 \brief A method exit trace macro with arguments for class methods or global functions. |
|
241 |
|
242 CNT_EXIT_ARGS(args) is similar to CNT_EXIT but it allows arguments to be output on the |
|
243 same line without needing to resort to a separate CNT_LOG_ARGS call. This is especially |
|
244 handy for outputting the return value of the method call. |
|
245 |
|
246 The following example shows proper usage of the CNT_EXIT_ARGS(args) macro. Assuming a |
|
247 class has been declared with a static method that is implemented like this: |
|
248 |
|
249 \code |
|
250 #include <QString> |
|
251 #include <cntdebug.h> |
|
252 |
|
253 int MyClass::myStaticMethod(const QString &text) |
|
254 { |
|
255 CNT_STATIC_ENTRY_ARGS("text =" << text); |
|
256 |
|
257 int length = text.length(); |
|
258 |
|
259 CNT_EXIT_ARGS("length" << length); |
|
260 |
|
261 return length; |
|
262 } |
|
263 \endcode |
|
264 |
|
265 calling MyClass::myStaticMethod(QString("foo")) generates output lines of the following format: |
|
266 |
|
267 \code |
|
268 2009-03-25 13:20:36.448 : static int MyClass::myStaticMethod(const QString&) entry, text = "foo" |
|
269 2009-03-25 13:20:36.448 : static int MyClass::myStaticMethod(const QString&) exit, length 3 |
|
270 \endcode |
|
271 |
|
272 Although the example above is a static method, CNT_EXIT_ARGS(args) works identically for |
|
273 non-static class methods and global functions. |
|
274 |
|
275 \param args Any number of arguments that can be streamed into a QTextStream, joined together |
|
276 by the streaming operator <<. |
|
277 \sa CNT_EXIT |
|
278 */ |
|
279 |
|
280 /*! |
|
281 \def CNT_LOG |
|
282 \brief A trace macro for class methods or global functions. |
|
283 |
|
284 Invoking CNT_LOG outputs a timestamp followed by the scope in which the macro |
|
285 was invoked and the this pointer value of the instance invoking the |
|
286 macro. |
|
287 |
|
288 CNT_LOG is similar to CNT_ENTRY but it is especially handy for marking calls to methods that |
|
289 cannot fail, such as an empty constructor, without needing to resort to a separate CNT_EXIT call. |
|
290 |
|
291 The following example shows proper usage of the CNT_LOG(args) macro. Assuming a |
|
292 class has been declared with a static method that is implemented like this: |
|
293 |
|
294 \code |
|
295 #include <QString> |
|
296 #include <cntdebug.h> |
|
297 |
|
298 MyClass::MyClass() |
|
299 { |
|
300 CNT_LOG |
|
301 } |
|
302 \endcode |
|
303 |
|
304 calling new MyClass() generates output lines of the following format: |
|
305 |
|
306 \code |
|
307 2009-03-25 13:20:36.448 : MyClass::MyClass() this 0x6cdab90 |
|
308 \endcode |
|
309 |
|
310 \sa CNT_LOG_ARGS |
|
311 */ |
|
312 |
|
313 /*! |
|
314 \def CNT_LOG_ARGS(args) |
|
315 \brief A generic trace macro with arguments for class methods or global functions. |
|
316 |
|
317 The following example shows how to produce arbitrary debug output: |
|
318 |
|
319 \code |
|
320 #include <QString> |
|
321 #include <cntdebug.h> |
|
322 |
|
323 void MyClass::myMethod() |
|
324 { |
|
325 CNT_ENTRY |
|
326 |
|
327 QString myString("This is a string."); |
|
328 int myValue = 109; |
|
329 |
|
330 CNT_LOG_ARGS("this is a debug message, myString =" << myString << "myValue =" << myValue) |
|
331 |
|
332 CNT_EXIT |
|
333 } |
|
334 \endcode |
|
335 |
|
336 calling myMethod() on an instance of MyClass generates output lines of the following format: |
|
337 |
|
338 \code |
|
339 2009-03-25 13:45:22.083 : void MyClass::myMethod() this 0x6cdab90 entry |
|
340 2009-03-25 13:45:22.083 : void MyClass::myMethod() this is a debug message, myString = "This is a string." myValue = 109 |
|
341 2009-03-25 13:45:22.083 : void MyClass::myMethod() exit |
|
342 \endcode |
|
343 |
|
344 Any number of arguments may be printed by chaining them together with the streaming operator |
|
345 <<. Notice that a single space character is automatically added between each streamed |
|
346 argument, hence the hardcoded strings in the example above, such as "myValue =", do not have |
|
347 a space at the beginning and end of the string. This automatic space addition is a feature |
|
348 of qDebug() streaming and cannot be disabled. |
|
349 |
|
350 \param args Any number of arguments that can be streamed into a QTextStream, joined together |
|
351 by the streaming operator <<. |
|
352 */ |
|
353 |
|
354 // traces for debug builds by default, or if |
|
355 // TRACES macro is defined |
|
356 #if defined (_DEBUG) && !defined (TRACES) |
|
357 #define TRACES |
|
358 #endif |
|
359 |
|
360 #if defined (TRACES) || defined (TRACE2FILE) |
|
361 #define CNT_UNUSED(name) |
|
362 #define CNT_STATIC_ENTRY qDebug() << __PRETTY_FUNCTION__ << "entry"; |
|
363 #define CNT_STATIC_ENTRY_ARGS(args) qDebug() << __PRETTY_FUNCTION__ << "entry," << args; |
|
364 #define CNT_ENTRY qDebug() << __PRETTY_FUNCTION__ << "this" << (void *)this << "entry"; |
|
365 #define CNT_ENTRY_ARGS(args) qDebug() << __PRETTY_FUNCTION__ << "this" << (void *)this << "entry," << args; |
|
366 #define CNT_EXIT qDebug() << __PRETTY_FUNCTION__ << "exit"; |
|
367 #define CNT_EXIT_ARGS(args) qDebug() << __PRETTY_FUNCTION__ << "exit," << args; |
|
368 #define CNT_LOG qDebug() << __PRETTY_FUNCTION__ << "this" << (void *)this; |
|
369 #define CNT_LOG_ARGS(args) qDebug() << __PRETTY_FUNCTION__ << args; |
|
370 #define CNT_WARNING(args) qWarning() << __PRETTY_FUNCTION__ << args; |
|
371 #define CNT_CRITICAL(args) qCritical() << __PRETTY_FUNCTION__ << args; |
|
372 #define CNT_FATAL(args) qFatal() << __PRETTY_FUNCTION__ << args; |
|
373 #else |
|
374 #define CNT_UNUSED(name) Q_UNUSED(name) |
|
375 #define CNT_STATIC_ENTRY |
|
376 #define CNT_STATIC_ENTRY_ARGS(args) |
|
377 #define CNT_ENTRY |
|
378 #define CNT_ENTRY_ARGS(args) |
|
379 #define CNT_EXIT |
|
380 #define CNT_EXIT_ARGS(args) |
|
381 #define CNT_LOG |
|
382 #define CNT_LOG_ARGS(args) |
|
383 #define CNT_WARNING(args) |
|
384 #define CNT_CRITICAL(args) |
|
385 #define CNT_FATAL(args) |
|
386 #endif // TRACES || TRACE2FILE |
|
387 |
|
388 // for tracing memory leaks |
|
389 #ifdef TRACK_MEMORY_LEAKS |
|
390 #include <hbapplication.h> |
|
391 |
|
392 #define CNT_TRACK_QOBJECTLIFE(obj) { new CntQObjectTracker(obj, __FILE__, __LINE__); } |
|
393 #define CNT_TRACK_QOBJECTLIVES(objects) { foreach (QObject* object, objects) new CntQObjectTracker(object, __FILE__, __LINE__); } |
|
394 |
|
395 class CntQObjectTracker : public QObject |
|
396 { |
|
397 Q_OBJECT |
|
398 public: |
|
399 CntQObjectTracker(QObject *obj, QString fileName, int fileLine) { |
|
400 objectName = obj->metaObject()->className(); |
|
401 createdInFile = fileName; |
|
402 createdAtLine = fileLine; |
|
403 connect(obj, SIGNAL(destroyed()), this, SLOT(objectDestroyed())); |
|
404 connect(HbApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(reportMemoryLeak())); |
|
405 } |
|
406 public slots: |
|
407 void objectDestroyed() { delete this; } |
|
408 private slots: |
|
409 void reportMemoryLeak() { qDebug() << "MEMORY LEAK: The" << objectName << "object in" << createdInFile << "at line" << createdAtLine << "was never destroyed."; delete this; } |
|
410 private: // functions |
|
411 ~CntQObjectTracker() {} |
|
412 private: // data |
|
413 QString objectName; |
|
414 QString createdInFile; |
|
415 int createdAtLine; |
|
416 }; |
|
417 #else |
|
418 #define CNT_TRACK_QOBJECTLIFE(obj) |
|
419 #define CNT_TRACK_QOBJECTLIVES(obj) |
|
420 #endif |
|
421 |
|
422 // filter phonebook app traces |
|
423 #ifdef TRACE2FILE |
|
424 #include <QFile> |
|
425 #include <QTextStream> |
|
426 static void cntCustomLog2File(QtMsgType type, const char *msg) |
|
427 { |
|
428 QFile logFile("c:/cnt_logs.log"); |
|
429 if (!logFile.open(QIODevice::Append | QIODevice::Text)) |
|
430 { |
|
431 qFatal("error opening c:/cnt_logs.log file"); |
|
432 return; |
|
433 } |
|
434 |
|
435 QTextStream out(&logFile); |
|
436 switch (type) |
|
437 { |
|
438 case QtDebugMsg: |
|
439 out << "[CNT] Debug: " << msg; |
|
440 break; |
|
441 case QtWarningMsg: |
|
442 out << "[CNT] Warning: " << msg; |
|
443 break; |
|
444 case QtCriticalMsg: |
|
445 out << "[CNT] Critical: " << msg; |
|
446 break; |
|
447 case QtFatalMsg: |
|
448 out << "[CNT] Fatal: " << msg; |
|
449 abort(); |
|
450 break; |
|
451 default: |
|
452 out << "[CNT] No Log Selection Type: " << msg; |
|
453 break; |
|
454 } |
|
455 } |
|
456 #define MSG_HANDLER cntCustomLog2File |
|
457 #else |
|
458 #ifdef Q_OS_SYMBIAN |
|
459 #include <e32debug.h> |
|
460 static void cntCustomLog(QtMsgType type, const char *msg) |
|
461 { |
|
462 switch (type) { |
|
463 case QtDebugMsg: |
|
464 RDebug::Printf("[CNT] Debug: %s\n", msg); |
|
465 break; |
|
466 case QtWarningMsg: |
|
467 RDebug::Printf("[CNT] Warning: %s\n", msg); |
|
468 break; |
|
469 case QtCriticalMsg: |
|
470 RDebug::Printf("[CNT] Critical: %s\n", msg); |
|
471 break; |
|
472 case QtFatalMsg: |
|
473 RDebug::Printf("[CNT] Fatal: %s\n", msg); |
|
474 abort(); |
|
475 break; |
|
476 default: |
|
477 break; |
|
478 } |
|
479 } |
|
480 #define MSG_HANDLER cntCustomLog |
|
481 #else |
|
482 #define MSG_HANDLER 0 |
|
483 #endif // Q_OS_SYMBIAN |
|
484 #endif // TRACE2FILE |
|
485 |
|
486 #endif // CNTDEBUG_H |