logbackgrafana-loki

Logback appender (Loki4jAppender) not sending logs to Loki


I am trying to send logs to Loki with the help of Loki4jAppender (https://github.com/loki4j/loki-logback-appender) but the logs do not reach their destination and i do not get an error message or some hint, as to why it is not working.

I tried to use tinyloki (https://github.com/mjfryc/mjaron-tinyloki-java) and it worked fine. I used the same configuration in both of them but somehow the Logback appender does not work.

This is the Tinyloki code that worked just fine:

        LogController logController = TinyLoki
                .withUrl("http://<ip>:<port>/loki/api/v1/push")
                .start();

        ILogStream stream = logController.stream() // Before v0.3.2 use createStream()
                .info()
                .l("host", "MyComputerName")
                .l("customLabel", "custom_value")
                .build();

        stream.log("Hello world.");

        logController.softStop().hardStop();

And this the Logback configuration:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration>

<configuration>
    <import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
    <import class="ch.qos.logback.core.ConsoleAppender"/>
    <import class="com.github.loki4j.logback.Loki4jAppender"/>

    <appender name="STDOUT" class="ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="LOKI" class="Loki4jAppender">
        <http>
            <url>http://<ip>:<port>/loki/api/v1/push</url>
        </http>
        <format>
            <label>
                <pattern>app=my-app,host=${HOSTNAME},level=%level</pattern>
            </label>
            <message>
                <pattern>l=%level h=${HOSTNAME} c=%logger{20} t=%thread | %msg %ex</pattern>
            </message>
            <sortByTime>true</sortByTime>
        </format>
        <verbose>true</verbose>
    </appender>

    <root level="debug">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="LOKI" />
    </root>
</configuration>

Logback test java source:

import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogbackToLokiTest {
    Logger logger = LoggerFactory.getLogger(LogbackToLokiTest.class);

    @Test
    public void loggingTest() {
        logger.info("Test log entry");
    }
}

I would like to continue using Logback instead of Tinyloki as it has more features.

These are the maven dependencies:

        <dependency>
            <groupId>io.github.mjfryc</groupId>
            <artifactId>mjaron-tinyloki-java</artifactId>
            <version>0.3.11</version>
        </dependency>
        
        <dependency>
            <groupId>com.github.loki4j</groupId>
            <artifactId>loki-logback-appender</artifactId>
            <version>1.5.0-m1</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.3.5</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.4</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.3.5</version>
        </dependency>

Does someone have an idea?


Solution

    1. Loki4j is async client, which means log messages are not immediately sent to Loki one by one as they arrive. Instead, Loki4j accumulates them in batches and sends only when the batch is complete. By default, batch is complete if it contains 1000 messages, or if it is kept for 1 minute. If you want to send a few test messages and see the result immediately, you can set batchMaxItems to 1. But please don't forget to change this setting back for a real-life production logging.

    2. Please don't use unit tests for your evaluation. Instead, turn the Loki4j appender on for the main code. It could be that your logback configuration is not picked up for tests, or test jvm process got killed before Loki4j managed to send anything, and so on. If you want to test Loki4j on a regular basis (which I bet you don't really want), you need integration tests instead of unit tests.