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

Why are you using logging event messages?
LifeCycle events (like in your example) can be monitored using a LifeCycle.Listener.

package jetty.examples;

import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.preventers.LoginConfigurationLeakPreventer;

public class LifecycleEvents
{
    public static class EventCapture implements LifeCycle.Listener
    {
        @Override
        public void lifeCycleStarting(LifeCycle event)
        {
            System.out.printf("[starting] %s%n",event);
        }

        @Override
        public void lifeCycleStarted(LifeCycle event)
        {
            System.out.printf("[started] %s%n",event);
        }

        @Override
        public void lifeCycleFailure(LifeCycle event, Throwable cause)
        {
            System.out.printf("[failure] %s%n",event);
            cause.printStackTrace();
        }

        @Override
        public void lifeCycleStopping(LifeCycle event)
        {
            System.out.printf("[stopping] %s%n",event);
        }

        @Override
        public void lifeCycleStopped(LifeCycle event)
        {
            System.out.printf("[stopped] %s%n",event);
        }
    }
    
    public static void main(String[] args) throws Exception
    {
        LoginConfigurationLeakPreventer component = new LoginConfigurationLeakPreventer();
        
        EventCapture capture = new EventCapture();
        component.addLifeCycleListener(capture);
        component.start();
        System.out.printf("isRunning: %b%n",component.isRunning());
        component.stop();
    }
}

/* output 
[starting] org.eclipse.jetty.util.preventers.LoginConfigurationLeakPreventer@69c78571
[started] org.eclipse.jetty.util.preventers.LoginConfigurationLeakPreventer@69c78571
isRunning: true
[stopping] org.eclipse.jetty.util.preventers.LoginConfigurationLeakPreventer@69c78571
[stopped] org.eclipse.jetty.util.preventers.LoginConfigurationLeakPreventer@69c78571
*/

That would be a better choice than using the logging event messages.
This way could also distinguish between different instances of the same object type as well.


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


On Mon, Nov 25, 2013 at 9:24 AM, Lothar Kimmeringer <job@xxxxxxxxxxxxxx> wrote:
Am 25.11.2013 16:50, schrieb Joakim Erdfelt:

> Create a src/test/resources/jetty-logging.properties
> Specify your own Logger implementation there.

in my testcases I use an Inner class deriving from StdErrLog,
so this way doesn't work.

> Static loggers are there to limit GC churn for something that
> is not instance dependant,

Given all the instance-members that single static member shouldn't
change anything at all in terms of GC-runtimes. E.g. AbstractLifeCycle
creates an ArrayList with every instantiation and non-static final
members being used as constants, so as long as Log.getLogger
isn't a bottleneck in terms of performance, the impact on memory
overhead should be minimal.

> and is an extremely common logger pattern.

A pattern that - in my eyes - is not a very good one because it
prevents you from a couple of things like changing the logger
during runtime and creates effects like the ones I described.

> You can also use Log.setLog(Logger) to specify your own Logger impl.

That's exactly what I already do and "now" doesn't work (as already
mentioned here in the list, I'm doing a migration from 7.0 to 9.x).
Here is what I do:

public class __Test_AuthServiceJettyLoginService extends TestCase {

    static LinkedList<String> messages = new LinkedList<String>();

    static{
        Log.setLog(new StdErrLog(){
            @Override
            public void debug(String msg, Object... objects){
                super.debug(msg, objects);
                messages.add("D: " + msg);
            }
            @Override
            public void info(String msg, Object... objects){
                super.info(msg, objects);
                messages.add("I: " + msg);
            }
            @Override
            public void warn(String msg, Object... objects){
                super.warn(msg, objects);
                messages.add("E: " + msg);
            }
            @Override
            public void warn(String msg, Throwable t){
                super.warn(msg, t);
                if (t != null){
                    msg += "\r\n  " + t.getClass().getName() + ": " + t.getMessage();
                }
                messages.add("E: " + msg);
            }
        });
        Log.getLog().setDebugEnabled(true);
    }

    public void testStartStop() throws Exception {
        // reduced to the relevant part, there is more happening IRL of course
        AuthServiceJettyLoginService service = new AuthServiceJettyLoginService();

        service.start();
        assertEquals("check number of messages", 3, messages.size());
        assertEquals("check message", "D: Starting {}", messages.removeFirst());
        assertEquals("check message", "I: Starting", messages.removeFirst());
        assertEquals("check message", "D: STARTED {}", messages.removeFirst());
        assertEquals("check service is running", true, service.isRunning());
    }
}

STDERR contains the following messages:

2013-11-25 17:15:57.743:DBUG:oejuc.AbstractLifeCycle:main: starting AuthServiceJettyLoginService[DEFAULT]
2013-11-25 17:15:57.743:INFO::main: Starting
2013-11-25 17:15:57.743:DBUG:oejuc.AbstractLifeCycle:main: STARTED AuthServiceJettyLoginService[DEFAULT]

The LinkedList doesn't contain any messages of AbstractLifeCycle
at the end (only the main-message coming from my own class). Reason
is that the ClassLoader already loaded AbstractLifeCycle which invoked
the static constructor. Reason can be a class in the import-list that
derives from AbstractLifeCycle or has members of Jetty-classes that
derives from it. You can throw away all imports which makes your
source-code a mess or you use wildcards with your imports and hope that
nobody (e.g. Eclipse) is changing that back to specific imports (e.g.
because the FindBugs-module suggests doing exactly that).

As I said, I solved that problem in my application by setting the
Logger in a class that is called before other classes using Jetty
are even loaded. But my testcases are doomed to fail at the moment.
The property-file isn't a real option here, either, so I'm screwed
in a way, technically speaking. Am I correct?


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


Back to the top