Build a Custom Logging Service with Logback: From Appender to Queue

This article explains what a logging service is, compares ELK and custom appender solutions, shows how to create a Logback appender by extending AppenderBase, provides a complete Java example with configuration, and demonstrates the custom appender in action for backend developers.

Lin is Dream
Lin is Dream
Lin is Dream
Build a Custom Logging Service with Logback: From Appender to Queue

Logging Service is a system for collecting, processing, storing, and querying log information, acting as a record of system behavior to help developers quickly locate issues.

Two common solutions exist: (1) the ELK stack (Elasticsearch + Logstash + Kibana), where Logstash collects data, Elasticsearch stores it, and Kibana visualizes and monitors; (2) a custom log appender that transmits logs via UDP, RPC, or Kafka by overriding the Logback or Log4j appender.

Using the second approach, Logback outputs logs through a defined Appender; the Appender determines the output path, and implementing a custom Appender requires extending AppenderBase and overriding its append() method.

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
    <charset>${CHARSET}</charset>
    <pattern>${APP_PATTERN}</pattern>
  </encoder>
</appender>
<root level="INFO">
  <appender-ref ref="STDOUT"/>
</root>

Referencing the custom Appender in the root logger routes logs to the specified output.

Two design schemes are presented: a generic flow (client → Kafka → logging service → Elasticsearch) and a storage‑saving flow (client → UDP → service → compressed disk), the latter reducing two rounds of serialization and deserialization.

Simple demonstration

A sample BlockingQueueAppender stores log events in a BlockingQueue, uses a thread pool to consume them, and prints each message with a custom prefix.

package com.su4j.service;
import ch.qos.logback.core.AppenderBase;
import ch.qos.logback.classic.spi.ILoggingEvent;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BlockingQueueAppender extends AppenderBase<ILoggingEvent> {
    private final BlockingQueue<String> logQueue = new LinkedBlockingQueue<>();
    private final ExecutorService executorService = Executors.newFixedThreadPool(4);

    @Override
    public void start() {
        super.start();
        executorService.submit(() -> {
            while (true) {
                try {
                    String logMessage = logQueue.take();
                    System.out.println("Custom outputter:" + logMessage);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
    }

    @Override
    protected void append(ILoggingEvent eventObject) {
        try {
            String logMessage = eventObject.getFormattedMessage();
            logQueue.put(logMessage);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void stopSender() {
        executorService.shutdown();
    }
}

Configuration example shows how to declare the BLOCKING_QUEUE appender and attach it to the root logger:

<appender name="BLOCKING_QUEUE" class="com.su4j.service.BlockingQueueAppender">
  <!-- optional custom parameters -->
</appender>
<root level="INFO">
  <appender-ref ref="BLOCKING_QUEUE"/>
</root>

Running the application prints logs prefixed with “Custom outputter:” confirming that the custom appender works as intended.

In summary, the article walks through the core mechanisms of a logging framework and demonstrates a complete custom Appender implementation, providing a practical reference for building a tailored logging service.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend Developmentlogbackcustom appender
Lin is Dream
Written by

Lin is Dream

Sharing Java developer knowledge, practical articles, and continuous insights into computer engineering.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.