diff --git a/docs/deployment/settings.md b/docs/deployment/settings.md
index 40ce90015..cdb5451e4 100644
--- a/docs/deployment/settings.md
+++ b/docs/deployment/settings.md
@@ -286,6 +286,7 @@ kyuubi\.session\.engine
\.login\.timeout|
USER
|(deprecated) - Using kyuubi.engine.share.level instead
|string
|1.0.0
kyuubi\.session\.engine
\.spark\.main\.resource|<undefined>
|The package used to create Spark SQL engine remote application. If it is undefined, Kyuubi will use the default
|string
|1.0.0
kyuubi\.session\.engine
\.startup\.error\.max
\.size|8192
|During engine bootstrapping, if error occurs, using this config to limit the length error message(characters).
|int
|1.1.0
+kyuubi\.session\.engine
\.startup\.maxLogLines|10
|The maximum number of engine log lines when errors occur during engine startup phase. Note that this max lines is for client-side to help track engine startup issue.
|int
|1.4.0
kyuubi\.session\.idle
\.timeout|PT6H
|session idle timeout, it will be closed when it's not accessed for this duration
|duration
|1.2.0
kyuubi\.session\.name|<undefined>
|A human readable name of session and we use empty string by default. This name will be recorded in event. Note that, we only apply this value from session conf.
|string
|1.4.0
kyuubi\.session
\.timeout|PT6H
|(deprecated)session timeout, it will be closed when it's not accessed for this duration
|duration
|1.0.0
diff --git a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala
index c70a7838b..9e010b8d4 100644
--- a/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala
+++ b/kyuubi-common/src/main/scala/org/apache/kyuubi/config/KyuubiConf.scala
@@ -594,6 +594,15 @@ object KyuubiConf {
.toSequence()
.createWithDefault(Nil)
+ val SESSION_ENGINE_STARTUP_MAX_LOG_LINES: ConfigEntry[Int] =
+ buildConf("session.engine.startup.maxLogLines")
+ .doc("The maximum number of engine log lines when errors occur during engine startup phase." +
+ " Note that this max lines is for client-side to help track engine startup issue.")
+ .version("1.4.0")
+ .intConf
+ .checkValue(_ > 0, "the maximum must be positive integer.")
+ .createWithDefault(10)
+
val SERVER_EXEC_POOL_SIZE: ConfigEntry[Int] =
buildConf("backend.server.exec.pool.size")
.doc("Number of threads in the operation execution thread pool of Kyuubi server")
diff --git a/kyuubi-server/src/main/scala/org/apache/kyuubi/engine/ProcBuilder.scala b/kyuubi-server/src/main/scala/org/apache/kyuubi/engine/ProcBuilder.scala
index a2b863ff3..f90ad213c 100644
--- a/kyuubi-server/src/main/scala/org/apache/kyuubi/engine/ProcBuilder.scala
+++ b/kyuubi-server/src/main/scala/org/apache/kyuubi/engine/ProcBuilder.scala
@@ -24,6 +24,7 @@ import java.nio.file.{Files, Path}
import scala.collection.JavaConverters._
import scala.util.matching.Regex
+import com.google.common.collect.EvictingQueue
import org.apache.commons.lang3.StringUtils.containsIgnoreCase
import org.apache.kyuubi.{KyuubiSQLException, Logging}
@@ -64,7 +65,9 @@ trait ProcBuilder {
}
@volatile private var error: Throwable = UNCAUGHT_ERROR
- @volatile private var lastRowOfLog: String = "unknown"
+
+ private val engineLogMaxLines = conf.get(KyuubiConf.SESSION_ENGINE_STARTUP_MAX_LOG_LINES)
+ private val lastRowsOfLog: EvictingQueue[String] = EvictingQueue.create(engineLogMaxLines)
// Visible for test
@volatile private[kyuubi] var logCaptureThreadReleased: Boolean = true
private var logCaptureThread: Thread = _
@@ -130,7 +133,7 @@ trait ProcBuilder {
error = KyuubiSQLException(sb.toString() + s"\n See more: $engineLog")
} else if (line != null) {
- lastRowOfLog = line
+ lastRowsOfLog.add(line)
}
} else {
Thread.sleep(300)
@@ -153,7 +156,7 @@ trait ProcBuilder {
val YARN_APP_NAME_REGEX: Regex = "application_\\d+_\\d+".r
- def killApplication(line: String = lastRowOfLog): String =
+ def killApplication(line: String = lastRowsOfLog.toArray.mkString("\n")): String =
YARN_APP_NAME_REGEX.findFirstIn(line) match {
case Some(appId) =>
env.get(KyuubiConf.KYUUBI_HOME) match {
@@ -187,7 +190,8 @@ trait ProcBuilder {
error match {
case UNCAUGHT_ERROR =>
KyuubiSQLException(s"Failed to detect the root cause, please check $engineLog at server " +
- s"side if necessary. The last line log is: $lastRowOfLog")
+ s"side if necessary. The last $engineLogMaxLines line(s) of log is: " +
+ s"${lastRowsOfLog.toArray.mkString("\n")}")
case other => other
}
}
diff --git a/kyuubi-server/src/test/scala/org/apache/kyuubi/operation/KyuubiOperationPerConnectionSuite.scala b/kyuubi-server/src/test/scala/org/apache/kyuubi/operation/KyuubiOperationPerConnectionSuite.scala
index b0fc125e0..993fc99ec 100644
--- a/kyuubi-server/src/test/scala/org/apache/kyuubi/operation/KyuubiOperationPerConnectionSuite.scala
+++ b/kyuubi-server/src/test/scala/org/apache/kyuubi/operation/KyuubiOperationPerConnectionSuite.scala
@@ -63,7 +63,6 @@ class KyuubiOperationPerConnectionSuite extends WithKyuubiServer with JDBCTestUt
}
val verboseMessage = Utils.stringifyException(exception)
assert(verboseMessage.contains("Failed to detect the root cause"))
- assert(verboseMessage.contains("The last line log"))
}
}
}