package org.lumberjack.plugin; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricSet; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; import org.graylog2.plugin.ServerStatus; import org.graylog2.plugin.configuration.Configuration; import org.graylog2.plugin.configuration.ConfigurationRequest; import org.graylog2.plugin.configuration.fields.ConfigurationField; import org.graylog2.plugin.configuration.fields.NumberField; import org.graylog2.plugin.configuration.fields.TextField; import org.graylog2.plugin.inputs.MessageInput; import org.graylog2.plugin.inputs.MisfireException; import org.graylog2.plugin.inputs.annotations.ConfigClass; import org.graylog2.plugin.inputs.annotations.FactoryClass; import org.graylog2.plugin.inputs.codecs.CodecAggregator; import org.graylog2.plugin.inputs.transports.Transport; import org.graylog2.plugin.journal.RawMessage; import org.lumberjack.server.LogEvent; import org.lumberjack.server.LogEventListener; import org.lumberjack.server.LumberjackServer; import org.lumberjack.server.ServerConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.ByteArrayOutputStream; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created on 9/4/15. */ public class LumberjackTransport implements Transport { private static final Logger LOGGER = LoggerFactory.getLogger(LumberjackTransport.class.getName()); private final Configuration configuration; private final MetricRegistry metricRegistry; private ServerStatus serverStatus; private LumberjackServer lumberjackServer; private static final String CK_KEYSTORE_PATH = "keystorePath"; private static final String CK_KEYSTORE_PASSWORD = "keystorePassword"; private static final String CK_KEY_PASSWORD = "keyPassword"; private static final String CK_BIND_IP = "bindIP"; private static final String CK_BIND_PORT = "bindPort"; @AssistedInject public LumberjackTransport(@Assisted Configuration configuration, MetricRegistry metricRegistry, ServerStatus serverStatus) { this.configuration = configuration; this.metricRegistry = metricRegistry; this.serverStatus = serverStatus; } @Override public void setMessageAggregator(CodecAggregator codecAggregator) { } @Override public void launch(final MessageInput messageInput) throws MisfireException { LogEventListener listener = new LogEventListener() { @Override public void onEvents(List<LogEvent> list) { ObjectMapper mapper = new ObjectMapper(); try { for (LogEvent event : list) { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); mapper.writeValue(byteStream,convertToGELF(event)); messageInput.processRawMessage(new RawMessage(byteStream.toByteArray())); byteStream.close(); } } catch (Exception e) { LOGGER.warn("Exception while processing event ",e); } } }; ServerConfiguration serverConfiguration = new ServerConfiguration(); serverConfiguration.setIpAddress(configuration.getString(CK_BIND_IP)); serverConfiguration.setPort(configuration.getInt(CK_BIND_PORT)); serverConfiguration.setKeyStorePath(configuration.getString(CK_KEYSTORE_PATH)); serverConfiguration.setKeyStorePass(configuration.getString(CK_KEYSTORE_PASSWORD)); serverConfiguration.setKeyPass(configuration.getString(CK_KEY_PASSWORD)); LOGGER.info("Starting LumberjackTransport with config :" + configuration); lumberjackServer = new LumberjackServer(serverConfiguration, listener); lumberjackServer.start(); LOGGER.info("Lumberjack transport started"); } private Map<String,String> convertToGELF(LogEvent lumberjackEvent) { Map<String,String> eventData = new HashMap<>(lumberjackEvent.getEventData().size() + 1); eventData.put("version", "1.1"); eventData.put("host",lumberjackEvent.getEventData().remove("host")); eventData.put("file",lumberjackEvent.getEventData().remove("file")); eventData.put("short_message", lumberjackEvent.getEventData().remove("line")); for(Map.Entry<String,String> entry : lumberjackEvent.getEventData().entrySet()) { eventData.put("_" + entry.getKey(),entry.getValue()); } return eventData; } @Override public void stop() { lumberjackServer.stop(); } @Override public MetricSet getMetricSet() { return null; } @FactoryClass public interface Factory extends Transport.Factory<LumberjackTransport> { @Override LumberjackTransport create(Configuration configuration); @Override Config getConfig(); } @ConfigClass public static class Config implements Transport.Config { @Override public ConfigurationRequest getRequestedConfiguration() { final ConfigurationRequest cr = new ConfigurationRequest(); cr.addField(new TextField(CK_KEYSTORE_PATH, "Keystore Path", "", "Absolute path of JKS keystore")); cr.addField(new TextField(CK_KEYSTORE_PASSWORD, "Keystore Password", "", "-deststorepass argument in keytool", ConfigurationField.Optional.NOT_OPTIONAL, TextField.Attribute.IS_PASSWORD)); cr.addField(new TextField(CK_KEY_PASSWORD, "Key Password", "", "-destkeypass argument in keytool", ConfigurationField.Optional.NOT_OPTIONAL, TextField.Attribute.IS_PASSWORD)); cr.addField(new TextField(CK_BIND_IP, "Bind IP Address", "0.0.0.0", "Local IP Address to bind", ConfigurationField.Optional.NOT_OPTIONAL)); cr.addField(new NumberField(CK_BIND_PORT, "Port", 5043, "Local port to listen for events", ConfigurationField.Optional.NOT_OPTIONAL, NumberField.Attribute.IS_PORT_NUMBER)); return cr; } } }