All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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