On Mon, Jan 27, 2014 at 10:24 AM, Paul Benedict <pbened...@apache.org>wrote:
> I propose this: > > 1) If you are willing to view standard levels as a type of DSL, then you > should refactor the Logger interface to separate those concerns. Create a > new superinterface that contains everything else. This is what custom > loggers will extend. > That's brilliant! The Logger interface contains methods like log(Level, ...) and StandardLogger extends Logger to provide info(), warn() and so on. This let's me create a custom Logger (DEFCON example) AND an extension to StandardLogger with refined levels (NOTICE, DIAG, VERBOSE). This makes it clear that a Custom Logger is different than an Extensible Logger to StandardLogger. Gary > 2) The customer loggers not only register an interface but also the > implementation that goes with it. > > 3) Retrieve a custom logger as follows: > <T extends LoggerSuperInterface> T Logger.getCustomLogger(T t); > > Paul > > > On Mon, Jan 27, 2014 at 8:51 AM, Gary Gregory <garydgreg...@gmail.com>wrote: > >> I also want to avoid extending Logger for domain specific applications. >> For medical devices for example I could only have critical, warning, >> advisory. >> >> >> -------- Original message -------- >> From: Remko Popma >> Date:01/27/2014 09:15 (GMT-05:00) >> To: Log4J Developers List >> Subject: Re: Using Custom Levels with a Custom/Wrapper Interface >> >> How about starting with something very simple at first? >> >> >> We provide a tool that generates the source code for a custom logger >> interface. >> >> To invoke the tool the user passes it the fully qualified name of the >> interface, and a list of NAME=INTLEVEL custom log levels. >> >> The generated source code contains both the interface and an >> implementation. The implementation is an inner class of the interface (so >> users only need to manage one single file). >> >> The generated interface is annotated with the class name of the >> implementation class. >> >> >> At runtime, users call LogManager.getCustomLogger(Class, String) to get a >> custom logger instance. >> >> The LogManager then uses the annotation on the interface class to >> instantiate objects of the implementation class. >> >> >> >> Example tool invocation: >> >> java org.apache.logging.log4j.util.Generate com.mycomp.myproject.MyLogger >> DIAG=350 NOTICE=450 VERBOSE=550 >> >> >> >> Generated code: >> >> >> @CustomLoggerImplementation(MyLogger.Impl.class) >> >> public interface MyLogger extends Logger { >> >> void diag(Marker marker, Message msg); >> >> void diag(Marker marker, Message msg, Throwable t); >> >> // ... other methods >> >> public static final class Impl extends AbstractLoggerWrapper implements >> MyLogger { >> >> private final static Level DIAG = Level.getOrCreateLevel("DIAG", >> 350); >> >> private final static Level NOTICE = Level.getOrCreateLevel("NOTICE", >> 450); >> >> private final static Level VERBOSE = >> Level.getOrCreateLevel("VERBOSE", 550); >> >> >> public Impl(final AbstractLogger logger) { >> >> super(logger, logger.getName(), logger.getMessageFactory()); >> >> } >> >> >> public void diag(Marker marker, Message msg) { >> >> logger.log(DIAG, marker, msg); >> >> } >> >> >> public void diag(Marker marker, Message msg, Throwable t) { >> >> logger.log(DIAG, marker, msg, t); >> >> } >> >> >> // ... other methods >> >> } >> >> } >> >> >> >> LogManager: >> >> public static <T extends Logger> T getCustomLogger(Class<T> cls, String >> name) { >> >> Logger wrapped = getLogger(name); >> >> return wrap(cls, wrapped); >> >> } >> >> >> private static <T extends Logger> T wrap(Class<T> cls, Logger wrapped) { >> >> CustomLoggerImplementation annotation = >> cls.getAnnotation(CustomLoggerImplementation.class); >> >> Class<?> implClass = annotation.value(); >> >> try { >> >> Constructor<?> constr = implClass.getConstructor(Logger.class); >> >> return (T) constr.newInstance(wrapped); >> >> } catch (Exception ex) { >> >> throw new IllegalStateException( >> >> "Unable to construct instance of custom logger class " >> >> + implClass.getName(), ex); >> >> } >> >> } >> >> >> >> On Monday, January 27, 2014, Scott Deboy <scott.de...@gmail.com> wrote: >> >>> I know we can't do what I would like via configuration. My point was to >>> primarily to spark discussion on how we could make the api as simple as >>> possible. >>> >>> I'm ok with where we are on the custom level support. >>> >>> I do think this brings us back around to adding built in levels, in a >>> separate thread. >>> >>> I'm really pleased with how things are coming together. Good stuff. >>> >>> Scott >>> On Jan 26, 2014 9:25 PM, "Nicholas Williams" < >>> nicho...@nicholaswilliams.net> wrote: >>> >>> Yes, I was saying that. But, unless I'm misunderstanding, Scott doesn't >>> want the user to even have to write the interface. He wants them to just >>> configure it and the interface become available "magically." I was pointing >>> out that there's a disconnect between when the configuration is used >>> (runtime) and when the user needs the interface (compile time). >>> >>> Unless we provide a code-generation tool for the user to run from the >>> command line or from Ant/Maven/Gradle, they're going to have to write the >>> interface themselves. >>> >>> Nick >>> >>> Sent from my iPhone, so please forgive brief replies and frequent typos >>> >>> On Jan 26, 2014, at 22:49, Remko Popma <remko.po...@gmail.com> wrote: >>> >>> Nick, I thought that you meant that users would provide their own >>> interface, like this: >>> public interface MyLogger extends Logger { >>> @LoggingLevel(name="DIAG") >>> void diag(String message); >>> // optional other methods >>> } >>> >>> That way, this interface exists at compile time. >>> >>> On Monday, January 27, 2014, Nicholas Williams < >>> nicho...@nicholaswilliams.net> wrote: >>> >>> Scott, invokedynamic and javassist...those are all /runtime/ things. The >>> user needs Logger#notice to be available at compile time. Those are not >>> compatible. >>> >>> Nick >>> >>> Sent from my iPhone, so please forgive brief replies and frequent typos >>> >>> > On Jan 26, 2014, at 22:37, Scott Deboy <scott.de...@gmail.com> wrote: >>> > >>> > Yes, I would like to declare in the config: >>> > >>> > Level: NOTICE, value: 232 >>> > >>> > And in Java code be able to use logger.notice("some message"). >>> > >>> > But I think that'd require invokedynamic..which would probably >>> > require..javassist/ASM? >>> > >>> > I'd be ok with anything that's really close to that :) >>> > >>> > Scott >>> > >>> > >>> >> On 1/26/14, Ralph Goers <ralph.go...@dslextreme.com> wrote: >>> >> Scott would like users to add a level definition to the logging >>> >> configuration and have everything else happen auto-magically. That >>> would >>> >> happen at run-time which is a bit late since the methods need to be >>> >> available at compile time. >>> >> >>> >> I believe Scott said he would be fine if users had to do >>> >> >>> >> logger.log(SomeClass.SomeLevel, "message); >>> >> >>> >> but even that requires "SomeClass" to be available at compile time. >>> >> >>> >> So what Scott says he would like and what Nick is proposing are two >>> >> different things. >>> >> >>> >> Ralph >>> >> >>> >> >>> >> >>> >>> On Jan 26, 2014, at 8:09 PM, Remko Popma <remko.po...@gmail.com> >>> wrote: >>> >>> >>> >>> I actually thought that Nick's idea was the answer to that: users >>> create a >>> >>> custom interface, something like this: >>> >>> >>> >>> public interface MyLogger extends Logger { >>> >>> @LoggingLevel(name="DIAG") >>> >>> void diag(String message); >>> >>> // optional other methods >>> >>> } >>> >>> >>> >>> They get an instance of this interface by calling: >>> >>> LogManager.getCustomLogger(MyLogger.class); >>> >>> >>> >>> LogManager has access to the processed configuration. The config has >>> >>> <Levels><Level name="DIAG" intValue="450"> elements. During >>> configuration >>> >>> processing, the custom Level instances are created and registered, >>> so on >>> >>> the firs >>> >>> > > > -- > Cheers, > Paul > -- E-Mail: garydgreg...@gmail.com | ggreg...@apache.org Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> Spring Batch in Action <http://www.manning.com/templier/> Blog: http://garygregory.wordpress.com Home: http://garygregory.com/ Tweet! http://twitter.com/GaryGregory