Showing posts with label logging. Show all posts
Showing posts with label logging. Show all posts

Saturday, February 11, 2017

make logger.debug() obsolete

IMHO logging is the weakest point in application development, the Cinderella of IT.
Most people don't log enough information to enable effective troubleshooting, the context is lost, changing logging level in PROD is hell, if you enable debug level you end up being flooded with unwanted info, most of the time operators don't even have instructions on how to do it.
Besides one is interested in knowing what happened immediately before an error occurred, so one should always have like a Flight Recorder with some history preceding the error and ready to be dumped when this happens.
Also, frameworks like ByteBuddy or Btrace or AOP products allows you to dynamically define loggers... logging is a cross-cutting concern, it should not be interspersed in the business code cluttering it. Just define what to log in a separate module - configuration and convention over code.
Here at OverOps they seem to bring some value:

https://www.overops.com/java-monitoring

watch the short video:




Monday, December 30, 2013

OSB, WebLogic and Logback / SLF4j

Being totally fed up with the OSB reporting provider, I am setting up logback.
Maven:
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-core</artifactId>
  <version>1.0.13</version>
</dependency>
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.0.13</version>
</dependency>
             
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-parent</artifactId>
  <version>1.0.13</version>
  <type>pom</type>
</dependency>
 
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.5</version>
</dependency>



vi /opt/oracle/fmw11_1_1_5/wlserver_10.3/common/bin/commEnv.sh

add this to WEBLOGIC_CLASSPATH:

${CLASSPATHSEP}/opt/oracle/fmw11_1_1_5/wlserver_10.3/server/lib/slf4j-api-1.7.5.jar${CLASSPATHSEP}/opt/oracle/fmw11_1_1_5/wlserver_10.3/server/lib/logback-core-1.0.13.jar${CLASSPATHSEP}/opt/oracle/fmw11_1_1_5/wlserver_10.3/server/lib/logback-classic-1.0.13.jar

and copy the JARs:

cd /opt/oracle/fmw11_1_1_5/wlserver_10.3/server/lib/

this only if you have Nexus, otherwise.... copy them manually:

wget http://nexus.nespresso.com/service/local/repositories/adobe-ext/content/ch/qos/logback/logback-core/1.0.13/logback-core-1.0.13.jar

wget http://nexus.nespresso.com/service/local/repositories/adobe-ext/content/ch/qos/logback/logback-classic/1.0.13/logback-classic-1.0.13.jar

wget http://nexus.nespresso.com/service/local/repositories/adobe-ext/content/org/slf4j/slf4j-api/1.7.5/slf4j-api-1.7.5.jar

vi /opt/oracle/domains/osbpl1do/config/osb/logback.xml

<configuration debug="true" scan="true" scanPeriod="30 seconds">
    <jmxConfigurator />
 
    <property name="LOG_DIR" value="/opt/var/log/weblogic/server/" />
 
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder
            by default -->
        <encoder>
            <pattern>%d %-5level [%thread] %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>
 
    <appender name="GM"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_DIR}GM.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
              <fileNamePattern>GM.%i.log.zip</fileNamePattern>
              <minIndex>1</minIndex>
              <maxIndex>10</maxIndex>
            </rollingPolicy>
            <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
              <maxFileSize>50MB</maxFileSize>
            </triggeringPolicy>
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
                </pattern>
            </encoder>
    </appender>
 
 
    <logger name="POC_LOG4j" additivity="false" level="INFO">
        <appender-ref ref="GM" />
    </logger>
 
    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
    </root>
 
 
</configuration>


I provide a custom XPath to log :
package com.acme.osb.logging;
import org.apache.xmlbeans.XmlObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * Used by OSB to report an Event
 *
 * @author NNVernetPI
 *
 */
