Skip to content

Commit 84dcceb

Browse files
[Bugfix] Insights on query execution error (#475) (#486)
* BugFix: Add error logs * Add IT * Fix IT * Log stacktrace * Use full msg instead of prefix --------- (cherry picked from commit 3c8a490) Signed-off-by: Louis Chu <clingzhi@amazon.com> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 3ace9fb commit 84dcceb

File tree

2 files changed

+75
-10
lines changed

2 files changed

+75
-10
lines changed

integ-test/src/test/scala/org/apache/spark/sql/FlintREPLITSuite.scala

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,69 @@ class FlintREPLITSuite extends SparkFunSuite with OpenSearchSuite with JobTest {
422422
}
423423
}
424424

425+
test("create table with dummy location should fail with excepted error message") {
426+
try {
427+
createSession(jobRunId, "")
428+
threadLocalFuture.set(startREPL())
429+
430+
val dummyLocation = "s3://path/to/dummy/location"
431+
val testQueryId = "110"
432+
val createTableStatement =
433+
s"""
434+
| CREATE TABLE $testTable
435+
| (
436+
| name STRING,
437+
| age INT
438+
| )
439+
| USING CSV
440+
| LOCATION '$dummyLocation'
441+
| OPTIONS (
442+
| header 'false',
443+
| delimiter '\\t'
444+
| )
445+
|""".stripMargin
446+
val createTableStatementId =
447+
submitQuery(s"${makeJsonCompliant(createTableStatement)}", testQueryId)
448+
449+
val createTableStatementValidation: REPLResult => Boolean = result => {
450+
assert(
451+
result.results.size == 0,
452+
s"expected result size is 0, but got ${result.results.size}")
453+
assert(
454+
result.schemas.size == 0,
455+
s"expected schema size is 0, but got ${result.schemas.size}")
456+
failureValidation(result)
457+
true
458+
}
459+
pollForResultAndAssert(createTableStatementValidation, testQueryId)
460+
assert(
461+
!awaitConditionForStatementOrTimeout(
462+
statement => {
463+
statement.error match {
464+
case Some(error)
465+
if error == """{"Message":"Fail to run query. Cause: No FileSystem for scheme \"s3\""}""" =>
466+
// Assertion passed
467+
case _ =>
468+
fail(s"Statement error is: ${statement.error}")
469+
}
470+
statement.state == "failed"
471+
},
472+
createTableStatementId),
473+
s"Fail to verify for $createTableStatementId.")
474+
// clean up
475+
val dropStatement =
476+
s"""DROP TABLE $testTable""".stripMargin
477+
submitQuery(s"${makeJsonCompliant(dropStatement)}", "999")
478+
} catch {
479+
case e: Exception =>
480+
logError("Unexpected exception", e)
481+
assert(false, "Unexpected exception")
482+
} finally {
483+
waitREPLStop(threadLocalFuture.get())
484+
threadLocalFuture.remove()
485+
}
486+
}
487+
425488
/**
426489
* JSON does not support raw newlines (\n) in string values. All newlines must be escaped or
427490
* removed when inside a JSON string. The same goes for tab characters, which should be

spark-sql-application/src/main/scala/org/apache/spark/sql/FlintJobExecutor.scala

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -425,18 +425,22 @@ trait FlintJobExecutor {
425425

426426
private def handleQueryException(
427427
e: Exception,
428-
message: String,
428+
messagePrefix: String,
429429
errorSource: Option[String] = None,
430430
statusCode: Option[Int] = None): String = {
431-
432-
val errorDetails = Map("Message" -> s"$message: ${e.getMessage}") ++
431+
val errorMessage = s"$messagePrefix: ${e.getMessage}"
432+
val errorDetails = Map("Message" -> errorMessage) ++
433433
errorSource.map("ErrorSource" -> _) ++
434434
statusCode.map(code => "StatusCode" -> code.toString)
435435

436436
val errorJson = mapper.writeValueAsString(errorDetails)
437437

438-
statusCode.foreach { code =>
439-
CustomLogging.logError(new OperationMessage("", code), e)
438+
// CustomLogging will call log4j logger.error() underneath
439+
statusCode match {
440+
case Some(code) =>
441+
CustomLogging.logError(new OperationMessage(errorMessage, code), e)
442+
case None =>
443+
CustomLogging.logError(errorMessage, e)
440444
}
441445

442446
errorJson
@@ -480,16 +484,14 @@ trait FlintJobExecutor {
480484
case r: SparkException =>
481485
handleQueryException(r, ExceptionMessages.SparkExceptionErrorPrefix)
482486
case r: Exception =>
483-
val rootCauseClassName = ex.getClass.getName
484-
val errMsg = ex.getMessage
485-
logDebug(s"Root cause class name: $rootCauseClassName")
486-
logDebug(s"Root cause error message: $errMsg")
487+
val rootCauseClassName = r.getClass.getName
488+
val errMsg = r.getMessage
487489
if (rootCauseClassName == "org.apache.hadoop.hive.metastore.api.MetaException" &&
488490
errMsg.contains("com.amazonaws.services.glue.model.AccessDeniedException")) {
489491
val e = new SecurityException(ExceptionMessages.GlueAccessDeniedMessage)
490492
handleQueryException(e, ExceptionMessages.QueryRunErrorPrefix)
491493
} else {
492-
handleQueryException(ex, ExceptionMessages.QueryRunErrorPrefix)
494+
handleQueryException(r, ExceptionMessages.QueryRunErrorPrefix)
493495
}
494496
}
495497
}

0 commit comments

Comments
 (0)