[logback-dev] Logback Chainsaw Bridge
Maarten Bosteels
maarten at apache.org
Wed Sep 26 11:10:32 CEST 2007
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