Collecting Spring Boot Application Logs with Graylog
Spring Boot Log Aggregation with Graylog
- Graylog ovevriew
- Centralized log platform built around Elasticsearch for search/storage and MongoDB for configuration/state.
- Ingests logs via inputs such as GELF (UDP/TCP), Syslog, and more.
- Web UI and REST API exposed on port 9000 by default.
- Deployment with Docker Compose The stack below runs MongoDB, Elasticsearch, and Graylog. Adjust versions and memory for your environment.
version: "3.8"
services:
mongo:
image: mongo:3
es:
image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.6.1
environment:
http.host: 0.0.0.0
transport.host: localhost
network.host: 0.0.0.0
ES_JAVA_OPTS: "-Xms256m -Xmx256m"
ulimits:
memlock:
soft: -1
hard: -1
deploy:
resources:
limits:
memory: 512M
graylog:
image: graylog/graylog:3.0
environment:
GRAYLOG_PASSWORD_SECRET: somepasswordpepper # at least 16 chars
# SHA-256 for "admin"
GRAYLOG_ROOT_PASSWORD_SHA2: 8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
GRAYLOG_HTTP_EXTERNAL_URI: "http://127.0.0.1:9000/"
depends_on:
- mongo
- es
ports:
- "9000:9000" # Web UI + REST API
- "1514:1514" # Syslog TCP
- "1514:1514/udp" # Syslog UDP
- "12201:12201" # GELF TCP
- "12201:12201/udp"# GELF UDP
Notes
- Replace 127.0.0.1 with your public IP/hostname for remote access.
- Ensure UDP/TCP ports are reachable from application hosts.
- Graylog configuraton
- Log in at http://:9000 using username admin and the configured password.
- Navigate to System -> Inputs.
- Choose GELF UDP and click Launch new input.
- Select the running node, set port 12201, and save.
- Verify the input is running before sending logs.
- Forwarding Spring Boot logs to Graylog Two configurations are demonstrated: Logback and Log4j2. Both send GELF messages to the Graylog input on port 12201.
4.1 Logback using logback-gelf Dependency configuration (Maven):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>boot-graylog-logback</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>de.siegmar</groupId>
<artifactId>logback-gelf</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Create src/main/resources/logback-spring.xml:
<configuration>
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<property name="APP_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n%wEx"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${APP_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- Send logs to Graylog via GELF UDP -->
<appender name="GELF_UDP" class="de.siegmar.logbackgelf.GelfUdpAppender">
<graylogHost>127.0.0.1</graylogHost>
<graylogPort>12201</graylogPort>
<!-- Optional: <facility>spring-app</facility> -->
</appender>
<root level="INFO">
<appender-ref ref="GELF_UDP"/>
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
Start the application and verify events appear in Graylog’s "Search" page. If logs do not arrive, confirm that the GELF UDP input is running and the host/port are correct.
4.2 Log4j2 using log4j2-gelf Dependency configuration (Mavan):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>boot-graylog-log4j2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.graylog2.log4j2</groupId>
<artifactId>log4j2-gelf</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Create src/main/resources/log4j2-spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" packages="org.graylog2.log4j2">
<Properties>
<Property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%t] %c{1.}:%L - %m%n</Property>
</Properties>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${PATTERN}"/>
</Console>
<!-- GELF UDP appender to Graylog -->
<GELF name="GelfToGraylog" server="127.0.0.1" port="12201" hostName="service-a">
<PatternLayout pattern="%logger{36} - %msg%n"/>
<Filters>
<Filter type="MarkerFilter" marker="FLOW" onMatch="DENY" onMismatch="NEUTRAL"/>
<Filter type="MarkerFilter" marker="EXCEPTION" onMatch="DENY" onMismatch="ACCEPT"/>
</Filters>
<KeyValuePair key="environment" value="dev"/>
<KeyValuePair key="jvm" value="${java:vm}"/>
</GELF>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="GelfToGraylog"/>
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
- Choosing Graylog vs. ELK (Elasticsearch, Logstash, Kibana)
- Operational complexity: Graylog bundles the ingestion and UI layers, often simpler to stand up for GELF/Syslog sources. ELK provides more flexibility with Logstash/Beats but can require more moving parts.
- Storage/search: Both rely on Elasticsearch (or compatible) for indexing and query performance.
- Existing stack: If MongoDB is already part of your platform, Graylog’s MongoDB dependency may be acceptable. If you already operate Beats/Logstash pipelines, ELK may integrate more naturally.
- Features: Graylog offers built-in streams, alerts, dashboards, and extractors foccused on log management; ELK offers broadder data ingestion and transformation options.
All examples assume a GELF UDP input bound to port 12201 and that host networking permits UDP traffic from application nodes to the Graylog server.