Skip to content

Commit ea542d2

Browse files
jiangxb1987gatorsmile
authored andcommitted
[SPARK-19824][CORE] Update JsonProtocol to keep consistent with the UI
## What changes were proposed in this pull request? Fix any inconsistent part in JsonProtocol with the UI. This PR also contains the modifications in #17181 ## How was this patch tested? Updated JsonProtocolSuite. Before this change, localhost:8080/json shows: ``` { "url" : "spark://xingbos-MBP.local:7077", "workers" : [ { "id" : "worker-20170615172946-192.168.0.101-49450", "host" : "192.168.0.101", "port" : 49450, "webuiaddress" : "http://192.168.0.101:8081", "cores" : 8, "coresused" : 8, "coresfree" : 0, "memory" : 15360, "memoryused" : 1024, "memoryfree" : 14336, "state" : "ALIVE", "lastheartbeat" : 1497519481722 }, { "id" : "worker-20170615172948-192.168.0.101-49452", "host" : "192.168.0.101", "port" : 49452, "webuiaddress" : "http://192.168.0.101:8082", "cores" : 8, "coresused" : 8, "coresfree" : 0, "memory" : 15360, "memoryused" : 1024, "memoryfree" : 14336, "state" : "ALIVE", "lastheartbeat" : 1497519484160 }, { "id" : "worker-20170615172951-192.168.0.101-49469", "host" : "192.168.0.101", "port" : 49469, "webuiaddress" : "http://192.168.0.101:8083", "cores" : 8, "coresused" : 8, "coresfree" : 0, "memory" : 15360, "memoryused" : 1024, "memoryfree" : 14336, "state" : "ALIVE", "lastheartbeat" : 1497519486905 } ], "cores" : 24, "coresused" : 24, "memory" : 46080, "memoryused" : 3072, "activeapps" : [ { "starttime" : 1497519426990, "id" : "app-20170615173706-0001", "name" : "Spark shell", "user" : "xingbojiang", "memoryperslave" : 1024, "submitdate" : "Thu Jun 15 17:37:06 CST 2017", "state" : "RUNNING", "duration" : 65362 } ], "completedapps" : [ { "starttime" : 1497519250893, "id" : "app-20170615173410-0000", "name" : "Spark shell", "user" : "xingbojiang", "memoryperslave" : 1024, "submitdate" : "Thu Jun 15 17:34:10 CST 2017", "state" : "FINISHED", "duration" : 116895 } ], "activedrivers" : [ ], "status" : "ALIVE" } ``` After the change: ``` { "url" : "spark://xingbos-MBP.local:7077", "workers" : [ { "id" : "worker-20170615175032-192.168.0.101-49951", "host" : "192.168.0.101", "port" : 49951, "webuiaddress" : "http://192.168.0.101:8081", "cores" : 8, "coresused" : 8, "coresfree" : 0, "memory" : 15360, "memoryused" : 1024, "memoryfree" : 14336, "state" : "ALIVE", "lastheartbeat" : 1497520292900 }, { "id" : "worker-20170615175034-192.168.0.101-49953", "host" : "192.168.0.101", "port" : 49953, "webuiaddress" : "http://192.168.0.101:8082", "cores" : 8, "coresused" : 8, "coresfree" : 0, "memory" : 15360, "memoryused" : 1024, "memoryfree" : 14336, "state" : "ALIVE", "lastheartbeat" : 1497520280301 }, { "id" : "worker-20170615175037-192.168.0.101-49955", "host" : "192.168.0.101", "port" : 49955, "webuiaddress" : "http://192.168.0.101:8083", "cores" : 8, "coresused" : 8, "coresfree" : 0, "memory" : 15360, "memoryused" : 1024, "memoryfree" : 14336, "state" : "ALIVE", "lastheartbeat" : 1497520282884 } ], "aliveworkers" : 3, "cores" : 24, "coresused" : 24, "memory" : 46080, "memoryused" : 3072, "activeapps" : [ { "id" : "app-20170615175122-0001", "starttime" : 1497520282115, "name" : "Spark shell", "cores" : 24, "user" : "xingbojiang", "memoryperslave" : 1024, "submitdate" : "Thu Jun 15 17:51:22 CST 2017", "state" : "RUNNING", "duration" : 10805 } ], "completedapps" : [ { "id" : "app-20170615175058-0000", "starttime" : 1497520258766, "name" : "Spark shell", "cores" : 24, "user" : "xingbojiang", "memoryperslave" : 1024, "submitdate" : "Thu Jun 15 17:50:58 CST 2017", "state" : "FINISHED", "duration" : 9876 } ], "activedrivers" : [ ], "completeddrivers" : [ ], "status" : "ALIVE" } ``` Author: Xingbo Jiang <[email protected]> Closes #18303 from jiangxb1987/json-protocol.
1 parent 112bd9b commit ea542d2

