[jira] [Commented] (LOG4J2-599) Support lambda functions (or similar) for log message parameters
[ https://issues.apache.org/jira/browse/LOG4J2-599?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14679377#comment-14679377 ] Bruce Brouwer commented on LOG4J2-599: -- I wonder how well that would work using generics like that. What gotchas will I run into? I have to say that I'm not entirely thrilled with introducing the whole Logger2 interface. The main argument against just adding it to Logger is that anything that implements the Logger interface (particularly something that is not part of the log4j project) will break BC. From a technical standpoint, this is true, but from a practical standpoint, I don't think it is important. I just made a little example project to prove this out, and things don't actually break. If you add a method to the Logger api, implementors of the 2.3 version will not blow up once the 2.4 log4j-api is on the classpath. The only thing that will blow up is if I call the new method and the implementor has not yet implemented it. To me, that seems like a completely reasonable outcome. Consider why I am using the log4j-api 2.4 without a log4j implementation. The only real case I can think of is if if there is a bridge APIs that Log4j doesn't cover. Perhaps a custom logging implementation that some company has. If they did come across a library that required the new methods from log4j-api version 2.4, it doesn't seem that unreasonable to require them to update their custom bridge. And if nothing actually used those new methods, nothing will blow up, which I believe is by far the most likely situation. Other API libraries deal with this exact same issue. For example, JPA when it went from 2.0 to 2.1 added new API methods to the CriteriaBuilder. They weren't forced to version 3.0 simply because they added a new method to an API. And furthermore, I don't like where this will ultimately lead us to. So we know today what we're talking about adding to Logger2, but what about for version 2.5 when there is more stuff we want to add. Do we make Logger3 so that we don't break the BC for Logger2? and then Logger4? That seems ridiculous to me. I would much rather see a few new methods added to the main Logger API. Support lambda functions (or similar) for log message parameters Key: LOG4J2-599 URL: https://issues.apache.org/jira/browse/LOG4J2-599 Project: Log4j 2 Issue Type: Brainstorming Components: Core Reporter: Matt Sicker Assignee: Remko Popma Priority: Minor Labels: Java8 Fix For: 2.4 It would be nice if we could support 0-param lambda functions (or the equivalent: interfaces with a single empty-parameter message call), or more simply, allow Runnables (or something similar) to be passed which will be dynamically executed if the log message is enabled. The use case here is that although string construction of the log message is a performance issue that is already solved quite well, the problem of adding in information to the log message that makes other calculations still needs to be wrapped in an if check. I'm not sure if it'd be best to just use Runnable, or create a new interface, or try to emulate how Java 1.8 lambdas work via an interface with a single method defined. The details here would still need to be fleshed out, but I think this sort of feature could be rather handy (especially in a Java 1.8+ environment, or in Groovy/Scala/etc.). -- This message was sent by Atlassian JIRA (v6.3.4#6332) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org
[jira] [Commented] (LOG4J2-599) Support lambda functions (or similar) for log message parameters
[ https://issues.apache.org/jira/browse/LOG4J2-599?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14679435#comment-14679435 ] Bruce Brouwer commented on LOG4J2-599: -- My test showed that implementors of the old Logger interface continue to load just fine with the newer API. An exception is only thrown when calling the new method. That exception is {{java.lang.AbstractMethodError}} Support lambda functions (or similar) for log message parameters Key: LOG4J2-599 URL: https://issues.apache.org/jira/browse/LOG4J2-599 Project: Log4j 2 Issue Type: Brainstorming Components: Core Reporter: Matt Sicker Assignee: Remko Popma Priority: Minor Labels: Java8 Fix For: 2.4 It would be nice if we could support 0-param lambda functions (or the equivalent: interfaces with a single empty-parameter message call), or more simply, allow Runnables (or something similar) to be passed which will be dynamically executed if the log message is enabled. The use case here is that although string construction of the log message is a performance issue that is already solved quite well, the problem of adding in information to the log message that makes other calculations still needs to be wrapped in an if check. I'm not sure if it'd be best to just use Runnable, or create a new interface, or try to emulate how Java 1.8 lambdas work via an interface with a single method defined. The details here would still need to be fleshed out, but I think this sort of feature could be rather handy (especially in a Java 1.8+ environment, or in Groovy/Scala/etc.). -- This message was sent by Atlassian JIRA (v6.3.4#6332) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org
[jira] [Comment Edited] (LOG4J2-599) Support lambda functions (or similar) for log message parameters
[ https://issues.apache.org/jira/browse/LOG4J2-599?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14679435#comment-14679435 ] Bruce Brouwer edited comment on LOG4J2-599 at 8/10/15 12:42 AM: My test showed that implementors of the old Logger interface continue to load and old methods continue to work just fine with the newer API. An exception is only thrown when calling the new method. That exception is {{java.lang.AbstractMethodError}} was (Author: bruce.brouwer): My test showed that implementors of the old Logger interface continue to load just fine with the newer API. An exception is only thrown when calling the new method. That exception is {{java.lang.AbstractMethodError}} Support lambda functions (or similar) for log message parameters Key: LOG4J2-599 URL: https://issues.apache.org/jira/browse/LOG4J2-599 Project: Log4j 2 Issue Type: Brainstorming Components: Core Reporter: Matt Sicker Assignee: Remko Popma Priority: Minor Labels: Java8 Fix For: 2.4 It would be nice if we could support 0-param lambda functions (or the equivalent: interfaces with a single empty-parameter message call), or more simply, allow Runnables (or something similar) to be passed which will be dynamically executed if the log message is enabled. The use case here is that although string construction of the log message is a performance issue that is already solved quite well, the problem of adding in information to the log message that makes other calculations still needs to be wrapped in an if check. I'm not sure if it'd be best to just use Runnable, or create a new interface, or try to emulate how Java 1.8 lambdas work via an interface with a single method defined. The details here would still need to be fleshed out, but I think this sort of feature could be rather handy (especially in a Java 1.8+ environment, or in Groovy/Scala/etc.). -- This message was sent by Atlassian JIRA (v6.3.4#6332) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org
[jira] [Commented] (LOG4J2-599) Support lambda functions (or similar) for log message parameters
[ https://issues.apache.org/jira/browse/LOG4J2-599?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14661006#comment-14661006 ] Bruce Brouwer commented on LOG4J2-599: -- Could we avoid the whole api change thing by having a static method that I could static import which had a signature something like public static Object lazyParam(Callable param) { return param; } Then it would be simple to even mix and match lazy and non-lazy params. logger.trace(msg {} {}, lazyParam(() - expensive operation()), nonLazy); On Aug 6, 2015 7:04 PM, Remko Popma (JIRA) j...@apache.org wrote: [ https://issues.apache.org/jira/browse/LOG4J2-599?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14660945#comment-14660945 ] Remko Popma commented on LOG4J2-599: That is the use case for this ticket: users on Java 8 will be able to avoid the explicit level check and instead write {code} logger.trace(Some expensive operation returned {}, () - expensiveOperation()); {code} resulting in more compact and cleaner code. The only logging product that I am aware of that currently supports lambda expressions for lazy logging is the JDK [Logger| http://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#log-java.util.logging.Level-java.util.function.Supplier-]. But IMHO the JDK Logger is only doing a partial job: it only lazily constructs the whole log message. There is no API for lazily constructing message parameters. I think keeping up to date with Java language developments makes this a strategic feature that adds to the reasons why Log4j 2 is the logging library of choice for our users. equivalent: interfaces with a single empty-parameter message call), or more simply, allow Runnables (or something similar) to be passed which will be dynamically executed if the log message is enabled. is a performance issue that is already solved quite well, the problem of adding in information to the log message that makes other calculations still needs to be wrapped in an if check. interface, or try to emulate how Java 1.8 lambdas work via an interface with a single method defined. The details here would still need to be fleshed out, but I think this sort of feature could be rather handy (especially in a Java 1.8+ environment, or in Groovy/Scala/etc.). -- This message was sent by Atlassian JIRA (v6.3.4#6332) Support lambda functions (or similar) for log message parameters Key: LOG4J2-599 URL: https://issues.apache.org/jira/browse/LOG4J2-599 Project: Log4j 2 Issue Type: Brainstorming Components: Core Reporter: Matt Sicker Priority: Minor Labels: Java8 It would be nice if we could support 0-param lambda functions (or the equivalent: interfaces with a single empty-parameter message call), or more simply, allow Runnables (or something similar) to be passed which will be dynamically executed if the log message is enabled. The use case here is that although string construction of the log message is a performance issue that is already solved quite well, the problem of adding in information to the log message that makes other calculations still needs to be wrapped in an if check. I'm not sure if it'd be best to just use Runnable, or create a new interface, or try to emulate how Java 1.8 lambdas work via an interface with a single method defined. The details here would still need to be fleshed out, but I think this sort of feature could be rather handy (especially in a Java 1.8+ environment, or in Groovy/Scala/etc.). -- This message was sent by Atlassian JIRA (v6.3.4#6332) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org
[jira] [Assigned] (LOG4J2-514) ConsoleAppender closing System.out on Windows
[ https://issues.apache.org/jira/browse/LOG4J2-514?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer reassigned LOG4J2-514: Assignee: Bruce Brouwer ConsoleAppender closing System.out on Windows - Key: LOG4J2-514 URL: https://issues.apache.org/jira/browse/LOG4J2-514 Project: Log4j 2 Issue Type: Bug Components: Appenders Affects Versions: 2.0-beta9 Environment: Windows 7 64-bit Oracle JDK 1.7.0_51 Reporter: Wolf480 Pl Assignee: Bruce Brouwer Attachments: LOG4J2-514.patch.txt If the Console appender is not specified in the configuration file, after the configuration is read, the Console appender is being destroyed, which causes it to release its OutputStreamManager, When this manager is released and closed, it checks if the stream is System.out or System.err, and if it is, doesn't close it. But on Windows, ConsoleAppender wraps the System.out into a WindowsAnsiOutputStream. The OutputStreamManager closes the stream when it's released, and the stream closes the underlaying System.out. proof: http://imageshack.com/a/img31/8296/cg6b.png -I think the easiest solution would be to use new FileOutputStream(FileDescriptor.out)) instead of System.out in ConsoleAppender implementation.- unfortunately, that would still cause System.out to be closed. A solution would be to wrap System.out with some FilterStream that overrides close() to do nothing. -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14062201#comment-14062201 ] Bruce Brouwer commented on LOG4J2-609: -- Why should the {{StatusData}} constructor be public (other than it is a small breaking API change)? Nothing should be creating these {{StatusData}} objects other than {{StatusLogger}}. The only thing that ever registered {{StatusConsoleListener}} was {{JsonConfiguration}} or {{XmlConfiguration}}, both of which are in -core. So if someone only included log4j-api, the behavior now will be the same now as before. Well, I suppose it is a little different than before. Before, the default level was FATAL, so {{StatusLogger.getLogger().isEnabled(Level.FATAL, null)}} would return true, even though it wouldn't actually do anything when {{.fatal(some error)}} was called. Now, I did like the suggestion that Matt made where perhaps sending {{StatusLogger}} output to {{System.out}} or {{System.err}} should have nothing to do with {{JsonConfiguration}} or {{XmlConfiguration}}, but rather should be configured from the Log4j properties. I would be on board with that change as long as we rip out that configuration from {{JsonConfiguration}} and {{XmlConfiguration}}. This way if I only included log4j-api, I could still get some messages to show on {{System.out}}. I actually would like this change very much. Right now, nothing will ever remove that {{StatusConsoleListener}}. With changing this to use Log4j properties, nobody would expect the ability to turn off {{StatusLogger}} output to {{System.out}}. In fact, I probably wouldn't even implement this as a {{StatusListener}}, but rather directly inside {{StatusLogger}}. What do you say to that? StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: LOG4J2-609.unfinished.patch, log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14062219#comment-14062219 ] Bruce Brouwer commented on LOG4J2-609: -- You know, since this would be the majority case, this could simplify {{StatusLogger}} even further by not requiring it to keep a bounded list of past Status messages. No longer would we expect future listeners to receive past status messages. There would be no longer be any chance that Status messages would be lost when being sent to {{System.out}}. StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: LOG4J2-609.unfinished.patch, log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14062503#comment-14062503 ] Bruce Brouwer commented on LOG4J2-609: -- I will relent on the public constructor for {{StatusData}}. You're right about the {{SimpleLogger.isEnabled(...)}}. I should have been looking at the code when I wrote my statements. I updated it on the branch according to my next statements. With all the talk about how to configure log4j so that status logs go the stdout or stderr, I decided to try out the approach of making a log4j property that controls what goes to System.out or System.err. I think it makes it much simpler. It eliminates {{StatusConsoleListener}} completely. I'm looking for some feedback on this idea. StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: LOG4J2-609.unfinished.patch, log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14063016#comment-14063016 ] Bruce Brouwer commented on LOG4J2-609: -- I had to revert most of that last simplification as it was causing too much impact for now. Please check what is there now. StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: LOG4J2-609.unfinished.patch, log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14060930#comment-14060930 ] Bruce Brouwer commented on LOG4J2-609: -- # You're right. .getStatusLevel() can remain. The important part was removing the caching of .getStatusLevel() from StatusLogger. I put that back to the way it was before. As for .registerListener(...), the code on the branch was simplified beyond what is identified in this JIRA as a result of the mailing list discussion. That is why no such parameter is added to .registerListener(...) on the branch. It isn't necessary on .registerListener(...) with this simplification. # I was originally thinking that status listeners might make some decision based on the Marker. Also, why not include the marker. Every other piece of information from the logged message is included. I'm guessing nothing that uses StatusLogger provides a marker so I can see your point from that perspective. But if we decide to start doing more with StatusLogger and Markers, it is ready. To prevent the StatusData constructor becoming part of the public API (and possibly making it harder to add a Marker in the future) I made the constructor package private. This will allow us to add the Marker back in later without being considered a breaking API change. What do you think of that? If people like this, I'm pretty happy with the way it has turned out without being too impactful. To recap what was mentioned on the mailing list, * The StatusLogger no longer maintains a cached copy of the logger level * StatusConsoleListener was moved to log4j-core with subclasses of StatusStdErrListener and StatusStdOutListener which correctly track changes to System.out and System.err * There is no longer an option in XML or JSON configuration to direct StatusLogger messages to a file; only System.out and/or System.err StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: LOG4J2-609.unfinished.patch, log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Comment Edited] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14060930#comment-14060930 ] Bruce Brouwer edited comment on LOG4J2-609 at 7/14/14 5:50 PM: --- # You're right. .getStatusLevel() can remain. The important part was removing the caching of .getStatusLevel() from StatusLogger. I put that back to the way it was before. As for .registerListener(...), the code on the branch was simplified beyond what is identified in this JIRA as a result of the mailing list discussion. That is why no such parameter is added to .registerListener(...) on the branch. It isn't necessary on .registerListener(...) with this simplification. # I was originally thinking that status listeners might make some decision based on the Marker. Also, why not include the marker. Every other piece of information from the logged message is included. I'm guessing nothing that uses StatusLogger provides a marker so I can see your point from that perspective. But if we decide to start doing more with StatusLogger and Markers, it is ready. To prevent the StatusData constructor becoming part of the public API (and possibly making it harder to add a Marker in the future) I made the constructor package private. This will allow us to add the Marker back in later without being considered a breaking API change. What do you think of that? If people like this, I'm pretty happy with the way it has turned out without being too impactful. To recap what has actually changed: * The StatusLogger no longer maintains a cached copy of the logger level * StatusConsoleListener was moved to log4j-core with subclasses of StatusStdErrListener and StatusStdOutListener which correctly track changes to System.out and System.err * There is no longer an option in XML or JSON configuration to direct StatusLogger messages to a file; only System.out and/or System.err was (Author: bruce.brouwer): # You're right. .getStatusLevel() can remain. The important part was removing the caching of .getStatusLevel() from StatusLogger. I put that back to the way it was before. As for .registerListener(...), the code on the branch was simplified beyond what is identified in this JIRA as a result of the mailing list discussion. That is why no such parameter is added to .registerListener(...) on the branch. It isn't necessary on .registerListener(...) with this simplification. # I was originally thinking that status listeners might make some decision based on the Marker. Also, why not include the marker. Every other piece of information from the logged message is included. I'm guessing nothing that uses StatusLogger provides a marker so I can see your point from that perspective. But if we decide to start doing more with StatusLogger and Markers, it is ready. To prevent the StatusData constructor becoming part of the public API (and possibly making it harder to add a Marker in the future) I made the constructor package private. This will allow us to add the Marker back in later without being considered a breaking API change. What do you think of that? If people like this, I'm pretty happy with the way it has turned out without being too impactful. To recap what was mentioned on the mailing list, * The StatusLogger no longer maintains a cached copy of the logger level * StatusConsoleListener was moved to log4j-core with subclasses of StatusStdErrListener and StatusStdOutListener which correctly track changes to System.out and System.err * There is no longer an option in XML or JSON configuration to direct StatusLogger messages to a file; only System.out and/or System.err StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: LOG4J2-609.unfinished.patch, log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- This message was sent by Atlassian JIRA (v6.2#6252) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands,
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14019805#comment-14019805 ] Bruce Brouwer commented on LOG4J2-609: -- I forgot one other point: 5. I removed StatusListener.getStatusLevel() and moved it to a parameter on StatusLogger.registerListener(...). Before, I might be inclined to allow my listener to change its level, but that would actually not work in many cases. It seemed better to require a listener to be removed and then re-registered if you wanted to change the status level. StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: LOG4J2-609.unfinished.patch, log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Updated] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-609: - Attachment: LOG4J2-609.unfinished.patch Here is my second attempt. It's going to require some explanation. It isn't finished, but I wanted to get your thoughts. # Using just a listener that many configurations shared will not work when they each want to log at a different level. The real goal is to make configure (or filter) which status logs end up on System.out or System.err or some file. So rather than a single registerListener which takes a StatusListener, I have added registerSystemOutFilter, registerSystemErrFilter and registerFileFilter. This way, each configuration can register its own filter and the StatusLogger will look for the least specific filter for the specified target and log at that level. # Rather than a single fall-back SimpleLogger, there is now a SimpleLogger registered for System.out, System.err and each file filter that is registered. I don't know if that simplified the code much, but at least the logging statements are much closer to a straight pass-through for the majority of cases # The only thing that is using registerListener now is jmx.StatusLoggerAdmin some JmsTests in log4j-core, which I haven't figured out why they are there yet. # I refactored away StatusConfiguration in favor of AbstractStatusLoggingConfiguration so that XmlConfiguration and JsonConfiguration can be more consistent in their configuration. The only different I saw is that they had seemingly opposite behavior for what verbose meant, and even if you don't consider it opposite (the terminology I think is confusing) they were definitely using different values (true/false vs. quiet/verbose). StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: LOG4J2-609.unfinished.patch, log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=14019537#comment-14019537 ] Bruce Brouwer commented on LOG4J2-609: -- I don't think there is anything in there that will cause stdout or stderr to be closed. By making SimpleLogger implement Closeable, it does open that possibility for someone using their own SimpleLogger to do that, but in this code StatusLogger never closes SimpleLogger instances that represent stdout or stderr. The only SimpleLoggers that get closed are the ones that are created for files. And as I said, it isn't finished yet, but I think it is close, at least conceptually. StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: LOG4J2-609.unfinished.patch, log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Closed] (LOG4J2-242) Make Messages more fluent
[ https://issues.apache.org/jira/browse/LOG4J2-242?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer closed LOG4J2-242. Make Messages more fluent - Key: LOG4J2-242 URL: https://issues.apache.org/jira/browse/LOG4J2-242 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-beta5 Reporter: Bruce Brouwer Assignee: Nick Williams Labels: backlog Attachments: LOG4J2-242.patch Original Estimate: 48h Remaining Estimate: 48h I really like the feature were we can pass in a Message object into the logger methods. However, it bugs me that some of the implementations of Message provide vararg constructors, and others only provide an Object[] parameter. I really would like to write this code: log.info(new ParameterizedMessage(abc: {} xyz: {}, abc, xyz), throwable); I realize that this particular example would work with this code by default: log.info(abc: {} xyz: {}, abc, xyz, throwable); But the other Message implementations don't provide a vararg constructor, nor do they try to detect the last parameter as a Throwable. [LOG4J2-48] addresses some of the complexity of having varargs with the last vararg being an implicit final parameter, but again, this only works with ParameterizedMessage. But I would like this to be more consistent across the board. One idea that I had was this: log.info(new ParameterizedMessage(abc: {} xyz: {}, abc, xyz).throwing(throwable)); Now all of the message constructors (not just ParameterizedMessage) could have varargs with none of them providing a Throwable parameter in the constructor, but provided through a more fluent API. I don't know that it would warrant adding it to the Message interface, but we could go further with it by adding these methods: Message withParameters(Object... parameters); Message throwing(Throwable throwable); It wouldn't be absolutely necessary as the concrete implementations could define that and work in my case. Another idea that I had was maybe a bit more impactful to the Logger API. What if I wrote my code like this: log.with(exception).info(abc: {} xyz: {}, abc, xyz); // or maybe this log.message(abc: {} xyz: {}, abc, xyz).with(exception).info(); That would necessitate something like a LogBuilder interface, maybe tie it into the MessageFactory classes. This LogBuilder interface could have these methods: LogBuilder message(String pattern, Object... params); LogBuilder with(Throwable t); LogBuilder marker(Marker marker); LogBuilder level(Level level); void info(); // and others like it void info(String pattern, Object... params); // and others like it I'm not exactly sure what the best way would be to go and implement this as I'm sure you don't want to have objects created all over the place. Is this an idea worth pursuing a bit further? -- 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
[jira] [Closed] (LOG4J2-439) Create a LogEventPatternConverter to escape newlines and HTML special characters
[ https://issues.apache.org/jira/browse/LOG4J2-439?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer closed LOG4J2-439. Create a LogEventPatternConverter to escape newlines and HTML special characters Key: LOG4J2-439 URL: https://issues.apache.org/jira/browse/LOG4J2-439 Project: Log4j 2 Issue Type: New Feature Components: Layouts Affects Versions: 2.0-beta9 Reporter: Bruce Brouwer Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: EncodingPatternConverter.patch, log4j2-439-doc.patch To prevent log forging and HTML based attacks from viewing logs in a browser, we could add a LogEventPatternConverter that escapes newlines and HTML special characters. [ESAPI has a method to do this|http://owasp-esapi-java.googlecode.com/svn/trunk_doc/2.0-rc7/apidocs/org/owasp/esapi/Logger.html], but it doesn't have any of the nice API features that Log4j 2 has. I was able to create a LogEventPatternConverter to do this. Note, this is only a proof of concept. I didn't try to exhaustively list all the special characters that might need to be replaced. I also didn't provide any configuration so we could choose to not escape HTML, for example. With this configuration: {code:xml} PatternLayout pattern=%d %-5p [%t] %c %encode{%m}%n/ {code} And logging this message: {code} LOG.warn(hi\n h1 there); {code} Would result in this being logged: {code} 2013-10-28 16:31:21,606 WARN [main] example.Test hi\n amp; lt;h1gt; there {code} instead of this (which shows the potential for log forging): {code} 2013-10-28 16:31:21,606 WARN [main] example.Test hi h1 there {code} This is roughly the code I used: {code} @Plugin(name = escape, category = Converter) @ConverterKeys({ escape }) public final class EscapingReplacementConverter extends LogEventPatternConverter { private final ListPatternFormatter formatters; private EscapingReplacementConverter(final ListPatternFormatter formatters) { super(escape, escape); this.formatters = formatters; } public static EscapingReplacementConverter newInstance(final Configuration config, final String[] options) { if (options.length != 1) { LOGGER.error(Incorrect number of options on escape. Expected 1, received + options.length); return null; } if (options[0] == null) { LOGGER.error(No pattern supplied on escape); return null; } final PatternParser parser = PatternLayout.createPatternParser(config); final ListPatternFormatter formatters = parser.parse(options[0]); return new EscapingReplacementConverter(formatters); } @Override public void format(final LogEvent event, final StringBuilder toAppendTo) { final StringBuilder buf = new StringBuilder(); for (final PatternFormatter formatter : formatters) { formatter.format(event, buf); } toAppendTo.append(buf.toString() .replaceAll(\\r, r) .replaceAll(\\n, n) .replaceAll(, amp;) .replaceAll(, lt;) .replaceAll(, gt;)); } } {code} If this sounds good, I would like to hear feedback and ideas on how to make this better. I will then contribute this to the project. Do you think this could this get in 2.0? -- 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
[jira] [Closed] (LOG4J2-558) Create a log4j-bom
[ https://issues.apache.org/jira/browse/LOG4J2-558?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer closed LOG4J2-558. Create a log4j-bom -- Key: LOG4J2-558 URL: https://issues.apache.org/jira/browse/LOG4J2-558 Project: Log4j 2 Issue Type: Improvement Reporter: Bruce Brouwer Assignee: Matt Sicker Fix For: 2.0-rc2 Attachments: log4j-bom.patch Create a log4j-bom (Bill of Materials) POM to make it easier for clients to keep consistent versions for multiple log4j artifacts. -- 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
[jira] [Closed] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer closed LOG4J2-585. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Fix For: 2.0-rc2 Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13986527#comment-13986527 ] Bruce Brouwer commented on LOG4J2-609: -- It seemed odd to me that a configuration (be it XMLConfiguration or JSONConfiguration) would modify a different configuration's listener. I thought it would be better if each configuration held onto a reference of its own StatusConsoleListener and unregistered it at appropriate times (e.g. reconfigure or close). This way, if I modified my XML config file to switch from one destination file to another destination file, the old destination file will get closed and the new destination file will start to be used. In the original code, there would be no switch from the previous destination to the new destination file and no way to close the destination file. This is probably the most impactful part of my change, so I appreciate that you are looking carefully into what I did. StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13986604#comment-13986604 ] Bruce Brouwer commented on LOG4J2-609: -- Ah yes, I wasn't thinking about that. I'll have to come up with a different solution then. StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Assignee: Ralph Goers Attachments: log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Updated] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-609: - Attachment: log4j2-609.patch With log4j2-609.patch, now all tests pass with a clean install on Windows. This patch gets into some of the deeper guts of log4j that I haven't had to deal with before, so I would appreciate someone vetting what I did. But at least all the tests pass, so that's good. StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: log4j2-609.patch {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Created] (LOG4J2-609) StatusConfiguration doesn't close files
Bruce Brouwer created LOG4J2-609: Summary: StatusConfiguration doesn't close files Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer org.apache.logging.log4j.core.config.status.StatusConfiguration allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a StatusConsoleListener that is added to the StatusLogger. Those StatusLogger listeners are never cleaned up when the XmlConfiguration is reconfigured or when the LoggerContext is shut down (e.g. in InitialLoggerContext.apply()). This leaves open file handles and is the source of the failing test FileOutputTest on Windows. -- 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
[jira] [Updated] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-609: - Description: {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. (was: org.apache.logging.log4j.core.config.status.StatusConfiguration allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a StatusConsoleListener that is added to the StatusLogger. Those StatusLogger listeners are never cleaned up when the XmlConfiguration is reconfigured or when the LoggerContext is shut down (e.g. in InitialLoggerContext.apply()). This leaves open file handles and is the source of the failing test FileOutputTest on Windows. ) StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13976289#comment-13976289 ] Bruce Brouwer commented on LOG4J2-609: -- It is also not clear to me why {{StatusConfiguration}} keeps a static reference to {{System.out}}. {{System.out}} can change over time. I've been digging into this for a little while because I wanted to provide a patch, but it is not obvious to me where the right place is to fix this. I could use some guidance, or I could let someone else take this one on. StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Commented] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13976301#comment-13976301 ] Bruce Brouwer commented on LOG4J2-609: -- Why is {{StatusConfiguration.configureExistingStatusConsoleListener}} reconfiguring all {{StatusConsoleListener}}s? If I had multiple {{LoggerContext}}s with different XML configurations, why should the newest {{LoggerContext}} be modifying the listeners from other {{LoggerContext}}s? If a {{LoggerContext}} is shutting down or being reconfigured, I would think it should only mess around with the listeners that it had registered. What I was thinking of doing was changing {{StatusConfiguration.initialize()}} to return a {{StatusConsoleListener}}, which {{XMLConfiguration}} could store in a field so that when {{XMLConfiguration.stop()}} or {{XMLConfiguration.reconfigure()}} is called, it can unregister just its own listener from the {{StatusLogger}}. Then it could add a new listener if necessary, such as when calling {{reconfigure()}}. Or maybe it keeps the {{StatusConfiguration}} object in a field instead and calls a new {{StatusConfiguration.stop()}} method that unregisters whatever it registered. I'm not an expert in here. Am I thinking about this correctly? StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Comment Edited] (LOG4J2-609) StatusConfiguration doesn't close files
[ https://issues.apache.org/jira/browse/LOG4J2-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13976301#comment-13976301 ] Bruce Brouwer edited comment on LOG4J2-609 at 4/22/14 2:13 AM: --- Why is {{StatusConfiguration.configureExistingStatusConsoleListener}} reconfiguring all {{StatusConsoleListener}} instances? If I had multiple {{LoggerContext}} instances with different XML configurations, why should the newest {{LoggerContext}} be modifying the listeners from other {{LoggerContext}} instances? If a {{LoggerContext}} is shutting down or being reconfigured, I would think it should only mess around with the listeners that it had registered. What I was thinking of doing was changing {{StatusConfiguration.initialize()}} to return a {{StatusConsoleListener}}, which {{XMLConfiguration}} could store in a field so that when {{XMLConfiguration.stop()}} or {{XMLConfiguration.reconfigure()}} is called, it can unregister just its own listener from the {{StatusLogger}}. Then it could add a new listener if necessary, such as when calling {{reconfigure()}}. Or maybe it keeps the {{StatusConfiguration}} object in a field instead and calls a new {{StatusConfiguration.stop()}} method that unregisters whatever it registered. I'm not an expert in here. Am I thinking about this correctly? was (Author: bruce.brouwer): Why is {{StatusConfiguration.configureExistingStatusConsoleListener}} reconfiguring all {{StatusConsoleListener}}s? If I had multiple {{LoggerContext}}s with different XML configurations, why should the newest {{LoggerContext}} be modifying the listeners from other {{LoggerContext}}s? If a {{LoggerContext}} is shutting down or being reconfigured, I would think it should only mess around with the listeners that it had registered. What I was thinking of doing was changing {{StatusConfiguration.initialize()}} to return a {{StatusConsoleListener}}, which {{XMLConfiguration}} could store in a field so that when {{XMLConfiguration.stop()}} or {{XMLConfiguration.reconfigure()}} is called, it can unregister just its own listener from the {{StatusLogger}}. Then it could add a new listener if necessary, such as when calling {{reconfigure()}}. Or maybe it keeps the {{StatusConfiguration}} object in a field instead and calls a new {{StatusConfiguration.stop()}} method that unregisters whatever it registered. I'm not an expert in here. Am I thinking about this correctly? StatusConfiguration doesn't close files --- Key: LOG4J2-609 URL: https://issues.apache.org/jira/browse/LOG4J2-609 Project: Log4j 2 Issue Type: Bug Components: Core Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer {{org.apache.logging.log4j.core.config.status.StatusConfiguration}} allows you to specify a destination such as out, err or a file name. If specifying a file, that file stream is used when creating a {{StatusConsoleListener}} that is added to the {{StatusLogger}}. Those {{StatusLogger}} listeners are never cleaned up when, for example, the {{XmlConfiguration}} is reconfigured or when the {{LoggerContext}} is shut down (e.g. in {{InitialLoggerContext.apply()}}). This leaves open file handles and is the source of the failing test {{FileOutputTest}} on Windows. -- 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
[jira] [Updated] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-547: - Attachment: (was: log4j2-547-builders-and-more.patch) Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: 0001-PrintStream-API-update.patch, MyBenchmark.java, PerfTestCalcLocation.java, log4j2-547-bbrouwer.patch, log4j2-547-new-module.patch, log4j2-547-remove-streams.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Comment Edited] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13972262#comment-13972262 ] Bruce Brouwer edited comment on LOG4J2-547 at 4/17/14 12:13 PM: I like the builder idea too. I was just following the pattern that all other Java related streams take. So I decided to take a stab at it with log4j2-547-builders.patch. Also in that patch are some things that I missed originally, so here's what it includes: * LoggerStreams.Builder (and related classes) * Updated log4j-bom to include streams * Moved helper classes into a .helpers package I haven't written the tests because I wanted to hear some feedback on the approach. was (Author: bruce.brouwer): I like the builder idea too. I was just following the pattern that all other Java related streams take. So I decided to take a stab at it with log4j2-547-builders-and-more.patch. Also in that patch are some things that I missed originally, so here's what it includes: * Builders * Updated log4j-bom to include streams * Moved helper classes into a .helpers package I haven't written the tests because I wanted to hear some feedback on the approach. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: 0001-PrintStream-API-update.patch, MyBenchmark.java, PerfTestCalcLocation.java, log4j2-547-bbrouwer.patch, log4j2-547-builders.patch, log4j2-547-new-module.patch, log4j2-547-remove-streams.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Updated] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-547: - Attachment: log4j2-547-builders.patch Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: 0001-PrintStream-API-update.patch, MyBenchmark.java, PerfTestCalcLocation.java, log4j2-547-bbrouwer.patch, log4j2-547-builders.patch, log4j2-547-new-module.patch, log4j2-547-remove-streams.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Updated] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-547: - Attachment: log4j2-547-builders-and-more.patch I like the builder idea too. I was just following the pattern that all other Java related streams take. So I decided to take a stab at it with log4j2-547-builders-and-more.patch. Also in that patch are some things that I missed originally, so here's what it includes: * Builders * Updated log4j-bom to include streams * Moved helper classes into a .helpers package I haven't written the tests because I wanted to hear some feedback on the approach. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: 0001-PrintStream-API-update.patch, MyBenchmark.java, PerfTestCalcLocation.java, log4j2-547-bbrouwer.patch, log4j2-547-builders-and-more.patch, log4j2-547-new-module.patch, log4j2-547-remove-streams.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13967953#comment-13967953 ] Bruce Brouwer commented on LOG4J2-585: -- * I like the new fluent API. * Do you think it will be confusing that we have one method called simply set, add or remove, while the getter is called getParents()? I'm thinking particularly about the set vs. getParents. * You synchronized add and remove, but not set. I know it isn't absolutely necessary, but might it cause confusing behavior if some race condition occurred from client code calling add and set concurrently? I doubt synchronizing set is going to cause serious performance problems. * Commentary: Alternatively, in getParents, you could simply return {{Arrays.copyOf(this.parents, this.parents.length);}} instead of creating a temporary array and calling {{System.arraycopy(...)}}. But what you wrote works perfectly fine. * It looks like you implemented what I asked regarding {{this.isInstanceOf(parent)}} by implementing that {{contains}} method. I like it. Thanks. * I see you deprecated the getMarker methods that specify a parent. Thanks. Is it the plan to remove deprecated methods before 2.0 GA? Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Resolved] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer resolved LOG4J2-585. -- Resolution: Fixed Fix Version/s: 2.0-rc2 Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Fix For: 2.0-rc2 Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Updated] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-547: - Attachment: log4j2-547-new-module.patch I've added log4j2-547-new-module.patch. It makes a new module called log4j-streams. It also changes the direction of looking for FQCN. It also includes tests to show that FQCN works for the streams. As I cannot create a branch, I'm providing this patch. You can decide how to apply this patch, either as a branch or into trunk. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: 0001-PrintStream-API-update.patch, MyBenchmark.java, PerfTestCalcLocation.java, log4j2-547-bbrouwer.patch, log4j2-547-new-module.patch, log4j2-547-remove-streams.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13961566#comment-13961566 ] Bruce Brouwer commented on LOG4J2-585: -- So, here are my thoughts. Maybe some of these should be made into new JIRAs. * Are we ok with getMarker sometimes creating a marker with the specified parents and sometimes returning a marker with a potentially different parent hierarchy? This is why my concept renamed those methods to define(name, parents...). * Do we want a version of getMarker (or define) that takes a list of parent marker names, in addition to the new one that takes a list of marker instances? * Should it be ok to add a parent twice in the hierarchy, once as a grand parent, once as a parent? If I was allowed to add marker X as an immediate parent of Y when X already existed as a grandparent, then removing the X grandparent would allow marker Y to remain an instance of X. The current implementation would not allow me to add X as a parent of Y and thus removing grandparent X would make Y no longer an instance of X, even though I explicitly specified I wanted X to be an immediate parent of Y. (This one is pretty minor and I'm willing to accept what is done) * Log4jMarker.getParents() should return a copy of the array so I can't change the contents from outside the control of log4j * Would a switch statement in Log4jMarker.isInstanceOf provide better performance, so there aren't multiple length checks? * slf4j-impl Log4jMarker is still backwards, treating parents as children and children as parents. My concept code showed how I took care of this. In most cases, there is no real performance penalty. * In slf4j-impl Log4jMarkerFactory.getDetachedMarker(), my impression was that it should create a marker that wasn't actually attached yet to log4j, but by adding it as a child to a parent that is attached would then make it attached. This implementation essentially creates the slf4j marker as already attached. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Comment Edited] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13961566#comment-13961566 ] Bruce Brouwer edited comment on LOG4J2-585 at 4/6/14 11:44 PM: --- So, here are my thoughts. Maybe some of these should be made into new JIRAs. * Are we ok with getMarker sometimes creating a marker with the specified parents and sometimes returning a marker with a potentially different parent hierarchy? This is why my concept renamed those methods to define(name, parents...). * Do we want a version of getMarker (or define) that takes a list of parent marker names, in addition to the new one that takes a list of marker instances? * Should it be ok to add a parent twice in the hierarchy, once as a grand parent, once as a parent? If I was allowed to add marker X as an immediate parent of Y when X already existed as a grandparent, then removing the X grandparent would allow marker Y to remain an instance of X. The current implementation would not allow me to add X as a parent of Y and thus removing grandparent X would make Y no longer an instance of X, even though I explicitly specified I wanted X to be an immediate parent of Y. (This one is pretty minor and I'm willing to accept what is done) * Log4jMarker.getParents() should return a copy of the array so I can't change the contents from outside the control of log4j * Would a switch statement in Log4jMarker.isInstanceOf provide better performance, so there aren't multiple length checks? * In slf4j-impl Log4jMarkerFactory.getDetachedMarker(), my impression was that it should create a marker that wasn't actually attached yet to log4j, but by adding it as a child to a parent that is attached would then make it attached. This implementation essentially creates the slf4j marker as already attached. was (Author: bruce.brouwer): So, here are my thoughts. Maybe some of these should be made into new JIRAs. * Are we ok with getMarker sometimes creating a marker with the specified parents and sometimes returning a marker with a potentially different parent hierarchy? This is why my concept renamed those methods to define(name, parents...). * Do we want a version of getMarker (or define) that takes a list of parent marker names, in addition to the new one that takes a list of marker instances? * Should it be ok to add a parent twice in the hierarchy, once as a grand parent, once as a parent? If I was allowed to add marker X as an immediate parent of Y when X already existed as a grandparent, then removing the X grandparent would allow marker Y to remain an instance of X. The current implementation would not allow me to add X as a parent of Y and thus removing grandparent X would make Y no longer an instance of X, even though I explicitly specified I wanted X to be an immediate parent of Y. (This one is pretty minor and I'm willing to accept what is done) * Log4jMarker.getParents() should return a copy of the array so I can't change the contents from outside the control of log4j * Would a switch statement in Log4jMarker.isInstanceOf provide better performance, so there aren't multiple length checks? * slf4j-impl Log4jMarker is still backwards, treating parents as children and children as parents. My concept code showed how I took care of this. In most cases, there is no real performance penalty. * In slf4j-impl Log4jMarkerFactory.getDetachedMarker(), my impression was that it should create a marker that wasn't actually attached yet to log4j, but by adding it as a child to a parent that is attached would then make it attached. This implementation essentially creates the slf4j marker as already attached. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13961593#comment-13961593 ] Bruce Brouwer commented on LOG4J2-585: -- * Well, my recommendation in using define is that it would actually change the parent hierarchy to be what is listed, so it is different than the current .getMarker(...). This way if I wasn't careful in my code, I wouldn't have to worry about the order of calls between .getMarker(name) and .define(name, parents...) (think if my markers are static member variables and I have little control over the order of class initialization). If getMarker(name) did somehow get called before define(name, parents...) they would both be pointing at the same marker and with the parent heirarchy I desired. I just now need to make sure that I only call define(name, parents...) once for each marker name. * Cool, thanks * I'm not talking about a cycle. I agree we need to avoid cycles. given A - B - C (A is child, B is parent, C is grand parent). If I add C to A, there is no cycle, it just is doubly parented on C. The cycle would happen if I tried to add A as a parent of C. The check {{parent.isInstanceOf(this)}} is completely valid and is what checks for the cycle. The check {{this.isInstanceOf(parent)}} is what I'm asking to change to only check immediate parents. * Cool, thanks * When I implemented this in my concept, I simply had the marker reference be null until it was attached. Once I add that detached marker to another attached marker, my reference to the detached marker should be considered invalid. Any use of it with the contains method against an attached marker should return false, even if there was an attached marker with the same name that was contained by the attached marker. When the marker is attached, I'm not asking to stop using the == check, I think that part is perfect. But I do understand that this makes the add method considerably more complicated, partly because it would need to check for cycles by checking parent names instead of ==, and partly because I might be attaching an entire parent hierarchy, not just a single marker. (I'm sure I'm just securing in your mind that it isn't worth it, aren't I?) Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13961604#comment-13961604 ] Bruce Brouwer commented on LOG4J2-585: -- * But we've made other breaking changes since RC1. Now, maybe they haven't broken the use of log4j-api, but changes have happened in log4j-core that could cause breakage. Should I make it a separate JIRA and see what others have to say? * Thanks * Honestly, I don't quite understand the point of detached markers. So I agree there is going to be very little benefit to this. And if someone finds a real use case that isn't handled, we can always fix it later. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Updated] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-585: - Attachment: CurrentMarkerBenchmark.java ConceptMarkerBenchmark.java Here are the benchmark classes I was using. They're pretty simple, just dealing with a single parent for each marker in order to compare the current vs. concept. I had an idea to try out myself with volatile references to immutable arrays where the array references are replaced when the parents change. Maybe that will be faster to iterate over than checking if something is in a ConcurrentHashMap. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13961148#comment-13961148 ] Bruce Brouwer commented on LOG4J2-585: -- Why make that rule that parents added during construction cannot be removed? If we allow any modification, it doesn't make sense to me why we would restrict those modifications. I suppose I'm asking you to convince me why that is better. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13961199#comment-13961199 ] Bruce Brouwer commented on LOG4J2-585: -- So, are you saying that the only benefit is that I am guaranteed that some relationships cannot be modified? That seems like it would add complexity if some relationships can be modified and not others. Why can't I just make sure my client code never modifies those relationships? I went ahead and tried the volatile immutable arrays, and it definitely helps. Here's my results: ||Depth||Current||Concept worst||Concept average | 3 | 340K ops/ms | 280K ops/ms (17% slower) | 380K ops/ms (12% faster) | 2 | 680K ops/ms | 360K ops/ms (47% slower) | 430K ops/ms (36% slower) | 1 | 1230K ops/ms | 500K ops/ms (60% slower) | same as worst | 0 | 2550K ops/ms | 2000K ops/ms (21% slower) | same as worst The difference between Concept Worst and Concept Average is because it might not take x number of checks for a parent that is x levels away. On average, it would take only x/2 checks since all parent names are merged together for testing purposes. As you can see, the average case is already faster now at 3 levels deep. I don't think there is any way to get the 0 and 1 level deep tests to be faster than what we have currently as the current implementation simply needs to check one or two variables, rather than iterating over an array. But in the end, we're talking about hundreds of millions of {{isInstanceOf}} invocations per second. This marker test is only one small part of the entire logging performance picture. And it is only going to cause a small (and I think very small) penalty for those who even use the markers. The benefit is a more flexible marker hierarchy and full support for slf4j. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13961223#comment-13961223 ] Bruce Brouwer commented on LOG4J2-585: -- {{java -jar target/microbenchmark.jar -t 8}} So, 8 concurrent threads running on a Windows 7 4-core machine. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: ConceptMarkerBenchmark.java, CurrentMarkerBenchmark.java, log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13960867#comment-13960867 ] Bruce Brouwer commented on LOG4J2-585: -- So another idea I had is along the lines of what Gary was proposing. So we have MarkerManager today, which is analogous to LogManager. But instead of MarkerManager holding onto a static map of markers, what if the LoggerContext is what actually kept track of all the markers, like it keeps track of all the Loggers. And like LoggerContext now returns LoggerProviders, LoggerContext could return MarkerProviders, while the MarkerManager static methods would return simple Markers. This would allow the public Marker API to be simpler than the Marker SPI. The Marker SPI could have the methods that make markers mutable. The only thing I can think that the API would be missing that the SPI has would be the {{getParents}} method. With this approach, there could be two LoggerContexts, each with their own marker hierarchy, rather than one set of markers that everything shares. Does this approach sound more palatable? I don't think it would be too hard to switch my concept over to this approach. Also, are the issues I've identified recognized as real issues? (e.g. slf4j-impl markers having almost no relation to log4j markers) If the rest of the team doesn't agree with me, I'll stop spending time on this. I will be using log4j 2 primarily through the slf4j interface and I personally see this as a real problem that needs to be fixed before 2.0. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Updated] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-585: - Attachment: log4j2-585-concept.patch Here is a log4j2-585-concept.patch that outlines my ideas for the Markers. It is merely a concept and not intended to be committed yet. I'm sure I've probably gone too far in some areas, but hear me out first. For performance, I checked with JMH. So long as the marker hierarchy is no more than 5 deep, the current Log4j code is faster, but after 5 deep, my concept is faster than the current Log4j code. For the normal case of only one parent, the current Log4j code can perform about 600,000 ops/ms, while my concept performs about 200,000 ops/ms. A simpler version of my concept that did not include the allParentNames variable was much slower, clocking in at only about 10,000 ops/ms. The big driver behind my concept was to make Log4j Markers just as powerful as slf4j. This means primarily two things: mutability and multiple parents. First, I got rid of MarkerManager and turned Marker into a concrete, final class. By making Marker an interface, clients might be inclined to implement the interface themselves and cause issues because the parent hierarchy of their markers would likely not match the parent hierarchy of Log4j's markers. It is because of this that I don't like the idea of pluggable Marker factories. Next, my ReadWriteLock is static. I did this to avoid creating a ton of lock objects for each Marker. The majority of time, marker hierarchies are not changing, so a lock that blocks most marker functions during an update is likely not a concern. Furthermore, the most prevalent cases, such as calling isInstanceOf, are not even guarded by a lock and allow ConcurrentHashMap to provide all the performance possible. getParents() is not a SetMarker instead of a simple Marker. This allows multiple parents. I went with a custom Set implementation to be able to react to changes to the parents set, which is used primarily to keep allParentNames up to date. The static methods that used to be on MarkerManager are not on Marker. Marker.get works exactly like MarkerManager.getMarker. An overloaded version allows you to indicate if you want a marker created if it does not exist. This was necessary for use in the Slf4j-impl, but I could see it being valuable elsewhere, too. Marker.define works a little bit like MarkerManager.getMarker(name, parent), but because Markers are not mutable, it ensures that the parents become the set provided here. I like the name define better because it is clear to me that this will make the marker look the way I just described. I did not like MarkerManager.getMarker(name, parent) because it does not guarantee me that the returned marker even has the specified parent. If the marker was created earlier to this call, it won't have my specified parent. Marker.undefine allows markers to be removed, which is a feature of slf4j and it was fairly easy to support here. So, is it worth a bit of a performance penalty to get all these features in Markers? Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we
[jira] [Comment Edited] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13958801#comment-13958801 ] Bruce Brouwer edited comment on LOG4J2-585 at 4/3/14 1:24 PM: -- Here is a log4j2-585-concept.patch that outlines my ideas for the Markers. It is merely a concept and not intended to be committed yet. I'm sure I've probably gone too far in some areas, but hear me out first. For performance, I checked with JMH. So long as the marker hierarchy is no more than 5 deep, the current Log4j code is faster, but after 5 deep, my concept is faster than the current Log4j code. For the normal case of only one parent, the current Log4j code can perform about 600,000 ops/ms, while my concept performs about 200,000 ops/ms. A simpler version of my concept that did not include the allParentNames variable was much slower, clocking in at only about 10,000 ops/ms. The big driver behind my concept was to make Log4j Markers just as powerful as slf4j. This means primarily two things: mutability and multiple parents. First, I got rid of MarkerManager and turned Marker into a concrete, final class. By making Marker an interface, clients might be inclined to implement the interface themselves and cause issues because the parent hierarchy of their markers would likely not match the parent hierarchy of Log4j's markers. It is because of this that I don't like the idea of pluggable Marker factories. Next, my ReadWriteLock is static. I did this to avoid creating a ton of lock objects for each Marker. The majority of time, marker hierarchies are not changing, so a lock that blocks most marker functions during an update is likely not a concern. Furthermore, the most prevalent cases, such as calling isInstanceOf, are not even guarded by a lock and allow ConcurrentHashMap to provide all the performance possible. getParents() is now a SetMarker instead of a simple Marker. This allows multiple parents. I went with a custom Set implementation to be able to react to changes to the parents set, which is used primarily to keep allParentNames up to date. The static methods that used to be on MarkerManager are now on Marker. Marker.get works exactly like MarkerManager.getMarker. An overloaded version allows you to indicate if you want a marker created if it does not exist. This was necessary for use in the Slf4j-impl, but I could see it being valuable elsewhere, too. Marker.define works a little bit like MarkerManager.getMarker(name, parent), but because Markers are now mutable, it ensures that the parents become the list provided here. I like the name define better because it is clear to me that this will make the marker look the way I just described. I did not like MarkerManager.getMarker(name, parent) because it does not guarantee me that the returned marker even has the specified parent. If the marker was created earlier to this call, it won't have my specified parent. Marker.undefine allows markers to be removed, which is a feature of slf4j and it was fairly easy to support here. So, is it worth a bit of a performance penalty to get all these features in Markers? was (Author: bruce.brouwer): Here is a log4j2-585-concept.patch that outlines my ideas for the Markers. It is merely a concept and not intended to be committed yet. I'm sure I've probably gone too far in some areas, but hear me out first. For performance, I checked with JMH. So long as the marker hierarchy is no more than 5 deep, the current Log4j code is faster, but after 5 deep, my concept is faster than the current Log4j code. For the normal case of only one parent, the current Log4j code can perform about 600,000 ops/ms, while my concept performs about 200,000 ops/ms. A simpler version of my concept that did not include the allParentNames variable was much slower, clocking in at only about 10,000 ops/ms. The big driver behind my concept was to make Log4j Markers just as powerful as slf4j. This means primarily two things: mutability and multiple parents. First, I got rid of MarkerManager and turned Marker into a concrete, final class. By making Marker an interface, clients might be inclined to implement the interface themselves and cause issues because the parent hierarchy of their markers would likely not match the parent hierarchy of Log4j's markers. It is because of this that I don't like the idea of pluggable Marker factories. Next, my ReadWriteLock is static. I did this to avoid creating a ton of lock objects for each Marker. The majority of time, marker hierarchies are not changing, so a lock that blocks most marker functions during an update is likely not a concern. Furthermore, the most prevalent cases, such as calling isInstanceOf, are not even guarded by a lock and allow ConcurrentHashMap to provide all the performance possible. getParents() is not a SetMarker
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13959213#comment-13959213 ] Bruce Brouwer commented on LOG4J2-585: -- The problem with creating all new immutable markers is that there are likely to be references to the old markers all throughout the code that are now invalid. Now, I suppose I have opened up that possibility now by allowing markers to be undefined and then redefined, but I think that is an even more rare case that we don't need to be concerned with. The other idea is something that I hadn't considered of before. I'm assuming you mean marker x.y.z would have a parent of x.y, which has a parent of x. However, this fails to give the ability to have multiple parents If we went a completely different route and just had markers be interfaces, I could see code like this: {code} public interface MyFirstParentMarker { } public interface MySecondParentMarker { } public interface MyChildMarker extends MyFirstParentMarker, MySecondParentMarker { } {code} This has a few problems, too. First, I have no idea how we could get it to work with slf4j which is based upon marker names being strings, not a Java type hierarchy. Second, how do we reference these markers? Would we do it like this: {code} private final static ClassMyChildMarker myChildMarker = MyChildMarker.class; {code} Or would we do something with Java proxies: {code} private final static MyChildMarker myChildMarker = MarkerManager.get(MyChildMarker.class); public class MarkerManager { public static T T get(ClassT markerType) { return java.lang.reflect.Proxy.proxyClass(markerType); } } {code} I like this idea, except that I don't see a way to make it work with slf4j. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Comment Edited] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13959213#comment-13959213 ] Bruce Brouwer edited comment on LOG4J2-585 at 4/3/14 9:04 PM: -- The problem with creating all new immutable markers is that there are likely to be references to the old markers all throughout the code that are now invalid. Now, I suppose I have opened up that possibility now by allowing markers to be undefined and then redefined, but I think that is an even more rare case that we don't need to be concerned with. The other idea is something that I hadn't considered of before. I'm assuming you mean marker x.y.z would have a parent of x.y, which has a parent of x. However, this fails to give the ability to have multiple parents If we went a completely different route and just had markers be interfaces, I could see code like this: {code} public interface MyFirstParentMarker extends Marker { } public interface MySecondParentMarker extends Marker { } public interface MyChildMarker extends MyFirstParentMarker, MySecondParentMarker { } {code} This has a few problems, too. First, I have no idea how we could get it to work with slf4j which is based upon marker names being strings, not a Java type hierarchy. Second, how do we reference these markers? The best idea I can come up with here is to change the log4j-api to take a {{Class? extends Marker marker}} instead of {{Marker marker}}. Now there is no need for a MarkerManager as the Java class loader takes care of it for me. I like this idea, except that I don't see a way to make it work with slf4j. was (Author: bruce.brouwer): The problem with creating all new immutable markers is that there are likely to be references to the old markers all throughout the code that are now invalid. Now, I suppose I have opened up that possibility now by allowing markers to be undefined and then redefined, but I think that is an even more rare case that we don't need to be concerned with. The other idea is something that I hadn't considered of before. I'm assuming you mean marker x.y.z would have a parent of x.y, which has a parent of x. However, this fails to give the ability to have multiple parents If we went a completely different route and just had markers be interfaces, I could see code like this: {code} public interface MyFirstParentMarker { } public interface MySecondParentMarker { } public interface MyChildMarker extends MyFirstParentMarker, MySecondParentMarker { } {code} This has a few problems, too. First, I have no idea how we could get it to work with slf4j which is based upon marker names being strings, not a Java type hierarchy. Second, how do we reference these markers? Would we do it like this: {code} private final static ClassMyChildMarker myChildMarker = MyChildMarker.class; {code} Or would we do something with Java proxies: {code} private final static MyChildMarker myChildMarker = MarkerManager.get(MyChildMarker.class); public class MarkerManager { public static T T get(ClassT markerType) { return java.lang.reflect.Proxy.proxyClass(markerType); } } {code} I like this idea, except that I don't see a way to make it work with slf4j. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Attachments: log4j2-585-concept.patch Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private
[jira] [Created] (LOG4J2-585) Markers not as powerful as slf4j
Bruce Brouwer created LOG4J2-585: Summary: Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13954753#comment-13954753 ] Bruce Brouwer commented on LOG4J2-585: -- About the performance, I suspected what Ralph is saying would be a very real concern. I looked at the way BasicMarker is implemented and there is nothing that requires us to extend from BasicMarker. I was playing around with an implementation that used a ReentrantReadWriteLock. In most cases, the time spend modifying markers is only in the startup of the app. So I agree, slapping a synchronized on the most important methods is a huge performance bottleneck. But with the ReentrantReadWriteLock, the major time of an application would cause no blocking at all. I also have some ideas on how we could get the performance of the regular Log4J markers better than they are today at the expense of a little bit more memory. Also, if we made the Log4J markers mutable, then we could have the SLF4J implementation simply delegate to the real Log4J markers. Right now, the two are completely separate. If you have code that mixes Log4J markers with SLF4J markers (because of some 3rd party library that uses SLF4J) the hierarchies can be completely different. This is probably not what people would expect to have happen. I think it will also have real issues when used with the MarkerFilter, which would be referencing a real log4j Marker while comparing against an SLF4J marker. Another thing that I noticed is that I think the SLF4J implementation is broken. SLF4J intends the pointers to be pointing at the children. Log4J intends the pointers to be to the parent. Because of this, the implementation of MarkerWrapper.isInstanceOf is backwards. I would like to fix this immutability issue, but the issue of allowing multiple parents I think more important, and one that is easy to fix. Would I have support of changing these things if I submitted a patch? Especially if I took careful consideration for performance issues? Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13954805#comment-13954805 ] Bruce Brouwer commented on LOG4J2-585: -- Cool. So, in my patch, when I make log4j Markers mutable, I will make sure read operations are as performant as possible, but for operations that modify markers, I am not going to spend a lot of effort making those highly performant as I think read operations are for more important. Of the items in the concurrent collections, the one that seemed promising to me for this situation was ConcurrentHashMap, but it does not maintain the original order. The only place where I think order might have some impact when allowing multiple parents is in the toString method. It wouldn't keep the order that was specified when creating the marker with parents. Do you think order is important in the toString method? Could I get away with just sorting the parent names for .toString()? If so, then I can seriously consider ConcurrentHashMap. Otherwise I'll have to go with another collection and use the ReentrantReadWriteLock. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Comment Edited] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13954805#comment-13954805 ] Bruce Brouwer edited comment on LOG4J2-585 at 3/30/14 7:12 PM: --- Cool. So, in my patch, when I make log4j Markers mutable, I will make sure read operations are as performant as possible, but for operations that modify markers, I am not going to spend a lot of effort making those highly performant as I think read operations are far more important. Of the items in the concurrent collections, the one that seemed promising to me for this situation was ConcurrentHashMap, but it does not maintain the original order and I don't really need the Map feature, just Set. The only place where I think order might have some impact when allowing multiple parents is in the toString method. It wouldn't keep the order that was specified when creating the marker with parents. Do you think order is important in the toString method? Could I get away with just sorting the parent names for .toString()? If so, then I can seriously consider ConcurrentHashMap. Otherwise I'll have to go with another collection and use the ReentrantReadWriteLock. was (Author: bruce.brouwer): Cool. So, in my patch, when I make log4j Markers mutable, I will make sure read operations are as performant as possible, but for operations that modify markers, I am not going to spend a lot of effort making those highly performant as I think read operations are for more important. Of the items in the concurrent collections, the one that seemed promising to me for this situation was ConcurrentHashMap, but it does not maintain the original order. The only place where I think order might have some impact when allowing multiple parents is in the toString method. It wouldn't keep the order that was specified when creating the marker with parents. Do you think order is important in the toString method? Could I get away with just sorting the parent names for .toString()? If so, then I can seriously consider ConcurrentHashMap. Otherwise I'll have to go with another collection and use the ReentrantReadWriteLock. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Commented] (LOG4J2-585) Markers not as powerful as slf4j
[ https://issues.apache.org/jira/browse/LOG4J2-585?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13954878#comment-13954878 ] Bruce Brouwer commented on LOG4J2-585: -- Interesting. I don't know if it makes sense for each logger to have a marker factory, but in the way we have different LoggerContextFactory implementations, we could have different MarkerFactory implementations. log4j-slf4j-impl could provide an alternate MarkerFactory. I don't know if I like the idea of simply including log4j-slf4j-impl and having it switch the implementation of MarkerFactory without me realizing it. But I suppose that is what happens when I include log4j-core with LoggerContextFactory. It seems different to me, somehow. I would expect log4j-slf4j-impl to be a thin wrapper around the real log4j implementation, including the markers. I was actually thinking a bit about the Marker interface. If we don't go with the MarkerFactory idea, what is the point of having Marker be an interface? It should be a concrete final class to prevent anyone or anything making other kinds of Markers. I could see weird things happening if we pass an SLF4J marker with one hierarchy passed into a Log4J marker's .isInstanceOf method. We could run into a situation where slf4jMarker.isInstanceOf(log4jMarker) returns true and also log4jMarker.isInstanceOf(slf4jMarker) returns true, event though they are not themselves equal. This doesn't really make good logical sense. The only impact I think would be that the log4j-slf4j-impl MarkerWrapper couldn't implement Marker, but would rather need to provide a getter. I'm willing to put in some time developing this, even at the risk of not using it if it proves to be too big of a performance hit. But if we don't go down this road, we run into the problem of the SLF4J marker hierarchy possibly being inconsistent with the Log4j marker hierarchy and having some of the weird behavior I described. Markers not as powerful as slf4j Key: LOG4J2-585 URL: https://issues.apache.org/jira/browse/LOG4J2-585 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Bruce Brouwer Log4J's markers are not as flexible as markers in SLF4J. First, SLF4J's markers are mutable. By allowing markers to be mutable, I can change the relationship of markers to each other based upon runtime or business conditions. Second, and more importantly I think, is that essentially SLF4J markers have this parent/child relationship, much like Log4J, except that in SLF4J, I can essentially have a marker with multiple parents. For example, I might want this structure: * Animal ** Bird *** Duck ** Mammal *** Bear *** Dolphin * Travels by ** Water *** Duck *** Dolphin ** Land *** Duck *** Bear ** Air *** Duck Of course, this is a contrived example, but I wanted to describe the relationships. Now, if I wanted to filter based on markers that travel by Water for some appenders, and another appender wants to filter by Mammals, I can't simply use the single marker of Dolphin. Either we need to reverse the marker relationship so that it contains its children, much like SLF4J, or we allow markers to have multiple parents, which I prefer because it could make it more succinct to define: {code} private static final Marker BY_LAND = MarkerManager.getMarker(BY_LAND); private static final Marker BY_WATER = MarkerManager.getMarker(BY_WATER); private static final Marker DUCK = MarkerManager.getMarker(DUCK, BY_LAND, BY_WATER); {code} As for the Marker API, we would either need to change getParent to getParents, or get rid of the getParent method from the API and just rely on the isInstanceOf method to handle checking multiple parents by looking at private member variables (my preference) -- 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
[jira] [Updated] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-547: - Attachment: log4j2-547-remove-streams.patch Perhaps we can agree to at least remove the streaming stuff from log4j-api. This way if we can't resolve the streaming solution before 2.0, we at least won't have it in the API where it will have to be supported forever. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: 0001-PrintStream-API-update.patch, MyBenchmark.java, PerfTestCalcLocation.java, log4j2-547-bbrouwer.patch, log4j2-547-remove-streams.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13944619#comment-13944619 ] Bruce Brouwer commented on LOG4J2-547: -- My comments of performance were me remembering the code I saw in {{ClassLoaderContextSelector}}, which I think actually doesn't come into play in this scenario. So, it probably is as simple as getting the stack trace (the expensive part) and iterating over the list doing a few string comparisons (maybe a few hundred). Would it help if I made a little performance test comparison? As for my comment about top-down being more technically correct, I was thinking that in the short stack trace example that Remko outlined, I think the top LoggerPrintStream should report its caller as {{FilterOutputStream.someMethod()}}, not {{ApplicationClass_TheCaller.theMethod()}}. However, in probably 90%+ of cases, the more useful caller to report would be {{ApplicationClass_TheCaller.theMethod()}}, which would be discovered by the bottom-up approach. It's an interesting edge case, but probably not worth worrying about. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: 0001-PrintStream-API-update.patch, log4j2-547-bbrouwer.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Updated] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-547: - Attachment: PerfTestCalcLocation.java I decided to run a quick performance test. You can see the tester code in {{PerfTestCalcLocation.java}}, which I attached. The alternate {{calcLocation}} code I wrote looks like this (which is actually much simpler than the current code: {code} public static StackTraceElement calcLocation2(final String fqcnOfLogger) { if (fqcnOfLogger == null) { return null; } final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); // start 2 below, just in case the last entry happens to match the FQCN for (int i = stackTrace.length - 2; i = 0; i--) { if (fqcnOfLogger.equals(stackTrace[i].getClassName())) { return stackTrace[i + 1]; } } return null; } {code} And here are the performance results: {code} 10 deep: Top-down: 83653 ops/sec, bottom-up: 86745 ops/sec, -3.5644684% slower 50 deep: Top-down: 24557 ops/sec, bottom-up: 24033 ops/sec, 2.180336% slower 100 deep: Top-down: 12854 ops/sec, bottom-up: 12927 ops/sec, -0.5647125% slower 200 deep: Top-down: 6640 ops/sec, bottom-up: 6640 ops/sec, 0.0% slower 500 deep: Top-down: 2623 ops/sec, bottom-up: 2630 ops/sec, -0.26615906% slower {code} It appears that the direction we traverse the stack trace has negligible impact on the performance, no matter how deep the stack trace. I've never seen the results go above 3% slower over multiple runs, and often, it shows it going faster. So if performance is the only concern, I kind of like the idea of switching to the bottom-up approach. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: 0001-PrintStream-API-update.patch, PerfTestCalcLocation.java, log4j2-547-bbrouwer.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Updated] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-547: - Attachment: MyBenchmark.java I took a stab at JMH. When I pulled out the code that actually takes the stack trace (using a pre-generated stack trace) and left only the iterating code, it shows the current code to be *much* faster. However, when you throw in the generation of the stack trace, it looks like it becomes inconsequential. Here are the results for a stack trace that is 200 entries deep. {code} BenchmarkMode Samples Mean Mean errorUnits o.s.MyBenchmark.bottomUpthrpt 2006.9230.036 ops/ms o.s.MyBenchmark.topDown thrpt 2006.9130.034 ops/ms {code} I've attached the benchmark code, too as {{MyBenchmark.java}}. This could be skewed somewhat as part of this time is spent making a recursive call of 208 methods deep just to make the call to build the stack trace, but I wasn't coming up with a better way to generate the stack trace and have it be part of the benchmark results. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: 0001-PrintStream-API-update.patch, MyBenchmark.java, PerfTestCalcLocation.java, log4j2-547-bbrouwer.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Closed] (LOG4J2-562) Improve ability to create custom extended logger
[ https://issues.apache.org/jira/browse/LOG4J2-562?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer closed LOG4J2-562. Resolution: Not A Problem It seems like everyone is comfortable with what is in LOG4J2-555. Improve ability to create custom extended logger Key: LOG4J2-562 URL: https://issues.apache.org/jira/browse/LOG4J2-562 Project: Log4j 2 Issue Type: Improvement Components: API Reporter: Bruce Brouwer Attachments: log4j2-loggerExtension.patch Create a LoggerExtension from the original logger which simply remembers the FQCN that will ultimately be the extension. Also by doing this, we can switch a bunch of methods that ended up being public back to protected. I'm guessing they became public so extensions could call them. This can simplify extensions (such as slf4j, jcl, custom extensions, logger streams) so they don't have to pass in the FQCN to that special log method on AbstractLogger anymore. Also, you don't have to wrap every extended log method with a check to see if the logging is enabled. Finally, you don't need to have any access to the MessageFactory. This even has to potential to eliminate AbstractLoggerWrapper. -- 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
[jira] [Commented] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13944149#comment-13944149 ] Bruce Brouwer commented on LOG4J2-555: -- All good points from everyone. Yes, it appears that all of the points that everyone made are things I simply missed. I am also ok with renaming the LoggerProvider {{log}} methods to {{logIfEnabled}}. I definitely appreciate all the extra eyes reviewing my code. I'm not planning on providing another patch as it sounds like Remko will clean it up. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 Attachments: LOG4J2-555-delegate.patch, log4j2-555-bbrouwer-2.patch, log4j2-555-bbrouwer.patch, log4j2-555-gg-v3.diff *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13944321#comment-13944321 ] Bruce Brouwer commented on LOG4J2-547: -- Yes, walking bottom-up would definitely solve this problem and would work in probably 99% of cases. One cost, though, that I can think of is that usually the entry we are looking for is usually closest to the top of the stack trace, not the bottom. So there might be a performance hit in the bottom-up approach. Also, in this case, I could theoretically pass a a LoggerPrintStream wrapping a FilterOutputStream wrapping another LoggerPrintStream. I have no idea why anyone would do that, but in this situation, the top down approach would be the only way that could identify the correct caller info. I'm not prepared to advocate for switching to a bottom-up approach, but if you thought it was best, I would be in support of it. If, we don't go for bottom-up, then I'll have to switch this to a delegating pattern, rather than simply subclassing PrintWriter. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, log4j2-547-bbrouwer.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-33) Support Annotations
[ https://issues.apache.org/jira/browse/LOG4J2-33?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13943808#comment-13943808 ] Bruce Brouwer commented on LOG4J2-33: - You should check out [Project Lombok|http://projectlombok.org/]. It uses Java's built in annotation processing features to make your code look like this: {code} @Log public class LogExample { public static void main(String... args) { log.error(Something's wrong here); } } {code} And no, that code did not neglect to extend another class, nor did it neglect to define the log field. You could probably take the concepts from Lombok to do stuff like this as well: {code} public class LogExample { @LogEntryExit public void doStuff() { // do stuff } } {code} Basically, it uses byte code manipulation to make this all work. From what I can tell, there is no need to setup anything special with javac or maven; it just works. It looks like there are some issues with some IDEs, which Project Lombok has solved. I haven't used it yet myself, but it might be fun to try it out in Log4j 2 (maybe after 2.0 is released) Support Annotations --- Key: LOG4J2-33 URL: https://issues.apache.org/jira/browse/LOG4J2-33 Project: Log4j 2 Issue Type: New Feature Components: API Affects Versions: 2.0-rc2 Reporter: Ralph Goers Fix For: 0.1, 2.0-rc2 Attachments: 0001-Add-Loggable.patch The Log4j API should support using annotations as provided in Java 6 so applications can use them instead of calls to logger APIs. This is especially useful for entering exiting type of events, but could be used wherever annotations are allowed. -- 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
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13943823#comment-13943823 ] Bruce Brouwer commented on LOG4J2-547: -- So, I put all this stream stuff in package {{org.apache.logging.log4j.streams}} inside the log4j-api project. It seems awkward to me to put these tests inside log4j-core when the code it is testing is inside log4j-api. To me, it seems like another reason to pull this into its own artifact called log4j-streams. This way there is nothing related to these streams in log4j-api, and the log4j-streams artifact could pull in log4j-core as a test dependency for the purpose of making this caller information test. I'm going to make some separate caller-info test classes inside log4j-core, but in the {{org.apache.logging.log4j.streams}} package (not {{org.apache.logging.log4j.*core*.streams}}) just so we can look at what we are talking about, but I don't expect things to stay where they are represented in my next patch. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, log4j2-547-bbrouwer.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13937728#comment-13937728 ] Bruce Brouwer commented on LOG4J2-555: -- After thinking some more about my change to log4j-jcl Log4jLog, I could quite easily be convinced to revert that back to extending AbstractLoggerWrapper. I could see some convenience in simply casting Log4jLog between jcl's Log and log4j's Logger interface. However, if we do that, then we should probably do the same thing to log4j-slf4j-impl's SLF4JLogger so it can also be cast to log4j's Logger interface. I suppose this change could be tracked in a separate JIRA. So what do people think? Should these alternate logging implementations be made so it is easy to cast to log4j's Logger interface, or should we try to keep the interface to these alternate logging implementations as free as possible of log4j public methods? Oh, and I now see that my comment about log4j-to-slf4j SLF4JLogger.logMessage was in error. It is fine as it is (which is how it remains in the patch) I also see that I was remiss in finishing up JavaDoc. If people like the direction of {{log4j-555-bbrouwer-2.patch}}, I can make a new patch, or I will commit to submitting a documentation patch if this is applied before that new patch. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 Attachments: LOG4J2-555-delegate.patch, log4j2-555-bbrouwer-2.patch, log4j2-555-bbrouwer.patch *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Comment Edited] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13937728#comment-13937728 ] Bruce Brouwer edited comment on LOG4J2-555 at 3/17/14 12:41 PM: After thinking some more about my change to log4j-jcl Log4jLog, I could quite easily be convinced to revert that back to extending AbstractLoggerWrapper. I could see some convenience in simply casting Log4jLog between jcl's Log and log4j's Logger interface. For example, if I was using jcl's interface to log4j, I could simply cast to a jcl Log to log4j's Logger to use the different logger streams depicted in LOG4J2-547. However, if we do that, then we should probably do the same thing to log4j-slf4j-impl's SLF4JLogger so it can also be cast to log4j's Logger interface. I suppose this change could be tracked in a separate JIRA. So what do people think? Should these alternate logging implementations be made so it is easy to cast to log4j's Logger interface, or should we try to keep the interface to these alternate logging implementations as free as possible of log4j public methods? Oh, and I now see that my comment about log4j-to-slf4j SLF4JLogger.logMessage was in error. It is fine as it is (which is how it remains in the patch) I also see that I was remiss in finishing up JavaDoc. If people like the direction of {{log4j-555-bbrouwer-2.patch}}, I can make a new patch, or I will commit to submitting a documentation patch if this is applied before that new patch. was (Author: bruce.brouwer): After thinking some more about my change to log4j-jcl Log4jLog, I could quite easily be convinced to revert that back to extending AbstractLoggerWrapper. I could see some convenience in simply casting Log4jLog between jcl's Log and log4j's Logger interface. However, if we do that, then we should probably do the same thing to log4j-slf4j-impl's SLF4JLogger so it can also be cast to log4j's Logger interface. I suppose this change could be tracked in a separate JIRA. So what do people think? Should these alternate logging implementations be made so it is easy to cast to log4j's Logger interface, or should we try to keep the interface to these alternate logging implementations as free as possible of log4j public methods? Oh, and I now see that my comment about log4j-to-slf4j SLF4JLogger.logMessage was in error. It is fine as it is (which is how it remains in the patch) I also see that I was remiss in finishing up JavaDoc. If people like the direction of {{log4j-555-bbrouwer-2.patch}}, I can make a new patch, or I will commit to submitting a documentation patch if this is applied before that new patch. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 Attachments: LOG4J2-555-delegate.patch, log4j2-555-bbrouwer-2.patch, log4j2-555-bbrouwer.patch *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- This message was sent by Atlassian JIRA (v6.2#6252) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
[jira] [Updated] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-547: - Attachment: log4j2-547-bbrouwer.patch Here is my solution to LoggerStream (log4j2-547-bbrouwer.patch). It includes logger versions of InputStream, BufferedInputStream, Reader, BufferedReader, OutputStream, PrintStream, Writer and PrintWriter. Something missing from the current LoggerPrintStream is that it cannot handle character sets other than the default system character set. In this patch, InputStream, BufferedInputStream, OutputStream and PrintStream can all handle any specified character set. Supporting other character sets is the reason for some of the extra complexity in this patch. Also, because of the wide variety of options for creating them, there are multiple constructors to all of these classes. This goes with the spirit of the corresponding classes in Java where they are created by calling their constructors. Because of the wide variety of options, this would add a significant amount of new methods on the LogManager interface. I am proposing that we not do that. As directed, I put this in log4j-api, but I want to make one last request that this not be included in log4j-api but rather in a new artifact called log4j-streams. These new classes stand alone on their own and I see little value in adding corresponding factory methods in LogManager for each constructor specified by these classes. This patch relies on my latest patch in LOG4J2-555 and because of the overlap with some classes in the LOG4J-555 patch, I am not able to cleanly provide a patch that gets rid of LoggerStream and LoggerWriter and the existing printStream and printWriter methods in LogManager. It is my intent that these all be removed should this patch be accepted. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, Add_caller_info_tests.patch, log4j2-547-bbrouwer.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-510) How to close inactive log files
[ https://issues.apache.org/jira/browse/LOG4J2-510?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13937411#comment-13937411 ] Bruce Brouwer commented on LOG4J2-510: -- How do you intend to manage all those log files? Why couldn't you simply log the sessionID in each log entry using the MDC and have only one rolling log file? I would think you would run into other problems with the file system with having thousands, or potentially far more than thousands, of log files sitting around. I know log management tools like Splunk prefer to watch fewer files. And grep will make short work of finding which logs are involved with a particular session id. How to close inactive log files --- Key: LOG4J2-510 URL: https://issues.apache.org/jira/browse/LOG4J2-510 Project: Log4j 2 Issue Type: Bug Components: Appenders Affects Versions: 2.0-beta9 Environment: linux Reporter: Eric Labels: performance Fix For: 2.0-beta9 Hi There, in log4j2 when the App start logging it create and open a file to log into and that file stay open as long as the App is running. in my case log4j2 create and open too many files base on ThreadContext and the OS (linux) will complaint that too many files are open and my App will crash and stop responding. My question is: 1 - how do you close those files with log4j2 if they are inactive for a period of time. 2 - How do you have access to the log4j2 handle that open those files. 3 - How do you tell log4j2 to open a file just for a period of time. Thanks Eric -- 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
[jira] [Commented] (LOG4J2-562) Improve ability to create custom extended logger
[ https://issues.apache.org/jira/browse/LOG4J2-562?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13936206#comment-13936206 ] Bruce Brouwer commented on LOG4J2-562: -- The one concept that this patch provided (which definitely needs some modification) that I think might have some merit is this LoggerExtension. My patch in LOG4J2-555 adds a bunch of log methods that include the FQCN. These methods end up being public, while the previous functionality was protected. Originally, some extensions of AbstractLogger switched this protected method(s) to public and others did not. If we wanted to keep as much stuff non-public as possible, then this LoggerExtension idea could be useful. Concerning my patch in LOG4J2-555, it would mean getting rid of all the log(FQCN, ...) methods from LoggerProvider and replacing it with one method called .getExtension(), returning a LoggerExtension. LoggerExtension could then have all the .log(FQCN, ...) methods on it instead. If everyone is generally ok with the approach of my patch in LOG4J2-555 where there are more public .log(FQCN, ...) methods on AbstractLogger (essentially abstract methods), then this issue can be closed. I don't care about any of the other stuff presented in the patch I provided here. Personally, I'm totally ok with closing this issue that I reported as long as the general direction I proposed in LOG4J2-555 comes through. Improve ability to create custom extended logger Key: LOG4J2-562 URL: https://issues.apache.org/jira/browse/LOG4J2-562 Project: Log4j 2 Issue Type: Improvement Components: API Reporter: Bruce Brouwer Attachments: log4j2-loggerExtension.patch Create a LoggerExtension from the original logger which simply remembers the FQCN that will ultimately be the extension. Also by doing this, we can switch a bunch of methods that ended up being public back to protected. I'm guessing they became public so extensions could call them. This can simplify extensions (such as slf4j, jcl, custom extensions, logger streams) so they don't have to pass in the FQCN to that special log method on AbstractLogger anymore. Also, you don't have to wrap every extended log method with a check to see if the logging is enabled. Finally, you don't need to have any access to the MessageFactory. This even has to potential to eliminate AbstractLoggerWrapper. -- 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
[jira] [Commented] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13936211#comment-13936211 ] Bruce Brouwer commented on LOG4J2-555: -- I ran the performance test on my Windows 7 64-bit laptop while plugged in. It is a single-proc, 4 core Intel i7 2.7GHz machine with 8GB RAM. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 Attachments: LOG4J2-555-delegate.patch, log4j2-555-bbrouwer-2.patch, log4j2-555-bbrouwer.patch *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Commented] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13935921#comment-13935921 ] Bruce Brouwer commented on LOG4J2-555: -- I wanted to give an overview of what my patch is trying to do: # Simplify most logger methods to be one line of code # Allow classes that wrap a logger (e.g. using AbstractLoggerWrapper) to use one line of code to log. To accomplish this, I created all the variants of the log(...) methods that now take a FQCN as the first parameter. # Created an interface called LoggerProvider that AbstractLogger implements. This I think makes it a bit clearer what extra methods are needed beyond what is in the Logger interface to succesfully wrap a logger. This also allows for different (future) logger implementations that don't need to extend AbstractLogger. # I changed LoggerContext to return LoggerProvider. Most people don't tend to go after the LoggerContext, so most people won't see this. But by doing this here, it makes it clear that loggers coming from here are guaranteed to have this extra functionality, and it eliminates some casting done in the code # I tried to fix some of the method parameter ordering to be consistent: fqcn, level, marker, message, ... This patch doesn't cover all cases where this could be done but in the cases were I was changing method signatures anyway, I thought I would make the order consistent. You may notice that this patch includes a change to log4j-jcl Log4jLog.java. This was not absolutely necessary, but it seemed somehow wrong to me to rely on the fact that the method signatures of jcl match up perfectly to log4j2. The patch implementation also prevents leaking a bunch of other public methods into the implementation coming from AbstractLogger and AbstractLoggerWrapper. If others don't agree with me, it would be easy to revert Log4jLog.java back to what it was before, but instead of the first constructor parameter being AbstractLogger, it would change to LoggerProvider. I also just noticed that log4j-to-slf4j SLF4JLogger.logMessage has an unnecessary switch statement. That should probably be cleaned up as switching it to simply call logger.log(FQCN, level, getMarker(marker), ...) would actually be more performant, not only because it eliminates the switch statement, but it would also go through fewer method invocations. Do you want me to provide an updated patch that does this? Finally, I ran PerfTestDriver, just the Loggers all async tests. I am not sure what the best thing is to do to communicate performance, but this is what I did. I was kind of surprised to see that this patch is actually consistently more performant than the current log4j2 code (at least that's how I'm reading it). h5. Original: 1. Log4j2: Loggers all async (single thread): throughput: 12,746,429 ops/sec. latency(ns): avg=980.2 99% 8192.0 99.99% 1101004.8 (494079 samples) 2. Log4j2: Loggers all async (4 threads): throughput: 6,603,641 ops/sec. latency(ns): avg=3157.4 99% 5120.0 99.99% 8703180.8 (3376684 samples) 3. Log4j2: Loggers all async (2 threads): throughput: 3,505,632 ops/sec. latency(ns): avg=1103.5 99% 5324.8 99.99% 2516582.4 (2339717 samples) h5. After: 1. Log4j2: Loggers all async (single thread): throughput: 13,612,251 ops/sec. latency(ns): avg=8463.0 99% 8192.0 99.99% 2936012.8 (344455 samples) 2. Log4j2: Loggers all async (4 threads): throughput: 7,395,284 ops/sec. latency(ns): avg=2690.5 99% 5939.2 99.99% 8231321.6 (5952262 samples) 3. Log4j2: Loggers all async (2 threads): throughput: 4,639,382 ops/sec. latency(ns): avg=1079.2 99% 6144.0 99.99% 2464153.6 (2312163 samples) Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 Attachments: LOG4J2-555-delegate.patch, log4j2-555-bbrouwer-2.patch, log4j2-555-bbrouwer.patch *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in
[jira] [Updated] (LOG4J2-439) Create a LogEventPatternConverter to escape newlines and HTML special characters
[ https://issues.apache.org/jira/browse/LOG4J2-439?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-439: - Attachment: log4j2-439-doc.patch Create a LogEventPatternConverter to escape newlines and HTML special characters Key: LOG4J2-439 URL: https://issues.apache.org/jira/browse/LOG4J2-439 Project: Log4j 2 Issue Type: New Feature Components: Layouts Affects Versions: 2.0-beta9 Reporter: Bruce Brouwer Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: EncodingPatternConverter.patch, log4j2-439-doc.patch To prevent log forging and HTML based attacks from viewing logs in a browser, we could add a LogEventPatternConverter that escapes newlines and HTML special characters. [ESAPI has a method to do this|http://owasp-esapi-java.googlecode.com/svn/trunk_doc/2.0-rc7/apidocs/org/owasp/esapi/Logger.html], but it doesn't have any of the nice API features that Log4j 2 has. I was able to create a LogEventPatternConverter to do this. Note, this is only a proof of concept. I didn't try to exhaustively list all the special characters that might need to be replaced. I also didn't provide any configuration so we could choose to not escape HTML, for example. With this configuration: {code:xml} PatternLayout pattern=%d %-5p [%t] %c %encode{%m}%n/ {code} And logging this message: {code} LOG.warn(hi\n h1 there); {code} Would result in this being logged: {code} 2013-10-28 16:31:21,606 WARN [main] example.Test hi\n amp; lt;h1gt; there {code} instead of this (which shows the potential for log forging): {code} 2013-10-28 16:31:21,606 WARN [main] example.Test hi h1 there {code} This is roughly the code I used: {code} @Plugin(name = escape, category = Converter) @ConverterKeys({ escape }) public final class EscapingReplacementConverter extends LogEventPatternConverter { private final ListPatternFormatter formatters; private EscapingReplacementConverter(final ListPatternFormatter formatters) { super(escape, escape); this.formatters = formatters; } public static EscapingReplacementConverter newInstance(final Configuration config, final String[] options) { if (options.length != 1) { LOGGER.error(Incorrect number of options on escape. Expected 1, received + options.length); return null; } if (options[0] == null) { LOGGER.error(No pattern supplied on escape); return null; } final PatternParser parser = PatternLayout.createPatternParser(config); final ListPatternFormatter formatters = parser.parse(options[0]); return new EscapingReplacementConverter(formatters); } @Override public void format(final LogEvent event, final StringBuilder toAppendTo) { final StringBuilder buf = new StringBuilder(); for (final PatternFormatter formatter : formatters) { formatter.format(event, buf); } toAppendTo.append(buf.toString() .replaceAll(\\r, r) .replaceAll(\\n, n) .replaceAll(, amp;) .replaceAll(, lt;) .replaceAll(, gt;)); } } {code} If this sounds good, I would like to hear feedback and ideas on how to make this better. I will then contribute this to the project. Do you think this could this get in 2.0? -- 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
[jira] [Reopened] (LOG4J2-439) Create a LogEventPatternConverter to escape newlines and HTML special characters
[ https://issues.apache.org/jira/browse/LOG4J2-439?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer reopened LOG4J2-439: -- I am only re-opening this to provide a documentation patch. Create a LogEventPatternConverter to escape newlines and HTML special characters Key: LOG4J2-439 URL: https://issues.apache.org/jira/browse/LOG4J2-439 Project: Log4j 2 Issue Type: New Feature Components: Layouts Affects Versions: 2.0-beta9 Reporter: Bruce Brouwer Assignee: Ralph Goers Fix For: 2.0-rc2 Attachments: EncodingPatternConverter.patch, log4j2-439-doc.patch To prevent log forging and HTML based attacks from viewing logs in a browser, we could add a LogEventPatternConverter that escapes newlines and HTML special characters. [ESAPI has a method to do this|http://owasp-esapi-java.googlecode.com/svn/trunk_doc/2.0-rc7/apidocs/org/owasp/esapi/Logger.html], but it doesn't have any of the nice API features that Log4j 2 has. I was able to create a LogEventPatternConverter to do this. Note, this is only a proof of concept. I didn't try to exhaustively list all the special characters that might need to be replaced. I also didn't provide any configuration so we could choose to not escape HTML, for example. With this configuration: {code:xml} PatternLayout pattern=%d %-5p [%t] %c %encode{%m}%n/ {code} And logging this message: {code} LOG.warn(hi\n h1 there); {code} Would result in this being logged: {code} 2013-10-28 16:31:21,606 WARN [main] example.Test hi\n amp; lt;h1gt; there {code} instead of this (which shows the potential for log forging): {code} 2013-10-28 16:31:21,606 WARN [main] example.Test hi h1 there {code} This is roughly the code I used: {code} @Plugin(name = escape, category = Converter) @ConverterKeys({ escape }) public final class EscapingReplacementConverter extends LogEventPatternConverter { private final ListPatternFormatter formatters; private EscapingReplacementConverter(final ListPatternFormatter formatters) { super(escape, escape); this.formatters = formatters; } public static EscapingReplacementConverter newInstance(final Configuration config, final String[] options) { if (options.length != 1) { LOGGER.error(Incorrect number of options on escape. Expected 1, received + options.length); return null; } if (options[0] == null) { LOGGER.error(No pattern supplied on escape); return null; } final PatternParser parser = PatternLayout.createPatternParser(config); final ListPatternFormatter formatters = parser.parse(options[0]); return new EscapingReplacementConverter(formatters); } @Override public void format(final LogEvent event, final StringBuilder toAppendTo) { final StringBuilder buf = new StringBuilder(); for (final PatternFormatter formatter : formatters) { formatter.format(event, buf); } toAppendTo.append(buf.toString() .replaceAll(\\r, r) .replaceAll(\\n, n) .replaceAll(, amp;) .replaceAll(, lt;) .replaceAll(, gt;)); } } {code} If this sounds good, I would like to hear feedback and ideas on how to make this better. I will then contribute this to the project. Do you think this could this get in 2.0? -- 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
[jira] [Updated] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-555: - Attachment: log4j2-555-bbrouwer-2.patch I fixed the problems with the failing tests. Everything now passes. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 Attachments: LOG4J2-555-delegate.patch, log4j2-555-bbrouwer-2.patch, log4j2-555-bbrouwer.patch *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Commented] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13932795#comment-13932795 ] Bruce Brouwer commented on LOG4J2-555: -- I've attached my patch that takes care of the FQCN issues. AbstractLogger is reduced by 171 lines and it does not involve that fun little enum trick that Remko proposed. This has impact to anything that extends AbstractLogger, which is included in my patch. I haven't finished checking all the tests as I'm getting some weird testing errors that I think are unrelated to my changes, but I'll check yet. My initial performance numbers show it is just as fast as before, but I'll post more complete numbers later. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 Attachments: LOG4J2-555-delegate.patch *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Updated] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-555: - Attachment: log4j2-555-bbrouwer.patch Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 Attachments: LOG4J2-555-delegate.patch, log4j2-555-bbrouwer.patch *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Commented] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13925424#comment-13925424 ] Bruce Brouwer commented on LOG4J2-555: -- That MsgBuilder stuff looks interesting. I'm not sure I'm for it yet. It is not incompatible with my ideas. I'm working on my own patch for this that I will post soon and I hope to receive feedback. There are a few things I'm trying to do to make it easier for things using the wrapper. * Instead of FQCN invading the API, which isn't terribly flexible, I've created a SourceLocator interface and related classes. This way custom loggers could use multiple FQCNs or something completely different. * Make the interface LoggerProvider in the spi package which extends Logger and which AbstractLogger implements. This has a few more isEnabled and log methods available which make it possible for extended loggers to use efficiently. LoggerContext would start to return LoggerProvider instead of just Logger, and other code would stop casting to AbstractLogger and could instead use the LoggerProvider interface. That second point ends up making more methods public on the concrete implementations. I had an alternative idea in LOG4J2-562 that would prevent these methods from needing to go public. I'll post my patch soon. I'll try to get performance numbers, too. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 Attachments: LOG4J2-555-delegate.patch *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Reopened] (LOG4J2-558) Create a log4j-bom
[ https://issues.apache.org/jira/browse/LOG4J2-558?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer reopened LOG4J2-558: -- Not quite right. Apply the patch I provided. This is an example of a pom using the bom {code:xml} project xmlns=http://maven.apache.org/POM/4.0.0; xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance; xsi:schemaLocation=http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd; modelVersion4.0.0/modelVersion groupIdcom.bhb.test/groupId artifactIdlog4j-testing/artifactId version0.0.1-SNAPSHOT/version dependencyManagement dependencies dependency groupIdorg.apache.logging.log4j/groupId artifactIdlog4j-bom/artifactId version2.0-rc2-SNAPSHOT/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement dependencies dependency groupIdorg.apache.logging.log4j/groupId artifactIdlog4j-core/artifactId /dependency /dependencies /project {code} Create a log4j-bom -- Key: LOG4J2-558 URL: https://issues.apache.org/jira/browse/LOG4J2-558 Project: Log4j 2 Issue Type: Improvement Reporter: Bruce Brouwer Assignee: Matt Sicker Fix For: 2.0-rc2 Attachments: log4j-bom.patch Create a log4j-bom (Bill of Materials) POM to make it easier for clients to keep consistent versions for multiple log4j artifacts. -- 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
[jira] [Updated] (LOG4J2-558) Create a log4j-bom
[ https://issues.apache.org/jira/browse/LOG4J2-558?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-558: - Attachment: log4j-bom.patch Create a log4j-bom -- Key: LOG4J2-558 URL: https://issues.apache.org/jira/browse/LOG4J2-558 Project: Log4j 2 Issue Type: Improvement Reporter: Bruce Brouwer Assignee: Matt Sicker Fix For: 2.0-rc2 Attachments: log4j-bom.patch Create a log4j-bom (Bill of Materials) POM to make it easier for clients to keep consistent versions for multiple log4j artifacts. -- 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
[jira] [Commented] (LOG4J2-519) Custom/Extended Loggers
[ https://issues.apache.org/jira/browse/LOG4J2-519?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13922497#comment-13922497 ] Bruce Brouwer commented on LOG4J2-519: -- With my work in LOG4J-547, this example would turn into something like this: {code} package com.bhb.log4j; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.simple.SimpleLogger; import org.apache.logging.log4j.spi.AbstractLogger; import org.apache.logging.log4j.spi.LoggerExtension; public final class ExtLogger extends AbstractLogger { private static final long serialVersionUID = 26876940739430L; private static final ConcurrentMapString, ExtLogger loggers = new ConcurrentHashMapString, ExtLogger(); private final LoggerExtension logger; private static final String FQCN = ExtLogger.class.getName(); private static final Level DIAG = Level.forName(DIAG, 350); private static final Level NOTICE = Level.forName(NOTICE, 450); private static final Level VERBOSE = Level.forName(VERBOSE, 550); private ExtLogger(LoggerExtension logger) { super(logger.getName()); this.logger = logger; } /** * Returns a custom Logger with the name of the calling class. * * @return The custom Logger for the calling class. */ public static ExtLogger getLogger() { return getLogger(getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will *default to the calling class. * @return The custom Logger. */ public static ExtLogger getLogger(final Class? clazz) { return getLogger(clazz != null ? clazz.getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will *default to the calling class. * @param messageFactory The message factory is used only when creating a logger, subsequent use *does not change the logger but will log a warning if mismatched. * @return The custom Logger. */ public static ExtLogger getLogger(final Class? clazz, final MessageFactory factory) { return getLogger(clazz != null ? clazz.getName() : getClassName(2), factory); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name *of the calling class will be used as the logger name. * @return The custom Logger. */ public static ExtLogger getLogger(final Object value) { return getLogger(value != null ? value.getClass().getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name *of the calling class will be used as the logger name. * @param messageFactory The message factory is used only when creating a logger, subsequent use *does not change the logger but will log a warning if mismatched. * @return The custom Logger. */ public static ExtLogger getLogger(final Object value, final MessageFactory factory) { return getLogger(value != null ? value.getClass().getName() : getClassName(2), factory); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @return The custom Logger. */ public static ExtLogger getLogger(final String name) { return getLogger(name != null ? name : getClassName(2), null); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @param messageFactory The message factory is used only when creating a logger, subsequent use *does not change the logger but will log a warning if mismatched. * @return The custom Logger. */ public static ExtLogger getLogger(final String name, final MessageFactory factory) { final String actualName = name != null ? name : getClassName(2); if
[jira] [Comment Edited] (LOG4J2-519) Custom/Extended Loggers
[ https://issues.apache.org/jira/browse/LOG4J2-519?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13922497#comment-13922497 ] Bruce Brouwer edited comment on LOG4J2-519 at 3/6/14 1:30 PM: -- With my work in LOG4J2-547, this example would turn into something like this: {code} package com.bhb.log4j; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.simple.SimpleLogger; import org.apache.logging.log4j.spi.AbstractLogger; import org.apache.logging.log4j.spi.LoggerExtension; public final class ExtLogger extends AbstractLogger { private static final long serialVersionUID = 26876940739430L; private static final ConcurrentMapString, ExtLogger loggers = new ConcurrentHashMapString, ExtLogger(); private final LoggerExtension logger; private static final String FQCN = ExtLogger.class.getName(); private static final Level DIAG = Level.forName(DIAG, 350); private static final Level NOTICE = Level.forName(NOTICE, 450); private static final Level VERBOSE = Level.forName(VERBOSE, 550); private ExtLogger(LoggerExtension logger) { super(logger.getName()); this.logger = logger; } /** * Returns a custom Logger with the name of the calling class. * * @return The custom Logger for the calling class. */ public static ExtLogger getLogger() { return getLogger(getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will *default to the calling class. * @return The custom Logger. */ public static ExtLogger getLogger(final Class? clazz) { return getLogger(clazz != null ? clazz.getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will *default to the calling class. * @param messageFactory The message factory is used only when creating a logger, subsequent use *does not change the logger but will log a warning if mismatched. * @return The custom Logger. */ public static ExtLogger getLogger(final Class? clazz, final MessageFactory factory) { return getLogger(clazz != null ? clazz.getName() : getClassName(2), factory); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name *of the calling class will be used as the logger name. * @return The custom Logger. */ public static ExtLogger getLogger(final Object value) { return getLogger(value != null ? value.getClass().getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name *of the calling class will be used as the logger name. * @param messageFactory The message factory is used only when creating a logger, subsequent use *does not change the logger but will log a warning if mismatched. * @return The custom Logger. */ public static ExtLogger getLogger(final Object value, final MessageFactory factory) { return getLogger(value != null ? value.getClass().getName() : getClassName(2), factory); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @return The custom Logger. */ public static ExtLogger getLogger(final String name) { return getLogger(name != null ? name : getClassName(2), null); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @param messageFactory The message factory is used only when creating a logger, subsequent use *does not change the logger but will log a warning if mismatched. * @return The custom Logger. */ public static ExtLogger getLogger(final String name, final MessageFactory factory) { final String actualName =
[jira] [Comment Edited] (LOG4J2-519) Custom/Extended Loggers
[ https://issues.apache.org/jira/browse/LOG4J2-519?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13922497#comment-13922497 ] Bruce Brouwer edited comment on LOG4J2-519 at 3/6/14 1:31 PM: -- With my work in LOG4J2-562, this example would turn into something like this: {code} package com.bhb.log4j; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.MessageFactory; import org.apache.logging.log4j.simple.SimpleLogger; import org.apache.logging.log4j.spi.AbstractLogger; import org.apache.logging.log4j.spi.LoggerExtension; public final class ExtLogger extends AbstractLogger { private static final long serialVersionUID = 26876940739430L; private static final ConcurrentMapString, ExtLogger loggers = new ConcurrentHashMapString, ExtLogger(); private final LoggerExtension logger; private static final String FQCN = ExtLogger.class.getName(); private static final Level DIAG = Level.forName(DIAG, 350); private static final Level NOTICE = Level.forName(NOTICE, 450); private static final Level VERBOSE = Level.forName(VERBOSE, 550); private ExtLogger(LoggerExtension logger) { super(logger.getName()); this.logger = logger; } /** * Returns a custom Logger with the name of the calling class. * * @return The custom Logger for the calling class. */ public static ExtLogger getLogger() { return getLogger(getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will *default to the calling class. * @return The custom Logger. */ public static ExtLogger getLogger(final Class? clazz) { return getLogger(clazz != null ? clazz.getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified name of the Class as the Logger name. * * @param loggerName The Class whose name should be used as the Logger name. If null it will *default to the calling class. * @param messageFactory The message factory is used only when creating a logger, subsequent use *does not change the logger but will log a warning if mismatched. * @return The custom Logger. */ public static ExtLogger getLogger(final Class? clazz, final MessageFactory factory) { return getLogger(clazz != null ? clazz.getName() : getClassName(2), factory); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name *of the calling class will be used as the logger name. * @return The custom Logger. */ public static ExtLogger getLogger(final Object value) { return getLogger(value != null ? value.getClass().getName() : getClassName(2)); } /** * Returns a custom Logger using the fully qualified class name of the value as the Logger name. * * @param value The value whose class name should be used as the Logger name. If null the name *of the calling class will be used as the logger name. * @param messageFactory The message factory is used only when creating a logger, subsequent use *does not change the logger but will log a warning if mismatched. * @return The custom Logger. */ public static ExtLogger getLogger(final Object value, final MessageFactory factory) { return getLogger(value != null ? value.getClass().getName() : getClassName(2), factory); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @return The custom Logger. */ public static ExtLogger getLogger(final String name) { return getLogger(name != null ? name : getClassName(2), null); } /** * Returns a custom Logger with the specified name. * * @param name The logger name. If null the name of the calling class will be used. * @param messageFactory The message factory is used only when creating a logger, subsequent use *does not change the logger but will log a warning if mismatched. * @return The custom Logger. */ public static ExtLogger getLogger(final String name, final MessageFactory factory) { final String actualName =
[jira] [Commented] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13923081#comment-13923081 ] Bruce Brouwer commented on LOG4J2-555: -- Would it be crazy to use a Java Proxy to proxy the loggers and have the proxy figure out the call stack? This should work fine when you're just dealing with the Logger interface. I don't know exactly what kind of performance impact this would create. Maybe there would be a way to detect if a logger is using a location pattern layout like %C and only proxy it if necessary. This wouldn't help for the extended loggers unless they implemented an interface. For those it could fall back to using cglib (most likely would be an optional dependency) I don't know if this is worth exploring, but I thought I would throw it out as an idea. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Commented] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13923094#comment-13923094 ] Bruce Brouwer commented on LOG4J2-555: -- As for the Set idea, I think that is close to what we need (sans proxies). I don't want this to walk up the class hierarchy, though. For what I was working on for LOG4J2-547 regarding the LoggerStream, I would be providing a subclass of Writer or OutputStream (e.g. LoggerWriter or LoggerOutputStream). These may wrap another Writer or OutputStream. If you simply walked up the class hierarchy of LoggerWriter, you would be watching for FQCNs of Writer, such as the wrapped Writer would also extend. This might cause this locator logic to incorrectly identify which class stack element was the outer most call stack used for locating caller information. I think it would be better if we simply gave the FQCN parameter a collection of FQCNs. If I knew I extended every method of AbstractLogger, then why bother checking for AbstractLogger in the call stack. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Commented] (LOG4J2-519) Custom/Extended Loggers
[ https://issues.apache.org/jira/browse/LOG4J2-519?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13923170#comment-13923170 ] Bruce Brouwer commented on LOG4J2-519: -- Sorry, I wasn't clear in what my code represents. I neglected to remove FQCN from the code I posted as in the last getLogger method, you'll see that my example is passing in the ExtLogger.class and AbstractLogger.class. Basically, what would have been two separate FQCN. I don't particularly need to pass in actual classes. They could be FQCN strings. Also, this is is just code that demonstrates where we could take it if we moved forward with what I am suggesting in LOG4J2-562 and influenced by the discussion in LOG4J2-555. The code as I provided does not actually work currently with the trunk on log4j2. It is important to note that I'm giving 2 FQCNs. Because some of the implemented methods are on AbstractLogger and others on ExtLogger, we need to tell the extended logger about both classes. I imagine we would want to allow any number of FQCNs if we pursued this approach. 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
[jira] [Created] (LOG4J2-562) Improve ability to create custom extended logger
Bruce Brouwer created LOG4J2-562: Summary: Improve ability to create custom extended logger Key: LOG4J2-562 URL: https://issues.apache.org/jira/browse/LOG4J2-562 Project: Log4j 2 Issue Type: Improvement Components: API Reporter: Bruce Brouwer Attachments: log4j2-loggerExtension.patch Create a LoggerExtension from the original logger which simply remembers the FQCN that will ultimately be the extension. Also by doing this, we can switch a bunch of methods that ended up being public back to protected. I'm guessing they became public so extensions could call them. This can simplify extensions (such as slf4j, jcl, custom extensions, logger streams) so they don't have to pass in the FQCN to that special log method on AbstractLogger anymore. Also, you don't have to wrap every extended log method with a check to see if the logging is enabled. Finally, you don't need to have any access to the MessageFactory. This even has to potential to eliminate AbstractLoggerWrapper. -- 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
[jira] [Updated] (LOG4J2-562) Improve ability to create custom extended logger
[ https://issues.apache.org/jira/browse/LOG4J2-562?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-562: - Attachment: log4j2-loggerExtension.patch This log4j2-loggerExtension.patch is in no way complete, but I would like some feedback on the direction I am taking on this. Improve ability to create custom extended logger Key: LOG4J2-562 URL: https://issues.apache.org/jira/browse/LOG4J2-562 Project: Log4j 2 Issue Type: Improvement Components: API Reporter: Bruce Brouwer Attachments: log4j2-loggerExtension.patch Create a LoggerExtension from the original logger which simply remembers the FQCN that will ultimately be the extension. Also by doing this, we can switch a bunch of methods that ended up being public back to protected. I'm guessing they became public so extensions could call them. This can simplify extensions (such as slf4j, jcl, custom extensions, logger streams) so they don't have to pass in the FQCN to that special log method on AbstractLogger anymore. Also, you don't have to wrap every extended log method with a check to see if the logging is enabled. Finally, you don't need to have any access to the MessageFactory. This even has to potential to eliminate AbstractLoggerWrapper. -- 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
[jira] [Commented] (LOG4J2-519) Custom/Extended Loggers
[ https://issues.apache.org/jira/browse/LOG4J2-519?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13918741#comment-13918741 ] Bruce Brouwer commented on LOG4J2-519: -- I've been wondering about the need here to cast to AbstractLogger. This ties us to the implementation of Loggers originally conceived in core. What if we had an interface that has the .log(...) methods defined on AbstractLogger that take the FQCN. Perhaps we could call this interface ExtensibleLogger or something like that. I would feel better about casting to an interface that any logging implementation could implement. I'm kind of looking at this for LOG4J2-547 which I am working on. 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
[jira] [Commented] (LOG4J2-555) Location-based functionality broken in AbstractLoggerWrapper subclasses
[ https://issues.apache.org/jira/browse/LOG4J2-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13918817#comment-13918817 ] Bruce Brouwer commented on LOG4J2-555: -- I am also very interested in knowing where this lands. I'm working on LOG4J2-547, the LoggerStream API. In a sense I am writing a logger wrapper, but I am unable to extend AbstractLoggerWrapper or AbstractLogger as I need to extend Writer or OutputStream. Location-based functionality broken in AbstractLoggerWrapper subclasses --- Key: LOG4J2-555 URL: https://issues.apache.org/jira/browse/LOG4J2-555 Project: Log4j 2 Issue Type: Bug Components: API, Core Affects Versions: 2.0-rc1 Reporter: Remko Popma Assignee: Remko Popma Fix For: 2.0-rc2 *How to reproduce* * Create a custom logger that extends {{AbstractLoggerWrapper}} (or generate one with the tool attached to LOG4J2-519) * In the custom logger provide a public method that invokes the {{log(Level, String)}} method * Configure a pattern layout that uses location, like %C for the logger FQCN * From a sample app, call the public method on your custom logger. * The output will show the class name of the custom logger instead of the class name of the calling class in the sample application. *Cause* {{AbstractLogger}}'s FQCN field is {{static final}} and initialized to {{AbstractLogger.class.getName()}}. Then, in {{Log4jLogEvent#calcLocation()}}, when walking over the stack trace elements, the element _following_ the FQCN is returned. So only loggers that directly subclass from {{AbstractLogger}} will work correctly. Loggers that inherit from {{AbstractLoggerWrapper}} are two levels removed from {{AbstractLogger}} and the {{calcLocation()}} method will not work correctly. *Solution* I think {{AbstractLogger}}'s FQCN field should be made non-static, and initialized to {{getClass().getName()}} in the constructor of {{AbstractLogger}}. {{Log4jLogEvent#calcLocation()}} can then be modified to return the {{StackElement}} whose class name matches the FQCN, instead of the next element. Location-based functionality should then work for arbitrarily deep subclass hierarchies of AbstractLogger. -- 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
[jira] [Commented] (LOG4J2-519) Custom/Extended Loggers
[ https://issues.apache.org/jira/browse/LOG4J2-519?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13918826#comment-13918826 ] Bruce Brouwer commented on LOG4J2-519: -- Definitely it would go in spi. It would allow flexibility in implementations that might not directly extend AbstractLogger and I think it might help me out with LOG4J2-547 where my logger needs to extend Writer and OutputStream. I could extend Writer and still implement ExtensibleLogger. 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 *
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917415#comment-13917415 ] Bruce Brouwer commented on LOG4J2-547: -- So, I've been thinking about the actual use case for this feature. I was thinking it would be even more helpful if I grabbed a writer that actually wrapped another writer. This way I could spy on the writer and send all its content to a Logger and to the actual writer. I'm thinking of a method signatures like this: {code} public Writer writer(Writer writer, Level level); public Writer writer(Writer writer, Marker marker, Level level); public OutputStream stream(OutputStream stream, Level level); public OutputStream stream(OutputStream stream, Marker marker, Level level); {code} We could also provide ones basically like before: {code} public Writer writer(Level level); public Writer writer(Marker marker, Level level); public OutputStream stream(Level level); public OutputStream stream(Marker marker, Level level); {code} Maybe we would keep the PrintWriter/PrintStream variants as well. But then why stop there. We could spy on Readers as well: {code} public Reader reader(Reader reader, Level level); public Reader reader(Reader reader, Marker marker, Level level); public InputStream stream(InputStream stream, Level level); public InputStream stream(InputStream stream, Marker marker, Level level); {code} Making this all work is not really any harder than what is already there. But now we're starting to really pollute the Logger interface with stuff that 99% of the time I'll never want or use. What if we took it a different direction and didn't put these reader/writer methods on Logger, but instead put them on LogManager or even a new class LogStreaming. Now I could get one of these things with code like this: {code} Writer writer = LogStreaming.writer(myWriter, Level.WARNING); {code} We could go even further and add debug/warn/info/error methods on here as well: {code} Writer writer = LogStreaming.debugWriter(myWriter); {code} This goes along with another idea I had in LOG4J-242 which would make a fluent interface for log4j. I eventually decided that all that stuff doesn't belong in Logger either, so instead I would want a FluentLogManager instead of LogManager. Now back to the whole FQCN thing. If I do the hack I mentioned coupled with these new methods I described, if I were to pass in a PrintWriter to this writer method, then using the FQCN of PrintWriter will determine the caller is the caller of the PrintWriter I passed in, and not the one being created by the writer method. Furthermore, the reason I would want one of these Writers is to pass to some function that expects a Writer, and therefore the call stack will not be from my code anyway and then the caller location probably won't be as useful to me as I would want. So, what are your thoughts on all of these ideas? Am I making this more complicated than it should be? Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, Add_caller_info_tests.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- This message was sent by Atlassian JIRA (v6.1.5#6160) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org
[jira] [Comment Edited] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917415#comment-13917415 ] Bruce Brouwer edited comment on LOG4J2-547 at 3/2/14 5:01 PM: -- So, I've been thinking about the actual use case for this feature. I was thinking it would be even more helpful if I grabbed a writer that actually wrapped another writer. This way I could spy on the writer and send all its content to a Logger and to the actual writer. I'm thinking of a method signatures like this: {code} public Writer writer(Writer writer, Level level); public Writer writer(Writer writer, Marker marker, Level level); public OutputStream stream(OutputStream stream, Level level); public OutputStream stream(OutputStream stream, Marker marker, Level level); {code} We could also provide ones basically like before: {code} public Writer writer(Level level); public Writer writer(Marker marker, Level level); public OutputStream stream(Level level); public OutputStream stream(Marker marker, Level level); {code} Maybe we would keep the PrintWriter/PrintStream variants as well. But then why stop there. We could spy on Readers as well: {code} public Reader reader(Reader reader, Level level); public Reader reader(Reader reader, Marker marker, Level level); public InputStream stream(InputStream stream, Level level); public InputStream stream(InputStream stream, Marker marker, Level level); {code} Making this all work is not really any harder than what is already there. But now we're starting to really pollute the Logger interface with stuff that 99% of the time I'll never want or use. What if we took it a different direction and didn't put these reader/writer methods on Logger, but instead put them on LogManager or even a new class LogStreaming. Now I could get one of these things with code like this: {code} Writer writer = LogStreaming.writer(myWriter, Level.WARNING); {code} We could go even further and add debug/warn/info/error methods on here as well: {code} Writer writer = LogStreaming.debugWriter(MyExample.class, myWriter); {code} This goes along with another idea I had in LOG4J-242 which would make a fluent interface for log4j. I eventually decided that all that stuff doesn't belong in Logger either, so instead I would want a FluentLogManager instead of LogManager. Now back to the whole FQCN thing. If I do the hack I mentioned coupled with these new methods I described, if I were to pass in a PrintWriter to this writer method, then using the FQCN of PrintWriter will determine the caller is the caller of the PrintWriter I passed in, and not the one being created by the writer method. Furthermore, the reason I would want one of these Writers is to pass to some function that expects a Writer, and therefore the call stack will not be from my code anyway and then the caller location probably won't be as useful to me as I would want. So, what are your thoughts on all of these ideas? Am I making this more complicated than it should be? was (Author: bruce.brouwer): So, I've been thinking about the actual use case for this feature. I was thinking it would be even more helpful if I grabbed a writer that actually wrapped another writer. This way I could spy on the writer and send all its content to a Logger and to the actual writer. I'm thinking of a method signatures like this: {code} public Writer writer(Writer writer, Level level); public Writer writer(Writer writer, Marker marker, Level level); public OutputStream stream(OutputStream stream, Level level); public OutputStream stream(OutputStream stream, Marker marker, Level level); {code} We could also provide ones basically like before: {code} public Writer writer(Level level); public Writer writer(Marker marker, Level level); public OutputStream stream(Level level); public OutputStream stream(Marker marker, Level level); {code} Maybe we would keep the PrintWriter/PrintStream variants as well. But then why stop there. We could spy on Readers as well: {code} public Reader reader(Reader reader, Level level); public Reader reader(Reader reader, Marker marker, Level level); public InputStream stream(InputStream stream, Level level); public InputStream stream(InputStream stream, Marker marker, Level level); {code} Making this all work is not really any harder than what is already there. But now we're starting to really pollute the Logger interface with stuff that 99% of the time I'll never want or use. What if we took it a different direction and didn't put these reader/writer methods on Logger, but instead put them on LogManager or even a new class LogStreaming. Now I could get one of these things with code like this: {code} Writer writer = LogStreaming.writer(myWriter, Level.WARNING); {code} We could go even further and add debug/warn/info/error methods on here as well: {code} Writer writer =
[jira] [Comment Edited] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917415#comment-13917415 ] Bruce Brouwer edited comment on LOG4J2-547 at 3/2/14 5:02 PM: -- So, I've been thinking about the actual use case for this feature. I was thinking it would be even more helpful if I grabbed a writer that actually wrapped another writer. This way I could spy on the writer and send all its content to a Logger and to the actual writer. I'm thinking of a method signatures like this: {code} public Writer writer(Writer writer, Level level); public Writer writer(Writer writer, Marker marker, Level level); public OutputStream stream(OutputStream stream, Level level); public OutputStream stream(OutputStream stream, Marker marker, Level level); {code} We could also provide ones basically like before: {code} public Writer writer(Level level); public Writer writer(Marker marker, Level level); public OutputStream stream(Level level); public OutputStream stream(Marker marker, Level level); {code} Maybe we would keep the PrintWriter/PrintStream variants as well. But then why stop there. We could spy on Readers as well: {code} public Reader reader(Reader reader, Level level); public Reader reader(Reader reader, Marker marker, Level level); public InputStream stream(InputStream stream, Level level); public InputStream stream(InputStream stream, Marker marker, Level level); {code} Making this all work is not really any harder than what is already there. But now we're starting to really pollute the Logger interface with stuff that 99% of the time I'll never want or use. What if we took it a different direction and didn't put these reader/writer methods on Logger, but instead put them on LogManager or even a new class LogStreaming. Now I could get one of these things with code like this: {code} Writer writer = LogStreaming.writer(MyExample.class, myWriter, Level.WARNING); {code} We could go even further and add debug/warn/info/error methods on here as well: {code} Writer writer = LogStreaming.debugWriter(MyExample.class, myWriter); {code} This goes along with another idea I had in LOG4J-242 which would make a fluent interface for log4j. I eventually decided that all that stuff doesn't belong in Logger either, so instead I would want a FluentLogManager instead of LogManager. Now back to the whole FQCN thing. If I do the hack I mentioned coupled with these new methods I described, if I were to pass in a PrintWriter to this writer method, then using the FQCN of PrintWriter will determine the caller is the caller of the PrintWriter I passed in, and not the one being created by the writer method. Furthermore, the reason I would want one of these Writers is to pass to some function that expects a Writer, and therefore the call stack will not be from my code anyway and then the caller location probably won't be as useful to me as I would want. So, what are your thoughts on all of these ideas? Am I making this more complicated than it should be? was (Author: bruce.brouwer): So, I've been thinking about the actual use case for this feature. I was thinking it would be even more helpful if I grabbed a writer that actually wrapped another writer. This way I could spy on the writer and send all its content to a Logger and to the actual writer. I'm thinking of a method signatures like this: {code} public Writer writer(Writer writer, Level level); public Writer writer(Writer writer, Marker marker, Level level); public OutputStream stream(OutputStream stream, Level level); public OutputStream stream(OutputStream stream, Marker marker, Level level); {code} We could also provide ones basically like before: {code} public Writer writer(Level level); public Writer writer(Marker marker, Level level); public OutputStream stream(Level level); public OutputStream stream(Marker marker, Level level); {code} Maybe we would keep the PrintWriter/PrintStream variants as well. But then why stop there. We could spy on Readers as well: {code} public Reader reader(Reader reader, Level level); public Reader reader(Reader reader, Marker marker, Level level); public InputStream stream(InputStream stream, Level level); public InputStream stream(InputStream stream, Marker marker, Level level); {code} Making this all work is not really any harder than what is already there. But now we're starting to really pollute the Logger interface with stuff that 99% of the time I'll never want or use. What if we took it a different direction and didn't put these reader/writer methods on Logger, but instead put them on LogManager or even a new class LogStreaming. Now I could get one of these things with code like this: {code} Writer writer = LogStreaming.writer(myWriter, Level.WARNING); {code} We could go even further and add debug/warn/info/error methods on here as well: {code} Writer writer =
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917565#comment-13917565 ] Bruce Brouwer commented on LOG4J2-547: -- Matt, you're going down the exact same thought-path I am. The way I'm looking at it, there are a number of alternate log4j interfaces available, some of which haven't come to light yet. There's the slf4j interface and the jcl interface. I'm starting to think of this streaming API in the same light, putting it in log4j-streaming. And I agree, my fluent api should go in another module: log4j-fluent. I like keeping the Logger interface more along the lines of the classic log4j interface without adding a bunch of other methods. Because of my viewpoint, I would prefer having a different root class that accessed this streaming API. I don't have a strong preference for the actual name, I kind of like StreamingLogManager. This new root class would live in log4j-streaming and not impact the classic nature of the LogManager interface. Is it too big of a change to introduce a new artifact this late in the game? Should the streaming API be pushed off to 2.1? But I like how there is general agreement to get it out of Logger. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, Add_caller_info_tests.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917644#comment-13917644 ] Bruce Brouwer commented on LOG4J2-547: -- If we were going to put the streaming interface in -core or -api, then I agree with Gary that there is no use for another JAR. If, however, we decide this streaming API isn't part of the core of log4j (as I am of the opinion), then I vote to put that in a -streaming JAR. That would include StreamingLogManager. I personally don't mind the extra JAR if it requires me to explicitly choose to include it for the desired functionality (like slf4j or jcl). I'm a big user of Spring and I felt the same way when they broke that up into a whole bunch of JARs. Now it just seems like common practice to have smaller, more targeted JARs. Sometimes it can be a pain to know which jar has a particular class, but [http://search.maven.org] class search makes that easy to figure out. Do you think we can gain consensus to just remove it completely until after 2.0 is released? Maybe some time will help us settle on a direction. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, Add_caller_info_tests.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Created] (LOG4J2-558) Create a log4j-bom
Bruce Brouwer created LOG4J2-558: Summary: Create a log4j-bom Key: LOG4J2-558 URL: https://issues.apache.org/jira/browse/LOG4J2-558 Project: Log4j 2 Issue Type: Improvement Reporter: Bruce Brouwer Create a log4j-bom (Bill of Materials) POM to make it easier for clients to keep consistent versions for multiple log4j artifacts. -- 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
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917664#comment-13917664 ] Bruce Brouwer commented on LOG4J2-547: -- Yes, the default search in search.maven.org can yield a ton of stuff. I'm talking about the advanced search where you can specify a fully qualified class name. And I agree, the Spring docs don't make it clear enough which JARs you need for any particular feature. As for the bom, that's a great idea. I created LOG4J2-558. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, Add_caller_info_tests.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917673#comment-13917673 ] Bruce Brouwer commented on LOG4J2-547: -- It sounds like the log4j team supports keeping this in core. I will put together a patch unless anyone else volunteers. I'll put the factory methods in LogManager as this being considered part of the core of log4j. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, Add_caller_info_tests.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917712#comment-13917712 ] Bruce Brouwer commented on LOG4J2-547: -- Ok, I need a bit of advice. In LogManager, I get access to a Logger. Is it ok to just cast that to AbstractLogger or is there some better way? Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, Add_caller_info_tests.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- 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
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917159#comment-13917159 ] Bruce Brouwer commented on LOG4J2-547: -- In looking at LoggerStream, I can see how it could help me when shelling out to commands when all I want to do is log the output of that shelled command. There is some non-trivial stuff that LoggerStream is doing, so I don't want to get rid of that concept. But I agree that as it stands, the most helpful part of LoggerStream is actually the HelperStream. I'm including a patch that gets rid of LoggerStream and instead returns a plain old PrintWriter. This involved making a LoggerWriter which does basically what HelperStream did before. I don't see a whole lot of value adding this to the LoggerContext. In the end it needs an AbstractLogger anyway, so why not get it from the AbstractLogger. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- This message was sent by Atlassian JIRA (v6.1.5#6160) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org
[jira] [Updated] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Bruce Brouwer updated LOG4J2-547: - Attachment: log4j2-loggerStream.patch Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- This message was sent by Atlassian JIRA (v6.1.5#6160) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org
[jira] [Comment Edited] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917159#comment-13917159 ] Bruce Brouwer edited comment on LOG4J2-547 at 3/1/14 7:04 PM: -- In looking at LoggerStream, I can see how it could help me when shelling out to commands when all I want to do is log the output of that shelled command. There is some non-trivial stuff that LoggerStream is doing, so I don't want to get rid of that concept. But I agree that as it stands, the most helpful part of LoggerStream is actually the HelperStream. I'm including a patch that gets rid of LoggerStream and instead returns a plain old PrintWriter. This involved making a LoggerWriter which does basically what HelperStream did before. I don't see a whole lot of value adding this to the LoggerContext. In the end it needs an AbstractLogger anyway, so why not get it from the AbstractLogger. Oh, and I called the method .printWriter(...) instead of .getStream(...). First, the old .getStream didn't even return an OutputStream, it returned something that extended PrintWriter. And also, by removing the .get part, users might not expect to get the exact same PrintWriter instance each time they call it. In this case, I don't think I would want to get the same instance each time. was (Author: bruce.brouwer): In looking at LoggerStream, I can see how it could help me when shelling out to commands when all I want to do is log the output of that shelled command. There is some non-trivial stuff that LoggerStream is doing, so I don't want to get rid of that concept. But I agree that as it stands, the most helpful part of LoggerStream is actually the HelperStream. I'm including a patch that gets rid of LoggerStream and instead returns a plain old PrintWriter. This involved making a LoggerWriter which does basically what HelperStream did before. I don't see a whole lot of value adding this to the LoggerContext. In the end it needs an AbstractLogger anyway, so why not get it from the AbstractLogger. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- This message was sent by Atlassian JIRA (v6.1.5#6160) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org
[jira] [Commented] (LOG4J2-547) Update LoggerStream API
[ https://issues.apache.org/jira/browse/LOG4J2-547?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917180#comment-13917180 ] Bruce Brouwer commented on LOG4J2-547: -- One thing I noticed I missed. We might want to synchronize on buf in the close() method. Update LoggerStream API --- Key: LOG4J2-547 URL: https://issues.apache.org/jira/browse/LOG4J2-547 Project: Log4j 2 Issue Type: Improvement Components: API Affects Versions: 2.0-rc1 Reporter: Matt Sicker Assignee: Ralph Goers Fix For: 2.0 Attachments: 0001-PrintStream-API-update.patch, log4j2-loggerStream.patch I've got some ideas on how to improve the LoggerStream idea that I added a little while ago. The main thing I'd like to do is extract an interface from it, rename the default implementation to SimpleLoggerStream (part of the SimpleLogger stuff), and allow log4j implementations to specify a different implementation if desired. In doing this, I'm not sure where specifically I'd prefer the getStream methods to be. Right now, it's in Logger, but really, it could be in LoggerContext instead. I don't think I should be required to get a Logger just to get a LoggerStream. Now if only the java.io package used interfaces instead of classes. This would be so much easier to design! -- This message was sent by Atlassian JIRA (v6.1.5#6160) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org
[jira] [Commented] (LOG4J2-510) How to close inactive log files
[ https://issues.apache.org/jira/browse/LOG4J2-510?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanelfocusedCommentId=13917181#comment-13917181 ] Bruce Brouwer commented on LOG4J2-510: -- What does your configuration look like that log4j2 is creating many open files? The general use case that I'm aware of opens a file and keeps it open for the life of the app. If you simply want a way to configure log4j to close a log file after some period of inactivity, this should be changed to an enhancement request. In that case, I would suggest delaying this until after 2.0 GA How to close inactive log files --- Key: LOG4J2-510 URL: https://issues.apache.org/jira/browse/LOG4J2-510 Project: Log4j 2 Issue Type: Bug Components: Appenders Affects Versions: 2.0-beta9 Environment: linux Reporter: Eric Labels: performance Fix For: 2.0-beta9 Hi There, in log4j2 when the App start logging it create and open a file to log into and that file stay open as long as the App is running. in my case log4j2 create and open too many files base on ThreadContext and the OS (linux) will complaint that too many files are open and my App will crash and stop responding. My question is: 1 - how do you close those files with log4j2 if they are inactive for a period of time. 2 - How do you have access to the log4j2 handle that open those files. 3 - How do you tell log4j2 to open a file just for a period of time. Thanks Eric -- This message was sent by Atlassian JIRA (v6.1.5#6160) - To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org