Spring Boot 3, logback integrated with Grafana Loki.

Tracing logs in an application is crucial for determining whether a problem causes an error in the application or an incorrect business process.
The developer relies on a log file to write clues that can help trace a problem in the log file. Tracing log files can be complicated when an application generates hundreds or thousands of log files from different clusters and servers. The developer must filter or narrow a log file to reduce it to a manageable size, also known as a trace.
Grafana Loki can solve this problem by helping developers manage and filter logs. The developer can also view a log in real-time on the Grafana Dashboard. Grafana Loki provides feature queries and filters logs.

The developer can create an initial Spring Boot project from
the Spring initialzr. It helps the developer create a template for a project quickly.

Install Grafana Loki, Grafana dashboards, and Promtail on Docker.

1. Directory structure

/grafana-loki
├── docker-compose.yml
├── loki
│   └── config
│       └── local-config.yaml
└── promtail
    └── config
        └── local-config.yaml

2. Create docker-compose.yml

version: '3.9'

services:
  loki:
    image: grafana/loki:3.0.0
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    volumes:
      - ./loki/config:/etc/loki
    networks:
      postgres_postgres-network:
        ipv4_address: 172.20.0.5
  grafana:
    image: grafana/grafana:10.4.4
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_SECURITY_ADMIN_USER=admin
    volumes:
      - grafana-storage:/var/lib/grafana
    networks:
      postgres_postgres-network:
        ipv4_address: 172.20.0.6
  promtail:
    image: grafana/promtail:3.0.0
    volumes:
      - /var/log:/var/log
      - ./promtail/config:/etc/promtail
    command: -config.file=/etc/promtail/local-config.yaml
    networks:
      postgres_postgres-network:
        ipv4_address: 172.20.0.7
volumes:
  grafana-storage:
networks:
  postgres_postgres-network:
    external: true

3. The developer can discover the latest version of each image.

4. Create a Loki config file local-config.yaml.

auth_enabled: false

server:
  http_listen_port: 3100

common:
  instance_addr: 172.20.0.5
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory

schema_config:
  configs:
    - from: 2020-10-24
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h

ruler:
  alertmanager_url: http://localhost:9093

# By default, Loki will send anonymous, but uniquely-identifiable usage and configuration
# analytics to Grafana Labs. These statistics are sent to https://stats.grafana.org/
#
# Statistics help us better understand how Loki is used, and they show us performance
# levels for most users. This helps us prioritize features and documentation.
# For more information on what's sent, look at
# https://github.com/grafana/loki/blob/main/pkg/usagestats/stats.go
# Refer to the buildReport method to see what goes into a report.
#
# If you would like to disable reporting, uncomment the following lines:
#analytics:
#  reporting_enabled: false

The developer can download the initial local-config.yaml file.

5. Create a Promtail config file `local-config.yaml`.

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://172.20.0.5:3100/loki/api/v1/push

