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 first call to LogManager.getCustomLogger(MyLogger.class), the MyLogger >>> instance is created and cached. Also, at this point the annotations are >>> parsed to see what Level instance the MyLogger implementation will pass to >>> the Logger.log(Level, String) method when the "diag" method is called. >>> >>> What is still open in this scenario is how the instance is created. Proxy? >>> Or generate source & compile? Or use a byte code library? >>> >>> On Monday, January 27, 2014, Ralph Goers <ralph.go...@dslextreme.com> >>> wrote: >>> I am going to have to echo what Nick said. If you can think of a way to >>> make >>> >>> logger.log(SomeClass.SomeLevel, "hello world"); >>> >>> work without actually creating SomeClass then please share! >>> >>> Ralph >>> >>> On Jan 26, 2014, at 7:45 PM, Nick Williams <nicho...@nicholaswilliams.net> >>> wrote: >>> >>>> It would not be possible to do this strictly through configuration >>>> because the user needs a compiled interface to code against. Where is >>>> that compiled interface to come from? >>>> >>>> Nick >>>> >>>>> On Jan 26, 2014, at 9:40 PM, Scott Deboy wrote: >>>>> >>>>> If there is a way to support this strictly through configuration that >>>>> would be ideal. >>>>> >>>>> I'm trying to find a way to remove my request for additional built in >>>>> levels but through configuration instead of adding them ourselves. >>>>> >>>>> Scott >>>>> Scott >>>>> >>>>> On Jan 26, 2014 7:38 PM, "Nick Williams" <nicho...@nicholaswilliams.net> >>>>> wrote: >>>>> Here's a split-off thread for discussing how we can make using custom >>>>> levels easier. Some on the team have expressed a desire to make it even >>>>> easier. Given hypothetical custom levels DIAG and NOTE, the following >>>>> would be nice to have: >>>>> >>>>> logger.note("message"); >>>>> logger.diag("message"); >>>>> etc. >>>>> >>>>> We're to discuss how best to approach this. My proposal (from previous >>>>> email): >>>>> >>>>>> Allow the user to define an interface that /must/ extend Logger. That >>>>>> interface may contain any methods that match the following signatures >>>>>> (the interface must have at least one method and there is no limit to >>>>>> the number of methods it may have): >>>>>> >>>>>> void [methodName](Marker, Message) >>>>>> void [methodName](Marker, Message, Throwable t) >>>>>> void [methodName](Marker, Object) >>>>>> void [methodName](Marker, Object, Throwable t) >>>>>> void [methodName](Marker, String) >>>>>> void [methodName](Marker, String, Object...) >>>>>> void [methodName](Marker, String throwable) >>>>>> void [methodName](Message) >>>>>> void [methodName](Message, Throwable t) >>>>>> void [methodName](Object) >>>>>> void [methodName](Object, Throwable t) >>>>>> void [methodName](String) >>>>>> void [methodName](String, Object...) >>>>>> void [methodName](String throwable) >>>>>> >>>>>> Each method /must/ be annotated with @LoggingLevel(name = >>>>>> "levelName"). Now LogManager has a few new methods: >>>>>> >>>>>> <T extends Logger> T getCustomLogger(Class<T> loggerClass) >>>>>> <T extends Logger> T getCustomLogger(Class<T> loggerClass, Class<?>) >>>>>> <T extends Logger> T getCustomLogger(Class<T> loggerClass, Class<?>, >>>>>> MessageFactory) >>>>>> <T extends Logger> T getCustomLogger(Class<T> loggerClass, >>>>>> MessageFactory) >>>>>> <T extends Logger> T getCustomLogger(Class<T> loggerClass, Object) >>>>>> <T extends Logger> T getCustomLogger(Class<T> loggerClass, Object, >>>>>> MessageFactory) >>>>>> <T extends Logger> T getCustomLogger(Class<T> loggerClass, String) >>>>>> <T extends Logger> T getCustomLogger(Class<T> loggerClass, String, >>>>>> MessageFactory) >>>>>> >>>>>> The user can then obtain such a logger like so, etc.: >>>>>> >>>>>> MyLogger logger = LogManager.getCustomLogger(MyLogger.class); >>>>>> >>>>>> Log4j will generate an implementation of MyLogger that extends the >>>>>> default implementation, cache that implementation so that it doesn't >>>>>> have to be implemented again, and then instantiate/cache the logger >>>>>> instance like normal. >>>>> >>>>> Others have suggested deriving the level name from the method name >>>>> instead of using an annotation. That's a viable alternative. >>>>> >>>>> Matt Sicker asked: >>>>> >>>>>> And can't getCustomLogger also provide a default method that uses the >>>>>> getClassName method? >>>>> >>>>> I think you misunderstand the purpose of the Class<T> argument. It has >>>>> nothing to do with the logger name--it's the class of the Logger >>>>> interface to automatically implement. >>>>> >>>>> Nick >>>>> --------------------------------------------------------------------- >>>>> To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org >>>>> For additional commands, e-mail: log4j-dev-h...@logging.apache.org > > --------------------------------------------------------------------- > To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org > For additional commands, e-mail: log4j-dev-h...@logging.apache.org > --------------------------------------------------------------------- To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org