Logging and tracing

All HCL Commerce assets can use the LoggingHelper utility class provided in the com.ibm.commerce.foundation.common.util.logging package for tracing and logging. This utility helps to resolve the Java Logger ( java.util.logging.Logger) associated with the package of the calling class. Once the Logger is resolved, the library used to log messages is java.util.logging.Logger.

The code sample below shows how to use the logger object for tracing. For more information see the Add logging and tracing to your application topic.

Note: Adding trace to the code typically results in creating new objects. You should check whether logging is enabled for your class by calling the LoggingHelper.isTraceEnabled(logger) method before calling the logging methods.

Logger logger = LoggingHelper.getLogger(ExceptionData.class);
    if (LoggingHelper.isTraceEnabled(logger)) {
    StringBuffer sb = new StringBuffer(80);
    sb.append("Could not resolve message key '");
    sb.append(_strMessagekey);
    sb.append("' from the properties file ");
    sb.append(logger.getResourceBundleName());
    logger.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL,  CLASSNAME,
METHODNAME, sb.toString());
}

Methods which are not automatically generated should have trace entry and exit points. All trace entry statements must be matched with exit statements. Trace entry statements typically include input parameters if there are any, while exit statements include the return value(s). The entry and exit trace statements should be put inside the if-then block to check if your component trace is enabled. Below is a sample code for tracing method's entry and exit points:


public class GetOrderExpressionBuilder {

private static final
    String CLASSNAME =  GetOrderExpressionBuilder.class.getName();
private static final
    Logger LOGGER =
LoggingHelper.getLogger(GetOrderExpressionBuilder.class);
/**
 * Forms an expression to query orders by status.
 */
public ExpressionType findByOrderStatus(Map amNVPs) {
    final String METHODNAME = "findByOrderStatus";

     if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {
        LOGGER.entering(CLASSNAME, METHODNAME, amNVPs);
    }

    ExpressionType findByOrderStatusExpression = null;
    // business logic...
    if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {
        LOGGER.exiting(CLASSNAME, METHODNAME,
findByOrderStatusExpression);
   }
    return findByOrderStatusExpression;
  }
}

Masking sensitive data in traces

There are many cases where masking sensitive data is required. HCL Commerce provides a MaskingFactory utility to help mask sensitive data.

MaskingFactory reads a list of masking policies and parameters from the following file: workspace_dir/WC/xml/config/wc-attribute-masking.xml It is called in the following form, for example:

String maskedValue = com.ibm.commerce.foundation.internal.common.util.masking.MaskingFactory.getInstance().mask("password", "abc123");
When it is called, it determines if and how the attributes are masked.

In the above example, MaskingFactory sees password as a parameter that is listed in the configuration file. Therefore, it returns a value of ******* instead of the abc123 value.

The wc-attribute-masking.xml file contains the following elements:
MaskingPolicy
Defines a masking policy to be used by the MaskingFactory.
MaskingPolicy.classname
Defines the masking policy implementation class name.
MaskingPolicyAttributes
Defines a list of attributes used to initialize the masking policy. This list is defined in the enclosed Attribute elements as name-value pairs.
Attribute.name
The name of an attribute.
Attribute.value
The value of an attribute.
MaskingAttributes
Defines a list of parameters to be masked by this masking policy.
MaskingAttribute.name
The name of the parameter whose corresponding value is to be masked.
MaskingAttribute.compareType
Indicates whether the exact parameter name or the beginning of the parameter name will result in a match. Valid values are equals and starts. The default value is equals.
MaskingAttribute.caseInsensitive
Indicates whether the parameter name match is case sensitive or not. Valid values are true and false. The default value is false, where a match is found if the case matches exactly with the configuration.
Multiple masking policies can be defined in the wc-attribute-masking.xml file. For example:

<!--
		mask value is always 8 *s
	-->
	<wc:MaskingPolicy description="Replace value with 8 *s"
		classname="com.ibm.commerce.masking.impl.ReplaceCharactersMaskingPolicyImpl">
		<wc:MaskingPolicyAttributes>
			<wc:Attribute name="contentLength" value="8" />
			<wc:Attribute name="replaceCharacter" value="*" />
		</wc:MaskingPolicyAttributes>
		<wc:MaskedAttributes>
			<wc:MaskedAttribute name="logonPassword" compareType="starts" />
			<wc:MaskedAttribute name="password" caseInsensitive="true" />
			....
		</wc:MaskedAttributes>
	</wc:MaskingPolicy>

	<!--
		mask value is the first digit, last four digits and the rest
		of the middle of the string is replaced by *s.
	-->
	<wc:MaskingPolicy
		description="Shows the 1st character and the last 4 characters.
				All other characters will be replaced with *s."
		classname="com.ibm.commerce.masking.impl.ShowEndCharactersMaskingPolicyImpl">
		<wc:MaskingPolicyAttributes>
			<wc:Attribute name="showFirst" value="1" />
			<wc:Attribute name="showLast" value="4" />
			<wc:Attribute name="replaceCharacter" value="*" />
		</wc:MaskingPolicyAttributes>
		<wc:MaskedAttributes>
			<wc:MaskedAttribute name="cardNumber" compareType="starts" />
			<wc:MaskedAttribute name="pay_cardNumber"	compareType="starts" />
			....
		</wc:MaskedAttributes>
	</wc:MaskingPolicy>
There are two policies in the above example. The first policy replaces the values with 8 * characters. The second policy shows the first and last 4 digits of the value, while the rest of the value is replaced with * characters.