public class MessageTrackerSLF4J {
    public static String logMessage(String technicalMessageid,
            String businessId, String eventType, String interfaceName,
            XmlObject payload) {
        Logger projectLogger = LoggerFactory.getLogger(interfaceName);
        StringBuilder sb = new StringBuilder();
        if (projectLogger.isDebugEnabled()) {
            sb.append(" ::InterfaceName::  ").append(interfaceName)
                    .append(" ::Payload:: ").append(payload.xmlText())
                    .append(" ::BusinessID::  ").append(businessId);
        } else {
            sb.append(" ::TechnicalMessageID::  ").append(technicalMessageid)
                    .append(" ::BusinessID::  ").append(businessId)
                    .append(" ::InterfaceName::  ").append(interfaceName)
                    .append(" ::EventType::  ").append(eventType)
                    .append(" ::ServerName:: ")
                    .append(System.getProperty("weblogic.Name"));
        }
        projectLogger.info(sb.toString());
        String logmessage = "Info Message Logged for:: " + interfaceName;
        return logmessage;
    }
    public static String errorLogger(String technicalMessageid,
            String businessId, String interfaceName, XmlObject payload,
            String priority, XmlObject fault) {
        Logger projectLogger = LoggerFactory.getLogger(interfaceName);
        StringBuilder sb = new StringBuilder();
        sb.append("::TechnicalMessageID::  ").append(technicalMessageid)
                .append("  ::InterfaceName::  ").append(interfaceName)
                .append("  ::BusinessID::  ").append(businessId)
                .append(" ::Payload:: ").append(payload.xmlText())
                .append(" ::Priority::  ").append(priority)
                .append(" ::FaultDescription:: ").append(fault.xmlText())
                .append(" ::ServerName:: ")
                .append(System.getProperty("weblogic.Name"));
        projectLogger.error(sb.toString());
        String responseMessage = "Error Message Logged for:: " + interfaceName;
        return responseMessage;
    }
}


which I expose as XPath this way:
  <xpf:function>
            <xpf:name>LOG_SLF_errorLogger</xpf:name>
            <xpf:comment>logs an error</xpf:comment>
            <xpf:namespaceURI>http://www.acme.com/acme2/xquery/xquery-functions</xpf:namespaceURI>
            <xpf:className>com.acme.osb.logging.MessageTrackerSLF4J</xpf:className>
            <xpf:method>java.lang.String errorLogger(java.lang.String, java.lang.String, java.lang.String, org.apache.xmlbeans.XmlObject, java.lang.String, org.apache.xmlbeans.XmlObject)</xpf:method>
            <xpf:isDeterministic>false</xpf:isDeterministic>
            <xpf:scope>Pipeline</xpf:scope>
            <xpf:scope>SplitJoin</xpf:scope>
        </xpf:function>     
        
  <xpf:function>
            <xpf:name>LOG_SLF_messageTracker</xpf:name>
            <xpf:comment>logs an event</xpf:comment>
            <xpf:namespaceURI>http://www.acme.com/acme2/xquery/xquery-functions</xpf:namespaceURI>
            <xpf:className>com.acme.osb.logging.MessageTrackerSLF4J</xpf:className>
            <xpf:method>java.lang.String logMessage(java.lang.String, java.lang.String, java.lang.String, java.lang.String, org.apache.xmlbeans.XmlObject)</xpf:method>
            <xpf:isDeterministic>false</xpf:isDeterministic>
            <xpf:scope>Pipeline</xpf:scope>
            <xpf:scope>SplitJoin</xpf:scope>
        </xpf:function>        


Since I have activated the jmxConfigurator, I can reload the logback.xml configuration file by connecting with JMX:

jconsole -J-Djava.class.path=C:\Oracle\MIDDLE~1\JDK160~1\lib\jconsole.jar;C:\Oracle\MIDDLE~1\JDK160~1\lib\tools.jar;C:\Oracle\Middleware\wlserver_10.3\server\lib\wlfullclient.jar -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote -debug
and connect as:
service:jmx:iiop://myserver.acme.com:8001/jndi/weblogic.management.mbeanservers.runtime



The advantage is that I can also set programmatically the logger level for each logger, via JMX.



see here the doc, the first argument is the loggerName, the second is the level

A note: reloadByFileName() requires the FULL PATH : /opt/oracle/domains/osbpl1do/config/osb/logback.xml



Monday, December 6, 2010

SOA Suite - logging in BPEL

I was wondering how to log debug information in a BPEL process,
and here I found an excellent article on using a Java embedded action.... great stuff, Brazilian friend, bem feito!

Just code this into a Java Embedded activity:

Object countLines = getVariableData("countLines");   
  
System.out.println("IN LOOP countLines=" + countLines);

/* writes to the audit trail - will then be visible in BPEL console at runtime*/
addAuditTrailEntry("countLines is: " + countLines);




This article seems to be interesting on how to use log4j from a BPEL process

See also here for more on logging XML in BPEL