From c6f96e00119f6b3bacd236821b520ed089efa835 Mon Sep 17 00:00:00 2001 From: Tomasz Kowalczewski Date: Tue, 3 May 2022 21:49:32 +0200 Subject: [PATCH 01/10] Re #87: Overhauled connection options. Added URL configuration field and option to specify loki endpoint (via url or separately vis dedicated options). --- .../tkowalcz/tjahzi/http/BootstrapUtil.java | 8 +-- .../tjahzi/http/ClientConfiguration.java | 7 ++ .../http/ClientConfigurationBuilder.java | 64 +++++++++++++++++++ .../tjahzi/log4j2/LokiAppenderBuilder.java | 10 ++- .../logback/LokiAppenderConfigurator.java | 19 ++++++ .../tjahzi/logback/LokiAppenderFactory.java | 4 +- .../LokiAppenderUrlConnectionTest.java | 46 +++++++++++++ .../appender-test-url-configuration.xml | 23 +++++++ 8 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 logback-appender/src/test/java/pl/tkowalcz/tjahzi/logback/LokiAppenderUrlConnectionTest.java create mode 100644 logback-appender/src/test/resources/appender-test-url-configuration.xml diff --git a/core/src/main/java/pl/tkowalcz/tjahzi/http/BootstrapUtil.java b/core/src/main/java/pl/tkowalcz/tjahzi/http/BootstrapUtil.java index f65d7e2..ee8d124 100644 --- a/core/src/main/java/pl/tkowalcz/tjahzi/http/BootstrapUtil.java +++ b/core/src/main/java/pl/tkowalcz/tjahzi/http/BootstrapUtil.java @@ -15,8 +15,6 @@ import javax.net.ssl.SSLException; public class BootstrapUtil { - public static final int HTTPS_PORT = 443; - public static ChannelFuture initConnection( EventLoopGroup group, ClientConfiguration clientConfiguration, @@ -25,7 +23,7 @@ public class BootstrapUtil { Bootstrap bootstrap = new Bootstrap(); SslContext sslContext = null; - if (isSsl(clientConfiguration)) { + if (clientConfiguration.isUseSSL()) { sslContext = createSslContext(); } @@ -49,10 +47,6 @@ public class BootstrapUtil { ).connect(); } - private static boolean isSsl(ClientConfiguration clientConfiguration) { - return clientConfiguration.getPort() == HTTPS_PORT; - } - private static SslContext createSslContext() { try { return SslContextBuilder.forClient() diff --git a/core/src/main/java/pl/tkowalcz/tjahzi/http/ClientConfiguration.java b/core/src/main/java/pl/tkowalcz/tjahzi/http/ClientConfiguration.java index 68242e7..9f24ceb 100644 --- a/core/src/main/java/pl/tkowalcz/tjahzi/http/ClientConfiguration.java +++ b/core/src/main/java/pl/tkowalcz/tjahzi/http/ClientConfiguration.java @@ -5,6 +5,7 @@ public class ClientConfiguration { private final String logEndpoint; private final String host; private final int port; + private boolean useSSL; private final String username; private final String password; @@ -19,6 +20,7 @@ public class ClientConfiguration { String logEndpoint, String host, int port, + boolean useSSL, String username, String password, int connectionTimeoutMillis, @@ -28,6 +30,7 @@ public class ClientConfiguration { this.logEndpoint = logEndpoint; this.host = host; this.port = port; + this.useSSL = useSSL; this.username = username; this.password = password; @@ -51,6 +54,10 @@ public class ClientConfiguration { return port; } + public boolean isUseSSL() { + return useSSL; + } + public String getUsername() { return username; } diff --git a/core/src/main/java/pl/tkowalcz/tjahzi/http/ClientConfigurationBuilder.java b/core/src/main/java/pl/tkowalcz/tjahzi/http/ClientConfigurationBuilder.java index f0fc73c..eed0b64 100644 --- a/core/src/main/java/pl/tkowalcz/tjahzi/http/ClientConfigurationBuilder.java +++ b/core/src/main/java/pl/tkowalcz/tjahzi/http/ClientConfigurationBuilder.java @@ -1,7 +1,13 @@ package pl.tkowalcz.tjahzi.http; +import java.net.MalformedURLException; +import java.net.URL; + public class ClientConfigurationBuilder { + public static final int HTTPS_PORT = 443; + public static final String HTTPS_STRING = "https"; + public static final String DEFAULT_LOG_ENDPOINT = "/loki/api/v1/push"; public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS = 5_000; @@ -12,9 +18,14 @@ public class ClientConfigurationBuilder { public static final int DEFAULT_MAX_RETRIES = 0; private String logEndpoint = DEFAULT_LOG_ENDPOINT; + + private String url; + private String host; private int port; + private boolean useSSL; + private String username; private String password; @@ -39,6 +50,11 @@ public class ClientConfigurationBuilder { return this; } + public ClientConfigurationBuilder withUseSSL(boolean useSSL) { + this.useSSL = useSSL; + return this; + } + public ClientConfigurationBuilder withUsername(String username) { this.username = username; return this; @@ -69,15 +85,23 @@ public class ClientConfigurationBuilder { return this; } + public ClientConfigurationBuilder withUrl(String url) { + this.url = url; + return this; + } + public ClientConfiguration build() { if (maxRequestsInFlight <= 0) { throw new IllegalArgumentException("Property maxRequestsInFlight must be greater than 0"); } + validateAndConfigureConnectionParameters(); + return new ClientConfiguration( logEndpoint, host, port, + useSSL, username, password, connectionTimeoutMillis, @@ -86,4 +110,44 @@ public class ClientConfigurationBuilder { maxRetries ); } + + private void validateAndConfigureConnectionParameters() { + if (url != null && host != null) { + throw new IllegalArgumentException("Only one of 'url' or 'host' can be configured. " + + "Current configuration sets url to '" + url + "' and host to '" + host + "'"); + } + + if (host != null) { + validateAndConfigureConnectionParametersNoUrl(); + } else if (url != null) { + validateAndConfigureConnectionParametersWithUrl(); + } + } + + private void validateAndConfigureConnectionParametersWithUrl() { + try { + URL parsedUrl = new URL(url); + host = parsedUrl.getHost(); + port = parsedUrl.getPort(); + + if (parsedUrl.getPath() != null) { + if (logEndpoint != null) { + throw new IllegalArgumentException("If Loki connection URL contains path part then you cannot at the " + + "same time define log endpoint. Url: '" + url + "', log endpoint: '" + logEndpoint + "'"); + } + + logEndpoint = parsedUrl.getPath(); + } + + if (HTTPS_STRING.equalsIgnoreCase(parsedUrl.getProtocol())) { + useSSL = true; + } + } catch (MalformedURLException e) { + throw new IllegalArgumentException("Creating configuration with Loki URL failed, url: '" + url + "'", e); + } + } + + private void validateAndConfigureConnectionParametersNoUrl() { + useSSL = port == HTTPS_PORT; + } } diff --git a/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/LokiAppenderBuilder.java b/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/LokiAppenderBuilder.java index 6f515fd..e194e30 100644 --- a/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/LokiAppenderBuilder.java +++ b/log4j2-appender/src/main/java/pl/tkowalcz/tjahzi/log4j2/LokiAppenderBuilder.java @@ -37,11 +37,15 @@ public class LokiAppenderBuilder> extends Abstr private static final int BYTES_IN_KILOBYTE = 1024; @PluginBuilderAttribute - @Required(message = "No Loki address provided for LokiAppender") + private String url; + + @PluginBuilderAttribute + private String logEndpoint; + + @PluginBuilderAttribute private String host; @PluginBuilderAttribute - @Required(message = "No Loki port provided for LokiAppender") private int port; @PluginBuilderAttribute @@ -95,6 +99,8 @@ public class LokiAppenderBuilder> extends Abstr @Override public LokiAppender build() { ClientConfiguration configurationBuilder = ClientConfiguration.builder() + .withUrl(url) + .withLogEndpoint(logEndpoint) .withHost(host) .withPort(port) .withUsername(username) diff --git a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderConfigurator.java b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderConfigurator.java index 0f29c55..0ca32cc 100644 --- a/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderConfigurator.java +++ b/logback-appender/src/main/java/pl/tkowalcz/tjahzi/logback/LokiAppenderConfigurator.java @@ -10,6 +10,9 @@ public abstract class LokiAppenderConfigurator extends UnsynchronizedAppenderBas static final int BYTES_IN_MEGABYTE = 1024 * 1024; + private String url; + private String logEndpoint; + private String host; private int port; @@ -33,6 +36,22 @@ public abstract class LokiAppenderConfigurator extends UnsynchronizedAppenderBas private final List
headers = new ArrayList<>(); private final List