JBAI-21522 [TRACE] Port text/code field distinction to 262, keeping TrueValidationRule creatable

Backport of the JBAI-20852 mechanism (master 1062c6873c196): add LlmFieldKind
and the TrueValidationRuleCode/TrueValidationRuleText accept-all rules so the
TRACE PII filter can anonymize code and text separately.

Unlike master, TrueValidationRule stays a concrete, instantiable class marked
@Deprecated instead of becoming abstract, and the deprecated single-arg
RequestPrivateData constructor / default CheckedFilePrivateData kind map to
LlmFieldKind.UNSPECIFIED -> the legacy `llm_parameters` rule. This keeps all
existing call sites compiling and their validation strings (and FUS group
versions) unchanged, so old usages do not need to be migrated. The TRACE PII
filter now matches llm_parameters, llm_code_parameters and llm_text_parameters.

IJ-MR-214799

GitOrigin-RevId: 19333a6aed6e47fcd9f7f58e62bb715a330924c4
This commit is contained in:
Samuel Soukup
2026-07-24 16:57:12 +00:00
committed by intellij-monorepo-bot
parent 8f33ac4c5c
commit 47ccefae99
2 changed files with 54 additions and 2 deletions
@@ -61,7 +61,11 @@ internal class TracePiiFilteringEventLogger(
}
internal object TraceLlmPiiDataFilter {
private const val LLM_PARAMETERS_RULE = "util#llm_parameters"
private val LLM_PARAMETERS_RULES = listOf(
"util#llm_parameters",
"util#llm_code_parameters",
"util#llm_text_parameters",
)
private val llmFieldPathsResolver = TraceLlmFieldPathsResolver()
fun createFilter(recorderOptionsProvider: RecorderOptionProvider?): (EventLogGroup, String, Map<String, Any>) -> Map<String, Any> {
@@ -273,7 +277,9 @@ internal object TraceLlmPiiDataFilter {
}
private fun shouldBePiiFiltered(validationRules: List<String>): Boolean {
return validationRules.any { rule -> rule.contains(LLM_PARAMETERS_RULE) }
return validationRules.any { rule ->
LLM_PARAMETERS_RULES.any { ruleName -> rule.contains(ruleName) }
}
}
}
}
@@ -173,6 +173,42 @@ class TracePiiFilteringEventLoggerTest {
assertEquals(input, filtered)
}
@Test
fun `filters fields validated by the code rule too`() {
val group = EventLogGroup("trace.event.log", 1, "TRACE")
group.registerVarargEvent("metadata.load.failed", LlmCodeParametersField("request"))
val provider = RecorderOptionProvider(
mapOf(TracePiiRegexRedactor.TRACE_PII_REGEXES_JSON_OPTION to """["AKIA[0-9A-Z]{16}"]""")
)
val filter = TraceLlmPiiDataFilter.createFilter(provider)
val input = mapOf<String, Any>(
"request" to "token AKIA1234567890ABCDEF",
)
val filtered = filter(group, "metadata.load.failed", input)
assertEquals("token [REDACTED]", filtered["request"])
}
@Test
fun `filters fields validated by the text rule too`() {
val group = EventLogGroup("trace.event.log", 1, "TRACE")
group.registerVarargEvent("metadata.load.failed", LlmTextParametersField("request"))
val provider = RecorderOptionProvider(
mapOf(TracePiiRegexRedactor.TRACE_PII_REGEXES_JSON_OPTION to """["AKIA[0-9A-Z]{16}"]""")
)
val filter = TraceLlmPiiDataFilter.createFilter(provider)
val input = mapOf<String, Any>(
"request" to "token AKIA1234567890ABCDEF",
)
val filtered = filter(group, "metadata.load.failed", input)
assertEquals("token [REDACTED]", filtered["request"])
}
}
private class LlmParametersField(override val name: String) : StringEventField(name) {
@@ -180,6 +216,16 @@ private class LlmParametersField(override val name: String) : StringEventField(n
get() = listOf("{util#llm_parameters}")
}
private class LlmCodeParametersField(override val name: String) : StringEventField(name) {
override val validationRule: List<String>
get() = listOf("{util#llm_code_parameters}")
}
private class LlmTextParametersField(override val name: String) : StringEventField(name) {
override val validationRule: List<String>
get() = listOf("{util#llm_text_parameters}")
}
private class CapturingLogger : StatisticsEventLogger {
var capturedDataProvider: (() -> Map<String, Any>?)? = null
var cleanupCalled = false