Network Logging

Problem

Your class is running inside a server container, and its debugging output is hard to obtain.

Solution

Use a network-based logger like the one shown here.

Discussion

Getting the debug output from a desktop client is fairly easy on most operating systems. But if the program you want to debug is running in a “container” like a servlet engine or EJB server, it can be difficult to obtain debugging output, particularly if the container is running on a remote computer. It would be convenient if you could have your program send messages back to a program on your desktop machine for immediate display. Needless to say, it’s not that hard to do this with Java’s socket mechanism. I have written a small, simple API to handle this type of logging function. The program being debugged is the “client” from a socket point of view -- even though it may be running in a server-side container such as a web server or application server -- since the “network client” is the program that initiates the connection. The program that runs on your desktop machine is the “server” program for sockets, since it waits for a connection to come along.

Example 16-8 is a simple client program called NetLogSimple.

Example 16-8. NetLogSimple.java

/* A simple example of using the NetLog program.
 * Unrealistic in that it's standalone; this API is
 * intended for use inside another program, possibly
 * a servlet or EJB.
 */
public class NetLogSimple {

    public static void main(String[] args) throws java.io.IOException {

        System.out.println("NetLogSimple: Starting...");

        // Get the connection to the NetLog
        NetLog nl = new NetLog(  );

        // Show sending a String
        nl.log("Hello Java");

        // Show sending Objects
        nl.log(new java.util.Date(  ));
        nl.log(nl);

        // Show sending null and "" (normally an accident...)
        nl.log(null);
        nl.log("");

        // All done, close the log
        nl.close(  );

        System.out.println("NetLogSimple: Done...");
    }
}

In Figure 16-1, I show both the server and client running side by side.

NetLog server and client

Figure 16-1. NetLog server and client

The client-side API and the server code are both online. Example 16-9 shows the code for the key parts of the server.

Example 16-9. NetLogServer.java

public class NetLogServer {

    public static final int PORT = 65432;

    public static final int NUM_THREADS = 8;

    JFrame theFrame;
    JTextArea theTextArea;

    /** Main method, to start the servers. */
    public static void main(String[] av)
    {
        new NetLogServer(PORT, NUM_THREADS);
    }

    /** Constructor */
    public NetLogServer(int port, int numThreads)
    {
        ServerSocket servSock;
        Socket clientSocket;

        try {
            servSock = new ServerSocket(PORT);

        } catch(IOException e) {
            /* Crash the server if IO fails. Something bad has happened */
            System.err.println("Could not create ServerSocket " + e);
            System.exit(1);
            return;  /*NOTREACHED*/
        }

        // Build the GUI - must be before Handler constructors!
        theFrame  = new JFrame("NetLog Server");
        theTextArea = new JTextArea(24, 80);
        theFrame.getContentPane(  ).add(new JScrollPane(theTextArea));

        // Now start the Threads
        for (int i=0; i<numThreads; i++) {
            new Thread(new Handler(servSock, i)).start(  );
        }

        theFrame.pack(  );
        theFrame.setVisible(true);
        theFrame.addWindowListener(new WindowAdapter(  ) {
            public void windowClosing(WindowEvent we) {
                System.exit(0);
            }
        });

    }

    public synchronized void log(int tid, String s) {
        StringBuffer sb = new StringBuffer(  );
        sb.append(tid);
        sb.append(": ");

        if (s == null) {
            sb.append("(null)");
        }
        else if (s.length(  ) == 0) {
            sb.append("(null string)");
        }
        else
            sb.append(s);

        sb.append('
'),
        theTextArea.append(sb.toString(  ));
        theTextArea.setCaretPosition(theTextArea.getText().length(  ));
        theFrame.toFront(  );
    }

    /** A Thread subclass to handle one client conversation. */
    class Handler extends Thread {
        ServerSocket servSock;
        int tid;

        /** Construct a Handler. */
        Handler(ServerSocket s, int i) {
            super(  );
            servSock = s;
            tid = i;
            setName("Thread " + tid);
        }

        public void run(  )
        {
            /* Wait for a connection */
            while (true){
                try {
                    // log(tid, getName(  ) + " waiting");
                    Socket clientSocket = servSock.accept(  );
                    log(tid,getName(  ) + " START, IP=" +
                        clientSocket.getInetAddress(  ));
                    BufferedReader is = new BufferedReader(
                        new InputStreamReader(clientSocket.getInputStream(  )));
                    String line;
                    while ((line = is.readLine(  )) != null) {
                        // System.out.println(">> " + line);
                        log(tid,line);
                    }
                    log(tid,getName(  ) + " ENDED ");
                    clientSocket.close(  );
                } catch (IOException ex) {
                    log(tid, getName(  ) + ": IO Error on socket " + ex);
                    return;
                }
            }
        }
    }
}

See Also

If you want to run this on a network, you need to be very aware of security issues. One very common form of attack is a simple denial-of-service, during which the attacker makes a lot of connections to your server in order to slow it down. If you had extended this program by writing the log to disk, the attacker could fill up your disk by sending lots of garbage. However, because this example displays the log on the screen, you would see this happening. Don’t leave the server running while you’re not around to watch it!

The Apache Foundation Jakarta Project (http://jakarta.apache.org) offers log4j, which provides a similar service but is more fully fleshed out; it can write to a file, an OutputStream or Writer, or a remote log4j, Unix Syslog or NT Event Logger server. Java 2 SDK (JDK 1.4) includes a new Event Logger mechanism.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.148.104.242