Re #4: Added ability to pass preconfigured headers in every http call to Loki.

This commit is contained in:
tomasz.kowalczewski committed 2020-11-19 21:21:40 +01:00
1 parent 06b212f425
commit a42a9cdbed
7 files changed
+252 -22

No files matched your search

@@ -20,11 +20,13 @@ import pl.tkowalcz.tjahzi.http.HttpClientFactory;
import pl.tkowalcz.tjahzi.http.NettyHttpClient;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import static java.util.Arrays.stream;
/**
* Loki Appender.
@@ -81,9 +83,16 @@ public class LokiAppender extends AbstractAppender {
.withRequestTimeoutMillis(readTimeoutMillis)
.build();
String[] additionalHeaders = stream(headers)
.flatMap(header -> Stream.of(header.getName(), header.getValue()))
.toArray(String[]::new);
NettyHttpClient httpClient = HttpClientFactory
.defaultFactory()
.getHttpClient(configurationBuilder);
.getHttpClient(
configurationBuilder,
additionalHeaders
);
LoggingSystem loggingSystem = new TjahziInitializer().createLoggingSystem(
httpClient,
@@ -92,17 +101,7 @@ public class LokiAppender extends AbstractAppender {
);
HashMap<String, String> lokiLabels = Maps.newHashMap();
Arrays.stream(labels).forEach(property -> {
String value = getConfiguration()
.getStrSubstitutor()
.replace(property.getValue());
lokiLabels.put(
property.getName(),
value
);
}
);
stream(labels).forEach(__ -> lokiLabels.put(__.getName(), __.getValue()));
return new LokiAppender(
getName(),
@@ -218,7 +217,10 @@ public class LokiAppender extends AbstractAppender {
);
Objects.requireNonNull(layout, "layout");
this.appenderLogic = new AppenderLogic(loggingSystem, lokiLabels);
this.appenderLogic = new AppenderLogic(
loggingSystem,
lokiLabels
);
}
@Override
+7
View File
@@ -48,6 +48,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<version>2.27.2</version>
<scope>test</scope>
</dependency>
<!-- Testcontainers -->
<dependency>
<groupId>org.junit.jupiter</groupId>
@@ -4,8 +4,13 @@ public class HttpClientFactory {
private static final HttpClientFactory INSTANCE = new HttpClientFactory();
public NettyHttpClient getHttpClient(ClientConfiguration clientConfiguration) {
return new NettyHttpClient(clientConfiguration);
public NettyHttpClient getHttpClient(
ClientConfiguration clientConfiguration,
String[] additionalHeaders) {
return new NettyHttpClient(
clientConfiguration,
additionalHeaders
);
}
public static HttpClientFactory defaultFactory() {
@@ -15,15 +15,20 @@ import java.util.concurrent.ThreadFactory;
public class NettyHttpClient implements AutoCloseable {
public static final String PROTOBUF_MIME_TYPE = "application/x-protobuf";
private final EventLoopGroup group;
private final String logEndpoint;
private final Channel channel;
private final String host;
private final HttpHeaders headers;
private final Snappy snappy = new Snappy();
public NettyHttpClient(ClientConfiguration clientConfiguration) {
public NettyHttpClient(
ClientConfiguration clientConfiguration,
String[] additionalHeaders) {
host = clientConfiguration.getHost();
logEndpoint = clientConfiguration.getLogEndpoint();
@@ -46,6 +51,11 @@ public class NettyHttpClient implements AutoCloseable {
.connect()
.syncUninterruptibly()
.channel();
headers = new ReadOnlyHttpHeaders(
true,
additionalHeaders
);
}
public void log(ByteBuf dataBuffer) {
@@ -59,9 +69,11 @@ public class NettyHttpClient implements AutoCloseable {
output
);
request.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/x-protobuf");
request.headers().set(HttpHeaderNames.CONTENT_LENGTH, output.readableBytes());
request.headers().set(HttpHeaderNames.HOST, host);
request.headers()
.add(headers)
.set(HttpHeaderNames.CONTENT_TYPE, PROTOBUF_MIME_TYPE)
.set(HttpHeaderNames.CONTENT_LENGTH, output.readableBytes())
.set(HttpHeaderNames.HOST, host);
channel.writeAndFlush(request);
}
@@ -54,7 +54,10 @@ class LoggingSystemSanityCheckTest {
.build();
NettyHttpClient httpClient = HttpClientFactory.defaultFactory()
.getHttpClient(clientConfiguration);
.getHttpClient(
clientConfiguration,
new String[0]
);
TjahziInitializer initializer = new TjahziInitializer();
LoggingSystem loggingSystem = initializer.createLoggingSystem(
@@ -0,0 +1,198 @@
package pl.tkowalcz.tjahzi;
import com.github.tomakehurst.wiremock.WireMockServer;
import org.awaitility.Durations;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import pl.tkowalcz.tjahzi.http.ClientConfiguration;
import pl.tkowalcz.tjahzi.http.HttpClientFactory;
import pl.tkowalcz.tjahzi.http.NettyHttpClient;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static org.awaitility.Awaitility.await;
class HeadersTest {
private WireMockServer wireMockServer;
private TjahziInitializer initializer;
private LoggingSystem loggingSystem;
@BeforeEach
void setUp() {
wireMockServer = new WireMockServer(
wireMockConfig()
.dynamicPort()
.dynamicHttpsPort()
);
wireMockServer.start();
initializer = new TjahziInitializer();
}
@AfterEach
void tearDown() {
wireMockServer.stop();
if (loggingSystem != null) {
loggingSystem.close(
(int) TimeUnit.SECONDS.toMillis(10),
System.out::println
);
loggingSystem = null;
}
}
@Test
void shouldIncludeAdditionalHeaders() {
// Given
wireMockServer.stubFor(
get(urlEqualTo("/loki/api/v1/push"))
.willReturn(
aResponse().withStatus(200)
));
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.withConnectionTimeoutMillis(10_000)
.withHost("localhost")
.withPort(wireMockServer.port())
.withMaxRetries(1)
.build();
NettyHttpClient httpClient = HttpClientFactory.defaultFactory()
.getHttpClient(
clientConfiguration,
new String[]{
"X-Scope-OrgID", "Circus",
"C", "Control"
}
);
LoggingSystem loggingSystem = initializer.createLoggingSystem(
httpClient,
1024 * 1024,
false
);
// WHen
TjahziLogger logger = loggingSystem.createLogger();
logger.log(
System.currentTimeMillis(),
Map.of(),
"Test"
);
// Then
await()
.atMost(Durations.FIVE_SECONDS)
.untilAsserted(() ->
wireMockServer.verify(
postRequestedFor(urlMatching("/loki/api/v1/push"))
.withHeader("X-Scope-OrgID", equalTo("Circus"))
));
}
@Test
void shouldHandleCaseWithNoAdditionalHeaders() {
// Given
wireMockServer.stubFor(
get(urlEqualTo("/loki/api/v1/push"))
.willReturn(
aResponse().withStatus(200)
));
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.withConnectionTimeoutMillis(10_000)
.withHost("localhost")
.withPort(wireMockServer.port())
.withMaxRetries(1)
.build();
NettyHttpClient httpClient = HttpClientFactory.defaultFactory()
.getHttpClient(
clientConfiguration,
new String[0]
);
LoggingSystem loggingSystem = initializer.createLoggingSystem(
httpClient,
1024 * 1024,
false
);
// WHen
TjahziLogger logger = loggingSystem.createLogger();
logger.log(
System.currentTimeMillis(),
Map.of(),
"Test"
);
// Then
await()
.atMost(Durations.FIVE_SECONDS)
.untilAsserted(() ->
wireMockServer.verify(
postRequestedFor(urlMatching("/loki/api/v1/push"))
));
}
@Test
void shouldNotOverrideCrucialHeaders() {
// Given
wireMockServer.stubFor(
get(urlEqualTo("/loki/api/v1/push"))
.willReturn(
aResponse().withStatus(200)
));
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.withConnectionTimeoutMillis(10_000)
.withHost("localhost")
.withPort(wireMockServer.port())
.withMaxRetries(1)
.build();
NettyHttpClient httpClient = HttpClientFactory.defaultFactory()
.getHttpClient(
clientConfiguration,
new String[]{
"content-type", "text/plain",
"content-length", "5232423423",
"host", "remote"
}
);
LoggingSystem loggingSystem = initializer.createLoggingSystem(
httpClient,
1024 * 1024,
false
);
// When
TjahziLogger logger = loggingSystem.createLogger();
logger.log(
System.currentTimeMillis(),
Map.of(),
"Test"
);
// Then
await()
.atMost(Durations.FIVE_SECONDS)
.untilAsserted(() ->
wireMockServer.verify(
postRequestedFor(urlMatching("/loki/api/v1/push"))
.withHeader("content-type", matching("application/x-protobuf"))
.withHeader("content-length", matching("29|30"))
.withHeader("host", matching("localhost"))
));
}
}
@@ -57,7 +57,10 @@ class LoggingSystemTest {
.build();
NettyHttpClient httpClient = HttpClientFactory.defaultFactory()
.getHttpClient(clientConfiguration);
.getHttpClient(
clientConfiguration,
new String[0]
);
TjahziInitializer initializer = new TjahziInitializer();
LoggingSystem loggingSystem = initializer.createLoggingSystem(