scrape_configs:
- job_name: system
  static_configs:
    - targets:
        - localhost
      labels:
        job: varlogs
        __path__: /var/log/*.log

In the Spring Boot project, the developer configured Logback to send the log to Grafana Loki.

6. Configuration `logback-spring.xml`.

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

    <!-- Define properties for log file locations -->
    <property name="APP_NAME" value="demo_logs" />

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg traceId=%X{traceId} spanId=%X{spanId}%n</pattern>
        </encoder>
    </appender>

    <appender name="LOKI" class="com.github.loki4j.logback.Loki4jAppender">
        <!-- (1) -->
        <http>
            <url>http://localhost:3100/loki/api/v1/push</url>
        </http>
        <format>
            <!-- (2) -->
            <label>
                <pattern>app=${APP_NAME},host=${HOSTNAME},level=%level</pattern>
                <!-- (3) -->
                <readMarkers>true</readMarkers>
            </label>
            <message>
                <!-- (4) -->
                <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg traceId=%X{traceId} spanId=%X{spanId}%n</pattern>
            </message>
        </format>
    </appender>

    <!-- Root logger configuration -->
    <root level="INFO">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="LOKI"/>
    </root>


</configuration>

7. When a Spring Boot project is deployed on Dockerthe developer must change the IP address to 172.20.0.5, which is confined to the Docker network.

Read more about the configuration of the Logback Grafana Loki appender.

Start Grafana Loki, Grafana dashboards, and Promtail.

1. Execute the command to download and start images.

>docker compose up

2. Check that the images were downloaded.

> docker images
REPOSITORY         TAG       IMAGE ID       CREATED        SIZE
grafana/grafana    10.4.4    7f12425a99f1   10 days ago    429MB
grafana/loki       3.0.0     b3ac890121a8   2 months ago   80.4MB
grafana/promtail   3.0.0     dd39094f5519   2 months ago   202MB

3. Check that containers have been started.

docker container ls
CONTAINER ID   IMAGE                    COMMAND                  CREATED          STATUS             PORTS                           NAMES
00f5c42ecfd3   grafana/promtail:3.0.0   "/usr/bin/promtail -…"   42 minutes ago   Up 41 minutes                                      grafana-loki-promtail-1
b24a022e95b5   grafana/grafana:10.4.4   "/run.sh"                42 minutes ago   Up 41 minutes      0.0.0.0:3000->3000/tcp          grafana-loki-grafana-1
f3a22365ea81   grafana/loki:3.0.0       "/usr/bin/loki -conf…"   42 minutes ago   Up 41 minutes      0.0.0.0:3100->3100/tcp          grafana-loki-loki-1

Connect Grafana dashboard and Grafana Loki

1. Login to the Grafana dashboard URL http://localhost:3000

Grafana login page

2. The input username and password are confined to `dock-compose.xml`.

Grafana add datasourfce

3. Add a new data source, Grafana Loki.
Choose menu Connections and sub menu Data sources .

Grafana add loki datasource

4. Connection with Grafana Loki.

Grafana loki datasource

5. Input the name Loki-1 and URL: http://172.20.0.5:3100 to connect to Grafana Loki. Click Save & test Button.

Read more about the setting, Grafana Loki.

Grafana loki additional settings
The data source was successfully connected.

Start the application, Spring Boot.

1. In the application log message example from RestController.

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/api/products")
@Slf4j
public class ProductsController {

    @GetMapping(path = "/{productId}", produces = "application/json")
    public ResponseEntity<Object> getUserprofile(@PathVariable String productId) {
        log.info("Example  info  message -> Received product ID {}", productId);
        log.debug("Example debug message -> Received product ID {}", productId);
        log.error("Example error message -> not found product ID {}", productId);
        return new ResponseEntity<>(null, HttpStatus.OK);
    }

}

2. Start the Spring Boot application.

>mvn package
>java -jar target/demo-0.0.1-SNAPSHOT.jar

The developer can deploy the Spring Boot application on Docker.

View the log message in the Grafana dashboard.

When the application starts, it sends a log to the Grafana Loki server, which is displayed on the Grafana dashboard.

1. In the Grafana dashboard, go to Exeplorer Menu.

Grafana loki exeplorer

2. The Developer selects Label filters.

Grafana loki display log filter

3. The Line contains input. Example For query log messages containing the word Example Only that helps the developer find an involved log process effectively.

  {
    "line": "2024-06-25 15:50:19 [http-nio-8080-exec-2] INFO  c.e.d.c.products.ProductsController - Example  info  message -> Received product ID 1 traceId=667a84cb6e626d564e530e93c04b8776 spanId=3c8ed8697a4389a6\r\n",
    "timestamp": "1719305419307307000",
    "fields": {
      "app": "demo_logs",
      "host": "DESKTOP-ULUNNQR",
      "level": "INFO",
      "service_name": "demo_logs"
    }
  },

4. The developer can query by trace ID to identify which log uses the same request or process.

Application replicas on Docker.

An application in Docker: The developer can filter logs for each container by hostname.

Grafana Loki filters by label

Read more about Grafana Exeplorer.

Finally

Grafana Loki offers several benefits for log management and monitoring, particularly in the modern context. It works seamlessly with Grafana and provides LogQL and Label-based Filtering features. The developer should use observability and logging tools that improve overall development team performance to find and solve problems.

Leave a Comment

Your email address will not be published. Required fields are marked *