Developing exteNd Director Applications

CHAPTER 15

Logging Information

This chapter provides information about logging information in exteNd Director applications. It has the following sections:

 
Top of page

About the exteNd Director logging facility

exteNd Director provides a runtime logging facility that writes information in one of several standard logs or in your own custom logs. You decide what level of detail you want in the logs. The output of the logs displays on the server console.

In addition to the standard logging facility, exteNd Director includes two logging providers that let you generate:

For more information    For more information, see Using the XML and IPDR Logging Providers.

 
Top of section

Uses for logging

In your application code, you can log all kinds of information. Uses for logging include:

If you use analysis tools to study your Web site usage, you can write the log in a format expected by the tools.

 
Top of section

What gets logged

Various classes in exteNd Director send status and information about errors to one of the standard logs. In addition, in your code you can instantiate a log variable for one of the standard logs or for your own log and write information to it.

Available logs

exteNd Director provides a log for each of the main packages. You can create additional logs in your application code when you get a log from EboLogFactory by specifying your own log identifier. The messages for all the logs are sent to the server console.

Package

Log identifier

Purpose of log: messages from the

com.sssw.cm

CM

Content Management subsystem

com.sssw.fw.directory

DIRECTORY

Directory subsystem

com.sssw.fw

FW

Framework subsystem

com.sssw.portal

PORTAL

Portal subsystem

com.sssw.re

RE

Rule subsystem

com.sssw.search

SEARCH

Search subsystem

com.sssw.fw.security

SECURITY

Security subsystem

com.sssw.fw.usermgr

USER

User subsystem

com.ssw.wf

WF

Workflow subsystem

Detail levels

exteNd Director supports four detail levels that determine how much information is written to the log. These detail levels are defined as constants on the EbiLog interface. Framework classes only send messages to the log that are at or below the current detail level. When you write the log you specify a detail level—and if the log's detail level is lower than the message being logged, the message does not appear.

Detail level name

Value

Description

DEACTIVATE_LEVEL

0

Nothing is written to the log

CRITICAL_ERROR_LEVEL

1

Critical errors are written to the log

ERROR_LEVEL

2

Unexpected errors are written to the log

WARNING_LEVEL

3

Expected errors are written to the log

INFO_LEVEL

4

Informational messages written to the log

TRACE_LEVEL

5

Debugging messages and messages about application progress are written to the log

You can change the detail level for a log in the DAC or in your exteNd Director application. For information about code that changes the level, see Setting the detail level.

Information in the log

The information in the logs has this format:

  logname | detail-level | time | thread | message

Here the separator is a vertical bar. You can change the separator character. For example, if you want to export the log to a spreadsheet, you could create a tab-delimited or comma-delimited log.

 
Top of section

Configuring the logs

In the DAC, you can specify the detail level for each of the logs, including your custom logs. You can also define your own custom logs by adding several entries to the config.xml for the target subsystem. For example, you could add a custom log called MyLog to the Portal Web tier by adding the following property settings to the config.xml for your application:

  <property>
   <key>MyLog.LoggingLevel</key>
   <value>3</value>
  </property>
  <property>
   <key>MyLog.LogFieldSeparator</key>
   <value>|</value>
  </property>
  <property>
   <key>MyLog.LoggingProvider</key>
   <value>com.sssw.fw.log.EboStandardOutLoggingProvider</value>
  </property>

You can also change log settings in code. For information, see com.sssw.fw.api.EbiLog and Using logs in your application next.

 
Top of page

Using logs in your application

Some of the file generation wizards in exteNd Director include logging code. For example, when you create a new portlet using the Portlet Wizard, logging code is automatically added to the source code. The code gets a log object and writes messages at the trace level for each method. You can modify this code to get a different log. You can add logging statements that report exceptions that have been caught or that log information about the application's status. This section describes the code you would use.

 
Top of section

Logging and scoped paths

You can use the exteNd Director scoped paths feature to access logs within pageflow and workflow applications.

For more information    For more information, see Working with Scoped Paths and XPaths.

 
Top of section

Logging API

The Logging API includes these classes:

 
Top of section

Getting a log

To get a log object for one of the standard logs, use code like this:

  import com.sssw.fw.log.*;
  EbiLog log = EboLogFactory.getLog(EboLogFactory.PORTAL);

To create a unique log of your own, specify the log name as the argument:

  import com.sssw.fw.log.*;
  EbiLog log = EboLogFactory.getLog("WebAppLog");

It will use the default settings, which you can change with EbiLog methods:

 
Top of section

Setting the detail level

At any point in your code you can check or change the logging level for a log. Any changes affect future logging until the setting is changed again in code or in the DAC. For example, to set the logging level to trace, you would need to add this line of code:

  log.setLoggingLevel(EbiLog.TRACE_LEVEL);

NOTE:   The logging level must be set to trace if you want to see logging messages for a portlet that is generated by the Portlet Wizard, or any other wizard that generates logging code.

You can check the current level with isLevel() or one of the methods that check specific levels:

  boolean traceOn = log.isLevel(EbiLog.TRACE_LEVEL);
  boolean traceOn = log.isTrace();

For efficiency, it is useful to check the level before logging a message, described next.

 
Top of section

Adding messages to the log

