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

Reply via email to