[logback-dev] Re: Logback Chainsaw Bridge

Maarten Bosteels maarten at apache.org
Wed Sep 26 11:41:13 CEST 2007


I forgot to mention that the code currently depends on log4j-1.3
(which is an abandoned version) because otherwise chainsaw wouldn't
show the location-info.

Maarten

On 9/26/07, Maarten Bosteels <maarten at apache.org> wrote:
> Hello,
>
> I've written a Logback Chainsaw Bridge: your programs can use logback
> and you can receive the events in Chainsaw using the SImpleReceiver.
>
> The idea is pretty simple:
>
> * You specify a "ch.qos.logback.classic.net.SocketAppender" in logback.xml
> * LogbackChainsawBridge reads incoming logback events from the wire
> * LogbackChainsawBridge converts the events to Log4j events
> * LogbackChainsawBridge sends the events  to chainsaw using a SocketAppender
>
> It's certainly not a perfect solution, I hope there will be a cool
> LogBackViewer someday that can compete with chainsaw. (maybe when I
> have lots of time...)
> Or does it exist already ?
>
> In the meantime, some of you might find it interesting.
> The following attributes are sent to chainsaw:
> * ThreadName
> * Logger
> * Timestamp
> * Message
> * Level
> * MDC
> * CallerData (LocationInfo)
> * Throwable
>
> Feedback welcome.
>
> Maarten
>
>
> package ch.org.logback;
>
> import java.net.ServerSocket;
> import java.net.Socket;
> import java.io.ObjectInputStream;
> import java.io.BufferedInputStream;
> import java.io.IOException;
> import java.io.EOFException;
> import java.util.Map;
> import java.util.Hashtable;
>
> /**
>  * This program will listen on the specified port for Logback logging events
>  * and forward them as Log4j events to another port (to be received by Chainsaw)
>  */
> public class LogbackChainsawBridge {
>
>   static int port;
>
>   static boolean includeCallerData = false;
>
>   public static void main(String argv[]) throws Exception {
>     if (argv.length == 0) {
>       init("5555", "false");
>     }
>     if (argv.length == 1) {
>       init(argv[0], "false");
>     }
>     if (argv.length == 2) {
>       init(argv[0], argv[1]);
>     }
>
>     if (argv.length > 2) {
>       usage("too many arguments");
>     }
>     runServer();
>   }
>
>   static void runServer() {
>     org.apache.log4j.net.SocketAppender socketAppender
>         = new org.apache.log4j.net.SocketAppender("localhost", 4445);
>     try {
>       info("Listening on port " + port);
>       ServerSocket serverSocket = new ServerSocket(port);
>       //noinspection InfiniteLoopStatement
>       while (true) {
>         info("Waiting to accept a new client.");
>         Socket socket = serverSocket.accept();
>         info("Connected to client at " + socket.getInetAddress());
>         info("Starting new socket node.");
>         new Thread(new SocketHandler(socket, socketAppender)).start();
>       }
>     } catch (Exception e) {
>       e.printStackTrace();
>     }
>   }
>
>   static void usage(String msg) {
>     System.err.println(msg);
>     System.err.println("Usage: java " +
> MySimpleSocketServer.class.getName() + "[port] [includeCallerData]");
>     System.err.println("  port : on which port the logback events are
> coming on");
>     System.err.println("  includeCallerData : true when you want to
> include caller data");
>     System.exit(1);
>   }
>
>   private static void info(String message) {
>     System.out.println(message);
>   }
>
>   static void init(String portStr, String includeCallerDataStr) {
>     try {
>       port = Integer.parseInt(portStr);
>     } catch (NumberFormatException e) {
>       e.printStackTrace();
>       usage("Could not interpret port number [" + portStr + "].");
>     }
>     includeCallerData = Boolean.parseBoolean(includeCallerDataStr);
>   }
>
>   private static org.apache.log4j.spi.ThrowableInformation
> convertToLog4jhTrowableInformation (
>       ch.qos.logback.classic.spi.ThrowableInformation throwableInformation) {
>
>     if (throwableInformation == null ||
>         throwableInformation.getThrowableStrRep() == null ||
>         throwableInformation.getThrowableStrRep().length == 0) {
>       return null;
>     }
>     return new org.apache.log4j.spi.ThrowableInformation(throwableInformation.getThrowableStrRep());
>   }
>
>   private static org.apache.log4j.spi.LocationInfo convertToLog4jLocationInfo (
>       ch.qos.logback.classic.spi.CallerData[] callerData) {
>     if (!includeCallerData || callerData == null || callerData.length == 0) {
>       return org.apache.log4j.spi.LocationInfo.NA_LOCATION_INFO;
>     }
>     ch.qos.logback.classic.spi.CallerData data = callerData[0];
>     return new org.apache.log4j.spi.LocationInfo(
>         data.getFileName(),
>         data.getClassName(),
>         data.getMethodName(),
>         String.valueOf(data.getLineNumber()));
>   }
>
>   private static org.apache.log4j.spi.LoggingEvent convertToLog4jEvent (
>       ch.qos.logback.classic.spi.LoggingEvent event) {
>     String fqnOfCategoryClass = "todo: fqn";
>     long timestamp = event.getTimeStamp();
>     org.apache.log4j.Level level = org.apache.log4j.Level.toLevel(
> event.getLevel().toInt() );
>     String message = event.getFormattedMessage();
>     String threadName = event.getThreadName();
>     String loggerName = event.getLoggerRemoteView().getName();
>     org.apache.log4j.spi.ThrowableInformation throwableInformation
>         = convertToLog4jhTrowableInformation(event.getThrowableInformation());
>     String ndc = null; // not supported by SLF4J and LogBack ?
>
>
>     org.apache.log4j.spi.LocationInfo locationInfo =
> convertToLog4jLocationInfo(event.getCallerData());
>
>
>     Map<String,String> mdc = event.getMDCPropertyMap();
>
>     org.apache.log4j.spi.LoggingEvent log4jEvent = new
> org.apache.log4j.spi.LoggingEvent();
>
>     log4jEvent.setFQNOfLoggerClass(fqnOfCategoryClass);
>     log4jEvent.setLoggerName(loggerName);
>     log4jEvent.setTimeStamp(timestamp);
>     log4jEvent.setLevel(level);
>     log4jEvent.setMessage(message);
>     log4jEvent.setThreadName(threadName);
>     log4jEvent.setThrowableInformation(throwableInformation);
>     if (mdc != null) {
>       //noinspection unchecked
>       log4jEvent.setProperties(new Hashtable(mdc));
>     }
>     log4jEvent.setLocationInformation(locationInfo);
>     log4jEvent.setNDC(ndc);
>     //log4jEvent.setSequenceNumber(4);
>     log4jEvent.setRenderedMessage(message);
>     return log4jEvent;
>   }
>
>
>   private static class SocketHandler implements Runnable {
>
>     Socket socket;
>     ObjectInputStream ois;
>     org.apache.log4j.net.SocketAppender log4jAppender;
>
>     public SocketHandler(Socket socket,
> org.apache.log4j.net.SocketAppender log4jAppender) {
>       this.socket = socket;
>       this.log4jAppender = log4jAppender;
>       try {
>         ois = new ObjectInputStream(new BufferedInputStream(socket
>             .getInputStream()));
>       } catch (Exception e) {
>         System.err.println("Could not open ObjectInputStream to " + socket);
>         e.printStackTrace();
>       }
>     }
>
>
>     public void run() {
>       ch.qos.logback.classic.spi.LoggingEvent event;
>       try {
>         while (true) {
>           // read an event from the wire
>           try {
>             event = (ch.qos.logback.classic.spi.LoggingEvent) ois.readObject();
>           } catch (EOFException e) {
>             info("client disconnected");
>             break;
>           } catch (IOException e) {
>             e.printStackTrace();
>             break;
>           } catch (ClassNotFoundException e) {
>             e.printStackTrace();
>             break;
>           }
>
>           if (event == null) {
>             continue;
>           }
>           org.apache.log4j.spi.LoggingEvent log4jEvent =
> convertToLog4jEvent(event);
>
>           log4jAppender.append(log4jEvent);
>
>         }
>       } catch (Exception e) {
>         System.err.println("Unexpected exception. Closing connection.");
>         e.printStackTrace();
>       }
>
>       try {
>         ois.close();
>       } catch (Exception e) {
>         System.err.println("Could not close connection.");
>         e.printStackTrace();
>       }
>     }
>   }
>
> }
>



More information about the logback-dev mailing list