package org.graylog2;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.UUID;
public class GelfAMQPSender implements GelfSender {
private volatile boolean shutdown = false;
private final ConnectionFactory factory;
private Connection connection;
private Channel channel;
private final String exchangeName;
private final String routingKey;
private final int maxRetries;
private final String channelMutex = "channelMutex";
public GelfAMQPSender(String host, String exchangeName, String routingKey, int maxRetries) throws IOException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException {
factory = new ConnectionFactory();
factory.setUri(host);
this.exchangeName = exchangeName;
this.routingKey = routingKey;
this.maxRetries = maxRetries;
}
public GelfSenderResult sendMessage(GelfMessage message) {
if (shutdown || !message.isValid()) {
return GelfSenderResult.MESSAGE_NOT_VALID_OR_SHUTTING_DOWN;
}
// set unique id to identify duplicates after connection failure
String uuid = UUID.randomUUID().toString();
String messageid = "gelf" + message.getHost() + message.getFacility() + message.getTimestamp() + uuid;
int tries = 0;
Exception lastException = null;
do {
try {
// establish the connection the first time
if (channel == null) {
synchronized(channelMutex) {
if (channel == null) {
connection = factory.newConnection();
channel = connection.createChannel();
channel.confirmSelect();
}
}
}
BasicProperties.Builder propertiesBuilder = new BasicProperties.Builder();
propertiesBuilder.contentType("application/json; charset=utf-8");
propertiesBuilder.contentEncoding("gzip");
propertiesBuilder.messageId(messageid);
propertiesBuilder.timestamp(new Date(message.getJavaTimestamp()));
BasicProperties properties = propertiesBuilder.build();
channel.basicPublish(exchangeName, routingKey, properties, message.toAMQPBuffer().array());
channel.waitForConfirms();
return GelfSenderResult.OK;
} catch (Exception e) {
channel = null;
tries++;
lastException = e;
}
} while (tries <= maxRetries || maxRetries < 0);
return new GelfSenderResult(GelfSenderResult.ERROR_CODE, lastException);
}
public void close() {
shutdown = true;
try {
channel.close();
} catch (Exception e) {
}
try {
connection.close();
} catch (Exception e) {
}
}
}