mirror of
https://github.com/tiennm99/tjahzi.git
synced 2026-10-14 00:17:02 +00:00
Re #36: More tests based on log4j tests. Changed test that erroneously set wait time to 10000 seconds. Fixed bug in logback and log4j2 versions that caused Tjahzi to complain about wring buffer size if it was in fact of correct size.
This commit is contained in:
1 parent
b9d4c74a13
commit
54be65a11c
16 files changed
+597
-6
No files matched your search
@@ -101,7 +101,7 @@ public class LokiAppenderBuilder<B extends LokiAppenderBuilder<B>> extends Abstr
|
||||
);
|
||||
|
||||
int bufferSizeBytes = getBufferSizeMegabytes() * BYTES_IN_MEGABYTE;
|
||||
if (TjahziInitializer.isCorrectSize(bufferSizeBytes)) {
|
||||
if (!TjahziInitializer.isCorrectSize(bufferSizeBytes)) {
|
||||
LOGGER.warn("Invalid log buffer size {} - using nearest power of two greater than provided value, no less than 1MB. {}",
|
||||
bufferSizeBytes,
|
||||
GitHubDocs.LOG_BUFFER_SIZING.getLogMessage()
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ class LogLevelLabelConfigurationTest {
|
||||
.withExposedPorts(3100);
|
||||
|
||||
@Test
|
||||
void shouldWorkWIthNoLogLevelConfigured() throws URISyntaxException {
|
||||
void shouldWorkWIthNoLogLevelConfigured() throws Exception {
|
||||
// Given
|
||||
System.setProperty("loki.host", loki.getHost());
|
||||
System.setProperty("loki.port", loki.getFirstMappedPort().toString());
|
||||
|
||||
+3
@@ -21,6 +21,9 @@ class LokiAppenderMonitoringTest {
|
||||
@Test
|
||||
void shouldInjectMonitoringAndUseIt() throws URISyntaxException {
|
||||
// Given
|
||||
System.setProperty("loki.host", "somewhere");
|
||||
System.setProperty("loki.port", "42");
|
||||
|
||||
URI uri = getClass()
|
||||
.getClassLoader()
|
||||
.getResource("basic-appender-test-configuration.xml")
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</Loggers>
|
||||
|
||||
<appenders>
|
||||
<Loki name="Loki" bufferSizeMegabytes="2" batchWait="10000">
|
||||
<Loki name="Loki" bufferSizeMegabytes="2" batchWait="10">
|
||||
<batchSize>1048576</batchSize>
|
||||
|
||||
<host>${sys:loki.host}</host>
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
<version>1.2.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.dropwizard.metrics</groupId>
|
||||
<artifactId>metrics-core</artifactId>
|
||||
<version>4.1.17</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.java-allocation-instrumenter</groupId>
|
||||
<artifactId>java-allocation-instrumenter</artifactId>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package pl.tkowalcz.tjahzi.logback;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Label {
|
||||
@@ -9,6 +10,15 @@ public class Label {
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
// For Logback this is just a convenience method for testing
|
||||
public static Label createLabel(String name, String value) {
|
||||
Label result = new Label();
|
||||
result.setName(name);
|
||||
result.setValue(value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean hasValidName() {
|
||||
return hasValidName(getName());
|
||||
}
|
||||
@@ -29,6 +39,11 @@ public class Label {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
// @VisibleForTests
|
||||
public Map.Entry<String, String> asEntry() {
|
||||
return Map.entry(getName(), getValue());
|
||||
}
|
||||
|
||||
public static boolean hasValidName(String label) {
|
||||
return LABEL_NAME_PATTER.matcher(label).matches();
|
||||
}
|
||||
|
||||
@@ -4,17 +4,21 @@ import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import pl.tkowalcz.tjahzi.LoggingSystem;
|
||||
import pl.tkowalcz.tjahzi.TjahziLogger;
|
||||
import pl.tkowalcz.tjahzi.stats.MonitoringModule;
|
||||
import pl.tkowalcz.tjahzi.stats.MutableMonitoringModuleWrapper;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
|
||||
public class LokiAppender extends LokiAppenderConfigurator {
|
||||
|
||||
|
||||
private PatternLayoutEncoder encoder;
|
||||
private LoggingSystem loggingSystem;
|
||||
|
||||
private TjahziLogger logger;
|
||||
private String logLevelLabel;
|
||||
private MutableMonitoringModuleWrapper monitoringModuleWrapper;
|
||||
|
||||
public PatternLayoutEncoder getEncoder() {
|
||||
return encoder;
|
||||
@@ -24,6 +28,19 @@ public class LokiAppender extends LokiAppenderConfigurator {
|
||||
this.encoder = encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an entry point to set monitoring (statistics) hooks for this appender. This
|
||||
* API is in beta and is subject to change (and probably will).
|
||||
*/
|
||||
public void setMonitoringModule(MonitoringModule monitoringModule) {
|
||||
monitoringModuleWrapper.setMonitoringModule(monitoringModule);
|
||||
}
|
||||
|
||||
// @VisibleForTesting
|
||||
public LoggingSystem getLoggingSystem() {
|
||||
return loggingSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void append(ILoggingEvent event) {
|
||||
String logLevel = event.getLevel().toString();
|
||||
@@ -50,6 +67,7 @@ public class LokiAppender extends LokiAppenderConfigurator {
|
||||
LokiAppenderFactory lokiAppenderFactory = new LokiAppenderFactory(this);
|
||||
loggingSystem = lokiAppenderFactory.createAppender();
|
||||
logLevelLabel = lokiAppenderFactory.getLogLevelLabel();
|
||||
monitoringModuleWrapper = lokiAppenderFactory.getMonitoringModuleWrapper();
|
||||
|
||||
logger = loggingSystem.createLogger();
|
||||
loggingSystem.start();
|
||||
|
||||
@@ -19,6 +19,7 @@ public class LokiAppenderFactory {
|
||||
|
||||
private final HashMap<String, String> lokiLabels;
|
||||
private final String logLevelLabel;
|
||||
private MutableMonitoringModuleWrapper monitoringModuleWrapper;
|
||||
|
||||
public LokiAppenderFactory(LokiAppenderConfigurator configurator) {
|
||||
this.configurator = configurator;
|
||||
@@ -47,7 +48,7 @@ public class LokiAppenderFactory {
|
||||
.flatMap(header -> Stream.of(header.getName(), header.getValue()))
|
||||
.toArray(String[]::new);
|
||||
|
||||
MutableMonitoringModuleWrapper monitoringModuleWrapper = new MutableMonitoringModuleWrapper();
|
||||
monitoringModuleWrapper = new MutableMonitoringModuleWrapper();
|
||||
monitoringModuleWrapper.setMonitoringModule(new StandardMonitoringModule());
|
||||
|
||||
NettyHttpClient httpClient = HttpClientFactory
|
||||
@@ -59,7 +60,7 @@ public class LokiAppenderFactory {
|
||||
);
|
||||
|
||||
int bufferSizeBytes = configurator.getBufferSizeMegabytes() * LokiAppenderConfigurator.BYTES_IN_MEGABYTE;
|
||||
if (TjahziInitializer.isCorrectSize(bufferSizeBytes)) {
|
||||
if (!TjahziInitializer.isCorrectSize(bufferSizeBytes)) {
|
||||
configurator.addWarn(
|
||||
String.format(
|
||||
"Invalid log buffer size %d - using nearest power of two greater than provided value, no less than 1MB. %s\n",
|
||||
@@ -83,4 +84,8 @@ public class LokiAppenderFactory {
|
||||
public String getLogLevelLabel() {
|
||||
return logLevelLabel;
|
||||
}
|
||||
|
||||
public MutableMonitoringModuleWrapper getMonitoringModuleWrapper() {
|
||||
return monitoringModuleWrapper;
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package pl.tkowalcz.tjahzi.logback;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.joran.JoranConfigurator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import pl.tkowalcz.tjahzi.logback.util.TestUtil;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class BufferSizeConfigurationTest {
|
||||
|
||||
@Test
|
||||
void shouldUseDefaultWhenLogBufferSizeIsNotSetViaConfiguration() throws Exception {
|
||||
// Given
|
||||
URI uri = getClass()
|
||||
.getClassLoader()
|
||||
.getResource("appender-test-with-buffer-size-megabytes-unset.xml")
|
||||
.toURI();
|
||||
|
||||
// When
|
||||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
JoranConfigurator configurator = new JoranConfigurator();
|
||||
configurator.setContext(context);
|
||||
|
||||
context.reset();
|
||||
configurator.doConfigure(uri.toURL());
|
||||
|
||||
// Then
|
||||
LokiAppender loki = TestUtil.getLokiAppender(context);
|
||||
assertThat(loki.getLoggingSystem().getLogBufferSize()).isEqualTo(32 * 1024 * 1024);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSetLogBufferSizeViaConfiguration() throws Exception {
|
||||
// Given
|
||||
URI uri = getClass()
|
||||
.getClassLoader()
|
||||
.getResource("appender-test-with-buffer-size-megabytes-set-to-64.xml")
|
||||
.toURI();
|
||||
|
||||
// When
|
||||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
JoranConfigurator configurator = new JoranConfigurator();
|
||||
configurator.setContext(context);
|
||||
|
||||
context.reset();
|
||||
configurator.doConfigure(uri.toURL());
|
||||
|
||||
// Then
|
||||
LokiAppender loki = TestUtil.getLokiAppender(context);
|
||||
assertThat(loki.getLoggingSystem().getLogBufferSize()).isEqualTo(64 * 1024 * 1024);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package pl.tkowalcz.tjahzi.logback;
|
||||
|
||||
import ch.qos.logback.core.ConsoleAppender;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class LabelFactoryTest {
|
||||
|
||||
@Test
|
||||
void shouldRemoveDuplicatedLabels() {
|
||||
// Given
|
||||
Label thisIsADuplicateAndShouldBeDropped = Label.createLabel("ip", "127.0.0.1");
|
||||
Label thisShouldStay = Label.createLabel("ip", "10.0.2.34");
|
||||
Label thisTooShouldStay = Label.createLabel("hostname", "hostname");
|
||||
|
||||
LabelFactory labelFactory = new LabelFactory(
|
||||
new ConsoleAppender<>(),
|
||||
"log_level",
|
||||
thisIsADuplicateAndShouldBeDropped,
|
||||
thisShouldStay,
|
||||
thisTooShouldStay
|
||||
);
|
||||
|
||||
// When
|
||||
HashMap<String, String> actual = labelFactory.convertLabelsDroppingInvalid();
|
||||
|
||||
// Then
|
||||
assertThat(actual).containsOnly(
|
||||
thisShouldStay.asEntry(),
|
||||
thisTooShouldStay.asEntry()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSkipLabelsWithInvalidName() {
|
||||
// Given
|
||||
Label thisShouldStay = Label.createLabel("ip", "10.0.2.34");
|
||||
Label thisShouldStayToo = Label.createLabel("region", "coruscant-west-2");
|
||||
Label invalidNameShouldBeDropped = Label.createLabel("host-name", "hostname");
|
||||
|
||||
LabelFactory labelFactory = new LabelFactory(
|
||||
new ConsoleAppender<>(),
|
||||
"log_level",
|
||||
thisShouldStayToo,
|
||||
thisShouldStay,
|
||||
invalidNameShouldBeDropped
|
||||
);
|
||||
|
||||
// When
|
||||
HashMap<String, String> actual = labelFactory.convertLabelsDroppingInvalid();
|
||||
|
||||
// Then
|
||||
assertThat(actual).containsOnly(
|
||||
thisShouldStay.asEntry(),
|
||||
thisShouldStayToo.asEntry()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAcceptNullLogLevel() {
|
||||
// Given
|
||||
Label label1 = Label.createLabel("ip", "10.0.2.34");
|
||||
Label label2 = Label.createLabel("region", "coruscant-west-2");
|
||||
|
||||
LabelFactory labelFactory = new LabelFactory(
|
||||
new ConsoleAppender<>(),
|
||||
null,
|
||||
label2,
|
||||
label1
|
||||
);
|
||||
|
||||
// When
|
||||
HashMap<String, String> actual = labelFactory.convertLabelsDroppingInvalid();
|
||||
|
||||
// Then
|
||||
assertThat(actual).containsOnly(
|
||||
label1.asEntry(),
|
||||
label2.asEntry()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void logLevelLabelShouldOverrideConflictingLabel() {
|
||||
// Given
|
||||
String logLevelLabel = "log_level";
|
||||
|
||||
Label thisShouldStay = Label.createLabel("ip", "10.0.2.34");
|
||||
Label thisShouldBeRemovedDueToConflict = Label.createLabel(logLevelLabel, "coruscant-west-2");
|
||||
|
||||
LabelFactory labelFactory = new LabelFactory(
|
||||
new ConsoleAppender<>(),
|
||||
logLevelLabel,
|
||||
thisShouldBeRemovedDueToConflict,
|
||||
thisShouldStay
|
||||
);
|
||||
|
||||
HashMap<String, String> labels = new HashMap<>(
|
||||
Map.ofEntries(
|
||||
thisShouldStay.asEntry(),
|
||||
thisShouldBeRemovedDueToConflict.asEntry()
|
||||
)
|
||||
);
|
||||
|
||||
// When
|
||||
String actual = labelFactory.validateLogLevelLabel(labels);
|
||||
|
||||
// Then
|
||||
assertThat(labels).containsOnly(
|
||||
thisShouldStay.asEntry()
|
||||
);
|
||||
|
||||
assertThat(actual).isEqualTo(logLevelLabel);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDisableLogLevelLabelIfItHasInvalidName() {
|
||||
// Given
|
||||
String logLevelLabel = "log-level";
|
||||
|
||||
LabelFactory labelFactory = new LabelFactory(new ConsoleAppender<>(), logLevelLabel);
|
||||
|
||||
// When
|
||||
String actual = labelFactory.validateLogLevelLabel(new HashMap<>());
|
||||
|
||||
// Then
|
||||
assertThat(actual).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleDisabledLogLevelLabel() {
|
||||
// Given
|
||||
String logLevelLabel = null;
|
||||
LabelFactory labelFactory = new LabelFactory(new ConsoleAppender<>(), logLevelLabel);
|
||||
|
||||
// When
|
||||
String actual = labelFactory.validateLogLevelLabel(new HashMap<>());
|
||||
|
||||
// Then
|
||||
assertThat(actual).isNull();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package pl.tkowalcz.tjahzi.logback;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class LabelTest {
|
||||
|
||||
@Test
|
||||
void shouldValidateNamePattern() {
|
||||
// Given
|
||||
Label correctLabel = Label.createLabel("aaa_bbb_ccc", "fobar");
|
||||
Label tooShortLabel = Label.createLabel("", "foobar");
|
||||
Label labelWithInvalidChars = Label.createLabel("log-level", "foobar");
|
||||
|
||||
// When & Then
|
||||
assertThat(correctLabel.hasValidName()).isTrue();
|
||||
assertThat(tooShortLabel.hasValidName()).isFalse();
|
||||
assertThat(labelWithInvalidChars.hasValidName()).isFalse();
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package pl.tkowalcz.tjahzi.logback;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.joran.JoranConfigurator;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.http.ContentType;
|
||||
import io.restassured.parsing.Parser;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.Durations;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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 java.net.URI;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
|
||||
@Testcontainers
|
||||
class LogLevelLabelConfigurationTest {
|
||||
|
||||
@Container
|
||||
public GenericContainer loki = new GenericContainer("grafana/loki:latest")
|
||||
.withCommand("-config.file=/etc/loki-config.yaml")
|
||||
.withClasspathResourceMapping("loki-config.yaml",
|
||||
"/etc/loki-config.yaml",
|
||||
BindMode.READ_ONLY)
|
||||
.waitingFor(
|
||||
Wait.forHttp("/ready")
|
||||
.forPort(3100)
|
||||
)
|
||||
.withExposedPorts(3100);
|
||||
|
||||
@Test
|
||||
void shouldWorkWIthNoLogLevelConfigured() throws Exception {
|
||||
// Given
|
||||
System.setProperty("loki.host", loki.getHost());
|
||||
System.setProperty("loki.port", loki.getFirstMappedPort().toString());
|
||||
|
||||
URI uri = getClass()
|
||||
.getClassLoader()
|
||||
.getResource("appender-test-with-log-label-unset.xml")
|
||||
.toURI();
|
||||
|
||||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
JoranConfigurator configurator = new JoranConfigurator();
|
||||
configurator.setContext(context);
|
||||
|
||||
context.reset();
|
||||
configurator.doConfigure(uri.toURL());
|
||||
|
||||
// When
|
||||
Logger logger = context.getLogger(LokiAppenderLargeBatchesTest.class);
|
||||
logger.info("Test");
|
||||
|
||||
// Then
|
||||
RestAssured.port = loki.getFirstMappedPort();
|
||||
RestAssured.baseURI = "http://" + loki.getHost();
|
||||
RestAssured.registerParser("text/plain", Parser.JSON);
|
||||
|
||||
Awaitility
|
||||
.await()
|
||||
.atMost(Durations.TEN_SECONDS)
|
||||
.pollInterval(Durations.ONE_SECOND)
|
||||
.ignoreExceptions()
|
||||
.untilAsserted(() -> {
|
||||
given()
|
||||
.contentType(ContentType.URLENC)
|
||||
.urlEncodingEnabled(false)
|
||||
.formParam("query=%7Bserver%3D%22127.0.0.1%22%7D")
|
||||
.when()
|
||||
.get("/loki/api/v1/query_range")
|
||||
.then()
|
||||
.log()
|
||||
.all()
|
||||
.statusCode(200)
|
||||
.body("status", equalTo("success"))
|
||||
.body("data.result.size()", equalTo(1))
|
||||
.body("data.result[0].stream.server", equalTo("127.0.0.1"))
|
||||
.body("data.result[0].stream.log_level", nullValue());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSendLogLevelAsConfigured() throws Exception {
|
||||
// Given
|
||||
System.setProperty("loki.host", loki.getHost());
|
||||
System.setProperty("loki.port", loki.getFirstMappedPort().toString());
|
||||
|
||||
URI uri = getClass()
|
||||
.getClassLoader()
|
||||
.getResource("appender-test-with-log-label-set.xml")
|
||||
.toURI();
|
||||
|
||||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
JoranConfigurator configurator = new JoranConfigurator();
|
||||
configurator.setContext(context);
|
||||
|
||||
context.reset();
|
||||
configurator.doConfigure(uri.toURL());
|
||||
|
||||
// When
|
||||
Logger logger = context.getLogger(LokiAppenderLargeBatchesTest.class);
|
||||
logger.info("Test");
|
||||
|
||||
// Then
|
||||
RestAssured.port = loki.getFirstMappedPort();
|
||||
RestAssured.baseURI = "http://" + loki.getHost();
|
||||
RestAssured.registerParser("text/plain", Parser.JSON);
|
||||
|
||||
Awaitility
|
||||
.await()
|
||||
.atMost(Durations.TEN_SECONDS)
|
||||
.pollInterval(Durations.ONE_SECOND)
|
||||
.ignoreExceptions()
|
||||
.untilAsserted(() -> {
|
||||
given()
|
||||
.contentType(ContentType.URLENC)
|
||||
.urlEncodingEnabled(false)
|
||||
.formParam("query=%7Bserver%3D%22127.0.0.1%22%7D")
|
||||
.when()
|
||||
.get("/loki/api/v1/query_range")
|
||||
.then()
|
||||
.log()
|
||||
.all()
|
||||
.statusCode(200)
|
||||
.body("status", equalTo("success"))
|
||||
.body("data.result.size()", equalTo(1))
|
||||
.body("data.result[0].stream.server", equalTo("127.0.0.1"))
|
||||
.body("data.result[0].stream.log_level", equalTo("INFO"));
|
||||
});
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package pl.tkowalcz.tjahzi.logback;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.joran.JoranConfigurator;
|
||||
import com.codahale.metrics.Counter;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import pl.tkowalcz.tjahzi.logback.util.TestUtil;
|
||||
import pl.tkowalcz.tjahzi.stats.DropwizardMonitoringModule;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
|
||||
@Testcontainers
|
||||
class LokiAppenderMonitoringTest {
|
||||
|
||||
@Test
|
||||
void shouldInjectMonitoringAndUseIt() throws Exception {
|
||||
// Given
|
||||
System.setProperty("loki.host", "somewhere");
|
||||
System.setProperty("loki.port", "42");
|
||||
|
||||
URI uri = getClass()
|
||||
.getClassLoader()
|
||||
.getResource("basic-appender-test-configuration.xml")
|
||||
.toURI();
|
||||
|
||||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
JoranConfigurator configurator = new JoranConfigurator();
|
||||
configurator.setContext(context);
|
||||
|
||||
context.reset();
|
||||
configurator.doConfigure(uri.toURL());
|
||||
|
||||
LokiAppender loki = TestUtil.getLokiAppender(context);
|
||||
|
||||
MetricRegistry metricRegistry = new MetricRegistry();
|
||||
loki.setMonitoringModule(
|
||||
new DropwizardMonitoringModule(
|
||||
metricRegistry,
|
||||
"appender.loki"
|
||||
)
|
||||
);
|
||||
|
||||
// When
|
||||
Logger logger = context.getLogger(LokiAppenderLargeBatchesTest.class);
|
||||
logger.info("Test test test");
|
||||
|
||||
// Then
|
||||
assertThat(metricRegistry.getMetrics()).isNotEmpty();
|
||||
|
||||
Counter connectAttemptsCounter = metricRegistry
|
||||
.getCounters()
|
||||
.get("appender.loki.httpConnectAttempts");
|
||||
assertThat(connectAttemptsCounter).isNotNull();
|
||||
|
||||
await().untilAsserted(() -> {
|
||||
assertThat(connectAttemptsCounter.getCount()).isEqualTo(1);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package pl.tkowalcz.tjahzi.logback;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import ch.qos.logback.classic.joran.JoranConfigurator;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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 java.lang.management.ManagementFactory;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
import java.net.URI;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@Testcontainers
|
||||
class LokiAppenderShutdownTest {
|
||||
|
||||
@Container
|
||||
public GenericContainer loki = new GenericContainer("grafana/loki:latest")
|
||||
.withCommand("-config.file=/etc/loki-config.yaml")
|
||||
.withClasspathResourceMapping("loki-config.yaml",
|
||||
"/etc/loki-config.yaml",
|
||||
BindMode.READ_ONLY)
|
||||
.waitingFor(
|
||||
Wait.forHttp("/ready")
|
||||
.forPort(3100)
|
||||
)
|
||||
.withExposedPorts(3100);
|
||||
|
||||
@Test
|
||||
void shouldSendData() throws Exception {
|
||||
// Given
|
||||
System.setProperty("loki.host", loki.getHost());
|
||||
System.setProperty("loki.port", loki.getFirstMappedPort().toString());
|
||||
|
||||
URI uri = getClass()
|
||||
.getClassLoader()
|
||||
.getResource("basic-appender-test-configuration.xml")
|
||||
.toURI();
|
||||
|
||||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
JoranConfigurator configurator = new JoranConfigurator();
|
||||
configurator.setContext(context);
|
||||
|
||||
context.reset();
|
||||
configurator.doConfigure(uri.toURL());
|
||||
|
||||
// Verify our assumptions that we can find threads started by Tjahzi
|
||||
Awaitility.await().untilAsserted(() -> {
|
||||
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
|
||||
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
|
||||
|
||||
assertThat(threadInfos)
|
||||
.extracting(ThreadInfo::getThreadName)
|
||||
.contains(
|
||||
"ReadingLogBufferAndSendingHttp",
|
||||
"tjahzi-worker"
|
||||
);
|
||||
});
|
||||
|
||||
// When
|
||||
context.stop();
|
||||
|
||||
// Then
|
||||
Awaitility.await().untilAsserted(() -> {
|
||||
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
|
||||
ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
|
||||
|
||||
assertThat(threadInfos)
|
||||
.extracting(ThreadInfo::getThreadName)
|
||||
.doesNotContain(
|
||||
"ReadingLogBufferAndSendingHttp",
|
||||
"tjahzi-worker"
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package pl.tkowalcz.tjahzi.logback.util;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import pl.tkowalcz.tjahzi.logback.LokiAppender;
|
||||
|
||||
import java.util.Spliterators;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class TestUtil {
|
||||
|
||||
public static LokiAppender getLokiAppender(LoggerContext context) {
|
||||
return (LokiAppender) context
|
||||
.getLoggerList()
|
||||
.stream()
|
||||
.flatMap(
|
||||
logger ->
|
||||
StreamSupport.stream(
|
||||
Spliterators.spliteratorUnknownSize(logger.iteratorForAppenders(), 0),
|
||||
false
|
||||
)
|
||||
)
|
||||
.filter(appender -> appender instanceof LokiAppender)
|
||||
.findAny()
|
||||
.orElseThrow(() -> new AssertionError("Expected to find Loki appender"));
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
<appender name="Loki" class="pl.tkowalcz.tjahzi.logback.LokiAppender">
|
||||
|
||||
<bufferSizeMegabytes>2</bufferSizeMegabytes>
|
||||
<batchWait>10000</batchWait>
|
||||
<batchWait>10</batchWait>
|
||||
<batchSize>1048576</batchSize>
|
||||
|
||||
<host>${loki.host}</host>
|
||||
|
||||
Reference in new issue
Block a user