generated from pricelees/issue-pr-template
feat: 전역으로 쓰이는 Masking Converter 구현 및 logback default 설정 추가
This commit is contained in:
parent
38d82e06b2
commit
fb9a647f32
@ -0,0 +1,77 @@
|
|||||||
|
package roomescape.common.log
|
||||||
|
|
||||||
|
import ch.qos.logback.classic.pattern.MessageConverter
|
||||||
|
import ch.qos.logback.classic.spi.ILoggingEvent
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode
|
||||||
|
import com.fasterxml.jackson.databind.node.TextNode
|
||||||
|
import io.github.oshai.kotlinlogging.KLogger
|
||||||
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
|
import roomescape.common.config.JacksonConfig
|
||||||
|
|
||||||
|
private val SENSITIVE_KEYS = setOf("password", "accessToken")
|
||||||
|
private val log: KLogger = KotlinLogging.logger {}
|
||||||
|
|
||||||
|
class RoomescapeLogMaskingConverter(
|
||||||
|
private val objectMapper: ObjectMapper = JacksonConfig().objectMapper()
|
||||||
|
) : MessageConverter() {
|
||||||
|
|
||||||
|
override fun convert(event: ILoggingEvent): String {
|
||||||
|
val message: String = event.formattedMessage
|
||||||
|
log.warn { "[RoomescapeLogMaskingConverter.convert] formattedMessage: $message" }
|
||||||
|
|
||||||
|
return if (isJsonString(message)) {
|
||||||
|
maskedJsonString(message)
|
||||||
|
} else {
|
||||||
|
maskedPlainMessage(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isJsonString(message: String): Boolean {
|
||||||
|
val trimmed = message.trim()
|
||||||
|
|
||||||
|
return trimmed.startsWith("{") && trimmed.endsWith("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun maskedJsonString(body: String): String = objectMapper.readValue(body, JsonNode::class.java)
|
||||||
|
.apply { maskRecursive(this) }
|
||||||
|
.toString()
|
||||||
|
|
||||||
|
private fun maskedPlainMessage(message: String): String {
|
||||||
|
val keys: String = SENSITIVE_KEYS.joinToString("|")
|
||||||
|
val regex = Regex("(?i)($keys)(\\s*=\\s*)(\\S+)")
|
||||||
|
|
||||||
|
return regex.replace(message) { matchResult ->
|
||||||
|
val key = matchResult.groupValues[1]
|
||||||
|
val delimiter = matchResult.groupValues[2]
|
||||||
|
|
||||||
|
"${key}${delimiter}****"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun maskRecursive(node: JsonNode?) {
|
||||||
|
node?.forEachEntry { key, childNode ->
|
||||||
|
when {
|
||||||
|
childNode.isValueNode -> {
|
||||||
|
if (key in SENSITIVE_KEYS) (node as ObjectNode).put(key, "****")
|
||||||
|
}
|
||||||
|
|
||||||
|
childNode.isObject -> maskRecursive(childNode)
|
||||||
|
childNode.isArray -> {
|
||||||
|
val arrayNode = childNode as ArrayNode
|
||||||
|
val originSize = arrayNode.size()
|
||||||
|
if (originSize > 1) {
|
||||||
|
val first = arrayNode.first()
|
||||||
|
arrayNode.removeAll()
|
||||||
|
arrayNode.add(first)
|
||||||
|
arrayNode.add(TextNode("(...logged only first of $originSize elements)"))
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayNode.forEach { maskRecursive(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<included>
|
<included>
|
||||||
|
<conversionRule conversionWord="maskedMessage"
|
||||||
|
class="roomescape.common.log.RoomescapeLogMaskingConverter" />
|
||||||
|
|
||||||
<property name="CONSOLE_LOG_PATTERN"
|
<property name="CONSOLE_LOG_PATTERN"
|
||||||
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %green(${PID:- }) --- [%15.15thread] %cyan(%-40logger{36}) : %msg%n%throwable"/>
|
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %green(${PID:- }) --- [%15.15thread] %cyan(%-40logger{36}) : %maskedMessage%n%throwable"/>
|
||||||
|
|
||||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
|
|||||||
@ -3,4 +3,8 @@
|
|||||||
<springProfile name="local">
|
<springProfile name="local">
|
||||||
<include resource="logback-local.xml"/>
|
<include resource="logback-local.xml"/>
|
||||||
</springProfile>
|
</springProfile>
|
||||||
|
|
||||||
|
<springProfile name="default">
|
||||||
|
<include resource="logback-local.xml"/>
|
||||||
|
</springProfile>
|
||||||
</configuration>
|
</configuration>
|
||||||
Loading…
x
Reference in New Issue
Block a user