Monitoring Log Volume - `spring`

Writing a custom encoder

package com.commons.logging;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import io.micrometer.core.instrument.MeterRegistry;
import net.logstash.logback.encoder.LogstashEncoder;

public class InstrumentedEncoder extends LogstashEncoder {

    private static final String METRIC_LINES_NAME = "log_messages_lines";
    private static final String METRIC_SIZE_BYTES_NAME = "log_messages_size_bytes";
    private static final String LABEL_LEVEL_NAME = "level";

    private static MeterRegistry meterRegistry;
    private static InstrumentedEncoder instance;

    public InstrumentedEncoder() {
        instance = this;
    }

    public static InstrumentedEncoder bind(MeterRegistry other) {
        meterRegistry = other;
        return instance;
    }

    @Override
    public byte[] encode(ILoggingEvent event) {
        byte[] bytes = super.encode(event);
        if (meterRegistry != null) {
            final String level = switch (event.getLevel().levelInt) {
                case Level.ERROR_INT -> "error";
                case Level.WARN_INT -> "warn";
                case Level.INFO_INT -> "info";
                case Level.DEBUG_INT -> "debug";
                case Level.TRACE_INT -> "trace";
                default -> "unknown";
            };
            meterRegistry.counter(METRIC_LINES_NAME, LABEL_LEVEL_NAME, level).increment();
            meterRegistry.counter(METRIC_SIZE_BYTES_NAME, LABEL_LEVEL_NAME, level).increment(bytes.length);
        }
        return bytes;
    }
}

Usage

<!-- logback.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="com.commons.logging.InstrumentedEncoder">
        </encoder>
    </appender>

    <root level="debug">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>
@Configuration
public class AppConfig {

    @Bean
    public InstrumentedEncoder instrumentedLogger(MeterRegistry meterRegistry) {
        return InstrumentedEncoder.bind(meterRegistry);
    }

}