From b8cdac2fba0cb859e9a1d841c37f4ae386338ea6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Sun, 20 Mar 2016 16:54:43 +0100 Subject: [PATCH] Polishing #68 Add author tags. Reformat code. Remove default port fallback in HTTP sender as default ports are specified by the protocol (HTTP/HTTPS). Add documentation for HTTP transport. Extend tests. --- .../biz/paluch/logging/gelf/GelfUtil.java | 64 +--------- .../gelf/intern/GelfSenderFactory.java | 8 +- .../sender/DefaultGelfSenderProvider.java | 116 ++++++++++++++---- .../gelf/intern/sender/GelfHTTPSender.java | 51 +++++--- src/site/markdown/http.md | 17 +++ src/site/site.xml | 1 + .../logging/gelf/GelfInboundHTTPHandler.java | 27 ++-- .../gelf/GelfInboundHTTPInitializer.java | 11 +- .../biz/paluch/logging/gelf/GelfUtilTest.java | 27 ++-- .../logging/gelf/NettyLocalHTTPServer.java | 22 +++- .../intern/sender/GelfHTTPSenderTest.java | 116 +++++++++++------- .../gelf/intern/sender/GelfTCPSenderTest.java | 1 - .../gelf/intern/sender/GelfUDPSenderTest.java | 1 - .../logback/GelfLogbackAppenderHTTPTest.java | 67 ++++++++++ 14 files changed, 334 insertions(+), 195 deletions(-) create mode 100644 src/site/markdown/http.md create mode 100644 src/test/java/biz/paluch/logging/gelf/logback/GelfLogbackAppenderHTTPTest.java diff --git a/src/main/java/biz/paluch/logging/gelf/GelfUtil.java b/src/main/java/biz/paluch/logging/gelf/GelfUtil.java index 0c08a83d6..46cb304c6 100644 --- a/src/main/java/biz/paluch/logging/gelf/GelfUtil.java +++ b/src/main/java/biz/paluch/logging/gelf/GelfUtil.java @@ -29,7 +29,7 @@ public class GelfUtil { public static final String MDC_REQUEST_DURATION = "profiling.requestDuration"; public static final String MDC_REQUEST_DURATION_MILLIS = "profiling.requestDuration.millis"; - + private GelfUtil() { } @@ -96,66 +96,4 @@ public static Set getMatchingMdcNames(DynamicMdcMessageField field, Set< return matchingMdcNames; } - public static String addDefaultPortIfMissing(String urlString, String defaultPort) { - URL url; - try { - url = new URL(urlString); - } catch (MalformedURLException e) { - return urlString; - } - if (url.getPort() != -1) { - return urlString; - } - String regex = "http://([^/]+)"; - String found = getFirstFound(urlString, regex); - String replacer = "http://" + found + ":" + defaultPort; - - if (!isEmpty(found)) { - urlString = urlString.replaceFirst(regex, replacer); - } - return urlString; - } - - public static String getFirstFound(String contents, String regex) { - List founds = getFound(contents, regex); - if (isEmpty(founds)) { - return null; - } - return founds.get(0); - } - - public static List getFound(String contents, String regex) { - if (isEmpty(regex) || isEmpty(contents)) { - return null; - } - List results = new ArrayList(); - Pattern pattern = Pattern.compile(regex, Pattern.UNICODE_CASE); - Matcher matcher = pattern.matcher(contents); - - while (matcher.find()) { - if (matcher.groupCount() > 0) { - results.add(matcher.group(1)); - } else { - results.add(matcher.group()); - } - } - return results; - } - - public static boolean isEmpty(List list) { - if (list == null || list.size() == 0) { - return true; - } - if (list.size() == 1 && isEmpty(list.get(0))) { - return true; - } - return false; - } - - public static boolean isEmpty(String str) { - if (str != null && str.trim().length() > 0) { - return false; - } - return true; - } } diff --git a/src/main/java/biz/paluch/logging/gelf/intern/GelfSenderFactory.java b/src/main/java/biz/paluch/logging/gelf/intern/GelfSenderFactory.java index d18532e78..a57483296 100644 --- a/src/main/java/biz/paluch/logging/gelf/intern/GelfSenderFactory.java +++ b/src/main/java/biz/paluch/logging/gelf/intern/GelfSenderFactory.java @@ -9,7 +9,11 @@ import biz.paluch.logging.gelf.intern.sender.RedisGelfSenderProvider; /** + * Factory to create a {@link GelfSender} based on the host and protocol details. This factory uses Java's {@link ServiceLoader} + * mechanism to discover classes implementing {@link GelfSenderProvider}. + * * @author Mark Paluch + * @author Aleksandar Stojadinovic * @since 26.09.13 15:12 */ public final class GelfSenderFactory { @@ -58,12 +62,13 @@ public Map getSpecificConfigurations() { * @return a new {@link GelfSender} instance */ public static GelfSender createSender(GelfSenderConfiguration senderConfiguration) { + ErrorReporter errorReporter = senderConfiguration.getErrorReporter(); if (senderConfiguration.getHost() == null) { senderConfiguration.getErrorReporter().reportError("GELF server hostname is empty!", null); } else { - try { + try { for (GelfSenderProvider provider : SenderProviderHolder.getSenderProvider()) { if (provider.supports(senderConfiguration.getHost())) { return provider.create(senderConfiguration); @@ -98,6 +103,7 @@ public static void removeAllAddedSenderProviders() { // For thread safe lazy intialization of provider list private static class SenderProviderHolder { + private static ServiceLoader gelfSenderProvider = ServiceLoader.load(GelfSenderProvider.class); private static List providerList = new ArrayList(); private static List addedProviders = new ArrayList(); diff --git a/src/main/java/biz/paluch/logging/gelf/intern/sender/DefaultGelfSenderProvider.java b/src/main/java/biz/paluch/logging/gelf/intern/sender/DefaultGelfSenderProvider.java index 271fa04d0..fca3b22e8 100644 --- a/src/main/java/biz/paluch/logging/gelf/intern/sender/DefaultGelfSenderProvider.java +++ b/src/main/java/biz/paluch/logging/gelf/intern/sender/DefaultGelfSenderProvider.java @@ -1,43 +1,37 @@ package biz.paluch.logging.gelf.intern.sender; -import biz.paluch.logging.gelf.intern.GelfSender; -import biz.paluch.logging.gelf.intern.GelfSenderConfiguration; -import biz.paluch.logging.gelf.intern.GelfSenderProvider; - import java.io.IOException; import java.net.URI; import java.net.URL; +import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; -import static biz.paluch.logging.gelf.GelfUtil.addDefaultPortIfMissing; +import biz.paluch.logging.gelf.intern.GelfSender; +import biz.paluch.logging.gelf.intern.GelfSenderConfiguration; +import biz.paluch.logging.gelf.intern.GelfSenderProvider; /** - * + * Default provider for {@link GelfSender} that creates UDP, TCP and HTTP senders. + * * @author https://github.com/Batigoal/logstash-gelf.git * @author Mark Paluch + * @author Aleksandar Stojadinovic */ public class DefaultGelfSenderProvider implements GelfSenderProvider { public static final int DEFAULT_PORT = 12201; + private static final Map factories; - @Override public boolean supports(String host) { - return host != null; - } - - @Override public GelfSender create(GelfSenderConfiguration configuration) throws IOException { - String graylogHost = configuration.getHost(); - - int port = configuration.getPort(); - if (port == 0) { - port = DEFAULT_PORT; - } + private static final GelfSenderProducer tcpSenderFactory = new GelfSenderProducer() { - if (graylogHost.startsWith("tcp:")) { + @Override + public GelfSender create(GelfSenderConfiguration configuration, String host, int port) throws IOException { int defaultTimeoutMs = (int) TimeUnit.MILLISECONDS.convert(2, TimeUnit.SECONDS); - URI uri = URI.create(graylogHost); + URI uri = URI.create(host); Map params = UriParser.parse(uri); int connectionTimeMs = (int) UriParser.getTimeAsMs(params, GelfTCPSender.CONNECTION_TIMEOUT, defaultTimeoutMs); @@ -48,19 +42,87 @@ public class DefaultGelfSenderProvider implements GelfSenderProvider { String tcpGraylogHost = UriParser.getHost(uri); return new GelfTCPSender(tcpGraylogHost, port, connectionTimeMs, readTimeMs, deliveryAttempts, keepAlive, configuration.getErrorReporter()); - } else if (graylogHost.startsWith("udp:")) { - URI uri = URI.create(graylogHost); + } + }; + + private static final GelfSenderProducer udpSenderFactory = new GelfSenderProducer() { + + @Override + public GelfSender create(GelfSenderConfiguration configuration, String host, int port) throws IOException { + + URI uri = URI.create(host); String udpGraylogHost = UriParser.getHost(uri); return new GelfUDPSender(udpGraylogHost, port, configuration.getErrorReporter()); - } else if (graylogHost.startsWith("http")) { - String graylogHostWithDefaultPort = addDefaultPortIfMissing(graylogHost, String.valueOf(port)); - URL url = new URL(graylogHostWithDefaultPort); - return new GelfHTTPSender(url, configuration.getErrorReporter()); + } + }; + + private static final GelfSenderProducer defaultSenderFactory = new GelfSenderProducer() { + + @Override + public GelfSender create(GelfSenderConfiguration configuration, String host, int port) throws IOException { + return new GelfUDPSender(host, port, configuration.getErrorReporter()); + } + }; - } else { - return new GelfUDPSender(graylogHost, port, configuration.getErrorReporter()); + private static final GelfSenderProducer httpSenderFactory = new GelfSenderProducer() { + + @Override + public GelfSender create(GelfSenderConfiguration configuration, String host, int port) throws IOException { + + int defaultTimeoutMs = (int) TimeUnit.MILLISECONDS.convert(2, TimeUnit.SECONDS); + URL url = new URL(host); + + return new GelfHTTPSender(url, defaultTimeoutMs, defaultTimeoutMs, configuration.getErrorReporter()); + } + }; + + static { + Map prefixToFactory = new HashMap(); + prefixToFactory.put("tcp:", tcpSenderFactory); + prefixToFactory.put("udp:", udpSenderFactory); + prefixToFactory.put("http", httpSenderFactory); + + factories = Collections.unmodifiableMap(prefixToFactory); + + } + + @Override + public boolean supports(String host) { + return host != null; + } + + @Override + public GelfSender create(GelfSenderConfiguration configuration) throws IOException { + + String graylogHost = configuration.getHost(); + + int port = configuration.getPort(); + if (port == 0) { + port = DEFAULT_PORT; + } + + for (Map.Entry entry : factories.entrySet()) { + if (graylogHost.startsWith(entry.getKey())) { + return entry.getValue().create(configuration, graylogHost, port); + } } + return defaultSenderFactory.create(configuration, graylogHost, port); + + } + + private interface GelfSenderProducer { + + /** + * Produce a {@link GelfSender} using {@code configuration}, {@code host} and {@code port}, + * + * @param configuration + * @param host + * @param port + * @return + * @throws IOException + */ + GelfSender create(GelfSenderConfiguration configuration, String host, int port) throws IOException; } } diff --git a/src/main/java/biz/paluch/logging/gelf/intern/sender/GelfHTTPSender.java b/src/main/java/biz/paluch/logging/gelf/intern/sender/GelfHTTPSender.java index 709d23419..16caadf91 100644 --- a/src/main/java/biz/paluch/logging/gelf/intern/sender/GelfHTTPSender.java +++ b/src/main/java/biz/paluch/logging/gelf/intern/sender/GelfHTTPSender.java @@ -1,51 +1,70 @@ package biz.paluch.logging.gelf.intern.sender; -import biz.paluch.logging.gelf.intern.ErrorReporter; -import biz.paluch.logging.gelf.intern.GelfMessage; -import biz.paluch.logging.gelf.intern.GelfSender; - import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; +import biz.paluch.logging.gelf.intern.ErrorReporter; +import biz.paluch.logging.gelf.intern.GelfMessage; +import biz.paluch.logging.gelf.intern.GelfSender; + /** - * Created by https://github.com/salex89 + * @author Aleksandar Stojadinovic */ public class GelfHTTPSender implements GelfSender { - final private ErrorReporter errorReporter; - final private URL url; - private HttpURLConnection connection = null; + private final int connectTimeoutMs; + private final int readTimeoutMs; + private final ErrorReporter errorReporter; + private final URL url; + private int HTTP_ACCEPTED_STATUS = 202; - public GelfHTTPSender(URL url, ErrorReporter errorReporter) { + public GelfHTTPSender(URL url, int connectTimeoutMs, int readTimeoutMs, ErrorReporter errorReporter) { + + this.connectTimeoutMs = connectTimeoutMs; + this.readTimeoutMs = readTimeoutMs; this.errorReporter = errorReporter; this.url = url; } - @Override public boolean sendMessage(GelfMessage message) { + @Override + public boolean sendMessage(GelfMessage message) { + + HttpURLConnection connection = null; + try { connection = (HttpURLConnection) url.openConnection(); + connection.setConnectTimeout(connectTimeoutMs); + connection.setReadTimeout(readTimeoutMs); connection.setDoOutput(true); + connection.setRequestMethod("POST"); + connection.addRequestProperty("Content-type", "application/json"); + OutputStream outputStream = connection.getOutputStream(); outputStream.write(message.toJson().getBytes()); outputStream.close(); + int responseCode = connection.getResponseCode(); if (responseCode == HTTP_ACCEPTED_STATUS) { return true; } else { - errorReporter.reportError("Server responded with unexpected status code: ", null); + errorReporter.reportError("Server responded with unexpected status code: " + responseCode, null); } } catch (IOException e) { - errorReporter.reportError("Error when sending log message", e); + errorReporter.reportError("Cannot send data to " + url, e); + } finally { + // disconnecting HttpURLConnection here to avoid underlying premature underlying Socket being closed. + if (connection != null) { + connection.disconnect(); + } } return false; } - @Override public void close() { - //disconnecting HttpURLConnection here to avoid underlying premature underlying Socket being closed. - if (connection != null) - connection.disconnect(); + @Override + public void close() { + } } diff --git a/src/site/markdown/http.md b/src/site/markdown/http.md new file mode 100644 index 000000000..80e50e730 --- /dev/null +++ b/src/site/markdown/http.md @@ -0,0 +1,17 @@ +# HTTP transport for logstash-gelf + + +logstash-gelf provides a HTTP/HTTPS transport to send log events to HTTP endpoints. The HTTP sender uses `POST` to +send uncompressed JSON data. It sets the `Content-type` header to `application/json` and expects response status `202 Accepted`. + + http://host[:port]/[path] (POST) + +Example: + + http://localhost/gelf + https://localhost/gelf + + * scheme (fixed: http or https, directly used to determine the to be used sender class) + * host (variable: the host) + * port (variable: optional, the port. Defaults to 80 for HTTP and 443 for HTTPS) + * path (variable: optional, path on the server) diff --git a/src/site/site.xml b/src/site/site.xml index 77925f790..742920844 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -31,6 +31,7 @@ + diff --git a/src/test/java/biz/paluch/logging/gelf/GelfInboundHTTPHandler.java b/src/test/java/biz/paluch/logging/gelf/GelfInboundHTTPHandler.java index a750ab615..dbfe81491 100644 --- a/src/test/java/biz/paluch/logging/gelf/GelfInboundHTTPHandler.java +++ b/src/test/java/biz/paluch/logging/gelf/GelfInboundHTTPHandler.java @@ -1,25 +1,22 @@ package biz.paluch.logging.gelf; -import io.netty.buffer.ByteBufInputStream; +import java.util.ArrayList; +import java.util.List; + +import org.json.simple.JSONValue; + import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.*; import io.netty.util.CharsetUtil; -import org.json.simple.JSONValue; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; /** - * Created by aleksandar on 3/12/16. + * @author Aleksandar Stojadinovic */ public class GelfInboundHTTPHandler extends SimpleChannelInboundHandler { + private List values = new ArrayList(); private HttpRequest httpRequest; private HttpContent httpContent; @@ -27,7 +24,8 @@ public class GelfInboundHTTPHandler extends SimpleChannelInboundHandler private final StringBuilder contentBuffer = new StringBuilder(); - @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object message) throws Exception { + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object message) throws Exception { resetState(); if (message instanceof HttpRequest) { @@ -36,6 +34,7 @@ public class GelfInboundHTTPHandler extends SimpleChannelInboundHandler if (message instanceof HttpContent) { httpContent = (HttpContent) message; contentBuffer.append(httpContent.content().toString(CharsetUtil.UTF_8)); + if (message instanceof LastHttpContent) { Object parsedContent = JSONValue.parse(contentBuffer.toString()); synchronized (values) { @@ -71,10 +70,10 @@ public String getUri() { return httpRequest.getUri(); } - public HttpMethod getMethod() { - return httpRequest.getMethod(); + public HttpRequest getHttpRequest() { + return httpRequest; } - + public void setReturnStatus(HttpResponseStatus status) { this.responseStatus = status; } diff --git a/src/test/java/biz/paluch/logging/gelf/GelfInboundHTTPInitializer.java b/src/test/java/biz/paluch/logging/gelf/GelfInboundHTTPInitializer.java index 8b27e0257..a9adc8730 100644 --- a/src/test/java/biz/paluch/logging/gelf/GelfInboundHTTPInitializer.java +++ b/src/test/java/biz/paluch/logging/gelf/GelfInboundHTTPInitializer.java @@ -1,23 +1,28 @@ package biz.paluch.logging.gelf; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; -import io.netty.channel.*; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; /** - * Created by aleksandar on 3/12/16. + * @author Aleksandar Stojadinovic */ public class GelfInboundHTTPInitializer extends ChannelInitializer { + protected GelfInboundHTTPHandler handler; public GelfInboundHTTPInitializer() { handler = new GelfInboundHTTPHandler(); } - @Override protected void initChannel(SocketChannel socketChannel) throws Exception { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new HttpRequestDecoder()); pipeline.addLast(new HttpObjectAggregator(1048576)); pipeline.addLast(new HttpResponseEncoder()); diff --git a/src/test/java/biz/paluch/logging/gelf/GelfUtilTest.java b/src/test/java/biz/paluch/logging/gelf/GelfUtilTest.java index 7e57a0dcb..a00fe8faa 100644 --- a/src/test/java/biz/paluch/logging/gelf/GelfUtilTest.java +++ b/src/test/java/biz/paluch/logging/gelf/GelfUtilTest.java @@ -2,21 +2,23 @@ import static org.junit.Assert.assertEquals; -import biz.paluch.logging.gelf.intern.GelfMessage; -import biz.paluch.logging.gelf.jboss7.JBoss7JulLogEvent; -import org.jboss.logmanager.ExtLogRecord; -import org.junit.Test; - import java.util.HashMap; import java.util.Map; import java.util.logging.Level; +import org.jboss.logmanager.ExtLogRecord; +import org.junit.Test; + +import biz.paluch.logging.gelf.intern.GelfMessage; +import biz.paluch.logging.gelf.jboss7.JBoss7JulLogEvent; + /** * @author Mark Paluch */ public class GelfUtilTest { - @Test public void testProfilingString() throws Exception { + @Test + public void testProfilingString() throws Exception { Map mdcMap = new HashMap(); mdcMap.put(GelfUtil.MDC_REQUEST_START_MS, "" + (System.currentTimeMillis() - 12000)); @@ -27,10 +29,10 @@ public class GelfUtilTest { GelfUtil.addMdcProfiling(new JBoss7JulLogEvent(extLogRecord), message); assertEquals("12sec", message.getAdditonalFields().get(GelfUtil.MDC_REQUEST_DURATION)); - } - @Test public void testProfilingLong() throws Exception { + @Test + public void testProfilingLong() throws Exception { Map mdcMap = new HashMap(); mdcMap.put(GelfUtil.MDC_REQUEST_START_MS, (System.currentTimeMillis() - 12000)); @@ -41,13 +43,6 @@ public class GelfUtilTest { GelfUtil.addMdcProfiling(new JBoss7JulLogEvent(extLogRecord), message); assertEquals("12sec", message.getAdditonalFields().get(GelfUtil.MDC_REQUEST_DURATION)); - - } - - @Test public void addDefaultPortIfMissing() { - String url = GelfUtil.addDefaultPortIfMissing("http://example.com/foo", String.valueOf(1234)); - assertEquals("http://example.com:1234/foo", url); - String url2 = GelfUtil.addDefaultPortIfMissing("http://example.com:8080/foo", String.valueOf(1234)); - assertEquals("http://example.com:8080/foo", url2); } + } diff --git a/src/test/java/biz/paluch/logging/gelf/NettyLocalHTTPServer.java b/src/test/java/biz/paluch/logging/gelf/NettyLocalHTTPServer.java index 71dbbc1b7..5e44e3258 100644 --- a/src/test/java/biz/paluch/logging/gelf/NettyLocalHTTPServer.java +++ b/src/test/java/biz/paluch/logging/gelf/NettyLocalHTTPServer.java @@ -1,17 +1,19 @@ package biz.paluch.logging.gelf; -import io.netty.bootstrap.Bootstrap; +import java.util.List; + import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.*; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpResponseStatus; -import java.util.List; - /** - * @author Mark Paluch - * @since 10.11.13 10:30 + * @author Aleksandar Stojadinovic */ public class NettyLocalHTTPServer { @@ -49,4 +51,12 @@ public void setReturnStatus(HttpResponseStatus status) { public GelfInboundHTTPInitializer getHandlerInitializer() { return handlerInitializer; } + + public HttpMethod getLastHttpRequest() { + return handlerInitializer.getHandler().getHttpRequest().getMethod(); + } + + public HttpHeaders getLastHttpHeaders() { + return handlerInitializer.getHandler().getHttpRequest().headers(); + } } diff --git a/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfHTTPSenderTest.java b/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfHTTPSenderTest.java index d29fc916c..5940e08c1 100644 --- a/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfHTTPSenderTest.java +++ b/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfHTTPSenderTest.java @@ -1,6 +1,26 @@ package biz.paluch.logging.gelf.intern.sender; -import biz.paluch.logging.gelf.GelfTestSender; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; + +import java.io.IOException; +import java.net.URL; +import java.util.List; + +import org.json.simple.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + import biz.paluch.logging.gelf.NettyLocalHTTPServer; import biz.paluch.logging.gelf.intern.ErrorReporter; import biz.paluch.logging.gelf.intern.GelfMessage; @@ -9,91 +29,93 @@ import ch.qos.logback.classic.joran.JoranConfigurator; import ch.qos.logback.core.joran.spi.JoranException; import io.netty.handler.codec.http.HttpResponseStatus; -import org.json.simple.JSONObject; -import org.junit.*; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.slf4j.MDC; - -import java.io.IOException; -import java.net.URL; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.*; +import org.mockito.runners.MockitoJUnitRunner; /** - * (c) Alekandar - https://github.com/salex89 + * @author Aleksandar Stojadinovic */ - +@RunWith(MockitoJUnitRunner.class) public class GelfHTTPSenderTest { + public static final GelfMessage GELF_MESSAGE = new GelfMessage("shortMessage", "fullMessage", 12121L, "WARNING"); private NettyLocalHTTPServer server; private GelfHTTPSender sender; - @Mock ErrorReporter errorReporter; - @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); + @Mock + ErrorReporter errorReporter; + + @Before + public void setUp() throws Exception { server = new NettyLocalHTTPServer(); server.run(); + String uri = "http://127.0.0.1:19393"; - sender = new GelfHTTPSender(new URL(uri), errorReporter); - + sender = new GelfHTTPSender(new URL(uri), 1000, 1000, errorReporter); } - @After public void tearDown() { + @After + public void tearDown() { server.close(); sender.close(); } - @Test public void sendMessageTest() throws IOException { + @Test + public void sendMessageTest() throws IOException { server.setReturnStatus(HttpResponseStatus.ACCEPTED); GelfMessage gelfMessage = new GelfMessage("shortMessage", "fullMessage", 12121l, "WARNING"); + boolean success = sender.sendMessage(gelfMessage); + assertTrue(success); verifyZeroInteractions(errorReporter); + List jsonValues = server.getJsonValues(); assertEquals(1, jsonValues.size()); + JSONObject messageJson = (JSONObject) jsonValues.get(0); assertEquals(gelfMessage.getShortMessage(), messageJson.get("short_message")); assertEquals(gelfMessage.getFullMessage(), messageJson.get("full_message")); assertEquals(gelfMessage.getTimestamp(), messageJson.get("timestamp")); assertEquals(gelfMessage.getLevel(), messageJson.get("level")); + } + @Test + public void shouldUsePostHttpMethod() throws IOException { + + server.setReturnStatus(HttpResponseStatus.ACCEPTED); + + boolean success = sender.sendMessage(GELF_MESSAGE); + + assertTrue(success); + assertEquals("POST", server.getLastHttpRequest().name()); } - @Test public void sendMessageFailureTest() throws IOException { + @Test + public void shouldUseJsonContentType() throws IOException { + + server.setReturnStatus(HttpResponseStatus.ACCEPTED); + + boolean success = sender.sendMessage(GELF_MESSAGE); + + assertTrue(success); + assertEquals("application/json", server.getLastHttpHeaders().get("Content-type")); + + } + + @Test + public void sendMessageFailureTest() throws IOException { server.setReturnStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR); + String uri = "http://127.0.0.1:19393"; - GelfHTTPSender sender = new GelfHTTPSender(new URL(uri), errorReporter); - GelfMessage gelfMessage = new GelfMessage("shortMessage", "fullMessage", 12121l, "WARNING"); - boolean success = sender.sendMessage(gelfMessage); - assertFalse(success); - verify(errorReporter, times(1)).reportError(anyString(), any(Exception.class)); - } + GelfHTTPSender sender = new GelfHTTPSender(new URL(uri), 1000, 1000, errorReporter); - @Test public void testWithLoggingContext() throws JoranException { - LoggerContext lc = new LoggerContext(); - JoranConfigurator configurator = new JoranConfigurator(); - configurator.setContext(lc); - URL xmlConfigFile = getClass().getResource("/logback-gelf-with-http.xml"); - configurator.doConfigure(xmlConfigFile); - Logger testLogger = lc.getLogger("testLogger"); - testLogger.error("Hi there"); - List jsonValues = server.getJsonValues(); - String uri = server.getHandlerInitializer().getHandler().getUri(); - assertEquals("/foo/bar", uri); - assertEquals(1, jsonValues.size()); - JSONObject jsonObject = (JSONObject) jsonValues.get(0); - assertEquals("Hi there", jsonObject.get("short_message")); + boolean success = sender.sendMessage(GELF_MESSAGE); + assertFalse(success); + verify(errorReporter, times(1)).reportError(anyString(), any(Exception.class)); } } diff --git a/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfTCPSenderTest.java b/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfTCPSenderTest.java index 1266bd2a4..b8f87c542 100644 --- a/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfTCPSenderTest.java +++ b/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfTCPSenderTest.java @@ -72,7 +72,6 @@ public void connectionTimeoutShouldApply() throws Exception { @Test(expected = UnknownHostException.class) public void unknownHostShouldThrowException() throws Exception { - new GelfTCPSender("unknown.host.unknown", 65534, 100, 100, errorReporter); } } \ No newline at end of file diff --git a/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfUDPSenderTest.java b/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfUDPSenderTest.java index 6b7608eaa..1eaea4a90 100644 --- a/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfUDPSenderTest.java +++ b/src/test/java/biz/paluch/logging/gelf/intern/sender/GelfUDPSenderTest.java @@ -43,7 +43,6 @@ public void unreachablePacketsShouldBeDiscardedSilently() throws Exception { @Test(expected = UnknownHostException.class) public void unknownHostShouldThrowException() throws Exception { - new GelfUDPSender("unknown.host.unknown", 65534, errorReporter); } } \ No newline at end of file diff --git a/src/test/java/biz/paluch/logging/gelf/logback/GelfLogbackAppenderHTTPTest.java b/src/test/java/biz/paluch/logging/gelf/logback/GelfLogbackAppenderHTTPTest.java new file mode 100644 index 000000000..2d2fb0897 --- /dev/null +++ b/src/test/java/biz/paluch/logging/gelf/logback/GelfLogbackAppenderHTTPTest.java @@ -0,0 +1,67 @@ +package biz.paluch.logging.gelf.logback; + +import static org.junit.Assert.assertEquals; + +import java.net.URL; +import java.util.List; + +import org.json.simple.JSONObject; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.MDC; + +import biz.paluch.logging.gelf.NettyLocalHTTPServer; +import biz.paluch.logging.gelf.intern.GelfMessage; +import biz.paluch.logging.gelf.intern.sender.GelfHTTPSender; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; + +/** + * @author Mark Paluch + */ +public class GelfLogbackAppenderHTTPTest { + + private NettyLocalHTTPServer server; + + LoggerContext lc = null; + + @Before + public void before() throws Exception { + lc = new LoggerContext(); + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(lc); + + URL xmlConfigFile = getClass().getResource("/logback-gelf-with-http.xml"); + + configurator.doConfigure(xmlConfigFile); + + server = new NettyLocalHTTPServer(); + server.run(); + + MDC.remove("mdcField1"); + } + + @After + public void after() throws Exception { + server.close(); + } + + @Test + public void testHttpSender() { + + Logger testLogger = lc.getLogger("testLogger"); + + testLogger.error("Hi there"); + + List jsonValues = server.getJsonValues(); + String uri = server.getHandlerInitializer().getHandler().getUri(); + + assertEquals("/foo/bar", uri); + assertEquals(1, jsonValues.size()); + + JSONObject jsonObject = (JSONObject) jsonValues.get(0); + assertEquals("Hi there", jsonObject.get("short_message")); + } +}