tags:

views:

43

answers:

2

I need to pass some value to enable certain code in may app (in this case is to optionally enable writing some stats to a file in certain conditions, but it might be anything generally).

My java app is installed as a service. So every way I have thought of has some drawbacks:

  1. Add another param to main(): cumbersome as customers already have the tool installed, and the command line would need to be changed every time.
  2. Adding java -DmyEnvVar=A_VALUE to my command line: same as above.
  3. Set an environment variable: service should at least be restarted, and even then you must take care of what user is the service running under etc.
  4. Adding the property in the config file: I prefer not to have this visible on the config file so the user does not see it, it is something for debugging etc.

So I thought maybe there is some way (or hack) to use log4j loggers to pass that value to my code. I have thought of one way already, although is very limited:

  1. Add a dummy class to my codebase com.dummy.DevOptions

    public class DevOptions { public static final Logger logger = Logger.getLogger(DevOptions.class);

  2. In my code, use it like this:

    if (DevOptions.logger.isInfoEnabled()){ //do my optional stuff } //... if (DevOptions.logger.isDebugEnabled()){ //do other stuff }

This allows me to use discriminate among various values, and I could increase the number by adding more loggers to DevOptions. But I wonder whether there is a cleaner way, possibly by configuring the loggers only in log4j.xml??

A: 

In log4j you dont need Java classes at all to create loggers (This may come as a surprise). All you need is a package qualified string and not a Java class to create logger category. If I were you I would do the following

PS: Code not guaranteed to compile/run

public class SomeAppCode {
      public static final Logger specialLogger = Logger.getLogger("com.mypackage.mysubpackage.speciallogger");

      public void someMethod() {
        if(specialLogger.isDebugEnabled()) {
           //do low level stuff
        } 

      }
}

In your log4j.xml add a category for this string mentioned and if you want you could set "additivity" to be true/false (depending on whether you want to propogate this log message to multiple loggerS)

PS: Note specialLogger is public static and such can be used by 100s of classes like it were their own loggers.

Calm Storm
thanks, but I knew that already, that is what I meant by 'adding more loggers to DevOptions', adding more loggers with different name. Ideally what I am looking for is some way do:if (specialLogger.isEnabled("feature.A")){//do low level stuff}And being able to set the feature.A somehow in log4j.xml. isEnabled(String) is the key here.
raticulin
A: 

ok I think I found what I needed, wasn't that difficult actually...

 public class DevOptions{
  public static boolean isEnabled(String myvalue){
    Logger logger = Logger.getLogger(myvalue);
    return logger.isDebugEnabled();
  }

}

public class SomeAppCode {
  public void someMethod() {
    if(DevOptions.isEnabled("value.A")) {
       //do low level stuff
    } 
  }

}

And I can add as many values like value.A in log4j.xml:

  <logger name="value.A" additivity="true"><level value="debug" /></logger>

This way I can add as many values as I want by only modifying log4j.xml, no need to add more loggers to DevOptions, only one is sufficient.

raticulin
If "DevOptions.isEnabled("value.A")" is your only acceptable syntax (perhaps you have written some other support code around this) then this sounds alright. Otherwise I would still have static specialLogger's as I have shown :)
Calm Storm
Calm Storm, see my reply now, can you see what I meant? No need to keep adding more loggers when I need another flag in some new code. Only one logger but as many flags as needed can be used now.
raticulin