When you write code that sends a message to the log at a particular detail level, the message is logged only if the current detail is at that level or lower. If the detail level is CRITICAL_ERROR_LEVEL, when the application runs and calls trace() the message won't be logged.

Because messages won't always be logged, you can avoid the inefficiency of instantiating strings that won't be used by checking the detail level for logging the message.

For example, log.isCritical(), the lowest logging level, returns true for this logging level and higher, so critical messages are always written to the log unless logging is off.

log.isError() returns true for ERROR_LEVEL and higher, so error-level messages are logged unless the level is set to CRITICAL_ERROR_LEVEL.

To accept all logging, set the level to TRACE_LEVEL, the highest and most verbose logging level.

Logging messages

To log a message at a specific detail level, you can call the method for that level:

  if (log.isTrace() ) 
  {
     log.trace("Portlet returned content type: "       + request.getContentType() );
  }

In a catch block, you could log the error like this:

  catch (EboException e)
  {
     log.error("General portal exception:" 
        + e.printStackTrace(context.getLocale()) );
  }

You can also call the generic logString() method and specify the level:

  log.logString("message", EbiLog.ERROR_LEVEL);

Broadcasting a message to all logs

You can send a message to all logs with the broadcast() method of EboLogFactory. You might use this when you want to set a mark in logs when conditions change so that you can note changes in application behavior:

  EboLogFactory.broadcast("Application going into production now!");

The broadcast is sent at the critical error level so it will appear unless logging is deactivated. The message will appear once for each log.

Logging session information

You can identify individual sessions by including the user's ID as part of the log message. For example:

  log.error(request.getUserPrincipal(getName() + log.getLogFieldSeparator() 
     + "General portal exception: " 
     + e.printStackTrace(context.getLocale()) );

 
Top of section

Sample logging code for portlets

This section shows some sample logging code that could be used in a portlet application.

Logging for tracing and debugging

If you want to use logging to observe the execution of your portlet application, you might instantiate a PORTAL log like this:

  EbiLog log = com.sssw.fw.log.EboLogFactory.getLog(
    com.sssw.fw.log.EboLogFactory.PORTLET);
    

The portlet code can generate content at the trace level and can log any caught exceptions at the error level. This example shows logging in the portlet doView() method:

  public void doView( RenderRequest request, RenderResponse response )  throws PortletException, java.io.IOException {                                                            
   	         
     try {
        PortletURL renderUrl = response.createRenderURL();
        renderUrl.setPortletMode( PortletMode.VIEW );
                        
        response.setContentType(
            EbiPortletConstants.MIME_TYPE_HTML );
        PrintWriter writer = response.getWriter();
  
        // Build the screen of HTML, set it as the content
        StringBuffer sb = new StringBuffer();           
              
        // Output code goes here
        sb.append( "View Mode" );
        sb.append( "<br></br>" );
            
       writer.print( sb.toString() ); 
     } 
          
     catch (EboUnrecoverableSystemException e)
     {
        ... // code to respond to error
        // Error string replaces portlet content
        sb.replace(0, sb.length(), 
           "msg describing what user should do");
        if (log.isCritical()) {
           log.criticalError(this.getPortletName() 
              + " : Bad system error \n" + e.printStackTrace() );
        }
     }
  
     catch (EboApiException e)
     {
        ... // code to respond to error
        if (log.isError()) {
           log.error(this.getPortletName() 
              + " : framework error \n" + e.printStackTrace() );
        }
     }
     catch (EboFactoryException e)
     {
        ... // code to respond to error
        if (log.isError()) {
           log.error(this.getPortletName() 
              + " : factory exception \n" + e.printStackTrace() );
        }
     }
     catch (RuntimeException e)
     {
        ... // code to respond to error
        if (log.isWarning()) {
           log.warning(this.getPortletName() 
              + " : runtime exception \n" + e.printStackTrace() );
        }
     }
      catch ( Throwable e ) {
        // Log other errors generated
           log.error(e);
           new PortletException( e );
         }
   }

Documenting portal usage in a log

If you want to collect data about the clients your users use and the pages they access, you could add this information to an APP_USAGE log, as shown in this example:

  // Instantiate the log 
  EbiLog log = com.sssw.fw.log.EboLogFactory.getLog(APP_USAGE);
  // log data in this format:
  // currentpage!browsername!browserversion!platform!callingpage
  
  java.util.Map browserinfo = context.getBrowserInfo();
  StringBuffer sb = new StringBuffer();
  
  sb.append(context.getURI() );
  sb.append("!");
  sb.append(getMapValue(browserinfo,
            EboRequestHelper.BROWSER_NAME));
  sb.append("!");
  sb.append(getMapValue(browserinfo,
            EboRequestHelper.BROWSER_MAJOR_VER));
  sb.append("!");
  sb.append(getMapValue(browserinfo, EboRequestHelper.PLATFORM));
  sb.append("!");
  sb.append(context.getCallingPage() );
  
  if (log.isInfo())
  {
     log.info(sb.toString() );
  }
  // Private method to get browser information from the Map object:
  private String getMapValue(Map map, String key)
  {                                                                              
     String val; 
     if (map.containsKey(key))
     { 
        val = (String) map.get(key);
     } 
     else
     {
        val = "";
     }
     return val;                                                                  
  } 


Copyright © 2004 Novell, Inc. All rights reserved. Copyright © 1997, 1998, 1999, 2000, 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved.  more ...