Wednesday, September 1, 2010

debugging tip

hi,

With some errors in Ax, I somethimes just don't know where to start debugging.
In those situations I use the call stack as a starting point to give me an idea on where to place breakpoints.

Here's what I do:


1 - create a new static method LAXGetCallStack in the Global class:
// this method returns the X++ call stack, the _offset is to skip entries at the top of the stack


client server static str LAXGetCallStack(int _offset = 0)
{
    #xppTexts
    container   callStack =    xsession::xppCallStack();
    int         k;
    int         lineNumber;
    str         entry;
    str         path;
    ;

    for (k = 1 + _offset ; k <= conlen(callSTack) ; k = k + 2)
    {
        path = conpeek(callStack,k);
        lineNumber = conpeek(callStack,k+1);
        entry += (entry ? #newline :'') + strfmt('-> %1 Line - %2', path, lineNumber);
    }
    return entry;
}


2 - modify the infolog.add method 
a - add this to the declaration section
    boolean     stackTraceActive;
    str         strInfoTxtToDebug;
    #xppTexts


b - add this at the beginning of the method (before switch(loglevel))
    stackTraceActive = true;
    strInfoTxtToDebug = 'debug';
    strInfoTxtToDebug = '*' + strInfoTxtToDebug + '*';

    if (stackTraceActive)
    {
        if (_txt like strInfoTxtToDebug)
        {
            _txt += #newLine + 'STACKTRACE for debugging:';
            _txt += #newLine + LAXGetCallStack(4);
        }
    }

If I get to investigate situations where the only clue is some strange info/warning/error, I use (a specific part of) the text of the infolog as a condition to in the infolog.add method to get the stacktrace an thus the calling objects.

This can be improved by making the stackTraceActive variable a user settable parameter. 
The same goes for the strInfoTxtToDebug variable.

No comments:

Post a Comment