How to configure java.util.logging in groovy for c

2019-06-25 12:24发布

问题:

testlog.java:

import java.util.logging.Logger;
public class testlog {
    private final static Logger log = Logger.getLogger(testlog.class.getName());
    public static void main(String[] args) {
        System.setProperty("java.util.logging.SimpleFormatter.format","[%1$tF %1$tT]:%4$s:(%2$s): %5$s%n");
        log.info("logging test");
    }
}

execute:

$ java testlog
[2014-01-18 11:08:51]:INFO:(testlog main): logging test

testlog.groovy:

import java.util.logging.Logger;
public class testlog {
    private final static Logger log = Logger.getLogger("testlog");
    public static void main(String[] args) {
        System.setProperty("java.util.logging.SimpleFormatter.format",'[%1$tF %1$tT]:%4$s:(%2$s): %5$s%n');
        log.info("logging test");
    }
}

execute:

$ groovy testlog
[2014-01-18 11:11:23]:INFO:(java_util_logging_Logger$info call): logging test

How to configure groovy for class/method name instead of "java_util_logging_Logger$info call" ?

回答1:

Groovy uses CallSite in bytecode, generally. Groovy code mentioned above would compile to below format of bytecode:

import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import java.util.logging.Logger;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;

public class testlog
  implements GroovyObject
{
  private static final Logger log;

  static
  {
    __$swapInit();long l1 = 0L;__timeStamp__239_neverHappen1390064566496 = l1;
      long l2 = 
        1390064566495L;__timeStamp = l2;
       Object localObject = 
        $getCallSiteArray()
           [2].call(Logger.class, "testlog");log = 
           (Logger)ScriptBytecodeAdapter.castToType(localObject, Logger.class);
  }

  public static void main(String... args)
  {
    CallSite[] arrayOfCallSite = 
      $getCallSiteArray();arrayOfCallSite[0].call(System.class, 
        "java.util.logging.SimpleFormatter.format", 
                  "[%1$tF %1$tT]:%4$s:(%2$s): %5$s%n");
    arrayOfCallSite[1].call(log, "logging test");
  }

  public testlog()
  {
    testlog this;
    CallSite[] arrayOfCallSite = $getCallSiteArray();
    MetaClass localMetaClass = $getStaticMetaClass();
    this.metaClass = localMetaClass;
  }
}

So it refers to the Log class when referred from the formatter. To work around with this you can use CompileStatic annotation on class level which converts source to bytecode in normal Java convention.

Here is how the script should look (Note:- Class name is CamelCase):

import java.util.logging.Logger
import groovy.transform.CompileStatic

@CompileStatic
public class Testlog {
    private final static Logger log = Logger.getLogger("testlog")
    public static void main(String[] args) {
        System.setProperty("java.util.logging.SimpleFormatter.format",
            '[%1$tF %1$tT]:%4$s:(%2$s): %5$s%n')
        log.info("logging test")
    }
}