|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic |
Last Thread Next Thread ![]() |
| Controlled debug logging even in Release |
|
![]() Archimage Member since: 10/10/2002 From: Ashbourne |
||||
|
|
||||
| I already use my own design of Logger class for all my logging requirements during debugging. In the past I have made it dependant on an '#ifdef _DEBUG' system to have it removed in the Release build (I know, there are better ways than #ifdef's scattered through the code). What I really would like though is to be able to leave it in, but only have it active in special circumstances (not decided yet, but maybe via a -debug command-line, holding Shift on Program start-up to get an Advanced Configuration page, adding a Debug=1 line to a CFG file, or something similar). The idea is that when a user has a problem with the software, Tech Support can tell them how to activate Logging/Reporting (maybe for a particular section eg Video), and the resulting file is sent to Tech Support. On the flip-side though, I don't want to lose a lot of cycles each time testing an internal 'bool _Logging' flag just to see if I should write out via the Logger class. Is there a good way for still keeping the ability in the program, but not inefficiently checking the Logging state at every place where data would be written out if Logging was on? On a similar note, a lot of modern programs generate an error report (call-stack etc) when there is a problem. How do you get call-stack data from Windows? Yours, Archimage (Ann-Marie Ratcliffe) |
||||
|
||||
![]() fredizzimo Member since: 10/9/2000 From: Helsingfors, Finland |
||||
|
|
||||
| Put the #ifdef in the Debuglog code instead of scattering it around. You could either have a DEBUGLOG define that calls your debuglog function if logging is enabled, or does nothing if it isn't. Or you could have it disable all functionality if it's disabled, so it generates empty functions, that will be optimized away, especially if they are inlined. Also you could have a define USEDEBUGLOG or something like that, that either enables or disables the log. Or you could even have some priority flag passed in that enables only important logging in Release. There's many options, use what makes sense in your project. |
||||
|
||||
![]() Archimage Member since: 10/10/2002 From: Ashbourne |
||||
|
|
||||
quote: For removing it totally from the Release version, I agree with you, but thats not what I'm looking for. I want it 'hidden' in the Release version, but if activated (via one of the options above, by the User following Tech Support's instructions), it would then produce a verbose Log-file which could be sent across e-mail, or be sent to a bug-tracker web-page etc. What I don't want is to have my Release's speed wrecked by continual checks of a '_Logging' flag every time there is a possible Log entry. I'm trying to find a way to work round it. One thought I had was to have two DLL's (one which contained the Logger, one which contained the same but with empty/basic members) and then use LoadLibrary at the start depending on the _Logging flag, but maybe thats worse. Hope you see where I'm coming from, Yours, Archimage (Ann-Marie Ratcliffe) [edited by - Archimage on May 11, 2004 7:24:47 PM] |
||||
|
||||
![]() fredizzimo Member since: 10/9/2000 From: Helsingfors, Finland |
||||
|
|
||||
| Oh yes, I see. The easiest and cleanest way would probably be to have a base class, and at least two derived classes, one that does debugging and one that doesn't. Then use standard polymorphism and virtual functions, for the correct behaviour. A function inside a dll wouldn't be inlined, so there's a function call, so the overhead of using virtual functions is almost none compared to that. |
||||
|
||||
![]() Xai Member since: 10/15/1999 From: Nashville, TN, United States |
||||
|
|
||||
| yeah, you're basically wanting aspect oriented programming behavior (or polymorphic behavior depending on your view) - but the problem is: all such methods cost about as much as a branch (the if you don't want to use). the normal #ifdef system causes the code to not be compiled in, at maximum possible efficieny, but 0 run time flexibility. the opposite end of the spectrum is always calling a log function, but having it do an IF internally based on some shared global (and therefore would need to be THREAD SAFE and SLOW if your program has more than 1 thread) control variable. every other system is basically just an attempt to optimize the above system for better run time performance in the case where no logging needs to be done. |
||||
|
||||
![]() Skizz Banned Member since: 1/31/2003 From: United Kingdom |
||||
|
||||
| The only thing I can think of that will give the best performance is to have two versions of the program: a pure release version and a release with logging version. You'd probably put the majority of the program in a DLL and have a small loader program that selects the required DLL to load. It wouldn't be hard to set up a build system that produces both versions of the DLL. Skizz |
||||
|
||||
![]() Zanthos Member since: 9/29/2001 From: Blackpool |
||||
|
|
||||
| Why not have a purely abstract class called LoggerInterface, then have two log classes, DummyLogger and DebugLogger. DummyLogger simply returns from every call you make to it without doing anything, and DebugLogger actually does the debug logging. This way at the start of your program you can have: myDebugLogger : ILoggerInterface; if (debuggingEnabled) myDebugLogger := TDebugLogger.Create else myDebugLogger := TDummyLogger.Create; and then in your code you can use.. myDebugLogger.writeWarningString('Oh dear its broken'); It's neat and effective, and about as efficient as you can get without doing two recompiles. "You are in a room. You can see a cow." ">look at cow" "It is a cow." .:Cubicle2:. [edited by - Zanthos on May 12, 2004 6:51:35 AM] |
||||
|
||||
All times are ET (US)![]() |
Last Thread Next Thread ![]() |
|