Understand messaging and logging in ICN

In this post, I’ll explain how messaging and logging work in ICN and how to use them to give meaningful information to users and developers.

First, what’s the difference between messaging and logging? Messaging means showing information to the user. These information are meaningful to them and have to be shown to all users.

Logging means persisting information to track the application execution. These information are not supposed to be shown to users. They help tracking defects more quickly.

Messaging

In ICN, the Messaging mechanism is built on the top of the Message class, which has as twin brother the com.ibm.ecm.json.JSONMessage object in Java on the server side. You have 2 main ways to display these messages in the out-of-the-box ICN:

  • The MessageBar at the bottom of the desktop
  • The ErrorDialog as an overlay

The way ICN works with services is: all returned messages are added to the desktop with the addMessage function, then depending of the level, they go either in the MessageBar or as a ErrorDialog. This is how to add a message to the desktop and therefore display it to the user:

ecm.model.desktop.addMessage(new Message({
    number: 0,
    level: 0, // The level of the message: 0 = information, 1 = warning, 2 = error.
    text: "Your text",
    explanation: "", // Optional, not use by the MessageBar but used by the ErrorDialog
    userResponse: "", // Optional, not use by the MessageBar but used by the ErrorDialog
    adminResponse: "", // Optional, not use by the MessageBar but used by the ErrorDialog
    moreInformation: "", // Optional, not use by the MessageBar but used by the ErrorDialog
    backgroundRequest: "", // Optional, default is false
}));

Both the MessageBar and the ErrorDialog are connected to the addMessage function of the desktop. The message bar displays all messages of level 0 (information) if their number are not in its exclude list (it’s empty by default but you can add excluded numbers by pushing them into the excludeMsgNumbers attribute of the MessageBar). If you want to add an excluded number to the MessageBar, there is no easy way to get it. I found that one:

/**
 * @return {ecm.widget.MessageBar} the MessageBar if found, <code>null</code> otherwise
 */
getMessageBar: function () {
    var i, children = ecm.model.desktop.getLayout().mainPane.getChildren();
    for (i = 0; i < children.length; i++) {
        if (children[i].declaredClass == 'ecm.widget.MessageBar') {
            return children[i];
        }
    }
    return null;
}

The ErrorDialog displays all message of level >= 2 (errors) and where backgroundRequest is false.

If you don’t want to deal yourself with displaying information to the user when returning information from your service. You can use the built-in mechanism. That means in your service, instantiate a JSONResponse then add messages to it and finally serialize that into the response’s output stream:

JSONResponse jsonResults = new JSONResponse();
JSONMessage msg = new JSONMessage(0, "Main Text", "Explanation", "userResponse", "adminResponse", "moreInformation");
jsonResults.addErrorMessage(msg);
jsonResults.addInfoMessage(msg);
jsonResults.addWarningMessage(msg); // Exist but won't be shown neither by the MessageBar nor the ErrorDialog
jsonResults.serialize(response.getOutputStream());

Your messages will be translated into ecm.model.Message and be added to the desktop by the ICN JavaScript API, meaning shown by the MessageBar or ErrorDialog depending on the message level.

 

Logging

Log on the server side

Logging into your plugin can be done using the com.ibm.ecm.extension.PluginLogger object given by the callbacks.getLogger() method.

Get the logger:

PluginLogger log = callbacks.getLogger();

Then use it

log.logEntry(this, "myMethod");
log.logDebug(this, "myMethod", "This is debug");
if (log.isDebugLogged()) {
    log.logDebug(this, "myMethod", "This is a complicated debug with" +
         " object " + object + " that we don't want to compute if not necessary");
}

To makes this easier, I prepared for you a bunch of Eclipse Java templates to insert log statements into your code.

That will look like that, and will take care of filling the method name and make test for debug and info level, that you can delete if you pass
a simple string, but should keep if you have to compute your log message.

Eclipse_PluginLogger_templates

Consult log on the server

To see logs you are generating in your service, you just need to activate the logs in the ICN admin desktop. Go to Settings > Logging tab and choose the level of log you want.

You should also specify a package, especially in DEBUG level or the log will grow really fast. For instance, fill the filter with: com.company.your.package.*

Then logs can be seen in the application server file. For Websphere, with a default installation, it will be /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/logs/server1/SystemOut.log.

This file will rotate really often if you are logging a lot of information so I would recommend you to increase the max size in your application server console. For WAS, it is under Troubeshooting > Logs and Trace > server_name > JVM Logs and change the File Size under Log File Rotation.

WAS_Logs_rotate_size

I usually keep a ssh session with a tail -f command running so I can see in real time what is going on. This, along with the JavaScript log (see below), it gives you a good outlook of what’s happening on your platform.

ICN_DEBUG_both

If you don’t have access to the server’s file system because you are not the one administrating the platform, usually logs can also be consulted from the console. For instance in WAS it is under:

Troubeshooting > Logs and Trace > server_name > JVM Logs > Runtime tab and choose your file and click View

Log on the client side

To log on your client JavaScript, just inherit from the ecm/LoggerMixin class.

define([
    "dojo/_base/declare", "dojo/_base/lang", "ecm/LoggerMixin"
], function (
    declare, lang, LoggerMixin
) {
    return declare([LoggerMixin], {
        // Here you can use all logger functions (see below)
    });
});

Then you can use the following function:

this.logInfo(yourfunctionname, message, extra);
this.logWarning(yourfunctionname, message, extra);
this.logError(yourfunctionname, message, extra);
this.logDebug(yourfunctionname, message, extra);
this.logEntry(yourfunctionname, message):
this.logExit(yourfunctionname, message):

Consult log on the client

To see the logs log by the client, the documentation advise to use the argument ?debug=true in the URL. However I wouldn’t recommend that because with the debug option you will loose access to your code using the debugging tool. See this post for more information.

I think it’s best to use ?logLevel=4 because it does not mess with the debugger tool and you can still access your class using the Ctrl+P shortcut (in Chrome). Levels are the following:

  • 0: None (This level indicates no logging.)
  • 1: Error
  • 2: Warning (This level is the default logging level.)
  • 3: Information
  • 4: Debug

If you wish, you also have an option useConsole=false/true to force the use of a popup instead of the console.

Leave a Reply