-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Maven and Groovy #4
Comments
The first warning is only really an issue if you are getting StackOverflowErrors because the org.sonatype.gossip.Gossip$LoggerImpl tries to log by printing to System.out/err, which is in turn directed to SLF4J, which delegates to org.sonatype.gossip.Gossip$LoggerImpl and so on. If this is happening it can be fixed by adding the following before you initialise sysout-over-slf4j: SysOutOverSLF4J.registerLoggingSystem("org.sonatype.gossip"); That will mean any class whose package starts with org.sonatype.gossip will print direct to the console rather than sending output to SLF4J, preventing an endless loop. If it is not happening (perhaps because they are just a wrapper around another logging system, like Logback or Log4J) then you can suppress this warning by raising the log level of Logger uk.org.lidalia.sysoutslf4j.context.SysOutOverSLF4JInitialiser to ERROR rather than WARN in the underlying log configuration. |
The second warning is telling you that now that the java.lang.System class has a static reference to an instance of a sysout-over-slf4j class, the ClassLoader that loaded sysout-over-slf4j cannot be garbage collected. This would be an issue if you had initialised sysout-over-slf4j in, for instance, a war file in Tomcat that you were regularly reloading without restarting the JVM; a ClassLoader maintains a reference to all Classes it has loaded, so you would have a steadily increasing number of classes you no longer use held in memory and would eventually fall over with an OutOfMemoryError. I have no idea how big a deal that is for gmaven - probably not much? After all Maven typically runs once then exits, so even if you do discard classloaders, resulting memory leaks are of less importance. Again you can suppress it by raising the level of uk.org.lidalia.sysoutslf4j.context.PrintStreamCoordinatorFactory to ERROR. |
I suppose the long and short of it is, are you actually seeing either an OutOfMemoryError or a StackOverflowError? |
I have tried doing the below
but looking at the code SysOutOverSLF4J clinit calls sysOutOverSLF4JInitialiser.initialise which is before I can call registerLoggingSystem You are correct I am not currently seeing any fatal errors - but currently I am still experimenting ;-) |
Regarding the classloader .... I agree its probably not critical in the context of maven. Could you clarify how "java.lang.System class has a static reference to an instance of a sysout-over-slf4j class" has happened? i.e. is this because you are replacing the System streams ? What about when you reset them back (using a try/finally pattern) ? How would you suggest changing the log.warn to e.g. debug in PrintStreamCoordinatorFactory ? |
Good spot... Missing a test there. I'll fix that up. And in the process I've found that the gnarliest bit of the problem (deducing from the stack trace what the calling class was and whether it was printing an exception) has been broken by changes in the JDK in such a way that exceptions will not be logged, which is a bit critical. In fact it raises severe questions about the safety of using sysout-over-slf4j at all; I'm beginning to wonder if I should stick a big "using this may be a mistake" sign on the front page now... I'm really struggling to find a robust way of solving that problem, which may be a smell that it's not a clever one to have ever tried to solve. |
Yes, that's exactly it - the System streams are replaced with sysout-over-slf4j's custom subtype of PrintStream, which is loaded by
If you did that with SysOutOverSLF4J.restoreOriginalSystemOutputs() you should be OK.
That's going to be totally dependent on your logging system's implementation - what does org.sonatype.gossip.Gossip$LoggerImpl do? Presumably it chooses what level to log at, and that is configurable? In Logback or Log4J it would be a case of setting the logger's level in logback.xml/log4j.properties or getting a reference to the Logger instance and calling setLevel on it. |
Given a try/finally pattern negates the class loader problem is the warning (in that scenario) not applicable? It might be nice if it was possible to automatically embed/wrap the sendSystemOutAndErrToSLF4J / restoreOriginalSystemOutputs. However that might require an API enhancement to do e.g. https://stackoverflow.com/questions/8657941/java-annotation-for-wrapping-a-method so that a method callback could be passed in. Regarding the logging - I am using Maven's default logging. What I actually meant was changing the PrintStreamCoordinatorFactory from warn to debug - but in might not be needed at all given the above callback suggestion. |
Ouch :-( Could you clarify whereabouts in the code you are referring to ? |
Issue occurs because the first stack line outside sysout-over-slf4j is no longer in Throwable.class but in an inner class of Throwable.class. Result (I think) is that sysout-over-slf4j concludes that that inner class originated the call to print to the console and that sysout-over-slf4j thinks it is not part of printing a stacktrace. I need to explore further what the implications are. My initial thought is that it means Throwable.printStackTrace() is being logged at INFO level on a Logger called java.lang.Thread$WrappedPrintStream, which is not good but perhaps not as disastrous as I thought at first. |
Raised issue #5 to track the incorrectly routed exceptions. |
I'm afraid I'm really not a believer in Annotations for control flow. I wouldn't necessarily mind adding a function as so:
which would be relatively light to use in Java 8:
|
That's not currently possible, and it's not really the way SLF4J expects things to work. The library writer decides on the probable importance of a log message by statically choosing trace/debug/info/warn/error, and if the end user decides they aren't interested in that particular message they alter the behaviour of the logging system to suppress it rather than altering the behaviour of the library to log it at a different level. I'd much rather see this handled in Maven's logging system than make it dynamically configurable in sysout-over-slf4j. |
This is less serious than I had thought, and I have a fix I'm relatively comfortable with, though I would appreciate review. Discussion moved to issue #5. |
Integrating sysout-over-slf4j as a dependency to the gmaven plugin which has some groovy code (that calls a third party library that has some system out calls) gives
The text was updated successfully, but these errors were encountered: