Could we leverage Rhino? :) Scott
On 1/26/14, 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 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 > > --------------------------------------------------------------------- To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org