Skip to content

Commit d7134b7

Browse files
committed
Make logger group repeated exceptions (e.g. "(x100) message")
1 parent a365f4e commit d7134b7

File tree

4 files changed

+92
-2
lines changed

4 files changed

+92
-2
lines changed

utbot-junit-contest/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ dependencies {
160160
}
161161
implementation group: 'org.apache.commons', name: 'commons-exec', version: '1.2'
162162
implementation group: 'io.github.microutils', name: 'kotlin-logging', version: kotlinLoggingVersion
163+
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: log4j2Version
164+
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: log4j2Version
163165
implementation group: 'org.jsoup', name: 'jsoup', version: '1.6.2'
164166
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1'
165167
implementation group: 'com.google.guava', name: 'guava', version: guavaVersion

utbot-junit-contest/src/main/kotlin/org/utbot/contest/usvm/ContestUsvm.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import org.utbot.contest.usvm.converter.toExecutableId
2828
import org.utbot.contest.usvm.jc.JcContainer
2929
import org.utbot.contest.usvm.jc.JcContainer.Companion.CONTEST_TEST_EXECUTION_TIMEOUT
3030
import org.utbot.contest.usvm.jc.JcTestExecutor
31+
import org.utbot.contest.usvm.log.ErrorCountingLoggerAppender
3132
import org.utbot.framework.codegen.domain.ProjectType
3233
import org.utbot.framework.codegen.domain.RuntimeExceptionTestsBehaviour
3334
import org.utbot.framework.codegen.domain.junitByVersion
@@ -63,6 +64,8 @@ fun runUsvmGeneration(
6364
expectedExceptions: ExpectedExceptionsForClass,
6465
methodNameFilter: String? = null // For debug purposes you can specify method name
6566
): StatsForClass = runBlocking {
67+
ErrorCountingLoggerAppender.resetOccurrenceCounter()
68+
6669
val testsByMethod: MutableMap<ExecutableId, MutableList<UtExecution>> = mutableMapOf()
6770

6871
val timeBudgetMs = timeLimitSec * 1000
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.utbot.contest.usvm.log
2+
3+
import org.apache.logging.log4j.Level
4+
import org.apache.logging.log4j.LogManager
5+
import org.apache.logging.log4j.core.Appender
6+
import org.apache.logging.log4j.core.Core
7+
import org.apache.logging.log4j.core.LogEvent
8+
import org.apache.logging.log4j.core.LoggerContext
9+
import org.apache.logging.log4j.core.config.plugins.Plugin
10+
import org.apache.logging.log4j.core.config.plugins.PluginFactory
11+
import org.apache.logging.log4j.core.layout.PatternLayout
12+
import org.apache.logging.log4j.core.appender.AbstractAppender
13+
import org.apache.logging.log4j.core.config.Property
14+
import org.apache.logging.log4j.core.config.plugins.PluginAttribute
15+
import org.apache.logging.log4j.core.impl.ThrowableProxy
16+
import org.apache.logging.log4j.message.Message
17+
import org.apache.logging.log4j.message.SimpleMessage
18+
import java.util.concurrent.ConcurrentHashMap
19+
20+
@Plugin(
21+
name = "ErrorCountingAppender",
22+
category = Core.CATEGORY_NAME,
23+
elementType = Appender.ELEMENT_TYPE,
24+
printObject = true
25+
)
26+
class ErrorCountingLoggerAppender(name: String, private val delegateAppenderName: String) : AbstractAppender(
27+
name,
28+
null,
29+
PatternLayout.createDefaultLayout(),
30+
false,
31+
Property.EMPTY_ARRAY
32+
) {
33+
34+
private val delegate: Appender by lazy {
35+
(LogManager.getContext(false) as LoggerContext)
36+
.configuration
37+
.getAppender(delegateAppenderName)
38+
}
39+
40+
companion object {
41+
private val occurrenceCountsToLogAt =
42+
generateSequence(1) { it * 10 }.take(10).toList() + listOf(2, 5, 50, 500)
43+
private val errorOccurrenceCounts: MutableMap<Any, Int> = ConcurrentHashMap<Any, Int>()
44+
45+
@PluginFactory
46+
@JvmStatic
47+
fun createAppender(
48+
@PluginAttribute("name") name: String,
49+
@PluginAttribute("delegateAppender") delegateAppenderName: String
50+
) = ErrorCountingLoggerAppender(name, delegateAppenderName)
51+
52+
fun resetOccurrenceCounter() {
53+
errorOccurrenceCounts.keys.toList().forEach { errorOccurrenceCounts[it] = 0 }
54+
}
55+
}
56+
57+
override fun append(event: LogEvent) {
58+
if (event.level >= Level.INFO) {
59+
delegate.append(event)
60+
return
61+
}
62+
63+
val key = event.thrown?.stackTrace?.firstOrNull() ?: event.message.formattedMessage
64+
val alreadyLogged = key in errorOccurrenceCounts
65+
val count = (errorOccurrenceCounts[key] ?: 0) + 1
66+
errorOccurrenceCounts[key] = count
67+
68+
if (!alreadyLogged) {
69+
delegate.append(event)
70+
} else if (count in occurrenceCountsToLogAt) {
71+
val modifiedMessage = "(x$count) ${event.message.formattedMessage}${
72+
event.thrown?.let { e ->
73+
"\n${e.javaClass.name}: ${e.message}\n\tat ${e.stackTrace.firstOrNull()}"
74+
}.orEmpty()
75+
}"
76+
delegate.append(object : LogEvent by event {
77+
override fun getMessage(): Message = SimpleMessage(modifiedMessage)
78+
override fun getThrown(): Throwable? = null
79+
override fun getThrownProxy(): ThrowableProxy? = null
80+
})
81+
}
82+
}
83+
}

utbot-junit-contest/src/main/resources/log4j2.xml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<Configuration>
2+
<Configuration packages="org.utbot.contest.usvm.log">
33
<Appenders>
44
<File name="FrameworkAppender"
55
append="false"
@@ -9,9 +9,11 @@
99
<PatternLayout pattern="%d{HH:mm:ss.SSS} | %-5level | %c{1} | %msg%n"/>
1010
</File>
1111

12-
<Console name="Console" target="SYSTEM_OUT">
12+
<Console name="ActualConsole" target="SYSTEM_OUT">
1313
<PatternLayout pattern="%d{HH:mm:ss.SSS} | %-5level | %msg%n"/>
1414
</Console>
15+
16+
<ErrorCountingAppender name="Console" delegateAppender="ActualConsole"/>
1517
</Appenders>
1618
<Loggers>
1719
<Logger name="org.utbot.contest" level="debug">

0 commit comments

Comments
 (0)