Improve log messages when failing to compile with daemon

Instead of letting `compileWithDaemon` return null, allow it to throw
exceptions so that the caller can catch those exceptions and log clearer
messages on why it failed.

^KT-31602 In progress
This commit is contained in:
Hung Nguyen
2022-06-17 15:46:27 +01:00
committed by teamcity
parent 98349411fb
commit 17bf6be807
@@ -18,10 +18,10 @@ import org.jetbrains.kotlin.gradle.report.*
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy
import org.jetbrains.kotlin.gradle.tasks.cleanOutputsAndLocalState import org.jetbrains.kotlin.gradle.tasks.cleanOutputsAndLocalState
import org.jetbrains.kotlin.gradle.tasks.throwGradleExceptionIfError import org.jetbrains.kotlin.gradle.tasks.throwGradleExceptionIfError
import org.jetbrains.kotlin.gradle.utils.stackTraceAsString
import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.incremental.ClasspathChanges import org.jetbrains.kotlin.incremental.ClasspathChanges
import org.jetbrains.kotlin.incremental.IncrementalModuleInfo import org.jetbrains.kotlin.incremental.IncrementalModuleInfo
import org.jetbrains.kotlin.util.suffixIfNot
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.* import java.io.*
import java.net.URLClassLoader import java.net.URLClassLoader
@@ -147,12 +147,14 @@ internal class GradleKotlinCompilerWork @Inject constructor(
} }
if (compilerExecutionStrategy == KotlinCompilerExecutionStrategy.DAEMON) { if (compilerExecutionStrategy == KotlinCompilerExecutionStrategy.DAEMON) {
val daemonExitCode = compileWithDaemon(messageCollector) try {
return compileWithDaemon(messageCollector) to KotlinCompilerExecutionStrategy.DAEMON
if (daemonExitCode != null) { } catch (e: Throwable) {
return daemonExitCode to KotlinCompilerExecutionStrategy.DAEMON log.warn(
} else { "Failed to compile with Kotlin daemon: ${e.stackTraceToString().suffixIfNot("\n")}" +
log.warn("Could not connect to kotlin daemon. Using fallback strategy.") "Using fallback strategy: Compile without Kotlin daemon\n" +
"Try ./gradlew --stop if this issue persists."
)
} }
} }
@@ -164,35 +166,21 @@ internal class GradleKotlinCompilerWork @Inject constructor(
} }
} }
private fun compileWithDaemon(messageCollector: MessageCollector): ExitCode? { private fun compileWithDaemon(messageCollector: MessageCollector): ExitCode {
val isDebugEnabled = log.isDebugEnabled || System.getProperty("kotlin.daemon.debug.log")?.toBoolean() ?: true val isDebugEnabled = log.isDebugEnabled || System.getProperty("kotlin.daemon.debug.log")?.toBoolean() ?: true
val daemonMessageCollector = val daemonMessageCollector =
if (isDebugEnabled) messageCollector else MessageCollector.NONE if (isDebugEnabled) messageCollector else MessageCollector.NONE
val connection = val connection =
metrics.measure(BuildTime.CONNECT_TO_DAEMON) { metrics.measure(BuildTime.CONNECT_TO_DAEMON) {
try { GradleCompilerRunner.getDaemonConnectionImpl(
GradleCompilerRunner.getDaemonConnectionImpl( clientIsAliveFlagFile,
clientIsAliveFlagFile, sessionFlagFile,
sessionFlagFile, compilerFullClasspath,
compilerFullClasspath, daemonMessageCollector,
daemonMessageCollector, isDebugEnabled = isDebugEnabled,
isDebugEnabled = isDebugEnabled, daemonJvmArgs = daemonJvmArgs
daemonJvmArgs = daemonJvmArgs )
) } ?: throw RuntimeException(COULD_NOT_CONNECT_TO_DAEMON_MESSAGE) // TODO: Add root cause
} catch (e: Throwable) {
log.error("Caught an exception trying to connect to Kotlin Daemon:")
log.error(e.stackTraceAsString())
null
}
}
if (connection == null) {
if (isIncremental) {
log.warn("Could not perform incremental compilation: $COULD_NOT_CONNECT_TO_DAEMON_MESSAGE")
} else {
log.warn(COULD_NOT_CONNECT_TO_DAEMON_MESSAGE)
}
return null
}
val (daemon, sessionId) = connection val (daemon, sessionId) = connection
@@ -218,19 +206,18 @@ internal class GradleKotlinCompilerWork @Inject constructor(
exitCodeFromProcessExitCode(log, res.get()) exitCodeFromProcessExitCode(log, res.get())
} catch (e: Throwable) { } catch (e: Throwable) {
bufferingMessageCollector.flush(messageCollector) bufferingMessageCollector.flush(messageCollector)
log.error("Compilation with Kotlin compile daemon was not successful") throw e
log.error(e.stackTraceAsString()) } finally {
null // todo: can we clear cache on the end of session?
} // often source of the NoSuchObjectException and UnmarshalException, probably caused by the failed/crashed/exited daemon
// todo: can we clear cache on the end of session? // TODO: implement a proper logic to avoid remote calls in such cases
// often source of the NoSuchObjectException and UnmarshalException, probably caused by the failed/crashed/exited daemon try {
// TODO: implement a proper logic to avoid remote calls in such cases metrics.measure(BuildTime.CLEAR_JAR_CACHE) {
try { daemon.clearJarCache()
metrics.measure(BuildTime.CLEAR_JAR_CACHE) { }
daemon.clearJarCache() } catch (e: RemoteException) {
log.warn("Unable to clear jar cache after compilation, maybe daemon is already down: $e")
} }
} catch (e: RemoteException) {
log.warn("Unable to clear jar cache after compilation, maybe daemon is already down: $e")
} }
log.logFinish(KotlinCompilerExecutionStrategy.DAEMON) log.logFinish(KotlinCompilerExecutionStrategy.DAEMON)
return exitCode return exitCode