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,13 +166,12 @@ 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,
@@ -179,20 +180,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
isDebugEnabled = isDebugEnabled, isDebugEnabled = isDebugEnabled,
daemonJvmArgs = daemonJvmArgs daemonJvmArgs = daemonJvmArgs
) )
} catch (e: Throwable) { } ?: throw RuntimeException(COULD_NOT_CONNECT_TO_DAEMON_MESSAGE) // TODO: Add root cause
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,10 +206,8 @@ 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? // 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 // often source of the NoSuchObjectException and UnmarshalException, probably caused by the failed/crashed/exited daemon
// TODO: implement a proper logic to avoid remote calls in such cases // TODO: implement a proper logic to avoid remote calls in such cases
@@ -232,6 +218,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
} catch (e: RemoteException) { } catch (e: RemoteException) {
log.warn("Unable to clear jar cache after compilation, maybe daemon is already down: $e") 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
} }