[ https://issues.apache.org/jira/browse/LOG4J2-519?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14049618#comment-14049618 ]
Remko Popma commented on LOG4J2-519: ------------------------------------ Update for RC2: {code} static final String METHODS = "" // + "%n" // + " /**%n" // + " * Logs a message with the specific Marker at the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param marker the marker data specific to this log statement%n" // + " * @param msg the message string to be logged%n" // + " */%n" // + " public void methodName(final Marker marker, final Message msg) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msg, (Throwable) null);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message with the specific Marker at the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param marker the marker data specific to this log statement%n" // + " * @param msg the message string to be logged%n" // + " * @param t A Throwable or null.%n" // + " */%n" // + " public void methodName(final Marker marker, final Message msg, final Throwable t) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msg, t);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param marker the marker data specific to this log statement%n" // + " * @param message the message object to log.%n" // + " */%n" // + " public void methodName(final Marker marker, final Object message) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, (Throwable) null);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" // + " * the {@link Throwable} {@code t} passed as parameter.%n" // + " * %n" // + " * @param marker the marker data specific to this log statement%n" // + " * @param message the message to log.%n" // + " * @param t the exception to log, including its stack trace.%n" // + " */%n" // + " public void methodName(final Marker marker, final Object message, final Throwable t) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, t);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param marker the marker data specific to this log statement%n" // + " * @param message the message object to log.%n" // + " */%n" // + " public void methodName(final Marker marker, final String message) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, (Throwable) null);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param marker the marker data specific to this log statement%n" // + " * @param message the message to log; the format depends on the message factory.%n" // + " * @param params parameters to the message.%n" // + " * @see #getMessageFactory()%n" // + " */%n" // + " public void methodName(final Marker marker, final String message, final Object... params) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, params);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" // + " * the {@link Throwable} {@code t} passed as parameter.%n" // + " * %n" // + " * @param marker the marker data specific to this log statement%n" // + " * @param message the message to log.%n" // + " * @param t the exception to log, including its stack trace.%n" // + " */%n" // + " public void methodName(final Marker marker, final String message, final Throwable t) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, t);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs the specified Message at the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param msg the message string to be logged%n" // + " */%n" // + " public void methodName(final Message msg) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msg, (Throwable) null);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs the specified Message at the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param msg the message string to be logged%n" // + " * @param t A Throwable or null.%n" // + " */%n" // + " public void methodName(final Message msg, final Throwable t) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msg, t);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param message the message object to log.%n" // + " */%n" // + " public void methodName(final Object message) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, (Throwable) null);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" // + " * the {@link Throwable} {@code t} passed as parameter.%n" // + " * %n" // + " * @param message the message to log.%n" // + " * @param t the exception to log, including its stack trace.%n" // + " */%n" // + " public void methodName(final Object message, final Throwable t) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, t);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param message the message object to log.%n" // + " */%n" // + " public void methodName(final String message) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, (Throwable) null);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" // + " * %n" // + " * @param message the message to log; the format depends on the message factory.%n" // + " * @param params parameters to the message.%n" // + " * @see #getMessageFactory()%n" // + " */%n" // + " public void methodName(final String message, final Object... params) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, params);%n" // + " }%n" // + "%n" // + " /**%n" // + " * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" // + " * the {@link Throwable} {@code t} passed as parameter.%n" // + " * %n" // + " * @param message the message to log.%n" // + " * @param t the exception to log, including its stack trace.%n" // + " */%n" // + " public void methodName(final String message, final Throwable t) {%n" // + " logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, t);%n" // + " }%n" // ; {code} > Custom/Extended Loggers > ----------------------- > > Key: LOG4J2-519 > URL: https://issues.apache.org/jira/browse/LOG4J2-519 > Project: Log4j 2 > Issue Type: New Feature > Components: API > Affects Versions: 2.0-rc1 > Reporter: Remko Popma > Attachments: Generate.java, Generate_old_20140130.java > > > Please try out the attached [^Generate.java] tool that provides the > functionality described below and give feedback if you notice any issues. > {anchor:Extending} > *[#Extending] the Logger interface* > LOG4J2-41 added support for custom log Levels. Users can now log messages at > the new custom level by passing the custom level to the {{Logger.log()}} > method: > {code} > final Logger logger = LogManager.getLogger(); > final Level VERBOSE = Level.forName("VERBOSE", 550); > logger.log(VERBOSE, "a verbose message"); > logger.log(VERBOSE, "another message"); > {code} > However, custom levels are not as easy to use as the built-in levels: one > needs to call the generic {{log()}} method and pass a {{Level}} parameter. > Built-in levels on the other hand have a set of convenience methods on the > Logger interface. For example, the Logger interface has 14 debug methods that > support the DEBUG level: > {code} > debug(Marker, Message) > debug(Marker, Message, Throwable) > debug(Marker, Object) > debug(Marker, Object, Throwable) > debug(Marker, String) > debug(Marker, String, Object...) > debug(Marker, String, Throwable) > debug(Message) > debug(Message, Throwable) > debug(Object) > debug(Object, Throwable) > debug(String) > debug(String, Object...) > debug(String, Throwable) > {code} > Similar method sets exist for the other built-in levels. > Several people have expressed the desire to have the same ease of use with > custom levels, so after declaring a custom VERBOSE level, we would like to be > able to use code like this: > {code} > logger.verbose("a verbose message"); // no need to pass the VERBOSE level as > a parameter > logger.verbose("another message"); > {code} > {anchor:Customizing} > *[#Customizing] the Logger interface* > In the above use case, convenience methods were _added_ to the Logger > interface, in addition to the existing {{trace()}}, {{debug()}}, {{info()}}, > ... methods for the built-in log levels. > There is another use case, Domain Specific Language loggers, where we want to > _replace_ the existing {{trace()}}, {{debug()}}, {{info()}}, ... methods with > all-custom methods. > For example, for medical devices we could have only {{critical()}}, > {{warning()}}, and {{advisory()}} methods. Another example could be a game > that has only {{defcon1()}}, {{defcon2()}}, and {{defcon3()}} levels. > Finally, if it were possible to hide existing log levels, users could > customize the Logger interface to match their requirements. Some people may > not want to have a {{FATAL}} or a {{TRACE}} level, for example. They would > like to be able to create a custom Logger that only has {{debug()}}, > {{info()}}, {{warn()}} and {{error()}} methods. > {anchor:wrapper} > *Proposal: Generate source code for a Logger [#wrapper]* > Common log4j usage is to get an instance of the {{Logger}} interface from the > {{LogManager}} and call the methods on this interface. This makes it hard to > achieve the above customization; especially taking away existing methods is > not possible. > An alternative is for the user to create a wrapper class that exposes only > the convenience methods for the desired log levels. When _extending_ the > {{Logger}} API (_adding_ methods), this wrapper class could subclass > {{org.apache.logging.log4j.spi.AbstractLoggerWrapper}}. When _customizing_ > the {{Logger}} API (_removing_ built-in methods), the wrapper class would > simply not extend AbstractLoggerWrapper, so the only public methods would be > the methods for the custom log levels. > As the custom log Levels are not known in advance, Log4J cannot provide > pre-built wrapper classes for these custom log Levels. However, we don't want > to ask the users to hand-code such a wrapper class: this is cumbersome and > error-prone: there are 14 methods for each built-in level. To provide > comparable functionality for custom log Levels one would need to provide 14 > methods for each custom log Level. > The proposal is to solve this by providing a tool that generates the source > code for a wrapper class. The user can specify: > * the fully qualified name of the class to generate > * the list of custom levels to support and their {{intLevel}} relative > strength > * whether to extend {{Logger}} (and keep the existing built-in methods) or > have only methods for the custom log levels > and the tool generates the source code for the wrapper class that has exactly > the required methods. Users would include this source code in the project > where they want to use custom log levels. > {anchor:GeneratedWrapperUsage} > Note that no Log4J API changes are required to support this functionality. > Users would create instances of the wrapper by calling a factory method on > the wrapper class, instead of calling the {{LogManager.getLogger()}} methods. > For example, instead of writing: > {code} > import org.apache.logging.log4j.Level; > import org.apache.logging.log4j.LogManager; > import org.apache.logging.log4j.Logger; > final Logger logger = LogManager.getLogger(MyClass.class); // standard log4j > logger > final Level VERBOSE = Level.forName("VERBOSE", 550); > logger.log(VERBOSE, "a verbose message"); > {code} > users would instead write: > {code} > // MyLogger is a generated customized logger wrapper > import com.mycompany.myproject.MyLogger; > final MyLogger logger = MyLogger.create(MyClass.class); > logger.verbose("a verbose message"); > {code} > Creating an extended or customized Logger is as easy as creating a standard > Logger (one line of code). Extended Loggers are drop-in replacements for > standard Loggers - they only add more convenience methods. -- This message was sent by Atlassian JIRA (v6.2#6252) --------------------------------------------------------------------- To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org