Skip to content

Instantly share code, notes, and snippets.

@libetl
Created December 31, 2022 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save libetl/4d9f7805a9035a8fb35cfd08886dca6b to your computer and use it in GitHub Desktop.
Save libetl/4d9f7805a9035a8fb35cfd08886dca6b to your computer and use it in GitHub Desktop.
Custom logback Joran Configuration in spring boot 3
package com.company.myservice.tool
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import ch.qos.logback.classic.LoggerContext
import ch.qos.logback.classic.joran.JoranConfigurator
import ch.qos.logback.classic.turbo.TurboFilter
import ch.qos.logback.core.spi.FilterReply
import ch.qos.logback.core.status.Status
import ch.qos.logback.core.status.StatusUtil
import ch.qos.logback.core.util.StatusPrinter
import org.slf4j.LoggerFactory
import org.slf4j.Marker
import org.springframework.boot.logging.LogFile
import org.springframework.boot.logging.LoggingInitializationContext
import org.springframework.boot.logging.LoggingSystem
import org.springframework.boot.logging.LoggingSystemFactory
import org.springframework.boot.logging.LoggingSystemProperties
import org.springframework.boot.logging.logback.CustomLogbackJoranConfigurator
import org.springframework.boot.logging.logback.LogbackLoggingSystem
import org.springframework.util.ResourceUtils
internal class CustomLogbackSystemFactory : LoggingSystemFactory {
override fun getLoggingSystem(classLoader: ClassLoader?): LoggingSystem {
return object : LogbackLoggingSystem(classLoader) {
private val denyFilter: TurboFilter = object : TurboFilter() {
override fun decide(
marker: Marker,
logger: Logger,
level: Level,
format: String,
params: Array<Any>,
t: Throwable
): FilterReply {
return FilterReply.DENY
}
}
override fun initialize(
initializationContext: LoggingInitializationContext?,
configLocation: String?,
logFile: LogFile?
) {
val loggerContext = LoggerFactory.getILoggerFactory() as? LoggerContext ?: return
if (loggerContext.getObject(LoggingSystem::class.java.name) != null) {
return
}
if (initializationContext != null) {
LoggingSystemProperties(initializationContext.environment).apply(logFile)
}
loggerContext.stop()
loggerContext.reset()
val configurator = CustomLogbackJoranConfigurator(
initializationContext!!,
classLoader!!
)
configurator.context = loggerContext
configurator.configureUsingAotGeneratedArtifacts()
initializeWithConventions(initializationContext, logFile)
loggerContext.turboFilterList?.remove(denyFilter)
loggerContext.putObject(LoggingSystem::class.java.name, Any())
}
fun initializeWithConventions(initializationContext: LoggingInitializationContext, logFile: LogFile?) {
var config: String? = selfInitializationConfig
if (config != null && logFile == null) {
// self initialization has occurred, reinitialize in case of property changes
reinitialize(initializationContext)
return
}
if (config == null) {
config = springInitializationConfig
}
if (config != null) {
loadConfiguration(initializationContext, config, logFile)
return
}
loadDefaults(initializationContext, logFile)
}
override fun loadConfiguration(
initializationContext: LoggingInitializationContext?,
location: String,
logFile: LogFile?
) {
if (initializationContext != null) {
applySystemProperties(initializationContext.environment, logFile)
}
val loggerContext = LoggerFactory.getILoggerFactory() as LoggerContext
loggerContext.stop()
loggerContext.reset()
val configurator: JoranConfigurator =
CustomLogbackJoranConfigurator(initializationContext!!, classLoader!!)
configurator.context = loggerContext
configurator.doConfigure(ResourceUtils.getURL(location))
val statuses = loggerContext.statusManager.copyOfStatusList
val errors = StringBuilder()
for (status in statuses) {
if (status.level == Status.ERROR) {
errors.append(if (errors.isNotEmpty()) String.format("%n") else "")
errors.append(status.toString())
}
}
check(errors.isEmpty()) { String.format("Logback configuration error detected: %n%s", errors) }
if (!StatusUtil.contextHasStatusListener(loggerContext)) {
StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment