eu.stratosphere.nephele.jobmanager.web.JobmanagerInfoServlet Maven / Gradle / Ivy
/***********************************************************************************************************************
* Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
**********************************************************************************************************************/
package eu.stratosphere.nephele.jobmanager.web;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.io.EofException;
import eu.stratosphere.api.common.accumulators.AccumulatorHelper;
import eu.stratosphere.nephele.event.job.AbstractEvent;
import eu.stratosphere.nephele.event.job.ExecutionStateChangeEvent;
import eu.stratosphere.nephele.event.job.JobEvent;
import eu.stratosphere.nephele.event.job.RecentJobEvent;
import eu.stratosphere.nephele.execution.ExecutionState;
import eu.stratosphere.nephele.jobgraph.JobID;
import eu.stratosphere.nephele.jobgraph.JobStatus;
import eu.stratosphere.nephele.jobmanager.JobManager;
import eu.stratosphere.nephele.managementgraph.ManagementGraph;
import eu.stratosphere.nephele.managementgraph.ManagementGraphIterator;
import eu.stratosphere.nephele.managementgraph.ManagementGroupVertex;
import eu.stratosphere.nephele.managementgraph.ManagementGroupVertexID;
import eu.stratosphere.nephele.managementgraph.ManagementVertex;
import eu.stratosphere.nephele.services.accumulators.AccumulatorEvent;
import eu.stratosphere.util.StringUtils;
public class JobmanagerInfoServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* The log for this class.
*/
private static final Log LOG = LogFactory.getLog(JobmanagerInfoServlet.class);
/**
* Underlying JobManager
*/
private final JobManager jobmanager;
public JobmanagerInfoServlet(JobManager jobmanager) {
this.jobmanager = jobmanager;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("application/json");
try {
if("archive".equals(req.getParameter("get"))) {
writeJsonForArchive(resp.getWriter(), jobmanager.getOldJobs());
}
else if("job".equals(req.getParameter("get"))) {
String jobId = req.getParameter("job");
writeJsonForArchivedJob(resp.getWriter(), jobmanager.getArchive().getJob(JobID.fromHexString(jobId)));
}
else if("groupvertex".equals(req.getParameter("get"))) {
String jobId = req.getParameter("job");
String groupvertexId = req.getParameter("groupvertex");
writeJsonForArchivedJobGroupvertex(resp.getWriter(), jobmanager.getArchive().getJob(JobID.fromHexString(jobId)), ManagementGroupVertexID.fromHexString(groupvertexId));
}
else if("taskmanagers".equals(req.getParameter("get"))) {
resp.getWriter().write("{\"taskmanagers\": " + jobmanager.getNumberOfTaskTrackers() +"}");
}
else if("cancel".equals(req.getParameter("get"))) {
String jobId = req.getParameter("job");
jobmanager.cancelJob(JobID.fromHexString(jobId));
}
else if("updates".equals(req.getParameter("get"))) {
String jobId = req.getParameter("job");
writeJsonUpdatesForJob(resp.getWriter(), JobID.fromHexString(jobId));
}
else{
writeJsonForJobs(resp.getWriter(), jobmanager.getRecentJobs());
}
} catch (Exception e) {
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
resp.getWriter().print(e.getMessage());
if (LOG.isWarnEnabled()) {
LOG.warn(StringUtils.stringifyException(e));
}
}
}
/**
* Writes ManagementGraph as Json for all recent jobs
*
* @param wrt
* @param jobs
*/
private void writeJsonForJobs(PrintWriter wrt, List jobs) {
try {
wrt.write("[");
// Loop Jobs
for (int i = 0; i < jobs.size(); i++) {
RecentJobEvent jobEvent = jobs.get(i);
writeJsonForJob(wrt, jobEvent);
//Write seperator between json objects
if(i != jobs.size() - 1) {
wrt.write(",");
}
}
wrt.write("]");
} catch (EofException eof) { // Connection closed by client
LOG.info("Info server for jobmanager: Connection closed by client, EofException");
} catch (IOException ioe) { // Connection closed by client
LOG.info("Info server for jobmanager: Connection closed by client, IOException");
}
}
private void writeJsonForJob(PrintWriter wrt, RecentJobEvent jobEvent) throws IOException {
ManagementGraph jobManagementGraph = jobmanager.getManagementGraph(jobEvent.getJobID());
//Serialize job to json
wrt.write("{");
wrt.write("\"jobid\": \"" + jobEvent.getJobID() + "\",");
wrt.write("\"jobname\": \"" + jobEvent.getJobName()+"\",");
wrt.write("\"status\": \""+ jobEvent.getJobStatus() + "\",");
wrt.write("\"time\": " + jobEvent.getTimestamp()+",");
// Serialize ManagementGraph to json
wrt.write("\"groupvertices\": [");
boolean first = true;
for(ManagementGroupVertex groupVertex : jobManagementGraph.getGroupVerticesInTopologicalOrder()) {
//Write seperator between json objects
if(first) {
first = false;
} else {
wrt.write(","); }
wrt.write(groupVertex.toJson());
}
wrt.write("]");
wrt.write("}");
}
/**
* Writes Json with a list of currently archived jobs, sorted by time
*
* @param wrt
* @param jobs
*/
private void writeJsonForArchive(PrintWriter wrt, List jobs) {
wrt.write("[");
// sort jobs by time
Collections.sort(jobs, new Comparator() {
@Override
public int compare(RecentJobEvent o1, RecentJobEvent o2) {
if(o1.getTimestamp() < o2.getTimestamp()) {
return 1;
} else {
return -1;
}
}
});
// Loop Jobs
for (int i = 0; i < jobs.size(); i++) {
RecentJobEvent jobEvent = jobs.get(i);
//Serialize job to json
wrt.write("{");
wrt.write("\"jobid\": \"" + jobEvent.getJobID() + "\",");
wrt.write("\"jobname\": \"" + jobEvent.getJobName()+"\",");
wrt.write("\"status\": \""+ jobEvent.getJobStatus() + "\",");
wrt.write("\"time\": " + jobEvent.getTimestamp());
wrt.write("}");
//Write seperator between json objects
if(i != jobs.size() - 1) {
wrt.write(",");
}
}
wrt.write("]");
}
/**
* Writes infos about archived job in Json format, including groupvertices and groupverticetimes
*
* @param wrt
* @param jobEvent
*/
private void writeJsonForArchivedJob(PrintWriter wrt, RecentJobEvent jobEvent) {
try {
wrt.write("[");
ManagementGraph jobManagementGraph = jobmanager.getManagementGraph(jobEvent.getJobID());
//Serialize job to json
wrt.write("{");
wrt.write("\"jobid\": \"" + jobEvent.getJobID() + "\",");
wrt.write("\"jobname\": \"" + jobEvent.getJobName()+"\",");
wrt.write("\"status\": \""+ jobEvent.getJobStatus() + "\",");
wrt.write("\"SCHEDULED\": "+ jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.SCHEDULED) + ",");
wrt.write("\"RUNNING\": "+ jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.RUNNING) + ",");
wrt.write("\"FINISHED\": "+ jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.FINISHED) + ",");
wrt.write("\"FAILED\": "+ jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.FAILED) + ",");
wrt.write("\"CANCELED\": "+ jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.CANCELED) + ",");
wrt.write("\"CREATED\": " + jobmanager.getArchive().getJobTime(jobEvent.getJobID(), JobStatus.CREATED)+",");
if (jobEvent.getJobStatus() == JobStatus.FAILED) {
ManagementGraphIterator managementGraphIterator = new ManagementGraphIterator(jobManagementGraph,true);
wrt.write("\"failednodes\": [");
HashSet map = new HashSet();
boolean first = true;
while (managementGraphIterator.hasNext()) {
ManagementVertex managementVertex = managementGraphIterator.next();
String instanceName = managementVertex.getInstanceName();
if (managementVertex.getExecutionState() == ExecutionState.FAILED && !map.contains(instanceName)) {
if (first) {
first = false;
} else {
wrt.write(",");
}
wrt.write("{");
wrt.write("\"node\": \"" + instanceName + "\",");
wrt.write("\"message\": \"" + StringUtils.escapeHtml(managementVertex.getOptMessage()) + "\"");
wrt.write("}");
map.add(instanceName);
}
}
wrt.write("],");
}
// Serialize ManagementGraph to json
wrt.write("\"groupvertices\": [");
boolean first = true;
for(ManagementGroupVertex groupVertex : jobManagementGraph.getGroupVerticesInTopologicalOrder()) {
//Write seperator between json objects
if(first) {
first = false;
} else {
wrt.write(","); }
wrt.write(groupVertex.toJson());
}
wrt.write("],");
// write accumulators
AccumulatorEvent accumulators = jobmanager.getAccumulatorResults(jobEvent.getJobID());
Map accMap = AccumulatorHelper.toResultMap(accumulators.getAccumulators());
wrt.write("\n\"accumulators\": [");
int i = 0;
for( Entry accumulator : accMap.entrySet()) {
wrt.write("{ \"name\": \""+accumulator.getKey()+" (" + accumulator.getValue().getClass().getName()+")\","
+ " \"value\": \""+accumulator.getValue().toString()+"\"}\n");
if(++i < accMap.size()) {
wrt.write(",");
}
}
wrt.write("],\n");
wrt.write("\"groupverticetimes\": {");
first = true;
for(ManagementGroupVertex groupVertex : jobManagementGraph.getGroupVerticesInTopologicalOrder()) {
if(first) {
first = false;
} else {
wrt.write(","); }
// Calculate start and end time for groupvertex
long started = Long.MAX_VALUE;
long ended = 0;
// Take earliest running state and latest endstate of groupmembers
for(int j = 0; j < groupVertex.getNumberOfGroupMembers(); j++) {
ManagementVertex vertex = groupVertex.getGroupMember(j);
long running = jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.RUNNING);
if(running != 0 && running < started) {
started = running;
}
long finished = jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.FINISHED);
long canceled = jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.CANCELED);
long failed = jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.FAILED);
if(finished != 0 && finished > ended) {
ended = finished;
}
if(canceled != 0 && canceled > ended) {
ended = canceled;
}
if(failed != 0 && failed > ended) {
ended = failed;
}
}
wrt.write("\""+groupVertex.getID()+"\": {");
wrt.write("\"groupvertexid\": \"" + groupVertex.getID() + "\",");
wrt.write("\"groupvertexname\": \"" + groupVertex + "\",");
wrt.write("\"STARTED\": "+ started + ",");
wrt.write("\"ENDED\": "+ ended);
wrt.write("}");
}
wrt.write("}");
wrt.write("}");
wrt.write("]");
} catch (EofException eof) { // Connection closed by client
LOG.info("Info server for jobmanager: Connection closed by client, EofException");
} catch (IOException ioe) { // Connection closed by client
LOG.info("Info server for jobmanager: Connection closed by client, IOException");
}
}
/**
* Writes all updates (events) for a given job since a given time
*
* @param wrt
* @param jobId
*/
private void writeJsonUpdatesForJob(PrintWriter wrt, JobID jobId) {
try {
List events = jobmanager.getEvents(jobId);
//Serialize job to json
wrt.write("{");
wrt.write("\"jobid\": \"" + jobId + "\",");
wrt.write("\"timestamp\": \"" + System.currentTimeMillis() + "\",");
wrt.write("\"recentjobs\": [");
boolean first = true;
for(RecentJobEvent rje: jobmanager.getRecentJobs()) {
if(first) {
first = false;
} else {
wrt.write(","); }
wrt.write("\""+rje.getJobID().toString()+"\"");
}
wrt.write("],");
wrt.write("\"vertexevents\": [");
first = true;
for(AbstractEvent event: events) {
if(event instanceof ExecutionStateChangeEvent) {
if(first) {
first = false;
} else {
wrt.write(","); }
ExecutionStateChangeEvent vertexevent = (ExecutionStateChangeEvent) event;
wrt.write("{");
wrt.write("\"vertexid\": \"" + vertexevent.getVertexID() + "\",");
wrt.write("\"newstate\": \"" + vertexevent.getNewExecutionState() + "\",");
wrt.write("\"timestamp\": \"" + vertexevent.getTimestamp() + "\"");
wrt.write("}");
}
}
wrt.write("],");
wrt.write("\"jobevents\": [");
first = true;
for(AbstractEvent event: events) {
if( event instanceof JobEvent) {
if(first) {
first = false;
} else {
wrt.write(","); }
JobEvent jobevent = (JobEvent) event;
wrt.write("{");
wrt.write("\"newstate\": \"" + jobevent.getCurrentJobStatus() + "\",");
wrt.write("\"timestamp\": \"" + jobevent.getTimestamp() + "\"");
wrt.write("}");
}
}
wrt.write("]");
wrt.write("}");
} catch (EofException eof) { // Connection closed by client
LOG.info("Info server for jobmanager: Connection closed by client, EofException");
} catch (IOException ioe) { // Connection closed by client
LOG.info("Info server for jobmanager: Connection closed by client, IOException");
}
}
/**
* Writes infos about one particular archived groupvertex in a job, including all groupmembers, their times and status
*
* @param wrt
* @param jobEvent
* @param groupvertexId
*/
private void writeJsonForArchivedJobGroupvertex(PrintWriter wrt, RecentJobEvent jobEvent, ManagementGroupVertexID groupvertexId) {
try {
ManagementGraph jobManagementGraph = jobmanager.getManagementGraph(jobEvent.getJobID());
ManagementGroupVertex groupvertex = jobManagementGraph.getGroupVertexByID(groupvertexId);
// Serialize ManagementGraph to json
wrt.write("{\"groupvertex\": "+groupvertex.toJson()+",");
wrt.write("\"verticetimes\": {");
boolean first = true;
for(ManagementGroupVertex groupVertex : jobManagementGraph.getGroupVerticesInTopologicalOrder()) {
for(int j = 0; j < groupVertex.getNumberOfGroupMembers(); j++) {
ManagementVertex vertex = groupVertex.getGroupMember(j);
if(first) {
first = false;
} else {
wrt.write(","); }
wrt.write("\""+vertex.getID()+"\": {");
wrt.write("\"vertexid\": \"" + vertex.getID() + "\",");
wrt.write("\"vertexname\": \"" + vertex + "\",");
wrt.write("\"CREATED\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.CREATED) + ",");
wrt.write("\"SCHEDULED\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.SCHEDULED) + ",");
wrt.write("\"ASSIGNED\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.ASSIGNED) + ",");
wrt.write("\"READY\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.READY) + ",");
wrt.write("\"STARTING\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.STARTING) + ",");
wrt.write("\"RUNNING\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.RUNNING) + ",");
wrt.write("\"FINISHING\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.FINISHING) + ",");
wrt.write("\"FINISHED\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.FINISHED) + ",");
wrt.write("\"CANCELING\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.CANCELING) + ",");
wrt.write("\"CANCELED\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.CANCELED) + ",");
wrt.write("\"FAILED\": "+ jobmanager.getArchive().getVertexTime(jobEvent.getJobID(), vertex.getID(), ExecutionState.FAILED) + "");
wrt.write("}");
}
}
wrt.write("}}");
} catch (EofException eof) { // Connection closed by client
LOG.info("Info server for jobmanager: Connection closed by client, EofException");
} catch (IOException ioe) { // Connection closed by client
LOG.info("Info server for jobmanager: Connection closed by client, IOException");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy