aboutsummaryrefslogtreecommitdiff
path: root/core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala
diff options
context:
space:
mode:
authorHari Shreedharan <hshreedharan@apache.org>2015-06-03 13:43:13 -0500
committerImran Rashid <irashid@cloudera.com>2015-06-03 13:43:13 -0500
commitd2a86eb8f0fcc02304604da56c589ea58c77587a (patch)
tree78d95e02f898f2925f0e5553bc6ba7adedfd31f0 /core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala
parentd053a31be93d789e3f26cf55d747ecf6ca386c29 (diff)
downloadspark-d2a86eb8f0fcc02304604da56c589ea58c77587a.tar.gz
spark-d2a86eb8f0fcc02304604da56c589ea58c77587a.tar.bz2
spark-d2a86eb8f0fcc02304604da56c589ea58c77587a.zip
[SPARK-7161] [HISTORY SERVER] Provide REST api to download event logs fro...
...m History Server This PR adds a new API that allows the user to download event logs for an application as a zip file. APIs have been added to download all logs for a given application or just for a specific attempt. This also add an additional method to the ApplicationHistoryProvider to get the raw files, zipped. Author: Hari Shreedharan <hshreedharan@apache.org> Closes #5792 from harishreedharan/eventlog-download and squashes the following commits: 221cc26 [Hari Shreedharan] Update docs with new API information. a131be6 [Hari Shreedharan] Fix style issues. 5528bd8 [Hari Shreedharan] Merge branch 'master' into eventlog-download 6e8156e [Hari Shreedharan] Simplify tests, use Guava stream copy methods. d8ddede [Hari Shreedharan] Remove unnecessary case in EventLogDownloadResource. ffffb53 [Hari Shreedharan] Changed interface to use zip stream. Added more tests. 1100b40 [Hari Shreedharan] Ensure that `Path` does not appear in interfaces, by rafactoring interfaces. 5a5f3e2 [Hari Shreedharan] Fix test ordering issue. 0b66948 [Hari Shreedharan] Minor formatting/import fixes. 4fc518c [Hari Shreedharan] Fix rat failures. a48b91f [Hari Shreedharan] Refactor to make attemptId optional in the API. Also added tests. 0fc1424 [Hari Shreedharan] File download now works for individual attempts and the entire application. 350d7e8 [Hari Shreedharan] Merge remote-tracking branch 'asf/master' into eventlog-download fd6ab00 [Hari Shreedharan] Fix style issues 32b7662 [Hari Shreedharan] Use UIRoot directly in ApiRootResource. Also, use `Response` class to set headers. 7b362b2 [Hari Shreedharan] Almost working. 3d18ebc [Hari Shreedharan] [WIP] Try getting the event log download to work.
Diffstat (limited to 'core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala')
-rw-r--r--core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala88
1 files changed, 82 insertions, 6 deletions
diff --git a/core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala b/core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala
index 14f2d1a589..e5b5e1bb65 100644
--- a/core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala
+++ b/core/src/test/scala/org/apache/spark/deploy/history/HistoryServerSuite.scala
@@ -16,10 +16,13 @@
*/
package org.apache.spark.deploy.history
-import java.io.{File, FileInputStream, FileWriter, IOException}
+import java.io.{File, FileInputStream, FileWriter, InputStream, IOException}
import java.net.{HttpURLConnection, URL}
+import java.util.zip.ZipInputStream
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
+import com.google.common.base.Charsets
+import com.google.common.io.{ByteStreams, Files}
import org.apache.commons.io.{FileUtils, IOUtils}
import org.mockito.Mockito.when
import org.scalatest.{BeforeAndAfter, Matchers}
@@ -147,6 +150,70 @@ class HistoryServerSuite extends SparkFunSuite with BeforeAndAfter with Matchers
}
}
+ test("download all logs for app with multiple attempts") {
+ doDownloadTest("local-1430917381535", None)
+ }
+
+ test("download one log for app with multiple attempts") {
+ (1 to 2).foreach { attemptId => doDownloadTest("local-1430917381535", Some(attemptId)) }
+ }
+
+ test("download legacy logs - all attempts") {
+ doDownloadTest("local-1426533911241", None, legacy = true)
+ }
+
+ test("download legacy logs - single attempts") {
+ (1 to 2). foreach {
+ attemptId => doDownloadTest("local-1426533911241", Some(attemptId), legacy = true)
+ }
+ }
+
+ // Test that the files are downloaded correctly, and validate them.
+ def doDownloadTest(appId: String, attemptId: Option[Int], legacy: Boolean = false): Unit = {
+
+ val url = attemptId match {
+ case Some(id) =>
+ new URL(s"${generateURL(s"applications/$appId")}/$id/logs")
+ case None =>
+ new URL(s"${generateURL(s"applications/$appId")}/logs")
+ }
+
+ val (code, inputStream, error) = HistoryServerSuite.connectAndGetInputStream(url)
+ code should be (HttpServletResponse.SC_OK)
+ inputStream should not be None
+ error should be (None)
+
+ val zipStream = new ZipInputStream(inputStream.get)
+ var entry = zipStream.getNextEntry
+ entry should not be null
+ val totalFiles = {
+ if (legacy) {
+ attemptId.map { x => 3 }.getOrElse(6)
+ } else {
+ attemptId.map { x => 1 }.getOrElse(2)
+ }
+ }
+ var filesCompared = 0
+ while (entry != null) {
+ if (!entry.isDirectory) {
+ val expectedFile = {
+ if (legacy) {
+ val splits = entry.getName.split("/")
+ new File(new File(logDir, splits(0)), splits(1))
+ } else {
+ new File(logDir, entry.getName)
+ }
+ }
+ val expected = Files.toString(expectedFile, Charsets.UTF_8)
+ val actual = new String(ByteStreams.toByteArray(zipStream), Charsets.UTF_8)
+ actual should be (expected)
+ filesCompared += 1
+ }
+ entry = zipStream.getNextEntry
+ }
+ filesCompared should be (totalFiles)
+ }
+
test("response codes on bad paths") {
val badAppId = getContentAndCode("applications/foobar")
badAppId._1 should be (HttpServletResponse.SC_NOT_FOUND)
@@ -202,7 +269,11 @@ class HistoryServerSuite extends SparkFunSuite with BeforeAndAfter with Matchers
}
def getUrl(path: String): String = {
- HistoryServerSuite.getUrl(new URL(s"http://localhost:$port/api/v1/$path"))
+ HistoryServerSuite.getUrl(generateURL(path))
+ }
+
+ def generateURL(path: String): URL = {
+ new URL(s"http://localhost:$port/api/v1/$path")
}
def generateExpectation(name: String, path: String): Unit = {
@@ -233,13 +304,18 @@ object HistoryServerSuite {
}
def getContentAndCode(url: URL): (Int, Option[String], Option[String]) = {
+ val (code, in, errString) = connectAndGetInputStream(url)
+ val inString = in.map(IOUtils.toString)
+ (code, inString, errString)
+ }
+
+ def connectAndGetInputStream(url: URL): (Int, Option[InputStream], Option[String]) = {
val connection = url.openConnection().asInstanceOf[HttpURLConnection]
connection.setRequestMethod("GET")
connection.connect()
val code = connection.getResponseCode()
- val inString = try {
- val in = Option(connection.getInputStream())
- in.map(IOUtils.toString)
+ val inStream = try {
+ Option(connection.getInputStream())
} catch {
case io: IOException => None
}
@@ -249,7 +325,7 @@ object HistoryServerSuite {
} catch {
case io: IOException => None
}
- (code, inString, errString)
+ (code, inStream, errString)
}