Skip to content

Commit

Permalink
initial version of plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
brettlangdon committed Apr 11, 2016
1 parent 6b2cc64 commit 5d338e8
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 82 deletions.
53 changes: 0 additions & 53 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -149,57 +149,4 @@
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>web-interface-build</id>
<activation>
<property>
<name>!skip.web.build</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>0.0.28</version>

<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v4.3.1</nodeVersion>
<npmVersion>3.7.3</npmVersion>
</configuration>
</execution>

<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<!-- Optional configuration which provides for running any npm command -->
<configuration>
<arguments>install</arguments>
</configuration>
</execution>

<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
213 changes: 208 additions & 5 deletions src/main/java/io/underdog/GraylogPluginDatadog.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,211 @@
package io.underdog;

/**
* This is the plugin. Your class should implement one of the existing plugin
* interfaces. (i.e. AlarmCallback, MessageInput, MessageOutput)
*/
public class GraylogPluginDatadog {
import com.floreysoft.jmte.Engine;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.apache.commons.lang3.StringUtils;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.graylog2.plugin.Message;
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.TextField;
import org.graylog2.plugin.outputs.MessageOutput;
import org.graylog2.plugin.outputs.MessageOutputConfigurationException;
import org.graylog2.plugin.streams.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

public class GraylogPluginDatadog implements MessageOutput {
private static final Logger LOG = LoggerFactory.getLogger(GraylogPluginDatadog.class);

private Configuration configuration;
private final AtomicBoolean isRunning = new AtomicBoolean(false);
private WebTarget eventTarget;
private String[] tags;
private String priority;
private String alertType;
private String aggregationKey;
private URI eventUrl;

private static final String CK_DATADOG_API_KEY = "datadog_api_key";
private static final String CK_DATADOG_APP_KEY = "datadog_app_key";
private static final String CK_DATADOG_TAGS = "datadog_tags";
private static final String CK_DATADOG_PRIORITY = "datadog_priority";
private static final String CK_DATADOG_ALERT_TYPE = "datadog_alert_type";
private static final String CK_DATADOG_AGGREGATION_KEY = "datadog_aggregation_KEY";
private static final String DATADOG_API_URL = "https://app.datadoghq.com/api/v1/events";

@Inject
public GraylogPluginDatadog(@Assisted Stream stream, @Assisted Configuration configuration) throws MessageOutputConfigurationException {
this.configuration = configuration;

tags = configuration.getString(CK_DATADOG_TAGS, "").split(",");
priority = configuration.getString(CK_DATADOG_PRIORITY, "normal");
alertType = configuration.getString(CK_DATADOG_ALERT_TYPE, "info");
aggregationKey = configuration.getString(CK_DATADOG_AGGREGATION_KEY, "info");

try {
eventUrl = new URI(String.format("%s?api_key=%s&app_key=%s",
DATADOG_API_URL,
configuration.getString(CK_DATADOG_API_KEY),
configuration.getString(CK_DATADOG_APP_KEY)));
} catch (URISyntaxException e){
throw new MessageOutputConfigurationException("Syntax error in datadog event URL");
}

Client client = ClientBuilder.newClient();
eventTarget = client.target(eventUrl);
isRunning.set(true);
}

@Override
public boolean isRunning() {
return isRunning.get();
}

public String getMessageText(Message message) {
final StringBuilder sb = new StringBuilder();
sb.append("%%% \n");

final Map<String, Object> filteredFields = Maps.newHashMap(message.getFields());
for (Map.Entry<String, Object> entry : filteredFields.entrySet()) {
sb.append("**").append(entry.getKey()).append("**: ").append(entry.getValue().toString()).append("\n\n");
}

sb.append("\n %%%");
return sb.toString();
}

public String getMessageTitle(Message message) {
final StringBuilder sb = new StringBuilder();
sb.append("graylog: ");
if (message.getField("facility") != null) {
sb.append(message.getField("facility")).append(" ");
}
sb.append("[").append(message.getSource()).append("] ");
sb.append(message.getMessage());
return sb.toString();
}

@Override
public void write(Message message) throws Exception {
HashMap<String, Object> payload = new HashMap<>();
payload.put("title", getMessageTitle(message));
payload.put("text", getMessageText(message));
payload.put("tags", tags);
payload.put("source_type_name", "graylog");
payload.put("priority", priority);
payload.put("alert_type", alertType);

if (aggregationKey != "") {
payload.put("aggregation_key", aggregationKey);
} else {
payload.put("aggregation_key", message.getSource());
}

Response response = eventTarget
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(payload, MediaType.APPLICATION_JSON), Response.class);

String result = String.format(
"POST [%s] to [%s], status code [%d], headers: %s, returned data: %s",
payload, eventUrl, response.getStatus(),
response.getHeaders(), response);
if (response.getStatus() >= 400) {
LOG.info(result);
} else {
LOG.debug(result);
}
}

@Override
public void write(List<Message> messages) throws Exception {
for (Message message : messages) {
write(message);
}
}

@Override
public void stop() {
LOG.info("Stopping Datadog output");
isRunning.set(false);
}

public interface Factory extends MessageOutput.Factory<GraylogPluginDatadog> {
@Override
GraylogPluginDatadog create(Stream stream, Configuration configuration);

@Override
Config getConfig();

@Override
Descriptor getDescriptor();
}

public static class Config extends MessageOutput.Config {
@Override
public ConfigurationRequest getRequestedConfiguration() {
final ConfigurationRequest configurationRequest = new ConfigurationRequest();

configurationRequest.addField(new TextField(
CK_DATADOG_API_KEY, "Datadog API key", "",
"API key for Datadog",
ConfigurationField.Optional.NOT_OPTIONAL)
);

configurationRequest.addField(new TextField(
CK_DATADOG_APP_KEY, "Datadog APP key", "",
"APP key for Datadog",
ConfigurationField.Optional.NOT_OPTIONAL)
);

configurationRequest.addField(new TextField(
CK_DATADOG_TAGS, "Datadog event tags", "",
"Comma separated list of tags to add to the event, e.g. 'tag:value,name,another:tag'",
ConfigurationField.Optional.OPTIONAL)
);

configurationRequest.addField(new TextField(
CK_DATADOG_PRIORITY, "Datadog event priority", "",
"Datadog event priority, one of ('normal', or 'low') [default: 'normal']",
ConfigurationField.Optional.OPTIONAL)
);

configurationRequest.addField(new TextField(
CK_DATADOG_ALERT_TYPE, "Datadog event alert type", "",
"Datadog event alert type, one of ('error', 'warning', 'success', or 'info') [default: 'info']",
ConfigurationField.Optional.OPTIONAL)
);

configurationRequest.addField(new TextField(
CK_DATADOG_AGGREGATION_KEY, "Datadog event aggregation key", "",
"Datadog event custom aggregation key [default: message source]",
ConfigurationField.Optional.OPTIONAL)
);

return configurationRequest;
}
}

public static class Descriptor extends MessageOutput.Descriptor {
public Descriptor() {
super("Datadog output", false, "", "An output plugin that adds log data as events to Datadog");
}
}
}
9 changes: 3 additions & 6 deletions src/main/java/io/underdog/GraylogPluginDatadogMetaData.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,12 @@ public String getName() {

@Override
public String getAuthor() {
// TODO Insert author name
return "GraylogPluginDatadog author";
return "Brett Langdon";
}

@Override
public URI getURL() {
// TODO Insert correct plugin website
return URI.create("https://www.graylog.org/");
return URI.create("https://github.com/underdogio/graylog-plugin-datadog");
}

@Override
Expand All @@ -41,8 +39,7 @@ public Version getVersion() {

@Override
public String getDescription() {
// TODO Insert correct plugin description
return "Description of GraylogPluginDatadog plugin";
return "Graylog plugin to forward messages to Datadog as events";
}

@Override
Expand Down
19 changes: 1 addition & 18 deletions src/main/java/io/underdog/GraylogPluginDatadogModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,6 @@ public Set<? extends PluginConfigBean> getConfigBeans() {

@Override
protected void configure() {
/*
* Register your plugin types here.
*
* Examples:
*
* addMessageInput(Class<? extends MessageInput>);
* addMessageFilter(Class<? extends MessageFilter>);
* addMessageOutput(Class<? extends MessageOutput>);
* addPeriodical(Class<? extends Periodical>);
* addAlarmCallback(Class<? extends AlarmCallback>);
* addInitializer(Class<? extends Service>);
* addRestResource(Class<? extends PluginRestResource>);
*
*
* Add all configuration beans returned by getConfigBeans():
*
* addConfigBeans();
*/
addMessageOutput(GraylogPluginDatadog.class, GraylogPluginDatadog.Factory.class);
}
}

0 comments on commit 5d338e8

Please sign in to comment.