I see...
I thought the most common use case would be adding custom levels, but I see
now that /taking away existing levels/ is also a use case. Perhaps that
should be a separate code-gen tool, which generates an interface (& impl)
that does not extend from Logger.

One advantage of having the custom logger interface extend Logger is that
the object can be passed to any method that accepts a Logger...

I'm beginning to think these use cases may need to be supported separately.


On Mon, Jan 27, 2014 at 11:51 PM, 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
>>
>>

Reply via email to