ADFLogger: Using a Custom Formatter Class to Print Log Messages

Based on some posts on the OTN JDeveloper forum this article shows how to implement a custom fdormatter class to use with ADFLogging and how to integrate it with the embedded WLS instance in JDeveloper. Sample workspace for the custom logger is available at the end of the article.
For this post I assume you now your way around java.util.logging. I show how to implement a custom formatter class to format the log messages with more information and a different style. The picture below shows the general java logging model:

General Logging Model

General Logging Model


As the model shows the formatter is used by the log handler which gets a log record and processes it by piping the record through a filter and then through a formatter to finaly pass it to the attached output target. In most cases the output target is a file, a db table, a system log or a stream. For the console logger its most often a stream (e.g. stdout and/or stderr).

A typlical JDev log message from the ConsoleFormatter looks like this:

<AdfcAppInitializer> <loadDebugFacades> ADFc: Initializing ADF Debugger

I’ll change this to:

FINE: 22.09.2011 13:18:17 - de.hahn.blog.popupregion.backingbeans.pageflow.SelectionBean$beaVersion0_39.selectionListenerEmp(SelectionBean.java:92) - 15 - de.hahn.blog.popupregion.backingbeans.pageflow.SelectionBean
  Selected: oracle.jbo.Key[105 ]

The general layout of the log message is

data in [] is customizable, data in {} is printed only if available
level: date time [- threadId] [- class] [- method] [- message] {- throwable.message}
These parameters configure which information to print
       t = thread
       n = logger name
       l = line number; if 'l' is selected 'c' and 'm' are not used
       c = class name
       m = method name

As you see there is more information printed, e.g. source and line number and log level. As this creates long log lines I made this customizable. How the parameters are passed to the logger is shown later.

First of all I implement a class DebugFormatter which extends java.util.logging.SimpleFromatter as this class is an implementation of the abstract class java.util.logging.Formatter the base of all formatter attached to a log handler. The key part of this class is the method

public String format(LogRecord record) {...}

which gets a log record and returns a string of the information which send to the handler for further action. The format method checks the parameters given and returns a string according to them.

To wire things up I modify the logging.xml file which can be reached from the ‘Application Server Navigator’. Right click on the integrated WLS and select ‘Configure Oracle Diagnostic Logging for …’. This will open a nice graphical overview

Logging.xml

Logging.xml


Now I add a new logger by clicking the green ‘+’ sign and specifying the log level and the name of the logger, which is actually the part of the class path the logger reacts on.
Add  Logger

Add Logger


this creates a new line in the logging.xml file looking like
Added Line

Added Line


Next I set up a new log handler in the logging.xml file which uses my DebugLogger class as formatter. Together with the log handler I specify the parameters which configure the output format of the string. The DebugLogger is not used directly, but instead a wrapper class WLSConsoleFormatter used which specifies default parameter set to the DebugFormatter. This way you can omit the parameters in the setup. Below is the resulting log handler entry in the logging.xml file:

        <log_handler name='blog-console-handler'
                     class='de.hahn.blog.consoleformatter.logger.BlogConsoleHandler' level='ALL'
                     encoding='UTF-8'>
            <property name='formatStyle' value='tnlcm'/>
            <property name='formatter'
                      value='de.hahn.blog.consoleformatter.logger.WLSConsoleFormatter'/>
        </log_handler>

To add this you need to change to the source view for the logging.xml file.
Finally I change the added logger to use the new handler

        <logger name='de' level='TRACE:1' useParentHandlers='false'>
            <handler name='blog-console-handler'/>
            <handler name="odl-handler"/>
        </logger>

I have to set the useParentHandlers to false to prevent that the messages get printed multiple times. To be able to analyze the messages with the log analyzer I add the ODL handler too. Now all log messages are printed to the console and to the ODL logger.

Now that the logger are setup in the logging.xml all I need to do is to make the classes available to the WLS instance. For this I build a jar from the project and put the resulting BlogConsoleFormatter.jar in a folder where WLS picks it up while starting. There a a couple of folder, but I choose <ide.system.dir>/DefaultDomain/lib folder. ide.system.dir is also known as the systemfolder of your JDeveloper installation. If you don't know where to find it check this blog. You can either copy the jar into the folder or setup the deployment profile to generate the jar in this folder.

Sample Oiutout

Sample Oiutout

The picture above show a small code sample with the generated output from DebugFormatter. As you see the log lines are marked as links. If you click on such a line you see that you are transfered to the code location of the message.

You can download the source code for the BlogLogConsoleFormatter.zip and a BlogPopupRegion.zip using the ADFLogger to generate messages in different log levels. After downloading the files you need to remove the ‘.doc’ suffix and rename them to ‘.zip’ as the files are normal zip files.
The sample workspaces are developed with JDeveloper 11.1.2.0.0, BlogPopupRegion uses the HR schema as DB connection.

About these ads

10 thoughts on “ADFLogger: Using a Custom Formatter Class to Print Log Messages

  1. Hi Timo,

    Great Job Done…
    Thanks a ton…. I was waiting for this post of yours……. you have shown us how to format log for console handler will it work for odlhandler (and other file handlers) and how??

    • In theory you can do something similar with the ODL handler, but you should not. The ODL handler collects many more information and uses an XML format which. is later shown to the user via the ‘Log Analyzer’. This is more like an XML transformation then to change the output format.
      However, you can write the output of a custom logger in a file so that you get the log in a format you want.

  2. Hi Timo,

    I see a class “BlogLogger” in bloglogconsoleformatter.zip. Can I use that class to create logs without modifying logging.xml? If so, how and when to call that getInstance() method?

    Thanks,
    Sriya

  3. Hello Mr. Hahn,
    Thanks for your great post, very usefull.

    I wrote a custom log handler using your example. I would like to have access to not only the ADF Message (of oracle.jbo, oracle.adf and oracle.adfinternal), but also to the ADF Message data, as seen in the ADF Request Logger in JDeveloper, see https://blogs.oracle.com/groundside/entry/adventures_in_adf_logging_part4 (screenprint just under section ‘But Wait, There’s More’). I tried several ways, but I dont see how how it is possible to get access to that data when i’m in the custom LogHandler. I still have valuable data, but only half of what should be possible. Do you pease have any suggestions ?

    • Frank,
      I see this as part of the analyze function. Here you use information from different log records to genders the info you see if you select ‘by ADF record’.
      As all loggers use java.util.logging as framework I’m not sure how you would access this kind info when writing one log message.

      Timo

  4. Pingback: Customize ADF Logger with IP and Username information | SOLARKID.INFO

  5. Hi,
    Very nice post.
    However, I’ve got an error message when I attempt to change the level of the logger on the fly.
    Weblogic doesn’t find anymore the jar and its classes. Could you help me ?
    But if you don’t change the level, it works perfectly !

    Thanks,
    Christophe

    • Somehow the class loader looses track of the jar. Seen this in one instance too. I never found out exactly why. Solution was to add the library to the start class path of the WLS. For this you can change the start environment (e.g. setDomainEnv.cmd for windows) and add a line like
      set CLASSPATH=%CLASSPATH%;
      Then the jar will we part of the startpath and the class loader will pick it up and keep it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s