Saturday, May 22, 2021

Customizing log4j in Sterling OMS

Introduction:

Logging is very important part of any application. It helps you detect issues and provide more information for triaging. IBM Sterling OMS application uses log4j utility for logging. The log4j utility writes trace and debug information to a log file.

As per your business requirements, you can modify the logging parameters in the log4j configuration file to control the location and level of the log files. You might want to send Application/Agent/Integration server logs to different locations. You might also have Custom java classes with loggers to capture the logs.

In this post, we will see how we can customize log4j as per our requirements.

Default Behavior:

By Default, product refers to yfs.properties file for log4j configuration property.

log4j.configuration=/resources/log4jconfig.xml

In log4jconfig.xml file, default file path would like:

<param name="file" value="<sterling_home>/logs/sci.log" />

So, if you enable the trace for any OOTB API then it will be written in sci.log file. It will be rotated based on other parameters given in the file. If you want to customize log4j then follow the steps below.

The SCIAppender is an implementation specific to the Sterling product and extends log4j's capabilities of where to write the logging statements to.

You can configure the logger to send different categories of messages to different destinations. Categories are organized hierarchically, which permits inheritance. Each category can be configured with a priority indicating a severity level. If a category is not configured with a priority, it inherits the priority of its closest ancestor with an assigned priority.

Steps to customize log4j:

1.       Copy the application-provided log4jconfig.xml file

from <sterling_home>/resources/

to <sterling_home>/extensions/global/resources/

and rename it as log4jconfig_custom.xml

2.       Customize it based on your business requirement. Consider the following appender

Before Change

After Change

<appender name="ALL" class="com.sterlingcommerce.woodstock.util.frame.logex.SCIAppender">

        <param name="rotateLogs" value="true" />

        <param name="maxLogSize" value="100000" />

        <param name="file" value="D:/sterling/logs/sci.log" />

        <layout class="com.sterlingcommerce.woodstock.util.frame.logex.SCICommonLayout">

            <param name="ConversionPatternRef" value="appender.ALL.pattern"/>

            <param name="DefaultConversionPattern" value="%d:%-7p:%t: %-60m [%X{AppUserId}]: [%X{TenantId}]: %-25c{1}%n"/>

        </layout>

        <!-- layout class="com.sterlingcommerce.woodstock.util.frame.logex.SCIBasicLayout" / -->

        <filter class="com.sterlingcommerce.woodstock.util.frame.logex.SCICommonFilter" />

        <filter class="com.sterlingcommerce.woodstock.util.frame.logex.SCIPatternFilter" />

    </appender>

<appender name="ALL" class="com.sterlingcommerce.woodstock.util.frame.logex.SCIAppender">

        <param name="rotateLogs" value="true" />

        <param name="maxLogSize" value="100000" />

        <param name="file" value="${log_dir}/${server_name}.log" />

        <layout class="com.sterlingcommerce.woodstock.util.frame.logex.SCICommonLayout">

            <param name="ConversionPatternRef" value="appender.ALL.pattern"/>

            <param name="DefaultConversionPattern" value="%d:%-7p:%t: %-60m [%X{AppUserId}]: [%X{TenantId}]: %-25c{1}%n"/>

        </layout>

        <!-- layout class="com.sterlingcommerce.woodstock.util.frame.logex.SCIBasicLayout" / -->

        <filter class="com.sterlingcommerce.woodstock.util.frame.logex.SCICommonFilter" />

        <filter class="com.sterlingcommerce.woodstock.util.frame.logex.SCIPatternFilter" />

    </appender>

 

3.       In the customer_overrides.properties file, set property:

yfs.log4j.configuration=/resources/extn/log4jconfig_custom.xml

4.       Build resource.jar file

<sterling_home>/bin/deployer.sh -t resourcejar

5.       Ensure that custom log4j configuration file exist in new resources.jar

6.       Build and deploy smcfs.ear to ensure Application Server will refer to custom log4j configuration for logging purpose

7.       Restart the Sterling JVMs and the Agent/Integrations servers will also refer to custom log4j configuration for logging purpose

8.       Ensure that in your server start scripts you add 2 parameters -> log_dir and server_name

For example, if you are using weblogic as your application server then in startWebLogic.cmd file you should add parameters as -Dlog_dir=D:\sterling95\logs -Dserver_name=sterlingapp

