]> jfr.im git - irc/rizon/moo.git/commitdiff
Add grafana webhook listener, closes #38
authorAdam <redacted>
Thu, 22 Dec 2016 23:40:53 +0000 (18:40 -0500)
committerAdam <redacted>
Thu, 22 Dec 2016 23:40:53 +0000 (18:40 -0500)
14 files changed:
grafana/grafana.yml.example [new file with mode: 0644]
grafana/pom.xml [new file with mode: 0644]
grafana/src/main/java/net/rizon/moo/plugin/grafana/Grafana.java [new file with mode: 0644]
grafana/src/main/java/net/rizon/moo/plugin/grafana/HttpServerHandler.java [new file with mode: 0644]
grafana/src/main/java/net/rizon/moo/plugin/grafana/HttpServerInitializer.java [new file with mode: 0644]
grafana/src/main/java/net/rizon/moo/plugin/grafana/JsonDecoder.java [new file with mode: 0644]
grafana/src/main/java/net/rizon/moo/plugin/grafana/beans/GrafanaNotification.java [new file with mode: 0644]
grafana/src/main/java/net/rizon/moo/plugin/grafana/beans/Metric.java [new file with mode: 0644]
grafana/src/main/java/net/rizon/moo/plugin/grafana/conf/GrafanaConfiguration.java [new file with mode: 0644]
grafana/src/test/java/net/rizon/moo/plugin/grafana/JsonDecoderTest.java [new file with mode: 0644]
moo.template.yml
moo/src/main/java/net/rizon/moo/Moo.java
moo/src/main/java/net/rizon/moo/conf/Configuration.java
pom.xml

