This repository has been archived by the owner on Jun 29, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
14 changed files
with
334 additions
and
195 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 <a href="mailto:[email protected]">Mark Paluch</a> | ||
* @author Aleksandar Stojadinovic | ||
* @since 26.09.13 15:12 | ||
*/ | ||
public final class GelfSenderFactory { | ||
|
@@ -58,12 +62,13 @@ public Map<String, Object> 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> gelfSenderProvider = ServiceLoader.load(GelfSenderProvider.class); | ||
private static List<GelfSenderProvider> providerList = new ArrayList<GelfSenderProvider>(); | ||
private static List<GelfSenderProvider> addedProviders = new ArrayList<GelfSenderProvider>(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <a href="mailto:[email protected]">Mark Paluch</a> | ||
* @author Aleksandar Stojadinovic | ||
*/ | ||
public class DefaultGelfSenderProvider implements GelfSenderProvider { | ||
|
||
public static final int DEFAULT_PORT = 12201; | ||
private static final Map<String, GelfSenderProducer> 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<String, String> 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<String, GelfSenderProducer> prefixToFactory = new HashMap<String, GelfSenderProducer>(); | ||
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<String, GelfSenderProducer> 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; | ||
} | ||
|
||
} |
51 changes: 35 additions & 16 deletions
51
src/main/java/biz/paluch/logging/gelf/intern/sender/GelfHTTPSender.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() { | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.