Re #87: Overhauled connection options. Added URL configuration field and option to specify loki endpoint (via url or separately vis dedicated options).

This commit is contained in:
Tomasz Kowalczewski committed 2022-05-03 21:49:32 +02:00
1 parent 1442ed899e
commit c6f96e0011
8 files changed
+171 -10

No files matched your search

@@ -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()
@@ -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;
}
@@ -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;
}
}
@@ -37,11 +37,15 @@ public class LokiAppenderBuilder<B extends LokiAppenderBuilder<B>> 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<B extends LokiAppenderBuilder<B>> extends Abstr
@Override
public LokiAppender build() {
ClientConfiguration configurationBuilder = ClientConfiguration.builder()
.withUrl(url)
.withLogEndpoint(logEndpoint)
.withHost(host)
.withPort(port)
.withUsername(username)
@@ -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<Header> headers = new ArrayList<>();
private final List<Label> labels = new ArrayList<>();
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getLogEndpoint() {
return logEndpoint;
}
public void setLogEndpoint(String logEndpoint) {
this.logEndpoint = logEndpoint;
}
public String getHost() {
return host;
}
@@ -40,9 +40,11 @@ public class LokiAppenderFactory {
public LoggingSystem createAppender() {
ClientConfiguration configurationBuilder = ClientConfiguration.builder()
.withUrl(configurator.getUrl())
.withLogEndpoint(configurator.getLogEndpoint())
.withHost(configurator.getHost())
.withConnectionTimeoutMillis(configurator.getConnectTimeoutMillis())
.withPort(configurator.getPort())
.withConnectionTimeoutMillis(configurator.getConnectTimeoutMillis())
.withMaxRetries(configurator.getMaxRetries())
.withRequestTimeoutMillis(configurator.getReadTimeoutMillis())
.withMaxRequestsInFlight(configurator.getMaxRequestsInFlight())
@@ -0,0 +1,46 @@
package pl.tkowalcz.tjahzi.logback;
import ch.qos.logback.classic.LoggerContext;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import pl.tkowalcz.tjahzi.logback.infra.IntegrationTest;
import static org.hamcrest.CoreMatchers.*;
import static pl.tkowalcz.tjahzi.logback.infra.LokiAssert.assertThat;
class LokiAppenderUrlConnectionTest extends IntegrationTest {
@Test
void shouldSendData() {
// Given
LoggerContext context = loadConfig("appender-test-url-configuration.xml");
Logger logger = context.getLogger(LokiAppenderUrlConnectionTest.class);
String expectedLogLine = "Hello World";
// When
logger.info(expectedLogLine);
// Then
assertThat(loki)
.returns(response -> response
.body("data.result.size()", equalTo(1))
.body("data.result[0].stream.server", equalTo("127.0.0.1"))
.body(
"data.result.values",
hasItems(
hasItems(
hasItems(
containsString("p.t.tjahzi.logback.LokiAppenderTest - " + expectedLogLine)
)
)
)
)
);
}
}
@@ -0,0 +1,23 @@
<configuration debug="true">
<appender name="Loki" class="pl.tkowalcz.tjahzi.logback.LokiAppender">
<url>https://${loki.host}:${loki.port}/monitoring/loki/api/v1/push</url>
<efficientLayout>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</efficientLayout>
<header>
<name>X-Org-Id</name>
<value>Circus</value>
</header>
<label>
<name>server</name>
<value>127.0.0.1</value>
</label>
</appender>
<root level="debug">
<appender-ref ref="Loki"/>
</root>
</configuration>