package se.pp.gustafson.marten.logback.appender;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.Map;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.net.LoggingEventPreSerializationTransformer;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import ch.qos.logback.core.spi.PreSerializationTransformer;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ConnectionParameters;
import com.rabbitmq.client.AMQP.BasicProperties;
public final class AmqpAppender extends AppenderBase<ILoggingEvent>
{
private static final Map<java.lang.String, java.lang.Object> defaultHeaders = null;
private static final Integer defaultDeliveryMode = new Integer(1);
private static final Integer defaultPriority = new Integer(4);
private static final Date defaultTimestamp = null;
private static final String defaultContentType = "text/plain";
private static final String defaultContentEncoding = "UTF-8";
private static final String defaultCorrelationId = null;
private static final String defaultReplyTo = null;
private static final String defaultExpiration = null;
private static final String defaultMessageId = null;
private static final String defaultType = null;
private static final String defaultUserId = null;
private static final String defaultAppId = null;
private static final String defaultClusterId = null;
private final PreSerializationTransformer<ILoggingEvent> pst = new LoggingEventPreSerializationTransformer();
private Connection conn;
private Channel channel;
private String username;
private String password;
private String virtualHost;
private String host;
private int port;
private String exchange;
private String key;
private boolean useLevelAsKey;
private boolean useLevelAsPriority;
private String contentType;
private String encoding;
private Integer deliveryMode;
@Override
public void start()
{
initalizeProperties();
try
{
final ConnectionParameters params = new ConnectionParameters();
params.setUsername(this.username);
params.setPassword(this.password);
params.setVirtualHost(this.virtualHost);
params.setRequestedHeartbeat(0);
final ConnectionFactory factory = new ConnectionFactory(params);
this.conn = factory.newConnection(this.host, this.port);
this.channel = this.conn.createChannel();
}
catch(final IOException e)
{
e.printStackTrace();
}
super.start();
//System.err.println(getClass().getSimpleName() + " configured: " + toString());
}
private void initalizeProperties()
{
this.contentType = (this.contentType == null || this.contentType.trim().length() == 0) ? defaultContentType : this.contentType;
this.encoding = (this.encoding == null || this.encoding.trim().length() == 0) ? defaultContentEncoding : this.encoding;
this.deliveryMode = (this.deliveryMode == null) ? defaultDeliveryMode : this.deliveryMode;
}
@Override
public void stop()
{
try
{
this.channel.close();
}
catch(final Exception ignored)
{}
try
{
this.conn.close();
}
catch(final Exception ignored)
{}
super.stop();
}
@Override
protected void append(final ILoggingEvent event)
{
try
{
final Level level = event.getLevel();
//final byte[] payload = super.getLayout().doLayout(event).getBytes();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this.pst.transform(event));
oos.close();
final byte[] payload = baos.toByteArray();
baos.close();
final String key = (this.useLevelAsKey) ? level.toString() : this.key;
this.channel.basicPublish(this.exchange, key, createProperties(event, level), payload);
}
catch(final IOException e)
{
e.printStackTrace();
}
}
private BasicProperties createProperties(final ILoggingEvent event, final Level level)
{
int priority;
try
{
priority = (this.useLevelAsPriority) ? LevelWithPriority.valueOf(level.toString()).intValue : defaultPriority;
}
catch(final IllegalArgumentException ignored)
{
priority = defaultPriority;
}
final BasicProperties props = new BasicProperties(this.contentType, this.encoding, defaultHeaders, this.deliveryMode, priority, defaultCorrelationId,
defaultReplyTo, defaultExpiration, defaultMessageId, defaultTimestamp, defaultType, defaultUserId, defaultAppId, defaultClusterId);
return props;
}
public void setUsername(final String username)
{
this.username = username;
}
public void setPassword(final String password)
{
this.password = password;
}
public void setVirtualHost(final String virtualHost)
{
this.virtualHost = virtualHost;
}
public void setHost(final String host)
{
this.host = host;
}
public void setPort(final int port)
{
this.port = port;
}
public void setExchange(final String exchange)
{
this.exchange = exchange;
}
public void setKey(final String key)
{
this.key = key;
}
public void setUseLevelAsKey(final boolean useLevelAsKey)
{
this.useLevelAsKey = useLevelAsKey;
}
public void setUseLevelAsPriority(final boolean useLevelAsPriority)
{
this.useLevelAsPriority = useLevelAsPriority;
}
public void setContentType(final String contentType)
{
this.contentType = contentType;
}
public void setEncoding(final String encoding)
{
this.encoding = encoding;
}
public void setPersistent(boolean persistent)
{
this.deliveryMode = (persistent) ? 2 : 1;
}
@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
sb.append("Exchange [");
sb.append(this.exchange);
sb.append("] at vhost [");
sb.append(this.virtualHost);
sb.append("] using ");
if(this.useLevelAsKey)
{
sb.append("log level as key");
}
else
{
sb.append("key [");
sb.append(this.key);
sb.append("],");
}
sb.append(" username [");
sb.append(this.username);
sb.append("] and connected to [");
sb.append(this.host);
sb.append(':');
sb.append(this.port);
sb.append(']');
return sb.toString();
}
}