Skip to content

Instantly share code, notes, and snippets.

@elbosso
Created June 23, 2018 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elbosso/c22d77105169a033612407d2f8fe2a6d to your computer and use it in GitHub Desktop.
Save elbosso/c22d77105169a033612407d2f8fe2a6d to your computer and use it in GitHub Desktop.
Appender for Log4j 1 streming logging events right into a time series database (InfluxDB)
package de.elbosso.util;
//This is by no means production-ready code!
/*Copyright (c) 2012-2018.
Juergen Key. Alle Rechte vorbehalten.
Weiterverbreitung und Verwendung in nichtkompilierter oder kompilierter Form,
mit oder ohne Veraenderung, sind unter den folgenden Bedingungen zulaessig:
1. Weiterverbreitete nichtkompilierte Exemplare muessen das obige Copyright,
die Liste der Bedingungen und den folgenden Haftungsausschluss im Quelltext
enthalten.
2. Weiterverbreitete kompilierte Exemplare muessen das obige Copyright,
die Liste der Bedingungen und den folgenden Haftungsausschluss in der
Dokumentation und/oder anderen Materialien, die mit dem Exemplar verbreitet
werden, enthalten.
3. Weder der Name des Autors noch die Namen der Beitragsleistenden
duerfen zum Kennzeichnen oder Bewerben von Produkten, die von dieser Software
abgeleitet wurden, ohne spezielle vorherige schriftliche Genehmigung verwendet
werden.
DIESE SOFTWARE WIRD VOM AUTOR UND DEN BEITRAGSLEISTENDEN OHNE
JEGLICHE SPEZIELLE ODER IMPLIZIERTE GARANTIEN ZUR VERFUEGUNG GESTELLT, DIE
UNTER ANDEREM EINSCHLIESSEN: DIE IMPLIZIERTE GARANTIE DER VERWENDBARKEIT DER
SOFTWARE FUER EINEN BESTIMMTEN ZWECK. AUF KEINEN FALL IST DER AUTOR
ODER DIE BEITRAGSLEISTENDEN FUER IRGENDWELCHE DIREKTEN, INDIREKTEN,
ZUFAELLIGEN, SPEZIELLEN, BEISPIELHAFTEN ODER FOLGENDEN SCHAEDEN (UNTER ANDEREM
VERSCHAFFEN VON ERSATZGUETERN ODER -DIENSTLEISTUNGEN; EINSCHRAENKUNG DER
NUTZUNGSFAEHIGKEIT; VERLUST VON NUTZUNGSFAEHIGKEIT; DATEN; PROFIT ODER
GESCHAEFTSUNTERBRECHUNG), WIE AUCH IMMER VERURSACHT UND UNTER WELCHER
VERPFLICHTUNG AUCH IMMER, OB IN VERTRAG, STRIKTER VERPFLICHTUNG ODER
UNERLAUBTE HANDLUNG (INKLUSIVE FAHRLAESSIGKEIT) VERANTWORTLICH, AUF WELCHEM
WEG SIE AUCH IMMER DURCH DIE BENUTZUNG DIESER SOFTWARE ENTSTANDEN SIND, SOGAR,
WENN SIE AUF DIE MOEGLICHKEIT EINES SOLCHEN SCHADENS HINGEWIESEN WORDEN SIND.
*/
import de.elbosso.util.geo.sbs1.LineProtocolWriter;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
/**
*
* @author elbosso
*/
public class InfluxDBAppender extends AppenderSkeleton
{
private boolean initialized;
private de.netsysit.ui.dialog.LoginDialog.BasicCredentials bc;
public InfluxDBAppender()
{
super();
}
@Override
public void activateOptions()
{
super.activateOptions();
bc=new de.netsysit.ui.dialog.LoginDialog.BasicCredentials(getUserName(),getPassword());
}
@Override
public boolean requiresLayout()
{
return true;
}
@Override
public void close()
{
}
@Override
protected void append(LoggingEvent le)
{
String msg=getLayout().format(le);
String msgString=convertToLineProtocol(le,msg);
java.lang.String url="http://"+getHost()+":"+java.lang.Integer.toString(getPort())+"/write?db="+getDatabaseName();
if(bc!=null)
{
if(((bc.getUserName()!=null)&&(bc.getUserName().trim().length()>0))&&
((bc.getPassword()!=null)&&(bc.getPassword().trim().length()>0)))
{
url += "&u=" + bc.getUserName();
url += "&p=" + bc.getPassword();
}
}
//explicitly mentioning precision is actually not needed because convertToLineProtocol makes sure that
//precision is always nanosecond for java.util.Date timestamps... (But not the resolution - this stays at millis!)
java.net.HttpURLConnection urlConn;
try
{
java.net.URL mUrl = new java.net.URL(url);
urlConn = (java.net.HttpURLConnection) mUrl.openConnection();
urlConn.addRequestProperty("Content-Type", "application/" + "POST");
urlConn.setDoOutput(true);
if (msgString != null)
{
byte[] msgBytes = msgString.getBytes("UTF8");
urlConn.setRequestProperty("Content-Length", Integer.toString(msgBytes.length));
urlConn.getOutputStream().write(msgBytes);
}
int httpErrorCode = urlConn.getResponseCode();
}
catch(java.lang.Throwable t)
{
t.printStackTrace();
}
}
public java.lang.String convertToLineProtocol(LoggingEvent le,java.lang.String msg)
{
java.util.Map<java.lang.String,java.lang.String> tags=new java.util.HashMap();
java.util.Map<java.lang.String,java.lang.Object> fields=new java.util.HashMap();
LineProtocolWriter lineProtocolWriter=new LineProtocolWriter(le.getLoggerName());
tags.put("ThreadName",le.getThreadName());
tags.put("ClassName",le.getLocationInformation().getClassName());
tags.put("FileName",le.getLocationInformation().getFileName());
if(le.getPropertyKeySet()!=null)
{
for(java.lang.Object key:le.getPropertyKeySet())
{
tags.put(key.toString(),le.getProperty(key.toString()));
}
}
fields.put("NDC",le.getNDC());
fields.put("RenderedMessage",msg);//le.getRenderedMessage());
fields.put("LineNumber",le.getLocationInformation().getLineNumber());
fields.put("MethodName",le.getLocationInformation().getMethodName());
return lineProtocolWriter.write(new java.util.Date(le.getTimeStamp()),tags,fields);
}
private java.lang.String databaseName;
public String getDatabaseName()
{
return databaseName;
}
public void setDatabaseName(String databaseName)
{
this.databaseName = databaseName;
}
private String host;
public String getHost()
{
return host;
}
public void setHost(String host)
{
this.host = host;
}
private int port;
public int getPort()
{
return port;
}
public void setPort(int port)
{
this.port = port;
}
private java.lang.String userName;
private java.lang.String password;
public void setUserName(java.lang.String newuserName)
{
userName = newuserName;
}
public void setPassword(java.lang.String newpassword)
{
password = newpassword;
}
public java.lang.String getUserName()
{
return userName;
}
public java.lang.String getPassword()
{
return password;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment