Thursday, October 20, 2011

Get Infolog details from code

On the Dynamics AX Community forums, the question was asked how to get detailed information on the type, message and prefixes of messages in the infolog. The original post can be found here. This type of code usually happens in modifications that need to somehow keep a log of sorts, so that the infolog details can be retrieved from somewhere even after a user has closed the infolog screen.

Well, it all revolves around containers. The infolog class has a "copy" and a "cut" method that return the contents of the infolog, in container form. The elements in the container are containers themselves, each one corresponding to a line in the infolog. So you get the container, loop over it, and for each iteration you can grab the sub-container and extract the details like the exception type, action class, helptext, etc.

I guess a code sample says more than a thousand words:

static void InfologParse(Args _args)
{
    container   infologCon, infoline;
    Exception   exception;
    int         i;
    str         message;
    str         helpURL;
    ClassName   actionClassName;
    container   actionClassOptions;
    ;

    // Put test data in infolog
    setPrefix("First Prefix");
    error("test error");
    warning("test warning");
    
    setPrefix("One more level");
    info("infolog!");
    
    // Get the infolog data and clear the messages (cut)
    infologCon = infolog.cut();

    for(i=1; i<=conLen(infologCon); i++)
    {
        infoline = conPeek(infologCon, i);

        exception = conPeek(infoline, 1);
        message = conPeek(infoline, 2);
        helpURL = conLen(infoline) > 2 ? conPeek(infoline, 3) : '';
        if(conLen(infoline) > 3 && conPeek(infoline, 4))
        {
            actionClassName    = classId2Name(conPeek(infoline, 4));
            actionClassOptions = conPeek(infoline, 5);
        }

        info(strFmt("Type: %1; Prefix: %2; Message: %3",
            exception,
            // replace the \t by / so we can see all prefixes
            strReplace(message, '\t', '/'),
            // copy the message from the last occurance of the \t to the end
            subStr(message,
                strScan(message, '\t',
                strLen(message),
                -strLen(message)) + 1,
                strLen(message))));
    }
}


4 comments:

  1. Another approach (result is not exactly the same, but I don't want to complicate the example):

    SysInfologEnumerator enumerator;
    SysInfologMessageStruct msgStruct;
    Exception exception;

    enumerator = SysInfologEnumerator::newData(infolog.cut());
    while (enumerator.moveNext())
    {
    msgStruct = new SysInfologMessageStruct(enumerator.currentMessage());
    exception = enumerator.currentException();
    info(strFmt("Type: %1; Prefix: %2; Message: %3",
    exception,
    msgStruct.preFixTextElement(1);
    msgStruct.message()));
    }

    ReplyDelete
    Replies
    1. There is an extra ";" in Martin's reply here: msgStruct.preFixTextElement(1);

      And replace "infolog.cut()" with "inflog.copy(1, infolog.line())" if you want the infolog to display. I want to use Martin's method to display in the batch log, but also send specific emails and logging.

      Great post!

      Delete
    2. Great..! It really helped me. Thanks Martin.

      Delete
  2. Hi Joris, Congratulations for post! You help me, a very long time ago I'd wanted make this code.
    Thank you!!!

    ReplyDelete