File tree

3 files changed

+149
-28
lines changed

3 files changed

+149
-28
lines changed

core/src/main/scala/org/apache/spark/deploy/JsonProtocol.scala

Lines changed: 137 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,74 +21,190 @@ import org.json4s.JsonAST.JObject
2121
import org.json4s.JsonDSL._
2222

2323
import org.apache.spark.deploy.DeployMessages.{MasterStateResponse, WorkerStateResponse}
24-
import org.apache.spark.deploy.master.{ApplicationInfo, DriverInfo, WorkerInfo}
24+
import org.apache.spark.deploy.master._
25+
import org.apache.spark.deploy.master.RecoveryState.MasterState
2526
import org.apache.spark.deploy.worker.ExecutorRunner
2627

2728
private[deploy] object JsonProtocol {
28-
def writeWorkerInfo(obj: WorkerInfo): JObject = {
29-
("id" -> obj.id) ~
30-
("host" -> obj.host) ~
31-
("port" -> obj.port) ~
32-
("webuiaddress" -> obj.webUiAddress) ~
33-
("cores" -> obj.cores) ~
34-
("coresused" -> obj.coresUsed) ~
35-
("coresfree" -> obj.coresFree) ~
36-
("memory" -> obj.memory) ~
37-
("memoryused" -> obj.memoryUsed) ~
38-
("memoryfree" -> obj.memoryFree) ~
39-
("state" -> obj.state.toString) ~
40-
("lastheartbeat" -> obj.lastHeartbeat)
41-
}
29+
/**
30+
* Export the [[WorkerInfo]] to a Json object. A [[WorkerInfo]] consists of the information of a
31+
* worker.
32+
*
33+
* @return a Json object containing the following fields:
34+
* `id` a string identifier of the worker
35+
* `host` the host that the worker is running on
36+
* `port` the port that the worker is bound to
37+
* `webuiaddress` the address used in web UI
38+
* `cores` total cores of the worker
39+
* `coresused` allocated cores of the worker
40+
* `coresfree` free cores of the worker
41+
* `memory` total memory of the worker
42+
* `memoryused` allocated memory of the worker
43+
* `memoryfree` free memory of the worker
44+
* `state` state of the worker, see [[WorkerState]]
45+
* `lastheartbeat` time in milliseconds that the latest heart beat message from the
46+
* worker is received
47+
*/
48+
def writeWorkerInfo(obj: WorkerInfo): JObject = {
49+
("id" -> obj.id) ~
50+
("host" -> obj.host) ~
51+
("port" -> obj.port) ~
52+
("webuiaddress" -> obj.webUiAddress) ~
53+
("cores" -> obj.cores) ~
54+
("coresused" -> obj.coresUsed) ~
55+
("coresfree" -> obj.coresFree) ~
56+
("memory" -> obj.memory) ~
57+
("memoryused" -> obj.memoryUsed) ~
58+
("memoryfree" -> obj.memoryFree) ~
59+
("state" -> obj.state.toString) ~
60+
("lastheartbeat" -> obj.lastHeartbeat)
61+
}
4262

63+
/**
64+
* Export the [[ApplicationInfo]] to a Json objec. An [[ApplicationInfo]] consists of the
65+
* information of an application.
66+
*
67+
* @return a Json object containing the following fields:
68+
* `id` a string identifier of the application
69+
* `starttime` time in milliseconds that the application starts
70+
* `name` the description of the application
71+
* `cores` total cores granted to the application
72+
* `user` name of the user who submitted the application
73+
* `memoryperslave` minimal memory in MB required to each executor
74+
* `submitdate` time in Date that the application is submitted
75+
* `state` state of the application, see [[ApplicationState]]
76+
* `duration` time in milliseconds that the application has been running
77+
*/
4378
def writeApplicationInfo(obj: ApplicationInfo): JObject = {
44-
("starttime" -> obj.startTime) ~
4579
("id" -> obj.id) ~
80+
("starttime" -> obj.startTime) ~
4681
("name" -> obj.desc.name) ~
47-
("cores" -> obj.desc.maxCores) ~
82+
("cores" -> obj.coresGranted) ~
4883
("user" -> obj.desc.user) ~
4984
("memoryperslave" -> obj.desc.memoryPerExecutorMB) ~
5085
("submitdate" -> obj.submitDate.toString) ~
5186
("state" -> obj.state.toString) ~
5287
("duration" -> obj.duration)
5388
}
5489

90+
/**
91+
* Export the [[ApplicationDescription]] to a Json object. An [[ApplicationDescription]] consists
92+
* of the description of an application.
93+
*
94+
* @return a Json object containing the following fields:
95+
* `name` the description of the application
96+
* `cores` max cores that can be allocated to the application, 0 means unlimited
97+
* `memoryperslave` minimal memory in MB required to each executor
98+
* `user` name of the user who submitted the application
99+
* `command` the command string used to submit the application
100+
*/
55101
def writeApplicationDescription(obj: ApplicationDescription): JObject = {
56102
("name" -> obj.name) ~
57-
("cores" -> obj.maxCores) ~
103+
("cores" -> obj.maxCores.getOrElse(0)) ~
58104
("memoryperslave" -> obj.memoryPerExecutorMB) ~
59105
("user" -> obj.user) ~
60106
("command" -> obj.command.toString)
61107
}
62108

109+
/**
110+
* Export the [[ExecutorRunner]] to a Json object. An [[ExecutorRunner]] consists of the
111+
* information of an executor.
112+
*
113+
* @return a Json object containing the following fields:
114+
* `id` an integer identifier of the executor
115+
* `memory` memory in MB allocated to the executor
116+
* `appid` a string identifier of the application that the executor is working on
117+
* `appdesc` a Json object of the [[ApplicationDescription]] of the application that the
118+
* executor is working on
119+
*/
63120
def writeExecutorRunner(obj: ExecutorRunner): JObject = {
64121
("id" -> obj.execId) ~
65122
("memory" -> obj.memory) ~
66123
("appid" -> obj.appId) ~
67124
("appdesc" -> writeApplicationDescription(obj.appDesc))
68125
}
69126

127+
/**
128+
* Export the [[DriverInfo]] to a Json object. A [[DriverInfo]] consists of the information of a
129+
* driver.
130+
*
131+
* @return a Json object containing the following fields:
132+
* `id` a string identifier of the driver
133+
* `starttime` time in milliseconds that the driver starts
134+
* `state` state of the driver, see [[DriverState]]
135+
* `cores` cores allocated to the driver
136+
* `memory` memory in MB allocated to the driver
137+
* `submitdate` time in Date that the driver is created
138+
* `worker` identifier of the worker that the driver is running on
139+
* `mainclass` main class of the command string that started the driver
140+
*/
70141
def writeDriverInfo(obj: DriverInfo): JObject = {
71142
("id" -> obj.id) ~
72143
("starttime" -> obj.startTime.toString) ~
73144
("state" -> obj.state.toString) ~
74145
("cores" -> obj.desc.cores) ~
75-
("memory" -> obj.desc.mem)
146+
("memory" -> obj.desc.mem) ~
147+
("submitdate" -> obj.submitDate.toString) ~
148+
("worker" -> obj.worker.map(_.id).getOrElse("None")) ~
149+
("mainclass" -> obj.desc.command.arguments(2))
76150
}
77151

152+
/**
153+
* Export the [[MasterStateResponse]] to a Json object. A [[MasterStateResponse]] consists the
154+
* information of a master node.
155+
*
156+
* @return a Json object containing the following fields:
157+
* `url` the url of the master node
158+
* `workers` a list of Json objects of [[WorkerInfo]] of the workers allocated to the
159+
* master
160+
* `aliveworkers` size of alive workers allocated to the master
161+
* `cores` total cores available of the master
162+
* `coresused` cores used by the master
163+
* `memory` total memory available of the master
164+
* `memoryused` memory used by the master
165+
* `activeapps` a list of Json objects of [[ApplicationInfo]] of the active applications
166+
* running on the master
167+
* `completedapps` a list of Json objects of [[ApplicationInfo]] of the applications
168+
* completed in the master
169+
* `activedrivers` a list of Json objects of [[DriverInfo]] of the active drivers of the
170+
* master
171+
* `completeddrivers` a list of Json objects of [[DriverInfo]] of the completed drivers
172+
* of the master
173+
* `status` status of the master, see [[MasterState]]
174+
*/
78175
def writeMasterState(obj: MasterStateResponse): JObject = {
79176
val aliveWorkers = obj.workers.filter(_.isAlive())
80177
("url" -> obj.uri) ~
81178
("workers" -> obj.workers.toList.map(writeWorkerInfo)) ~
179+
("aliveworkers" -> aliveWorkers.length) ~
82180
("cores" -> aliveWorkers.map(_.cores).sum) ~
83181
("coresused" -> aliveWorkers.map(_.coresUsed).sum) ~
84182
("memory" -> aliveWorkers.map(_.memory).sum) ~
85183
("memoryused" -> aliveWorkers.map(_.memoryUsed).sum) ~
86184
("activeapps" -> obj.activeApps.toList.map(writeApplicationInfo)) ~
87185
("completedapps" -> obj.completedApps.toList.map(writeApplicationInfo)) ~
88186
("activedrivers" -> obj.activeDrivers.toList.map(writeDriverInfo)) ~
187+
("completeddrivers" -> obj.completedDrivers.toList.map(writeDriverInfo)) ~
89188
("status" -> obj.status.toString)
90189
}
91190

191+
/**
192+
* Export the [[WorkerStateResponse]] to a Json object. A [[WorkerStateResponse]] consists the
193+
* information of a worker node.
194+
*
195+
* @return a Json object containing the following fields:
196+
* `id` a string identifier of the worker node
197+
* `masterurl` url of the master node of the worker
198+
* `masterwebuiurl` the address used in web UI of the master node of the worker
199+
* `cores` total cores of the worker
200+
* `coreused` used cores of the worker
201+
* `memory` total memory of the worker
202+
* `memoryused` used memory of the worker
203+
* `executors` a list of Json objects of [[ExecutorRunner]] of the executors running on
204+
* the worker
205+
* `finishedexecutors` a list of Json objects of [[ExecutorRunner]] of the finished
206+
* executors of the worker
207+
*/
92208
def writeWorkerState(obj: WorkerStateResponse): JObject = {
93209
("id" -> obj.workerId) ~
94210
("masterurl" -> obj.masterUrl) ~
@@ -97,7 +213,7 @@ private[deploy] object JsonProtocol {
97213
("coresused" -> obj.coresUsed) ~
98214
("memory" -> obj.memory) ~
99215
("memoryused" -> obj.memoryUsed) ~
100-
("executors" -> obj.executors.toList.map(writeExecutorRunner)) ~
101-
("finishedexecutors" -> obj.finishedExecutors.toList.map(writeExecutorRunner))
216+
("executors" -> obj.executors.map(writeExecutorRunner)) ~
217+
("finishedexecutors" -> obj.finishedExecutors.map(writeExecutorRunner))
102218
}
103219
}

core/src/test/scala/org/apache/spark/deploy/DeployTestUtils.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ private[deploy] object DeployTestUtils {
3939
}
4040

4141
def createDriverCommand(): Command = new Command(
42-
"org.apache.spark.FakeClass", Seq("some arg --and-some options -g foo"),
42+
"org.apache.spark.FakeClass", Seq("WORKER_URL", "USER_JAR", "mainClass"),
4343
Map(("K1", "V1"), ("K2", "V2")), Seq("cp1", "cp2"), Seq("lp1", "lp2"), Seq("-Dfoo")
4444
)
4545

4646
def createDriverDesc(): DriverDescription =
4747
new DriverDescription("hdfs://some-dir/some.jar", 100, 3, false, createDriverCommand())
4848

4949
def createDriverInfo(): DriverInfo = new DriverInfo(3, "driver-3",
50-
createDriverDesc(), new Date())
50+
createDriverDesc(), JsonConstants.submitDate)
5151

