/* * Copyright 2013 Future Systems * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.logdb.log4j; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.concurrent.ArrayBlockingQueue; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.spi.LocationInfo; import org.apache.log4j.spi.LoggingEvent; import org.json.JSONException; import org.json.JSONWriter; public class HttpAppender extends AppenderSkeleton { private volatile boolean doStop; private Thread t; private ArrayBlockingQueue<String> logs; private String url; public HttpAppender() { logs = new ArrayBlockingQueue<String>(10000); t = new Thread(new HttpSender(), "Kraken LogDB Logger"); t.start(); } public void setURL(String url) { this.url = url; } @Override protected void append(LoggingEvent event) { try { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ"); StringWriter sw = new StringWriter(); JSONWriter w = new JSONWriter(sw).object(); LocationInfo l = event.getLocationInformation(); w.key("_time").value(dateFormat.format(event.timeStamp)); w.key("level").value(s(event.getLevel())); w.key("msg").value(s(event.getMessage())); w.key("ndc").value(event.getNDC()); w.key("thread").value(event.getThreadName()); w.key("class").value(l.getClassName()); w.key("file").value(l.getFileName()); w.key("line").value(l.getLineNumber()); w.key("method").value(l.getMethodName()); w.key("stacktrace").value(printStackTrace(event)); w.endObject(); logs.put(sw.toString()); } catch (JSONException e) { } catch (InterruptedException e) { } } private void sendLogs() { if (url == null) return; if (logs.isEmpty()) return; HttpURLConnection con = null; OutputStream os = null; try { URL u = new URL(url); con = (HttpURLConnection) u.openConnection(); con.setConnectTimeout(5000); con.setReadTimeout(5000); con.setDoOutput(true); con.setRequestProperty("Content-Type", "text/json"); os = con.getOutputStream(); os.write("[".getBytes()); int i = 0; while (true) { String s = logs.poll(); if (s == null) break; if (i++ != 0) os.write(",".getBytes()); os.write(s.getBytes("utf-8")); } os.write("]".getBytes()); con.getResponseCode(); } catch (MalformedURLException e) { } catch (IOException e) { e.printStackTrace(); } finally { if (os != null) { try { os.close(); } catch (IOException e) { } } } } private String s(Object o) { if (o != null) return o.toString(); return null; } @Override public void close() { doStop = true; t.interrupt(); try { t.join(5000); } catch (InterruptedException e) { } } private String printStackTrace(LoggingEvent event) { if (event.getThrowableInformation() == null) return null; Throwable t = event.getThrowableInformation().getThrowable(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw, true); t.printStackTrace(pw); return sw.toString(); } @Override public boolean requiresLayout() { return false; } private class HttpSender implements Runnable { @Override public void run() { while (!doStop) { try { Thread.sleep(1000); sendLogs(); } catch (InterruptedException e) { } catch (Throwable t) { } } } } }