Power Pivot

To investigate performance problems in WDK applications I typically use capabilities of com.documentum.web.env.IFormRenderListener interface, the code below demonstrates a basic idea – when page starts rendering I put date into form return value and when page rendering gets finished I gather and log required information:

/**
 * @author Andrey B. Panfilov <andrew@panfilov.tel>
 */
public class FormRenderLogger implements IFormRenderListener {

    private static final String FORM_RENDER_LOGGER_START_DATE = "__FORM_RENDER_LOGGER_START_DATE__";

    public FormRenderLogger() {
        super();
    }

    public void notifyFormRenderStart(Form form) {
        form.setReturnValue(FORM_RENDER_LOGGER_START_DATE, new Date());
    }

    public void notifyFormRenderFinish(Form form) {
        Date startDate = (Date) form
                .getReturnValue(FORM_RENDER_LOGGER_START_DATE);
        form.removeReturnValue(FORM_RENDER_LOGGER_START_DATE);
        long diff = new Date().getTime() - startDate.getTime();
        String containerId = null;
        String componentId = null;
        ArgumentList initArgs = null;
        Context context = null;
        if (form instanceof Container) {
            containerId = ((Container) form).getId();
            componentId = ((Container) form).getContainedComponentId();
            initArgs = ((Container) form).getInitArgs();
            context = ((Container) form).getContext();
        } else if (form instanceof Component) {
            componentId = ((Component) form).getComponentId();
            initArgs = ((Component) form).getInitArgs();
            context = ((Component) form).getContext();
        }
        String userName = null;
        try {
            if (ComponentDispatcher.isRepositoryAccessRequiredComponent(form
                    .getId())) {
                IDfSessionManager sessionManager = SessionManagerHttpBinding
                        .getSessionManager();
                if (sessionManager != null
                        && SessionManagerHttpBinding.getCurrentDocbase() != null
                        && sessionManager.hasIdentity(SessionManagerHttpBinding
                                .getCurrentDocbase())
                        && form instanceof Component) {
                    userName = ((Component) form).getDfSession()
                            .getLoginUserName();
                }
            }
        } catch (DfException ex) {
            throw new WrapperRuntimeException(ex);
        }
        StringBuilder message = new StringBuilder(50);
        if (containerId != null) {
            message.append("Container: ").append(containerId).append(", ");
        }
        if (componentId != null) {
            message.append("Component: ").append(componentId).append(", ");
        }
        if (userName != null) {
            message.append("User: ").append(userName).append(", ");
        }
        if (initArgs != null) {
            message.append("InitArgs: ").append(initArgs).append(", ");
        }
        if (context != null) {
            message.append("Context: ").append(context).append(", ");
        }
        message.append("Remote IP: ")
                .append(form.getPageContext().getRequest().getRemoteHost())
                .append(", ");
        message.append("Render time: ").append(diff).append("ms");
        DfLogger.debug(this, message.toString().replaceAll("\\{", "[")
                .replaceAll("\\}", "]"), null, null);
    }

}

app.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<config>
 <scope>
  <application extends="webtop/app.xml">
   ...
   <listeners>
    ...
    <formrender-listeners>
     <listener>
      ...
      <class>FormRenderLogger</class>
     </listener>
    </formrender-listeners>
   </listeners>
  </application>
 </scope>
</config>

Something similar was described earlier by Stephane Marcon in Documentum Monitoring – platform logs’ centralization using Logfaces – Part 2, but the problem is logs accuracy of webtop logs collected by Stephane completely suck. Though, code, given above, does not provide information about delays caused by wdk actions, you can take advantage of IFormRenderListener, IApplicationListener and IRequestListener interfaces to implement more robust solution (see example of usage in Dynamic groups. Advances. Part IV).

But yesterday I have faced with a weird problem. Typically I parse performance logs into tab-delimited file, then load this file into excel and build some reports to figure out what wdk components are slow. But yesterday I have found that customer’s daily logs contain more than 3 million rows and Excel does not support such a amount of data. What to do? Power Pivot comes to the rescue!