logging
Moderators: hoijui, Moderators
logging
is there a way to suppress logging? my last game generated about 800MB in logs. if there isn't i'd like to nominate it for the todo list. perhaps passing the decision to log to the ai would be prudent.
I would also like to see a GotChatMsg method in the groupAI.
I would also like to see a GotChatMsg method in the groupAI.
Suppress logging? As in...the logging the debug header I sent you generated? Just comment out the output statements in void Send(). In general, you can set the AI-output threshhold in your game options. This corresponds to the IAICallback::SendTextMsg(msg,priority) - if your priority is higher than the option'd priority, then it will be ignored.
So, for the un-needed stuff, assign a lower priority. If you need, I can modify the debug header to take that into account (default 0, assign for your pleasure).
So, for the un-needed stuff, assign a lower priority. If you need, I can modify the debug header to take that into account (default 0, assign for your pleasure).
I use a macro in my AI such like:
So I'll be releasing two DLL's, one with the DOLOGGING defined to produce logs and one without.
Code: Select all
#ifdef DOLOGGING
#define LOG(a) GS->LogFile << a
#else
#define LOG(a)
#endif
What is GS? Also, a better solution (imo) is use inline functions (same functionality as #defines in this case, but safer) with default parameters. Inside the function, one could use a static that, based on the parameters (specified on, specified off, not-specified), could toggle logging on or off.Veylon wrote:I use a macro in my AI such like:So I'll be releasing two DLL's, one with the DOLOGGING defined to produce logs and one without.Code: Select all
#ifdef DOLOGGING #define LOG(a) GS->LogFile << a #else #define LOG(a) #endif
On second look - perhaps I misunderstood your comment and you'd meant two AI dlls (I was wondering why you were releasing logging dlls...doh...same suggestion though).
GS looks likes his global structure, just as I have G->L->print() to do similair things, G being the global structure and L the logging class.
I also have
L->open(bool plaintext=true) // if false then coloured plaintext logging is used
L->close()
L->print() //normal message
L->eprint() // exceptions errors etc
L->iprint() // print to console
L->gametime() // returns the gametime formatted in minutes hours and seconds rather than grame frame number.
All dealt with as std::string type.
edit:: oh and L->verbose() which if set to true outputs all logging to the screen
I also have
L->open(bool plaintext=true) // if false then coloured plaintext logging is used
L->close()
L->print() //normal message
L->eprint() // exceptions errors etc
L->iprint() // print to console
L->gametime() // returns the gametime formatted in minutes hours and seconds rather than grame frame number.
All dealt with as std::string type.
edit:: oh and L->verbose() which if set to true outputs all logging to the screen
The reason for using directives instead of inline functions is that with inline functions the code to write the logging is still compiled and when the function is called, it has to check to see whether the logging flag is enabled or not every time it comes up, costing a few CPU cycles. Not really a big deal, but that's why.
I don't think you understand what 'inline' means in C/C++. Find out here!. Using #define is equivalent to __forceinline...in most cases - #define is a string replacement call, which can have unintended (and unobvious) consequences that the compiler can not warn you about. By using inline, you indicated to the compiler the code 'should' be inlined (though it makes the final choice...unless you use __forceinline) while maintaining all the safety checks of normal function calls (better compiler feedback / debugger utilization).Veylon wrote:The reason for using directives instead of inline functions is that with inline functions the code to write the logging is still compiled and when the function is called, it has to check to see whether the logging flag is enabled or not every time it comes up, costing a few CPU cycles. Not really a big deal, but that's why.
Yes, but directives are applied before the code is compiled, so __forceinline never comes up. Thus:
Would convert to this with DOLOGGING defined:
and this without:
Whereas, with a inline function, it would go something like this:
and would be equivalent to this:
So that if statement would still have to be evaluated even if logging was disabled, costing a few insignificant CPU cycles.
I deliberately chose to use text replacement directives because of their flexibility as well as the fact that, if disabled, all logging code disappears entirely from the compiled DLL, costing no CPU cycles at run time.
As for debuggers, I haven't yet found any that work conveniently with a DLL or have I had any bugs that have been traced to my use of directives.
Code: Select all
int a;
LOG(a);
int b;
Code: Select all
int a;
GS->LogFile << a;
int b;
Code: Select all
int a;
;
int b;
Code: Select all
_inline void LogFunction(bool Logging = false, char *Text)
{
if(Logging)
GS->LogFile << Text;
}
...
int a;
LogFunction(true, "Stuff");
int b;
Code: Select all
int a;
if(Logging)
GS->LogFile << "Stuff";
int b;
I deliberately chose to use text replacement directives because of their flexibility as well as the fact that, if disabled, all logging code disappears entirely from the compiled DLL, costing no CPU cycles at run time.
As for debuggers, I haven't yet found any that work conveniently with a DLL or have I had any bugs that have been traced to my use of directives.
The compiler using version A or version B of the #define is irrespective of #define. It is based on the #ifdef - the same functionality exists with inline functions. For example, if I know I don't want my function to output anything in non-debug mode, then...
Same exact functionality, with none of the risks of #defines. I don't mean to sound like #defines are always a bad choice (there are some very cool and useful things one can do with them), but I think inline functions are more efficient, powerful, and safe in this case.
With that being said, one would need #defines to handle __LINE__ type macros in a meaningful, debug-oriented, way. For example...
Code: Select all
inline void MyLogFunc(string Msg, bool output=true)
{
#ifdef DebugMode
if(output) cout << Msg << endl;
#endif
}
With that being said, one would need #defines to handle __LINE__ type macros in a meaningful, debug-oriented, way. For example...
Code: Select all
inline void MyLogFunc(string Msg, int LineNum, bool output=true)
{
#ifdef DebugMode
if(output) cout << LineNum << ") " << Msg << endl;
#endif
}
#define DebugLog(a) MyLogFunc((a),__LINE__)
#define DebugLog(a,b) MyLogFunc((a),__LINE__,(b))