Nick, I don't understand your objection. I was not proposing replacing
Logger. All I said was extract out a superinterface. Keep Logger usage how
it is now, if you want -- and what I am recommending.


On Mon, Jan 27, 2014 at 1:15 PM, Nick Williams <
nicho...@nicholaswilliams.net> wrote:

> I would veto such a change, and here is my technical justification:
>
> You will break EVERYTHING currently using the Log4j 2 API.
>
> EVERYTHING that EVERY Log4j 2 user has currently written will have to be
> changed to use StandardLogger instead of Logger. That's not even
> considering the fact that Logger (or ILogger as the case may be) is *the*
> industry standard for logger interface names that provide info(), warn(),
> and other methods. I know that APIs can change when something's still beta,
> but this is a HUGE CHANGE.
>
> However, what I WOULD be okay with is creating a SimpleLogger interface
> for things like log(Level, ...), etc. and having Logger extend SimpleLogger
> to provide info(), warn(), and so on. This would be backwards compatible
> and abide by industry norms.
>
> Nick
>
> On Jan 27, 2014, at 12:46 PM, Gary Gregory wrote:
>
> 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
>
>
>


-- 
Cheers,
Paul

Reply via email to