import ch.qos.logback.access.spi.IAccessEvent
import ch.qos.logback.classic.util.LogbackMDCAdapter
import com.fasterxml.jackson.core.JsonGenerator
import net.logstash.logback.composite.AbstractFieldJsonProvider
import net.logstash.logback.composite.FieldNamesAware
import net.logstash.logback.composite.JsonWritingUtils
import net.logstash.logback.fieldnames.LogstashAccessFieldNames
import org.slf4j.MDC
import java.io.IOException
import java.util.*
class AccessMdcProvider : AbstractFieldJsonProvider<IAccessEvent>(), FieldNamesAware<LogstashAccessFieldNames> {
private var includeMdcKeyNames: MutableList<String> = ArrayList()
private var excludeMdcKeyNames: MutableList<String> = ArrayList()
override fun start() {
if (!this.includeMdcKeyNames.isEmpty() && !this.excludeMdcKeyNames.isEmpty()) {
addError("Both includeMdcKeyNames and excludeMdcKeyNames are not empty. Only one is allowed to be not empty.")
}
super.start()
}
@Throws(IOException::class)
override fun writeTo(generator: JsonGenerator, event: IAccessEvent) {
val mdcProperties = getMDCPropertyMap().takeIf { it.isNotEmpty() }?.let { props ->
if (!includeMdcKeyNames.isEmpty()) {
props.toMutableMap().also { it.keys.retainAll(includeMdcKeyNames) }
} else if (!excludeMdcKeyNames.isEmpty()) {
props.toMutableMap().also { it.keys.removeAll(excludeMdcKeyNames) }
} else
props
}
mdcProperties?.also {
if (fieldName != null) {
generator.writeObjectFieldStart(fieldName)
}
JsonWritingUtils.writeMapEntries(generator, it)
if (fieldName != null) {
generator.writeEndObject()
}
}
}
private fun getMDCPropertyMap(): Map<String, String> {
val mdcPropertyMap = MDC.getMDCAdapter().let { mdc->
if (mdc is LogbackMDCAdapter)
mdc.propertyMap
else
mdc.copyOfContextMap
} ?: emptyMap<String, String>()
return mdcPropertyMap
}
override fun setFieldNames(fieldNames: LogstashAccessFieldNames) {
}
fun getIncludeMdcKeyNames(): List<String> {
return Collections.unmodifiableList(includeMdcKeyNames)
}
fun addIncludeMdcKeyName(includedMdcKeyName: String) {
this.includeMdcKeyNames.add(includedMdcKeyName)
}
fun setIncludeMdcKeyNames(includeMdcKeyNames: List<String>) {
this.includeMdcKeyNames = ArrayList(includeMdcKeyNames)
}
fun getExcludeMdcKeyNames(): List<String> {
return Collections.unmodifiableList(excludeMdcKeyNames)
}
fun addExcludeMdcKeyName(excludedMdcKeyName: String) {
this.excludeMdcKeyNames.add(excludedMdcKeyName)
}
fun setExcludeMdcKeyNames(excludeMdcKeyNames: List<String>) {
this.excludeMdcKeyNames = ArrayList(excludeMdcKeyNames)
}
}