Index: src/webapps/job/stats-api.jsp =================================================================== --- src/webapps/job/stats-api.jsp (revision 0) +++ src/webapps/job/stats-api.jsp (revision 0) @@ -0,0 +1,461 @@ +<%@ page contentType="text/html; charset=UTF-8" import="javax.servlet.*" + import="javax.servlet.http.*" import="java.io.*" import="java.text.*" + import="java.util.*" import="java.text.DecimalFormat" + import="org.apache.hadoop.mapred.*" import="org.apache.hadoop.util.*" + import="org.apache.hadoop.fs.*" + import="org.apache.hadoop.mapred.JobHistory.*"%> +<% + JobTracker tracker = (JobTracker) application + .getAttribute("job.tracker"); + PathFilter jobLogFileFilter = new PathFilter() { + public boolean accept(Path path) { + return !(path.getName().endsWith(".xml")); + } + }; + + FileSystem fs = (FileSystem) application.getAttribute("fileSys"); + String historyLogDir = (String) application + .getAttribute("historyLogDir"); + if (fs == null) { + out + .println("Null file system. May be namenode is in safemode!"); + return; + } + + JobStatus[] all_jobs; + String jobname = request.getParameter("id"); + String type = request.getParameter("info"); + if (type == null + || (!type.equals("jobdetails") && !type + .equals("taskdetails"))) { + return; + } + JobID id = null; + all_jobs = tracker.getAllJobs(); + + for (JobStatus status : all_jobs) { + id = status.getJobID(); + + if (id.getId() == (Integer.parseInt(jobname))) { + break; + } else { + id = null; + } + } + if (id != null) { + + Path[] jobFiles = FileUtil.stat2Paths(fs.listStatus(new Path( + historyLogDir), jobLogFileFilter)); + + String selectedHistoryFile = null; + Path selectedFullPath = null; + String idstr = null; + for (Path jobFile : jobFiles) { + String decodedJobFileName = JobHistory.JobInfo + .decodeJobHistoryFileName(jobFile.getName()); + String encodedJobFileName = JobHistory.JobInfo + .encodeJobHistoryFileName(jobFile.getName()); + + String[] jobDetails = decodedJobFileName.split("_"); + int idnum = Integer.parseInt(jobDetails[4]); + if (idnum == id.getId()) { + idstr = jobDetails[2] + "_" + jobDetails[3] + "_" + + jobDetails[4]; + selectedHistoryFile = decodedJobFileName; + + selectedFullPath = new Path(jobFile.getParent(), + jobFile.getName()); + break; + } + + } + + JobInfo jobInfo = new JobHistory.JobInfo(idstr); + + DefaultJobHistoryParser.parseJobTasks(selectedFullPath + .toString(), jobInfo, fs); + + Map all_task_in_file = jobInfo + .getAllTasks(); + + if (type.equals("taskdetails")) { + List tasksCounterList = new LinkedList(); + for (JobHistory.Task task : all_task_in_file.values()) { + Map attempts = task + .getTaskAttempts(); + for (JobHistory.TaskAttempt attempt : attempts.values()) { + if (attempt.get(Keys.TASK_STATUS).equals( + Values.SUCCESS.name())) { + long avgFinishTime = (attempt + .getLong(Keys.FINISH_TIME) - attempt + .getLong(Keys.START_TIME)); + + TaskID tipidObj = TaskID.forName(attempt + .get(Keys.TASKID)); + + StringBuilder sb = new StringBuilder(); + Counters taskCounters = tracker + .getTipCounters(tipidObj); + sb.append("{ \"task_id\":\""); + sb.append(tipidObj); + sb.append("\","); + sb.append("\"time_delta\":\""); + sb.append(avgFinishTime); + sb.append("\","); + if (taskCounters != null) { + for (String groupName : taskCounters + .getGroupNames()) { + Counters.Group group = taskCounters + .getGroup(groupName); + String displayGroupName = group + .getDisplayName(); + for (Counters.Counter counter : group) { + String displayCounterName = counter + .getDisplayName() + .replaceAll(" ", "_") + .toLowerCase(); + long value = counter.getCounter(); + sb.append("\"" + displayCounterName + + "\":\"" + value + "\","); + } + } + } + sb.delete(sb.length() - 1, sb.length()); + sb.append("}"); + tasksCounterList.add(sb.toString()); + } + } + } + out.print("{ \"taskdetails\": ["); + int i = 0; + for (String kv : tasksCounterList) { + i++; + out.print(kv + + ((i < tasksCounterList.size()) ? "," : "")); + } + + out.print(" ] } "); + return; + } else if (type.equals("jobdetails")) { + + // + List kv_pairs = new LinkedList(); + + int finishedMaps = jobInfo.getInt(Keys.FINISHED_MAPS); + int finishedReduces = jobInfo.getInt(Keys.FINISHED_REDUCES); + JobHistory.Task[] mapTasks = new JobHistory.Task[finishedMaps]; + JobHistory.Task[] reduceTasks = new JobHistory.Task[finishedReduces]; + int mapIndex = 0, reduceIndex = 0; + long avgMapTime = 0; + long avgReduceTime = 0; + long avgShuffleTime = 0; + for (JobHistory.Task task : all_task_in_file.values()) { + Map attempts = task + .getTaskAttempts(); + for (JobHistory.TaskAttempt attempt : attempts.values()) { + if (attempt.get(Keys.TASK_STATUS).equals( + Values.SUCCESS.name())) { + long avgFinishTime = (attempt + .getLong(Keys.FINISH_TIME) - attempt + .getLong(Keys.START_TIME)); + if (Values.MAP.name().equals( + task.get(Keys.TASK_TYPE))) { + mapTasks[mapIndex++] = attempt; + avgMapTime += avgFinishTime; + } else { + reduceTasks[reduceIndex++] = attempt; + avgShuffleTime += (attempt + .getLong(Keys.SHUFFLE_FINISHED) - attempt + .getLong(Keys.START_TIME)); + avgReduceTime += (attempt + .getLong(Keys.FINISH_TIME) - attempt + .getLong(Keys.SHUFFLE_FINISHED)); + } + break; + } + } + } + + Comparator cShuffle = new Comparator() { + public int compare(JobHistory.Task t1, + JobHistory.Task t2) { + long l1 = t1.getLong(Keys.SHUFFLE_FINISHED) + - t1.getLong(Keys.START_TIME); + long l2 = t2.getLong(Keys.SHUFFLE_FINISHED) + - t2.getLong(Keys.START_TIME); + return (l2 < l1 ? -1 : (l2 == l1 ? 0 : 1)); + } + }; + + Comparator cFinishMapRed = new Comparator() { + public int compare(JobHistory.Task t1, + JobHistory.Task t2) { + long l1 = t1.getLong(Keys.FINISH_TIME); + long l2 = t2.getLong(Keys.FINISH_TIME); + return (l2 < l1 ? -1 : (l2 == l1 ? 0 : 1)); + } + }; + Arrays.sort(mapTasks, cFinishMapRed); + JobHistory.Task lastMap = mapTasks[0]; + + Arrays.sort(reduceTasks, cFinishMapRed); + JobHistory.Task lastReduce = reduceTasks[0]; + + Comparator cFinishShuffle = new Comparator() { + public int compare(JobHistory.Task t1, + JobHistory.Task t2) { + long l1 = t1.getLong(Keys.SHUFFLE_FINISHED); + long l2 = t2.getLong(Keys.SHUFFLE_FINISHED); + return (l2 < l1 ? -1 : (l2 == l1 ? 0 : 1)); + } + }; + Arrays.sort(reduceTasks, cFinishShuffle); + JobHistory.Task lastShuffle = reduceTasks[0]; + + long jobLaunch = jobInfo.getLong(Keys.LAUNCH_TIME); + long jobFinish = jobInfo.getLong(Keys.FINISH_TIME); + long jobDelta = jobFinish - jobLaunch; + long lastShuffleTask = lastShuffle + .getLong(Keys.SHUFFLE_FINISHED) + - jobInfo.getLong(Keys.LAUNCH_TIME); + long lastMapTask = lastMap.getLong(Keys.FINISH_TIME) + - jobInfo.getLong(Keys.LAUNCH_TIME); + long lastReduceTask = lastReduce.getLong(Keys.FINISH_TIME) + - jobInfo.getLong(Keys.LAUNCH_TIME); + String lastShuffleStr = "\"last_shuffle_time_delta\":\"" + + lastShuffleTask + "\""; + String lastMapStr = "\"last_map_time_delta\":\"" + + lastMapTask + "\""; + String lastRedStr = "\"last_red_time_delta\":\"" + + lastReduceTask + "\""; + String jobLaunchStr = "\"job_start_time\":\"" + jobLaunch + + "\""; + String jobFinishStr = "\"job_finish_time\":\"" + jobFinish + + "\""; + String jobDeltaStr = "\"job_delta_time\":\"" + jobDelta + + "\""; + kv_pairs.add(jobLaunchStr); + kv_pairs.add(jobFinishStr); + kv_pairs.add(jobDeltaStr); + kv_pairs.add(lastShuffleStr); + kv_pairs.add(lastMapStr); + kv_pairs.add(lastRedStr); + + Comparator cReduce = new Comparator() { + public int compare(JobHistory.Task t1, + JobHistory.Task t2) { + long l1 = t1.getLong(Keys.FINISH_TIME) + - t1.getLong(Keys.SHUFFLE_FINISHED); + long l2 = t2.getLong(Keys.FINISH_TIME) + - t2.getLong(Keys.SHUFFLE_FINISHED); + return (l2 < l1 ? -1 : (l2 == l1 ? 0 : 1)); + } + }; + Arrays.sort(reduceTasks, cReduce); + JobHistory.Task minReduce = reduceTasks[reduceTasks.length - 1]; + long realWorstReduce = reduceTasks[0] + .getLong(Keys.FINISH_TIME) + - reduceTasks[0].getLong(Keys.SHUFFLE_FINISHED); + String realWorstReduceStr = "\"real_max_reduce_time\":\"" + + realWorstReduce + "\""; + kv_pairs.add(realWorstReduceStr); + long realBestReduce = minReduce.getLong(Keys.FINISH_TIME) + - minReduce.getLong(Keys.SHUFFLE_FINISHED); + String realBestReduceStr = "\"real_min_reduce_time\":\"" + + realBestReduce + "\""; + kv_pairs.add(realBestReduceStr); + long cumReduce = 0; + for (org.apache.hadoop.mapred.JobHistory.Task redTmp : reduceTasks) { + cumReduce += redTmp.getLong(Keys.FINISH_TIME) + - redTmp.getLong(Keys.SHUFFLE_FINISHED); + } + float realMeanReduce = ((float) cumReduce) + / ((float) reduceTasks.length); + String realMeanReduceStr = "\"real_mean_reduce_time\":\"" + + realMeanReduce + "\""; + kv_pairs.add(realMeanReduceStr); + + if (reduceTasks.length > 0) { + Arrays.sort(reduceTasks, cShuffle); + JobHistory.Task minShuffle = reduceTasks[reduceTasks.length - 1]; + long minShuffleTime = minShuffle + .getLong(Keys.SHUFFLE_FINISHED) + - minShuffle.getLong(Keys.START_TIME); + int showTasks = 10; + long worstSuffle = Long.MIN_VALUE; + for (int i = 0; i < showTasks && i < reduceTasks.length; i++) { + long cur = reduceTasks[i] + .getLong(Keys.SHUFFLE_FINISHED) + - reduceTasks[i].getLong(Keys.START_TIME); + if (cur > worstSuffle) + worstSuffle = cur; + } + + if (finishedReduces > 0) { + avgReduceTime /= finishedReduces; + avgShuffleTime /= finishedReduces; + } + + String shuffle_max_tmp = "\"max_shuffle\":\"" + + worstSuffle + "\""; + String shuffle_min_tmp = "\"min_shuffle\":\"" + + minShuffleTime + "\""; + String shuffle_avg_tmp = "\"mean_shuffle\":\"" + + avgShuffleTime + "\""; + kv_pairs.add(shuffle_avg_tmp); + kv_pairs.add(shuffle_min_tmp); + kv_pairs.add(shuffle_max_tmp); + } + //END NF + + JobInProgress job = (JobInProgress) tracker.getJob(id); + TaskInProgress[] map_tasks = job.getMapTasks(); + TaskInProgress[] red_tasks = job.getReduceTasks(); + TaskReport[] red_reports = tracker.getReduceTaskReports(id); + TaskReport[] map_reports = tracker.getMapTaskReports(id); + ClusterStatus status = tracker.getClusterStatus(); + + int nodes = status.getTaskTrackers(); + int map_task_capacity = status.getMaxMapTasks(); + int red_task_capacity = status.getMaxReduceTasks(); + + String nodeCount = "\"node_count\":\"" + nodes + "\""; + String map_cap = "\"map_task_capacity\":\"" + + map_task_capacity + "\""; + String red_cap = "\"reduce_task_capacity\":\"" + + red_task_capacity + "\""; + kv_pairs.add(nodeCount); + kv_pairs.add(map_cap); + kv_pairs.add(red_cap); + + int m_totalTasks = map_tasks.length; + int m_runningTasks = 0; + int m_finishedTasks = 0; + int m_killedTasks = 0; + int m_failedTaskAttempts = 0; + int m_killedTaskAttempts = 0; + for (int i = 0; i < m_totalTasks; ++i) { + TaskInProgress task = map_tasks[i]; + + if (task.isComplete()) { + m_finishedTasks += 1; + } else if (task.isRunning()) { + m_runningTasks += 1; + } else if (task.wasKilled()) { + m_killedTasks += 1; + } + m_failedTaskAttempts += task.numTaskFailures(); + m_killedTaskAttempts += task.numKilledTasks(); + } + int r_totalTasks = red_tasks.length; + int r_runningTasks = 0; + int r_finishedTasks = 0; + int r_killedTasks = 0; + int r_failedTaskAttempts = 0; + int r_killedTaskAttempts = 0; + for (int i = 0; i < r_totalTasks; ++i) { + TaskInProgress task = red_tasks[i]; + if (task.isComplete()) { + r_finishedTasks += 1; + } else if (task.isRunning()) { + r_runningTasks += 1; + } else if (task.wasKilled()) { + r_killedTasks += 1; + } + r_failedTaskAttempts += task.numTaskFailures(); + r_killedTaskAttempts += task.numKilledTasks(); + } + long max_map = 0l; + long min_map = Long.MAX_VALUE; + long mean_map = 0; + for (int i = 0; i < map_reports.length; ++i) { + TaskReport report = map_reports[i]; + long delta = report.getFinishTime() + - report.getStartTime(); + max_map = Math.max(max_map, delta); + min_map = Math.min(min_map, delta); + mean_map += delta; + } + mean_map = mean_map / ((long) map_reports.length); + + long max_red = 0; + long min_red = Long.MAX_VALUE; + long mean_red = 0; + for (int i = 0; i < red_reports.length; ++i) { + TaskReport report = red_reports[i]; + long delta = report.getFinishTime() + - report.getStartTime(); + max_red = Math.max(max_red, delta); + min_red = Math.min(min_red, delta); + mean_red += delta; + } + mean_red = mean_red / ((long) red_reports.length); + + long total_running_time = job.getFinishTime() + - job.getStartTime(); + + Counters mapCounters = job.getMapCounters(); + Counters reduceCounters = job.getReduceCounters(); + Counters totalCounters = job.getCounters(); + + for (String groupName : totalCounters.getGroupNames()) { + Counters.Group totalGroup = totalCounters + .getGroup(groupName); + Counters.Group mapGroup = mapCounters + .getGroup(groupName); + Counters.Group reduceGroup = reduceCounters + .getGroup(groupName); + + Format decimal = new DecimalFormat(); + for (Counters.Counter counter : totalGroup) { + String name = counter.getDisplayName(); + String mapValue = decimal.format(mapGroup + .getCounter(name)); + String reduceValue = decimal.format(reduceGroup + .getCounter(name)); + String totalValue = decimal.format(counter + .getCounter()); + String map_tmp = "\"map_" + + name.toLowerCase().replace(" ", "_") + + "\":\"" + mapValue + "\""; + String red_tmp = "\"red_" + + name.toLowerCase().replace(" ", "_") + + "\":\"" + reduceValue + "\""; + String total_tmp = "\"total_" + + name.toLowerCase().replace(" ", "_") + + "\":\"" + totalValue + "\""; + kv_pairs.add(map_tmp); + kv_pairs.add(red_tmp); + kv_pairs.add(total_tmp); + } + } + + StringBuffer sb = new StringBuffer(); + boolean isFirst = true; + //Map tasks = job.getAllTasks(); + + out.println("{ \"total_reduce_tasks\":\"" + r_totalTasks + + "\", \"failed_reduce_tasks\":\"" + + r_failedTaskAttempts + + "\", \"total_map_tasks\":\"" + m_totalTasks + + "\", \"failed_map_tasks\":\"" + + m_failedTaskAttempts + "\", \"running_time\":\"" + + total_running_time + + "\", \"mean_map_task_time\":\"" + mean_map + + "\", \"max_map_task_time\":\"" + max_map + + "\", \"min_map_task_time\":\"" + min_map + + "\", \"mean_red_task_time\":\"" + mean_red + + "\", \"min_red_task_time\":\"" + min_red + + "\", \"max_red_task_time\":\"" + max_red + "\","); + + for (String kv : kv_pairs) { + out.print(kv + ", "); + } + out.print("}"); + + } + + // + + } +%>