Thursday, April 18, 2013

Logback Appender for RESTFull


Logback (http://logback.qos.ch/) is the big brother of popular log4j which is getting more support from the development community. 
By default Logback does not support RESTFull access
What needs to be done
  • Implementation of custom log appender to send data to remote server 
public class RestFullLogbackAppender extends AppenderBase<ILoggingEvent> {
    String url;
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    @Override
    protected void append(ILoggingEvent event) {
        sendToTrackingServer(event.getlogMessage());
    }
    private boolean sendToTrackingServer(String logMessage) {
        DefaultHttpClient httpclient = new DefaultHttpClient();
        if (logMessage != null || logMessage.length() > 1) {
            HttpPost request = new HttpPost(url);
            StringEntity params;
            try {
                params = new StringEntity(logMessage);
                request.addHeader("content-type", "application/json");
                request.setEntity(params);
                httpclient.execute(request);
            } catch (UnsupportedEncodingException e) {
            } catch (ClientProtocolException e) {
            } catch (IOException e) {
            }
        }
        return true;
    }
}
  • Implementation of custom log maker 
public class CustomLogMaker extends AbstractMatcherFilter<ILoggingEvent> {
    Marker markerToMatch;   
    public void start() {
        if (this.markerToMatch != null) {
            super.start();
        } else {
            addError(String.format("The marker property must be set for [%s]", getName()));
        }
    }
    public void setMarker(String markerStr) {
        if (markerStr != null) {
            markerToMatch = MarkerFactory.getMarker(markerStr);
        }
    }
    @Override
    public FilterReply decide(ILoggingEvent event) {
        Marker marker = event.getMarker();
        if (!isStarted()) {
            return FilterReply.NEUTRAL;
        }
        if (marker == null) {
            return onMismatch;
        }
        if (markerToMatch.contains(marker)) {
            return onMatch;
        }
        return onMismatch;
    }
}
  • Add following appender to  logback.xml 
<appender name="REMOTE"  class="com.boundry.logback.RestFullLogbackAppender">   
    <filter class="com.boundry.logback.CustomLogMaker">
        <marker>REST_LOGGER</marker>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
    <url>http://localhost:8080/boundry/logging</url>
</appender>
  • Add log maker 
public class RestFullLogMarkers {
   public static final Marker SEND_TO_LOG_SERVER =             MarkerFactory.getMarker("REST_LOGGER");
}
  • Create a Rest with SpringMVC
@RequestMapping(method = RequestMethod.POST, value = { "/logging" })
public @ResponseBody String postLogger(@RequestBody String log,HttpServletRequest request) throws IOException {
String logMessage = log;
//TODO: Write to the server
return "Log Message received at " + new Date();
}
  • How to use the new REST Logger
private static final Logger logger = LoggerFactory.getLogger(MyBoundry.class);

...

log.info(LogMarkers.SEND_TO_LOG_SERVER ,"Hello World");