diff --git a/grafana/grafana.yml.example b/grafana/grafana.yml.example
new file mode 100644 (file)
index 0000000..86b4664
--- /dev/null
@@ -0,0 +1,4 @@
+ip: 0.0.0.0
+port: 8085
+reportChannel: "#a"
+reportStates: [ Alerting ]
diff --git a/grafana/pom.xml b/grafana/pom.xml
new file mode 100644 (file)
index 0000000..2bedefd
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2016, Adam <Adam@rizon.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>net.rizon</groupId>
+               <artifactId>moo</artifactId>
+               <version>3.0</version>
+       </parent>
+
+       <groupId>net.rizon.moo</groupId>
+       <artifactId>grafana</artifactId>
+       <name>Grafana</name>
+
+       <dependencies>
+               <dependency>
+                       <groupId>net.rizon.moo</groupId>
+                       <artifactId>moo</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>com.google.code.gson</groupId>
+                       <artifactId>gson</artifactId>
+               </dependency>
+               
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>net.rizon.moo</groupId>
+                       <artifactId>test-utils</artifactId>
+                       <version>${project.version}</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+       
+       <build>
+               <plugins>
+                       <plugin>
+                               <artifactId>maven-jar-plugin</artifactId>
+                               <configuration>
+                                       <archive>
+                                               <manifest>
+                                                       <mainClass>net.rizon.moo.plugin.grafana.Grafana</mainClass>
+                                               </manifest>
+                                       </archive>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
\ No newline at end of file
diff --git a/grafana/src/main/java/net/rizon/moo/plugin/grafana/Grafana.java b/grafana/src/main/java/net/rizon/moo/plugin/grafana/Grafana.java
new file mode 100644 (file)
index 0000000..74a8383
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2016, Adam <Adam@rizon.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.rizon.moo.plugin.grafana;
+
+import com.google.inject.Inject;
+import com.google.inject.Provides;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import net.rizon.moo.Command;
+import net.rizon.moo.Moo;
+import net.rizon.moo.Plugin;
+import net.rizon.moo.conf.ConfigurationException;
+import net.rizon.moo.plugin.grafana.conf.GrafanaConfiguration;
+
+public class Grafana extends Plugin
+{
+       @Inject
+       private Moo moo;
+
+       @Inject
+       private HttpServerInitializer handler;
+
+       private Channel channel;
+       private GrafanaConfiguration conf;
+
+       public Grafana()
+       {
+               super("Grafana", "Shows Grafana notifications");
+       }
+
+       @Override
+       public void start() throws ConfigurationException, IOException
+       {
+               conf = GrafanaConfiguration.load();
+
+               ServerBootstrap bootstrap = new ServerBootstrap()
+                       .group(moo.getGroup())
+                       .channel(NioServerSocketChannel.class)
+                       .childHandler(handler);
+
+               channel = bootstrap.bind(conf.getIp(), conf.getPort()).channel();
+       }
+
+       @Override
+       public void stop()
+       {
+               channel.close().awaitUninterruptibly();
+       }
+
+       @Override
+       public List<Command> getCommands()
+       {
+               return Collections.EMPTY_LIST;
+       }
+
+       @Override
+       protected void configure()
+       {
+               bind(Grafana.class).toInstance(this);
+
+               bind(HttpServerInitializer.class);
+               bind(HttpServerHandler.class);
+       }
+
+       @Provides
+       public GrafanaConfiguration provideConfig()
+       {
+               return conf;
+       }
+
+}
diff --git a/grafana/src/main/java/net/rizon/moo/plugin/grafana/HttpServerHandler.java b/grafana/src/main/java/net/rizon/moo/plugin/grafana/HttpServerHandler.java
new file mode 100644 (file)
index 0000000..3fea529
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Adam <Adam@rizon.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.rizon.moo.plugin.grafana;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import net.rizon.moo.irc.Protocol;
+import net.rizon.moo.plugin.grafana.beans.GrafanaNotification;
+import net.rizon.moo.plugin.grafana.conf.GrafanaConfiguration;
+
+@Sharable
+public class HttpServerHandler extends SimpleChannelInboundHandler<GrafanaNotification>
+{
+       @Inject
+       private Protocol protocol;
+
+       @Inject
+       private Provider<GrafanaConfiguration> providerConfig;
+
+       @Override
+       protected void channelRead0(ChannelHandlerContext ctx, GrafanaNotification notification) throws Exception
+       {
+               GrafanaConfiguration conf = providerConfig.get();
+
+               if (conf.getReportStates().contains(notification.getState()) == false || notification.getEvalMatches().isEmpty())
+               {
+                       return;
+               }
+
+               protocol.privmsg(conf.getReportChannel(), "Grafana: " + notification.getRuleName() + " is now in state " + notification.getState() + " for metric " + notification.getEvalMatches().get(0).getMetric());
+
+               ctx.close();
+       }
+}
diff --git a/grafana/src/main/java/net/rizon/moo/plugin/grafana/HttpServerInitializer.java b/grafana/src/main/java/net/rizon/moo/plugin/grafana/HttpServerInitializer.java
new file mode 100644 (file)
index 0000000..6cdcd0a
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016, Adam <Adam@rizon.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.rizon.moo.plugin.grafana;
+
+import com.google.inject.Inject;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpServerCodec;
+import net.rizon.moo.plugin.grafana.beans.GrafanaNotification;
+
+public class HttpServerInitializer extends ChannelInitializer<SocketChannel>
+{
+       private static final int SIZE = 65536;
+
+       @Inject
+       private HttpServerHandler handler;
+
+       @Override
+       public void initChannel(SocketChannel ch)
+       {
+               ChannelPipeline pipeline = ch.pipeline();
+               pipeline.addLast("http", new HttpServerCodec());
+               pipeline.addLast("dechunker", new HttpObjectAggregator(SIZE));
+               pipeline.addLast("decoder", new JsonDecoder(GrafanaNotification.class));
+               pipeline.addLast("handler", handler);
+       }
+}
diff --git a/grafana/src/main/java/net/rizon/moo/plugin/grafana/JsonDecoder.java b/grafana/src/main/java/net/rizon/moo/plugin/grafana/JsonDecoder.java
new file mode 100644 (file)
index 0000000..985960e
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Adam <Adam@rizon.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.rizon.moo.plugin.grafana;
+
+import com.google.gson.Gson;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageDecoder;
+import io.netty.handler.codec.http.FullHttpRequest;
+import java.nio.charset.Charset;
+import java.util.List;
+
+public class JsonDecoder extends MessageToMessageDecoder<FullHttpRequest>
+{
+       private final Gson gson = new Gson();
+
+       private final Class<?> clazz;
+
+       public JsonDecoder(Class<?> clazz)
+       {
+               this.clazz = clazz;
+       }
+
+       @Override
+       protected void decode(ChannelHandlerContext ctx, FullHttpRequest msg, List<Object> out) throws Exception
+       {
+               String content = msg.content().toString(Charset.forName("UTF-8"));
+               Object object = gson.fromJson(content, clazz);
+               out.add(object);
+       }
+
+}
diff --git a/grafana/src/main/java/net/rizon/moo/plugin/grafana/beans/GrafanaNotification.java b/grafana/src/main/java/net/rizon/moo/plugin/grafana/beans/GrafanaNotification.java
new file mode 100644 (file)
index 0000000..c26837c
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016, Adam <Adam@rizon.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package net.rizon.moo.plugin.grafana.beans;
+
+import java.util.List;
+
+public class GrafanaNotification
+{
+       private String title;
+       private String ruleId;
+       private String ruleName;
+       private String ruleUrl;
+       private String state;
+       private String imageUrl;
+       private String message;
+       private List<Metric> evalMatches;
+
+       public String getTitle()
+       {
+               return title;
+       }
+
+       public void setTitle(String title)
+       {
+               this.title = title;
+       }
+
+       public String getRuleId()
+       {
+               return ruleId;
+       }
+
+       public void setRuleId(String ruleId)
+       {
+               this.ruleId = ruleId;
+       }
+
+       public String getRuleName()
+       {
+               return ruleName;
+       }
+
+       public void setRuleName(String ruleName)
+       {
+               this.ruleName = ruleName;
+       }
+
+       public String getRuleUrl()
+       {
+               return ruleUrl;
+       }
+
+       public void setRuleUrl(String ruleUrl)
+       {
+               this.ruleUrl = ruleUrl;
+       }
+
+       public String getState()
+       {
+               return state;
+       }
+
+       public void setState(String state)
+       {
+               this.state = state;
+       }
+
+       public String getImageUrl()
+       {
+               return imageUrl;
+       }
+
+       public void setImageUrl(String imageUrl)
+       {
+               this.imageUrl = imageUrl;
+       }
+
+       public String getMessage()
+       {
+               return message;
+       }
+
+       public void setMessage(String message)
+       {
+               this.message = message;
+       }
+
+       public List<Metric> getEvalMatches()
+       {
+               return evalMatches;
+       }
+
+       public void setEvalMatches(List<Metric> evalMatches)
+       {
+               this.evalMatches = evalMatches;
+       }
+
+}
diff --git a/grafana/src/main/java/net/rizon/moo/plugin/grafana/beans/Metric.java b/grafana/src/main/java/net/rizon/moo/plugin/grafana/beans/Metric.java
new file mode 100644 (file)
index 0000000..5e28a7e
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Adam <Adam@rizon.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package net.rizon.moo.plugin.grafana.beans;
+
+public class Metric
+{
+       private String metric;
+
+       public String getMetric()
+       {
+               return metric;
+       }
+
+       public void setMetric(String metric)
+       {
+               this.metric = metric;
+       }
+}
diff --git a/grafana/src/main/java/net/rizon/moo/plugin/grafana/conf/GrafanaConfiguration.java b/grafana/src/main/java/net/rizon/moo/plugin/grafana/conf/GrafanaConfiguration.java
new file mode 100644 (file)
index 0000000..f5a4d14
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016, Adam <Adam@rizon.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.rizon.moo.plugin.grafana.conf;
+
+import java.io.IOException;
+import java.util.List;
+import net.rizon.moo.conf.Configuration;
+import net.rizon.moo.conf.ConfigurationException;
+import net.rizon.moo.conf.Validator;
+
+public class GrafanaConfiguration extends Configuration
+{
+       private static final String CONF_NAME = "grafana.yml";
+
+       private String ip;
+       private int port;
+       private String reportChannel;
+       private List<String> reportStates;
+
+       public static GrafanaConfiguration load() throws ConfigurationException, IOException
+       {
+               return load(CONF_NAME, GrafanaConfiguration.class);
+       }
+
+       @Override
+       public void validate() throws ConfigurationException
+       {
+               Validator.validateNotEmpty("ip", ip);
+               Validator.validatePort("port", port, false);
+               Validator.validateChannelName("reportChannel", reportChannel);
+               Validator.validateNotEmpty("reportStates", reportStates);
+       }
+
+       public String getIp()
+       {
+               return ip;
+       }
+
+       public void setIp(String ip)
+       {
+               this.ip = ip;
+       }
+
+       public int getPort()
+       {
+               return port;
+       }
+
+       public void setPort(int port)
+       {
+               this.port = port;
+       }
+
+       public String getReportChannel()
+       {
+               return reportChannel;
+       }
+
+       public void setReportChannel(String reportChannel)
+       {
+               this.reportChannel = reportChannel;
+       }
+
+       public List<String> getReportStates()
+       {
+               return reportStates;
+       }
+
+       public void setReportStates(List<String> reportStates)
+       {
+               this.reportStates = reportStates;
+       }
+
+}
diff --git a/grafana/src/test/java/net/rizon/moo/plugin/grafana/JsonDecoderTest.java b/grafana/src/test/java/net/rizon/moo/plugin/grafana/JsonDecoderTest.java
new file mode 100644 (file)
index 0000000..438a831
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, Adam <Adam@rizon.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package net.rizon.moo.plugin.grafana;
+
+import io.netty.buffer.Unpooled;
+import io.netty.handler.codec.http.FullHttpRequest;
+import java.util.ArrayList;
+import java.util.List;
+import net.rizon.moo.plugin.grafana.beans.GrafanaNotification;
+import net.rizon.moo.test.MooJUnitRunner;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MooJUnitRunner.class)
+public class JsonDecoderTest
+{
+       private static final String NOTIFICATION = "{\n"
+               + "  \"title\": \"My alert\",\n"
+               + "  \"ruleId\": 1,\n"
+               + "  \"ruleName\": \"Load peaking!\",\n"
+               + "  \"ruleUrl\": \"http://url.to.grafana/db/dashboard/my_dashboard?panelId=2\",\n"
+               + "  \"state\": \"Alerting\",\n"
+               + "  \"imageUrl\": \"http://s3.image.url\",\n"
+               + "  \"message\": \"Load is peaking. Make sure the traffic is real and spin up more webfronts\",\n"
+               + "  \"evalMatches\": [\n"
+               + "    {\n"
+               + "      \"metric\": \"requests\",\n"
+               + "      \"tags\": {},\n"
+               + "      \"value\": 122\n"
+               + "    }\n"
+               + "  ]\n"
+               + "}";
+
+       @Mock
+       private FullHttpRequest request;
+
+       @Test
+       public void testDecode() throws Exception
+       {
+               when(request.content()).thenReturn(Unpooled.wrappedBuffer(NOTIFICATION.getBytes()));
+
+               JsonDecoder decoder = new JsonDecoder(GrafanaNotification.class);
+               
+               List<Object> objects = new ArrayList<>();
+               decoder.decode(null, request, objects);
+               
+               GrafanaNotification notification = (GrafanaNotification) objects.get(0);
+
+               Assert.assertEquals("My alert", notification.getTitle());
+               Assert.assertEquals(1, notification.getEvalMatches().size());
+       }
+
+}
index 48b6fd32613ffda32cb8c8045b32f65197b4d9a2..41fcfd9d4f33076a79cafdb9a690f0ebfff288f8 100644 (file)
@@ -111,6 +111,9 @@ plugins:
  - groupId: net.rizon.moo
    artifactId: fun
    version: 3.0
