package com.log.harvester; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.zip.GZIPOutputStream; import org.apache.log4j.Logger; import org.codehaus.jackson.map.ObjectMapper; public class LogSender extends Thread { private static final Logger LOGGER = Logger.getLogger(LogSender.class); private boolean stop; private int errorNumber = 0; private int retryDelayInMs = 30000; private String applicationId; private String loggingBoxHost; private String loggingBoxPort; private List<Log> writingQueue; private List<Log> readingQueue; private Object writeSyncObject = new Object(); private final ObjectMapper objectMapper = new ObjectMapper(); private String host; public LogSender() { readingQueue = new ArrayList<LogSender.Log>(); writingQueue = new ArrayList<LogSender.Log>(); setPriority(MIN_PRIORITY); try { InetAddress localMachine = InetAddress.getLocalHost(); host = localMachine.getHostName(); } catch (java.net.UnknownHostException uhe) { LOGGER.warn("Could not resolve hostname.", uhe); host = ""; } } public final void sendLog(Date date, String type, String logMessage, String level, String host) { if (stop) { return; } Log log = new Log(); log.date = date; log.level = level; log.data = logMessage; log.type = type; log.applicationId = applicationId; if (host == null) { log.host = this.host; } else { log.host = host; } synchronized (writeSyncObject) { writingQueue.add(log); writeSyncObject.notifyAll(); } } @Override public void run() { while (true) { while (readingQueue.isEmpty()) { synchronized (writeSyncObject) { if (!writingQueue.isEmpty()) { // swap the 2 lists List<Log> temp = readingQueue; readingQueue = writingQueue; writingQueue = temp; } else { try { writeSyncObject.wait(); } catch (InterruptedException e) { LOGGER.error(e); } } } } sendLogs(); if (errorNumber > 2) { // if we have more the 3 errors here, we empty the list : we // don't want out // of memory error because server is not responding. LOGGER.warn("Some logs won't be sent, because server is not responding"); continue; } readingQueue.clear(); } } private void sendLogs() { if (errorNumber > 3) { synchronized (this) { try { this.wait(retryDelayInMs); } catch (InterruptedException e) { LOGGER.error(e); } } } try { String parameters = objectMapper.writeValueAsString(readingQueue); URL url = new URL(String.format( "http://%s:%s/api/log/insert_batch", loggingBoxHost, loggingBoxPort)); HttpURLConnection connection = (HttpURLConnection) url .openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setRequestMethod("POST"); connection.setRequestProperty("charset", "utf-8"); connection.setRequestProperty("Content-Encoding", "gzip"); connection.setUseCaches(false); byte b[] = parameters.getBytes("UTF-8"); GZIPOutputStream gz = new GZIPOutputStream( connection.getOutputStream(), b.length); gz.write(b, 0, b.length); gz.flush(); gz.close(); BufferedReader reader = new BufferedReader(new InputStreamReader( connection.getInputStream())); reader.close(); errorNumber = 0; } catch (MalformedURLException e) { LOGGER.error(e); errorNumber++; } catch (IOException e) { LOGGER.error(e); errorNumber++; } } public static Logger getLogger() { return LOGGER; } public String getApplicationId() { return applicationId; } public String getLoggingBoxHost() { return loggingBoxHost; } public String getLoggingBoxPort() { return loggingBoxPort; } public void setApplicationId(String applicationId) { this.applicationId = applicationId; } public void setLoggingBoxHost(String loggingBoxHost) { this.loggingBoxHost = loggingBoxHost; } public void setLoggingBoxPort(String loggingBoxPort) { this.loggingBoxPort = loggingBoxPort; } public final class Log { private String applicationId; private String level; private Date date; private String host; private String type; private String data; /*********************** ******* GETTERS ******* **********************/ public String getApplicationId() { return applicationId; } public Date getDate() { return date; } public String getType() { return type; } public String getData() { return data; } public String getLevel() { return level; } public String getHost() { return host; } /*********************** ******* SETTERS ******* **********************/ public void setDate(Date date) { this.date = date; } public void setType(String type) { this.type = type; } public void setData(String data) { this.data = data; } public void setLevel(String level) { this.level = level; } public void setHost(String host) { this.host = host; } public void setApplicationId(String applicationId) { this.applicationId = applicationId; } } }