Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SUGGESTION: a SocketAppender that sends log messages to client #38

Closed
erelsgl opened this issue Jan 6, 2013 · 1 comment
Closed

SUGGESTION: a SocketAppender that sends log messages to client #38

erelsgl opened this issue Jan 6, 2013 · 1 comment

Comments

@erelsgl
Copy link

erelsgl commented Jan 6, 2013

Sometimes it is useful to route log messages, created anywhere on the server during a request, to the relevant client, in order to let the client trace the progress of his request.

I wrote a class that accomplishes this, for log4j. It uses the MDC feature. In order to use it, the server should set the MDC value to the actual client, at the beginning of each request, for example,

server.addEventListener("myevent", Request.class, new DataListener<Request>() {
    @Override public void onData(SocketIOClient client, Request request, AckRequest ackRequest) {
        MDC.put("client", client);
        /* code to handle the request and reply to the client */
    }
});

The appender can be used from the log4j properties file, for example:

log4j.rootLogger=info, socket
log4j.appender.socket = <package-name>.SocketAppender

Here is the appender itself:

package <package-name>;

import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;

import com.corundumstudio.socketio.SocketIOClient;

/**
 * Send log messages to web clients.
 * 
 * @author Erel Segal Halevi
 * @since 2013-01-01
 */
public class SocketAppender extends AppenderSkeleton {

@Override protected void append(LoggingEvent event) {
    SocketIOClient client = (SocketIOClient)event.getMDC("client");
    String eventLevel = event.getLevel().toString().toLowerCase();
    if (client!=null)
        client.sendEvent(eventLevel, event.getLoggerName()+": "+event.getMessage());
}

@Override public boolean requiresLayout() {
    return false;
}

@Override public void close() {
    // nothing to close
}

}

This will create a different event for each log level, for example, for an "info" log level, the client will receive an "info" event, etc. Possible client code for handling these events:

socket.on('trace', function(data) {
    // ignore trace events
});
socket.on('debug', function(data) {
    console.log(data);
});
socket.on('info', function(data) {
    console.info(data);
});
socket.on('warn', function(data) {
    console.warn(data);
});
socket.on('error', function(data) {
    console.error(data); 
});
socket.on('fatal', function(data) {
    alert("A fatal error has occured on the server: "+data);
});
@mrniko
Copy link
Owner

mrniko commented Feb 8, 2013

But my project using slf4j only without any log provider dependency. So, I think it is not necessary to package log4j right in project jar.

@mrniko mrniko closed this as completed Feb 8, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants