All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.kokuwa.micronaut.logging.configurator.RootAutoSelectAppenderAction Maven / Gradle / Ivy

package io.kokuwa.micronaut.logging.configurator;

import java.util.Optional;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
import ch.qos.logback.core.joran.action.Action;
import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
import io.kokuwa.micronaut.logging.layout.GcpJsonLayout;
import io.kokuwa.micronaut.logging.layout.JsonLayout;
import io.micronaut.core.util.StringUtils;

/**
 * Auto select appender by environment.
 *
 * @author Stephan Schnabel
 */
public class RootAutoSelectAppenderAction extends Action {

	private static final boolean IS_KUBERNETES = StringUtils.isNotEmpty(System.getenv("KUBERNETES_SERVICE_HOST"));
	private static final boolean IS_GCP = StringUtils.isNotEmpty(System.getenv("GOOGLE_CLOUD_PROJECT"));

	private static final String APPENDER_CONSOLE = "CONSOLE";
	private static final String APPENDER_JSON = "JSON";
	private static final String APPENDER_GCP = "GCP";
	private static final String LOGBACK_APPENDER = "LOGBACK_APPENDER";
	private static final String LOGBACK_PATTERN = "LOGBACK_PATTERN";
	private static final String LOGBACK_PATTERN_DEFAULT = """
			%cyan(%d{HH:mm:ss.SSS}) \
			%gray(%-6.6thread) \
			%highlight(%-5level) \
			%magenta(%32logger{32}) \
			%mdc \
			%msg%n""";

	@Override
	public void begin(SaxEventInterpretationContext ic, String name, org.xml.sax.Attributes attributes) {

		var rootLogger = LoggerContext.class.cast(context).getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
		var rootLoggerAppenders = rootLogger.iteratorForAppenders();
		if (rootLoggerAppenders.hasNext()) {
			addWarn("Skip because appender already found: " + rootLoggerAppenders.next().getName());
			return;
		}

		var envAppender = env(LOGBACK_APPENDER, null);
		if (envAppender != null) {
			setAppender(rootLogger, envAppender);
			return;
		}

		if (IS_KUBERNETES) {
			setAppender(rootLogger, APPENDER_JSON);
			return;
		}
		if (IS_GCP) {
			setAppender(rootLogger, APPENDER_GCP);
			return;
		}
		setAppender(rootLogger, APPENDER_CONSOLE);
	}

	@Override
	public void end(SaxEventInterpretationContext ic, String name) {}

	private void setAppender(Logger rootLogger, String appenderName) {
		addInfo("Use appender: " + appenderName);

		var layout = switch (appenderName) {
			case APPENDER_JSON -> json();
			case APPENDER_GCP -> gcp();
			case APPENDER_CONSOLE -> console();
			default -> {
				addError("Appender " + appenderName + " not found. Using console ...");
				yield console();
			}
		};
		layout.start();

		var encoder = new LayoutWrappingEncoder();
		encoder.setContext(context);
		encoder.setLayout(layout);
		encoder.start();

		var appender = new ConsoleAppender();
		appender.setContext(context);
		appender.setName(appenderName);
		appender.setEncoder(encoder);
		appender.start();

		rootLogger.addAppender(appender);
	}

	private Layout console() {
		var layout = new PatternLayout();
		layout.setContext(context);
		layout.setPattern(env(LOGBACK_PATTERN, LOGBACK_PATTERN_DEFAULT));
		return layout;
	}

	private Layout json() {
		var layout = new JsonLayout();
		layout.setContext(context);
		return layout;
	}

	private Layout gcp() {
		var layout = new GcpJsonLayout();
		layout.setContext(context);
		layout.setServiceName(env("SERVICE_NAME", null));
		layout.setServiceVersion(env("SERVICE_VERSION", null));
		return layout;
	}

	private String env(String name, String defaultValue) {
		var envValue = Optional.ofNullable(System.getenv(name)).map(String::trim).filter(StringUtils::isNotEmpty);
		var finalValue = envValue.orElse(defaultValue);
		if (envValue.isPresent()) {
			addInfo("Use provided config: " + name + "=" + finalValue);
		} else {
			addInfo("Use default config: " + name + "=" + finalValue);
		}
		return finalValue;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy