Showing posts with label log4j. Show all posts
Showing posts with label log4j. Show all posts

Thursday, August 29, 2013

Custom JCA Adapter and Dynamic log4j Logging Level Control with Weblogic

Recently I worked on dynamical log4j logging level control in a custom JCA adapter. I still don’t know much about JCA adapter. But I managed to make it work, and in the process I picked up a few more interesting things about Weblogic and log4j configurations.

At the core, the solution is the same as in http://yuanmengblog.blogspot.com/2013/08/weblogic-log-files-and-log4j-tricks.html i.e. use this code snippet in a "central" location of your code:

if (notInitialized) {
   String fileName = System.getProperty("jca.log4j.configFile");
   DOMConfigurator.configureAndWatch(fileName, 3000);
}

I stumbled upon a few subtle things about log4j and Weblogic before I made it to work. Here are a few things to pay close attention if you want to do it:

1. By default, Weblogic uses its own logging mechanism (it’s based on log4j)
2. setDomainEnv.sh script may set a specific Java system variable "-Dlog4j.configuration". Based on my test, this variable is sort of a "reserved" by Weblogic. The value of this variable is "file:yourAbsoluteFilePath". Be extra careful with the variable name and the "file:" prefix. 
3. If you place log4j.xml in the domain home directory, then Weblogic will pick it up and uses that one. It confused me for a while. I only found it out by trial and error.

The common thing about these scenarios is that Weblogic will internally pick up the log4j.xml file. When that happens, Weblogic initializes log4j, and you have no control of the file whatsoever. You can modify the log4j.xml all you want; weblogic is not going to do anything with the changes unless you restart the server.

So the solution is :
1. Do not to place "log4j.xml" in the domain folder, or use a different file name, such as "mylog4j.xml". 
2. Use a different Java system variable name, such as "jca.log4j.configFile" (just make sure do not "log4j.configuration").
3. Since you pick your own variable name, you should not use the "file:" prefix for the variable value. Instead, just use the full path name of you log4j configuration file.

That’s about it. I named my file "my-test-log4j.xml". I picked a variable name like "jca.log4j.confiureFile". I was able to change "my-test-log4j.xml" and watch the logging levels change on the fly.

Also, make sure if you start the server (such as AdminServer) with the script, then you need to update the script to pass the variable in. If you use nodeManager (for managed servers), then you should use weblogic console, server, startup argument field to pass in the variable.

Finally, in the JCA rar file, there is a weblogic-ra.xml that allows you to name your "<log-filename>" element, I tested that, it merely generated a file with that name; nothing gets logged into that file. I’m not sure how to use that file. So I simply skipped this element in the weblogic-ra.xml file.

Friday, August 9, 2013

Weblogic log files and log4j tricks

I have relied on weblogic log files for trouble shooting for many years, but never given a serious thought where they are configured and how to customize them. Well, I still don't know the whole story, but I managed to learn a couple of interesting things lately.

1. By default, WebLogic uses Java logging API which is based on log4j, but it is not exactly log4j. Therefore, if you install an out of box domain, there is no direct reference to log4j.

2. Your application can choose to use log4j for logging, then you can control how things are logged and where to log to etc.

3. If you want to system to dynamically pick up log4j.xml changes during run time, you can use https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/DOMConfigurator.html I'll show a full example below.

4. We also need to send certain log messages to sensage, which monitors the syslog. What we need was using log4j "syslogger" to direct log msgs to syslog, then we configured the /etc/syslog.conf to forward the messages to senage like:
# Sensage Configuration
*.notice;mail.none;user.none;auth.none;mark.none;kern.none     @sensage.acme.com
mail.crit;user.crit                                    @sensage.acme.com
kern.info                                              @sensage.acme.com
auth.info                                              @sensage.acme.com
user.info                                               @sensage.acme.com

However, in order to send message to syslog file, we had to modify "syslogd" start up script and add "-r" parameter.

Now, for the sample log4j and DOMConfigurator example. I grabbed some sample file online and modified it with the configurator:

import org.apache.log4j.Logger;
import java.io.*;
import java.sql.SQLException;
import java.util.*;
import org.apache.log4j.xml.DOMConfigurator;
public class logExample{
  static Logger log = Logger.getLogger(logExample.class.getName());
  public static void main(String[] args)
                throws IOException,SQLException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String file = System.getProperty("Log4jConfigFile");
System.out.println(String.format("Log4jConfigFile=%s",file));
DOMConfigurator.configureAndWatch(file, 3000);

     while (true) {
     log.debug("Hello this is an debug message");
     log.info("Hello this is an info message");
     System.out.println("modify your log4j.xml, then hit enter to continue, monitor the changes take effect.");

String x = null;
try {
x = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
  }
  }
}

Here is my local compile and run script:

javac -cp .;C:\Oracle\Middleware\Oracle_OSB1\lib\external\log4j_1.2.8.jar -d . logExample.java

java -cp .;C:\Oracle\Middleware\Oracle_OSB1\lib\external\log4j_1.2.8.jar -DLog4jConfigFile="c:\proj\poc\log4j\config\log4j.xml" logExample

You can use your own log4j.xml or grab a sample from here http://stackoverflow.com/questions/2619160/sample-xml-configuration-for-log4j-have-a-main-java-application-and-want-to-w

Finally, to integrate this sample into your web application, you need to find your initialization function, such as servlet context initializer, and insert the DCOMConfigurator over there. Of course, remember to put in -DLog4jConfigFile in your server startup script if your server is started with the script, or put it in the weblogic console server startup argument field if you use nodeManager to start your server(s).