+ - groupId: net.rizon.moo
+   artifactId: grafana
+   version: 3.0
  - groupId: net.rizon.moo
    artifactId: wiki
    version: 3.0
index 2b86635c5ea37e5e77d8f5f653373f5c36970480..b843329ae099dbbdba0b7b229e1d5e3c8969ddb0 100644 (file)
@@ -135,7 +135,6 @@ public class Moo
                        catch (Throwable ex)
                        {
                                logger.error("Error loading plugin", ex);
-                               //logger.error("Error loading plugin " + pkg, ex);
                                System.exit(-1);
                        }
                }
@@ -187,7 +186,7 @@ public class Moo
        
        public static void stop()
        {
-               moo.channel.close();
+               channel.close();
        }
 
        public static final String getCreated()
index 64f411cad55c282ff10590ed3ba7c2c13828d088..fe8186490758e06cdbad5d5214cc246917549a0f 100644 (file)
@@ -1,6 +1,7 @@
 package net.rizon.moo.conf;
 
 import java.io.FileInputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 
@@ -11,37 +12,30 @@ public abstract class Configuration implements Validatable
 {
        /**
         * Loads the specified file as a YAML configuration.
+        *
+        * @param <T>
         * @param file File.
         * @param c Class of configuration file.
         * @return Loaded configuration.
-        * @throws Exception When something is wrong :D
+        * @throws net.rizon.moo.conf.ConfigurationException
+        * @throws java.io.IOException
         */
-       public static <T extends Configuration> T load(final String file, final Class<T> c) throws Exception
+       public static <T extends Configuration> T load(final String file, final Class<T> c) throws ConfigurationException, IOException
        {
                Yaml yaml = new Yaml(new CustomClassLoaderConstructor(c, c.getClassLoader()));
-               InputStream io = null;
-               try
+               try (InputStream io = new FileInputStream(file))
                {
-                       io = new FileInputStream(file);
                        @SuppressWarnings("unchecked")
                        T conf = (T) yaml.load(io);
                        conf.validate();
                        return conf;
                }
-               finally
-               {
-                       try
-                       {
-                               io.close();
-                       }
-                       catch (Exception ex) { }
-               }
        }
 
        // TODO: Below classes should really be in some utilities.
-
        /**
         * Checks if the string is in the list, ignoring case.
+        *
         * @param text String to check.
         * @param list List of Strings.
         * @return True if string is in list, False otherwise.
@@ -49,13 +43,18 @@ public abstract class Configuration implements Validatable
        public static boolean containsIgnoreCase(final String text, final List<String> list)
        {
                for (String s : list)
+               {
                        if (s.equalsIgnoreCase(text))
+                       {
                                return true;
+                       }
+               }
                return false;
        }
 
        /**
         * Checks if the string is in the array, ignoring case.
+        *
         * @param text String to check.
         * @param array Array of Strings.
         * @return True if string is in array, False otherwise.
@@ -63,8 +62,12 @@ public abstract class Configuration implements Validatable
        public static boolean containsIgnoreCase(final String text, final String[] array)
        {
                for (String s : array)
+               {
                        if (s.equalsIgnoreCase(text))
+                       {
                                return true;
+                       }
+               }
                return false;
        }
 }
diff --git a/pom.xml b/pom.xml
index 58c6d0a2b9f16550c3058f83f8d17a48de0d6e5a..8843b548c53f62fe105c7ea78d40ab3b011a684c 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,7 @@
                <module>dnsbl</module>
                <module>dnsblstats</module>
                <module>fun</module>
+               <module>grafana</module>
                <module>grapher</module>
                <module>logging</module>
                <module>mxbl</module>