5252
def createWorkerInfo(): WorkerInfo = {
5353
val workerInfo = new WorkerInfo("id", "host", 8080, 4, 1234, null, "http://publicAddress:80")

core/src/test/scala/org/apache/spark/deploy/JsonProtocolSuite.scala

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ object JsonConstants {
104104
val submitDate = new Date(123456789)
105105
val appInfoJsonStr =
106106
"""
107-
|{"starttime":3,"id":"id","name":"name",
108-
|"cores":4,"user":"%s",
107+
|{"id":"id","starttime":3,"name":"name",
108+
|"cores":0,"user":"%s",
109109
|"memoryperslave":1234,"submitdate":"%s",
110110
|"state":"WAITING","duration":%d}
111111
""".format(System.getProperty("user.name", "<unknown>"),
@@ -134,19 +134,24 @@ object JsonConstants {
134134

135135
val driverInfoJsonStr =
136136
"""
137-
|{"id":"driver-3","starttime":"3","state":"SUBMITTED","cores":3,"memory":100}
138-
""".stripMargin
137+
|{"id":"driver-3","starttime":"3",
138+
|"state":"SUBMITTED","cores":3,"memory":100,
139+
|"submitdate":"%s","worker":"None",
140+
|"mainclass":"mainClass"}
141+
""".format(submitDate.toString).stripMargin
139142

140143
val masterStateJsonStr =
141144
"""
142145
|{"url":"spark://host:8080",
143146
|"workers":[%s,%s],
147+
|"aliveworkers":2,
144148
|"cores":8,"coresused":0,"memory":2468,"memoryused":0,
145149
|"activeapps":[%s],"completedapps":[],
146150
|"activedrivers":[%s],
151+
|"completeddrivers":[%s],
147152
|"status":"ALIVE"}
148153
""".format(workerInfoJsonStr, workerInfoJsonStr,
149-
appInfoJsonStr, driverInfoJsonStr).stripMargin
154+
appInfoJsonStr, driverInfoJsonStr, driverInfoJsonStr).stripMargin
150155

151156
val workerStateJsonStr =
152157
"""

0 commit comments

Comments
 (0)