App server log file name before changes - sci.log.D20210516.T220838

App server log file name after changes - sterlingapp.log.D20210516.T234144

 

Steps to enable logging for custom code:

1.       If custom code uses the com.yantra.yfc.log.YFCLogCategory logger and does not use a package name which is already defined in the log4jconfig_custom.xml file, a category entry must be added for that package.

For example, if the custom code is packaged in com.test, the fastest way to make sure that its use of com.yantra.yfc.log.YFCLogCategory is directed to the same place where Sterling code sends its logging, is to replace com.ibm with com.test as follows:

<category  name="com.test" class="com.yantra.yfc.log.YFCLogCategory" additivity="false" >

        <level class="com.yantra.yfc.log.YFCLogLevel" value="VERBOSE"  />

        <appender-ref ref="CONSOLE" />

        <appender-ref ref="ALL" />

    </category>

 

2.       Your sample custom code might look like this:

package com.test;

public class LoggerTest {

              private static YFCLogCategory logger = YFCLogCategory.instance(LoggerTest.class);

               public Document printMyLogs(YFSEnvironment env, Document docIn) {

                             logger.beginTimer("### Inside printMyLogs BeginTimer ###");

                             logger.info("### Inside printMyLogs Info ###");

                             logger.warn("### Inside printMyLogs Warn ###");

                              if (logger.isDebugEnabled()) {

                                           logger.debug("### Inside printMyLogs Debug ###");

                                           logger.debug("### Input doc::" + XMLUtil.getXMLString(docIn));

                             }

                             logger.endTimer("### Inside printMyLogs EndTimer ###");                                                return docIn;

              }

}

 

3.       To enable trace for a Custom Service or OOTB API,

a.       Go to Application console -> System -> Launch System Management



b.       In the System Management Console -> Tools -> Trace Components                                  



c.       Click on ‘Add’. A popup is displayed

d.       Select Component Type as ‘Services or API’

e.       Select Component Name as your Service/Api name. Ex – ‘TestLogger’

f.        Select Trace Level. Available options are: VERBOSE, DEBUG, SQLDEBUG, TIMER




g.       Click ‘Apply’      


4.       Now after invoking your service, you can see your logger messages in the log file!

 

Important Point to remember:

·       You can enable the tracing for a component two ways:

a.       System Management Console

b.       modifyTraces API (explore javadocs for more details)

·       If you do not define a logging level criteria through the System Management Console, the logging level is set to 'INFO' or the value defined in the log4jconfig.xml is considered. However, the system will consider the lowest value

·       For production, considering the performance you should enable either the INFO or WARN logging level. When needed, you can enable diagnostic logging levels for short periods of time in production

·       Sterling implementation of logging provides the following four application logging levels (you will use this in code):

ERRORDTL < ERROR < WARN < INFO

and the following four diagnostic logging levels (you will use this to enable trace):

TIMER < SQLDEBUG < DEBUG < VERBOSE

·       The application logging levels are cumulative. If you enable INFO, you get all four levels from INFO to ERRORDTL. If you enable WARN, you get three levels from WARN to ERRORDTL

·       Similarly, Enabling VERBOSE logging also enables all diagnostic logging levels from VERBOSE to TIMER as well as all application logging from INFO to ERRORDTL.

·       DEBUG and VERBOSE logs print out lots of information including the input, intermediate and resulting XMLs, debug information, and so forth. So, you need to be careful while enabling these tracing levels

·       More details on trace levels:

a.       Timer - The time taken to complete various events. You can use this information to find out what parts of the component are taking the longest to complete and resolve performance related problems

b.       SQLDebug - The SQL database statements that are actually run within the component. You can use this information to tune the database for optimal performance

c.       Debug - Information required to debug the component that does not work as expected

d.       Verbose - Comprehensive information about the component

·       Let’s understand more on logging levels with below table:

 

Default

(no trace enabled)

Timer

SQLDebug

Debug

Verbose

errordtl

X

X

X

X

X

error

X

X

X

X

X

info

X

X

X

X

X

warn

X

X

X

X

X

timer

 

X

X

X

X

sqldebug

 

 

X

X

X

debug

 

 

 

X

X

verbose

 

 

 

 

X





No comments:

Post a Comment