Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Why are Loggers static members in classes

Lothar,
 
I think the point in this discussion you are still missing is that what you are trying to do is still possible, just not the way you are currently doing it.  By moving to using the SLF4j adapter, you can then plug log4j, logback, or other logging frameworks which do allow you to "listen" to the logging output programmatically.   With log4j, you can programmatically manipulate the appenders that are attached to any Logger at runtime, or even "all Loggers" via the root logger. 
 
I've frequently done this in test cases in order to verify that proper log statements are logged.  Sometimes that's the only way to tell that the thing I'm trying to test actually happened. 
 
Example (using log4j 1.2):
Logger logger = Logger.getLogger(ClassIWantToWatch.class);
Appender appender = new MyCapturingAppender();
logger.addAppender(appender);
 
// do testing code that triggers logger
 
// read log statements from appender
 
logger.removeAppender(appender)
 
Some helpful links on the subject:
 
Sven.
 

From: jetty-users-bounces@xxxxxxxxxxx [jetty-users-bounces@xxxxxxxxxxx] On Behalf Of Joakim Erdfelt [joakim@xxxxxxxxxxx]
Sent: Wednesday, November 27, 2013 6:48 AM
To: JETTY user mailing list
Subject: Re: [jetty-users] Why are Loggers static members in classes

"pattern we read in a book" heh.

No, a core goal of jetty is to run on as wide an array of hardware as possible.
That means we reuse objects where we can, reduce GC churn, etc.. especially for those resource constrained environments.

We also have to make Jetty's Logging co-exist with the various logging frameworks that are out there now.
All of them initialize at (essentially) JVM start.
Changing them after the fact is not possible.

There are 2 parts of the Logging equation.
  1) Emitting Logs from code
  2) Runtime Configuration for selecting/filtering/routing Logs to an adapter/appender

The goal of Jetty Logging is to focus on #1, to emit named logging events, with severity, and let the Logging impl decide what to do with them.
The configuration of Logging in #2 is done by the logging implementation you choose. Once a Logger impl is selected it is used.

Your technique of swapping out the Logger selection at runtime is a bug, not a feature.  That should never have been allowed.

The change that you keep pointing to (7.0 to 7.6) isn't about static loggers, its about named logging with proper severity.

We went from:

import org.eclipse.jetty.util.Log;

Log.info("Something happened");

to:

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

private static final Logger LOG = Log.getLogger(HelloJettyServlet.class);

LOG.info("Something happened");

Note: the old Log.<severity>(String) methods were marked as deprecated in jetty-7 and removed in jetty-9.

This allowed the step #2 folks better control of logging via filtering and routing due to the named loggers.

Since logs then were not instance related then, and logs now are not instance related, there's no reason to have multiple copies of those Loggers in memory.
In fact, having multiple copies of Loggers is viewed as a negative in our minds.

This can be seen our choices in various parts of Jetty, not just the Loggers.
Some examples (off the top of my head, there's lots more)

jetty-http/src/main/java/org/eclipse/jetty/http/DateGenerator.java
   private static final ThreadLocal<DateGenerator> __dateGenerator =new ThreadLocal<DateGenerator>()

jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java
  private static final Trie<Float> __qualities = new ArrayTernaryTrie<>();

jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
  private static final PreparedResponse[] __preprepared = new PreparedResponse[HttpStatus.MAX_CODE+1];

jetty-jndi/src/main/java/org/eclipse/jetty/jndi/ContextFactory.java
  private static final WeakHashMap __contextMap = new WeakHashMap();

jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java
  private static final Map<Integer, StreamStatus> v2Codes = new HashMap<>();
  private static final Map<Integer, StreamStatus> v3Codes = new HashMap<>();

jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java
  private static final HashMap<String, Class<?>> name2Class=new HashMap<>();
  private static final HashMap<Class<?>, String> class2Name=new HashMap<>();
  private static final HashMap<Class<?>, Method> class2Value=new HashMap<>();

jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/ClientUpgradeRequest.java
  private static final Set<String> FORBIDDEN_HEADERS;

These fields are static because duplicating them per instance makes no sense.
Could they work as non-static fields? Yes, in all cases.  But we wont change that.

Point is, this change is not a "following the herd" or "what we see elsewhere" but rather a conscious decision to minimize pointless GC churn while simultaneously choosing a decision that makes sense for the second part of the Logging equation (configuration).

Years of debate went into this change on the jetty dev side, literally (no foolin!)
Even when the decision was made, more than half the existing devs were nervous / cautious about it.
Today, looking back, the change proved more than needed for the users, but immensely useful for troubleshooting and debugging of servers for us core devs as well.


--
Joakim Erdfelt <joakim@xxxxxxxxxxx>
Expert advice, services and support from from the Jetty & CometD experts


On Wed, Nov 27, 2013 at 2:28 AM, Lothar Kimmeringer <job@xxxxxxxxxxxxxx> wrote:
Am 26.11.2013 20:41, schrieb Joakim Erdfelt:
> Why are you relying on the StdErrLog fallback logging?

It helped solving my specific need at that time (half a decade ago).

[a lot of examples]

These examples are cool, thank you for these. I think, the Jetty-project
benefits from that (so this discussion has at least a positive effect ;-)

But your examples all work by setting the Logger using the resource-
file and not programmatically which is my point: This is no longer
possible with the way the logger is "now" (since 7.6) retrieved
from the Log-class.

I try to find some time to show this with examples how classes that
are semantically equal behave differently in dependence of the syntax
of the source.

There are reasons why I do it programmatically and not with the
resource-file. Changing that would bring up even more TODOs than
the ones I already have with the migration from 7.0 to 9.x

But my primary question (still in the subject) still stands: Why
the change to a static member (which it wasn't in 7.0)? The only
reason I heard so far is: It's a pattern we read in a book. ;-)


Regards, Lothar
_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/jetty-users


Back to the top