Skip to content

Commit

Permalink
Tweaked the search page
Browse files Browse the repository at this point in the history
  • Loading branch information
lishid committed Apr 2, 2014
1 parent 38e7081 commit f070109
Show file tree
Hide file tree
Showing 26 changed files with 1,004 additions and 153 deletions.
19 changes: 13 additions & 6 deletions app/com/linkedin/drelephant/ElephantAnalyser.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,25 @@ public class ElephantAnalyser {
private static final Logger logger = Logger.getLogger(ElephantAnalyser.class);
private static final ElephantAnalyser instance = new ElephantAnalyser();


private HeuristicResult nodata;
private List<Heuristic> heuristics = new ArrayList<Heuristic>();
public List<String> heuristicNames = new ArrayList<String>();


public ElephantAnalyser() {
nodata = new HeuristicResult("No data received", Severity.LOW);
heuristics.add(new MapperDataSkewHeuristic());
heuristics.add(new ReducerDataSkewHeuristic());
heuristics.add(new MapperInputSizeHeuristic());
heuristics.add(new MapperSpeedHeuristic());
heuristics.add(new ReducerTimeHeuristic());
heuristics.add(new ShuffleSortHeuristic());
addHeuristic(new MapperDataSkewHeuristic());
addHeuristic(new ReducerDataSkewHeuristic());
addHeuristic(new MapperInputSizeHeuristic());
addHeuristic(new MapperSpeedHeuristic());
addHeuristic(new ReducerTimeHeuristic());
addHeuristic(new ShuffleSortHeuristic());
}

public void addHeuristic(Heuristic heuristic) {
heuristics.add(heuristic);
heuristicNames.add(heuristic.getHeuristicName());
}

public HeuristicResult[] analyse(HadoopJobData data) {
Expand Down
1 change: 1 addition & 0 deletions app/com/linkedin/drelephant/analysis/Heuristic.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

public interface Heuristic {
public HeuristicResult apply(HadoopJobData data);
public String getHeuristicName();
}
4 changes: 1 addition & 3 deletions app/com/linkedin/drelephant/analysis/HeuristicResult.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.linkedin.drelephant.analysis;

import java.util.ArrayList;
import java.util.List;
import java.util.*;

public class HeuristicResult {

private String analysis;
private Severity severity;
private List<String> details;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@

public abstract class GenericDataSkewHeuristic implements Heuristic {
private HadoopCounterHolder.CounterName counterName;
private String analysisName;
private String heuristicName;

protected GenericDataSkewHeuristic(HadoopCounterHolder.CounterName counterName, String analysisName) {
@Override
public String getHeuristicName() {
return heuristicName;
}

protected GenericDataSkewHeuristic(HadoopCounterHolder.CounterName counterName, String heuristicName) {
this.counterName = counterName;
this.analysisName = analysisName;
this.heuristicName = heuristicName;
}

protected abstract HadoopTaskData[] getTasks(HadoopJobData data);
Expand Down Expand Up @@ -49,7 +54,7 @@ public HeuristicResult apply(HadoopJobData data) {
//This reduces severity if number of tasks is insignificant
severity = Severity.min(severity, Statistics.getNumTasksSeverity(groups[0].length));

HeuristicResult result = new HeuristicResult(analysisName, severity);
HeuristicResult result = new HeuristicResult(heuristicName, severity);

result.addDetail("Number of tasks", Integer.toString(tasks.length));
result.addDetail("Group A: Number of tasks", Integer.toString(groups[0].length));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import com.linkedin.drelephant.hadoop.HadoopTaskData;

public class MapperDataSkewHeuristic extends GenericDataSkewHeuristic {
private static final String analysisName = "Mapper Data Skew";
private static final String heuristicName = "Mapper Data Skew";

public MapperDataSkewHeuristic() {
super(HadoopCounterHolder.CounterName.HDFS_BYTES_READ, analysisName);
super(HadoopCounterHolder.CounterName.HDFS_BYTES_READ, heuristicName);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
import org.apache.commons.io.FileUtils;

public class MapperInputSizeHeuristic implements Heuristic {
private static final String analysisName = "Mapper input size";
private static final String heuristicName = "Mapper input size";

@Override
public String getHeuristicName() {
return heuristicName;
}

@Override
public HeuristicResult apply(HadoopJobData data) {
Expand All @@ -34,7 +39,7 @@ public HeuristicResult apply(HadoopJobData data) {
//This reduces severity if number of tasks is insignificant
severity = Severity.min(severity, Statistics.getNumTasksSeverity(tasks.length));

HeuristicResult result = new HeuristicResult(analysisName, severity);
HeuristicResult result = new HeuristicResult(heuristicName, severity);

result.addDetail("Number of tasks", Integer.toString(tasks.length));
String deviationFactor = Statistics.describeFactor(average, Constants.HDFS_BLOCK_SIZE, "x");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
import org.apache.commons.io.FileUtils;

public class MapperSpeedHeuristic implements Heuristic {
private static final String analysisName = "Mapper Speed";
private static final String heuristicName = "Mapper Speed";

@Override
public String getHeuristicName() {
return heuristicName;
}

@Override
public HeuristicResult apply(HadoopJobData data) {
Expand Down Expand Up @@ -42,7 +47,7 @@ public HeuristicResult apply(HadoopJobData data) {
//This reduces severity if task runtime is insignificant
severity = Severity.min(severity, getRuntimeSeverity(averageRuntime));

HeuristicResult result = new HeuristicResult(analysisName, severity);
HeuristicResult result = new HeuristicResult(heuristicName, severity);

result.addDetail("Number of tasks", Integer.toString(tasks.length));
result.addDetail("Average mapper speed", FileUtils.byteCountToDisplaySize(averageSpeed) + "/s");
Expand All @@ -62,8 +67,8 @@ public static Severity getDiskSpeedSeverity(long speed) {
public static Severity getRuntimeSeverity(long runtime) {
return Severity.getSeverityAscending(runtime,
5 * Statistics.MINUTE,
30 * Statistics.MINUTE,
1 * Statistics.HOUR,
5 * Statistics.HOUR);
20 * Statistics.MINUTE,
40 * Statistics.MINUTE,
1 * Statistics.HOUR);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import com.linkedin.drelephant.hadoop.HadoopTaskData;

public class ReducerDataSkewHeuristic extends GenericDataSkewHeuristic {
private static final String analysisName = "Reducer Data Skew";
private static final String heuristicName = "Reducer Data Skew";

public ReducerDataSkewHeuristic() {
super(HadoopCounterHolder.CounterName.REDUCE_SHUFFLE_BYTES, analysisName);
super(HadoopCounterHolder.CounterName.REDUCE_SHUFFLE_BYTES, heuristicName);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
import com.linkedin.drelephant.math.Statistics;

public class ReducerTimeHeuristic implements Heuristic {
private static final String analysisName = "Reducer Time";
private static final String heuristicName = "Reducer Time";

@Override
public String getHeuristicName() {
return heuristicName;
}

@Override
public HeuristicResult apply(HadoopJobData data) {
Expand All @@ -28,7 +33,7 @@ public HeuristicResult apply(HadoopJobData data) {
Severity longTimeSeverity = longTimeSeverity(averageRuntime, tasks.length);
Severity severity = Severity.max(shortTimeSeverity, longTimeSeverity);

HeuristicResult result = new HeuristicResult(analysisName, severity);
HeuristicResult result = new HeuristicResult(heuristicName, severity);

result.addDetail("Number of tasks", Integer.toString(tasks.length));
result.addDetail("Average task time", Statistics.readableTimespan(averageRuntime));
Expand All @@ -52,8 +57,8 @@ public static Severity getShortRuntimeSeverity(long runtime) {
return Severity.getSeverityDescending(runtime,
10 * Statistics.MINUTE,
5 * Statistics.MINUTE,
1 * Statistics.MINUTE,
30 * Statistics.SECOND);
2 * Statistics.MINUTE,
1 * Statistics.MINUTE);
}

public static Severity getLongRuntimeSeverity(long runtime) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
import java.util.Collections;

public class ShuffleSortHeuristic implements Heuristic {
private static final String analysisName = "Shuffle & Sort";
private static final String heuristicName = "Shuffle & Sort";

@Override
public String getHeuristicName() {
return heuristicName;
}

@Override
public HeuristicResult apply(HadoopJobData data) {
Expand Down Expand Up @@ -41,7 +46,7 @@ public HeuristicResult apply(HadoopJobData data) {
Severity sortSeverity = getShuffleSortSeverity(avgSortTime, avgExecTime);
Severity severity = Severity.max(shuffleSeverity, sortSeverity);

HeuristicResult result = new HeuristicResult(analysisName, severity);
HeuristicResult result = new HeuristicResult(heuristicName, severity);

result.addDetail("Number of tasks", Integer.toString(data.getReducerData().length));
result.addDetail("Average code runtime", Statistics.readableTimespan(avgExecTime));
Expand Down Expand Up @@ -83,8 +88,8 @@ public static Severity getShuffleSortSeverity(long runtime, long codetime) {
Severity runtimeSeverity = Severity.getSeverityAscending(runtime,
1 * Statistics.MINUTE,
5 * Statistics.MINUTE,
20 * Statistics.MINUTE,
1 * Statistics.HOUR);
10 * Statistics.MINUTE,
30 * Statistics.MINUTE);

if (codetime <= 0) {
return runtimeSeverity;
Expand Down
13 changes: 13 additions & 0 deletions app/com/linkedin/drelephant/notifications/EmailThread.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.linkedin.drelephant.notifications;

public class EmailThread extends Thread {

public EmailThread() {
setName("Email Thread");
}

@Override
public void run() {

}
}
80 changes: 65 additions & 15 deletions app/controllers/Application.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
package controllers;

import com.avaje.ebean.ExpressionList;
import com.linkedin.drelephant.analysis.Severity;
import model.JobResult;
import play.Logger;
import play.data.DynamicForm;
import play.data.Form;
import play.mvc.Controller;
import play.mvc.Result;
import views.html.index;
import views.html.multijob;
import views.html.search;
import views.html.singlejob;
import views.html.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class Application extends Controller {
private static final long DAY = 24 * 60 * 60 * 1000;
private static final long FETCH_DELAY = 60 * 1000;
private static long lastFetch = 0;
private static int numJobsAnalyzed = 0;
private static int numJobsCritical = 0;
private static int numJobsSevere = 0;

public static Result search() {
return ok(search.render(null));
}

public static Result queryJob() {
DynamicForm form = Form.form().bindFromRequest(request());
String jobId = form.get("jobid");
String username = form.get("username");
String username = form.get("user");
String severity = form.get("severity");
if (jobId != null) {
String analysis = form.get("analysis");
String dateStart = form.get("start-date");
String dateEnd = form.get("end-date");
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
if (jobId != null && !jobId.isEmpty()) {
JobResult result = JobResult.find.byId(jobId);
if (result != null) {
return ok(search.render(singlejob.render(result)));
Expand All @@ -37,10 +42,35 @@ public static Result queryJob() {
}
} else {
ExpressionList<JobResult> query = JobResult.find.where();
if (username != null) {
query = query.eq("username", username);
} else if (severity != null) {
query = query.ge("severity", severity);
if (username != null && !username.isEmpty()) {
query = query.ilike("username", username);
}
if (severity != null && !severity.isEmpty()) {
query = query.ge("heuristicResults.severity", severity);
}
if (analysis != null && !analysis.isEmpty()) {
query = query.eq("heuristicResults.analysisName", analysis);
}
if (dateStart != null && !dateStart.isEmpty()) {
try {
Date date = dateFormat.parse(dateStart);
Logger.debug(date.toString());
query = query.gt("startTime", date.getTime());
} catch (ParseException e) {
e.printStackTrace();
}
}
if (dateEnd != null && !dateEnd.isEmpty()) {
try {
Date date = dateFormat.parse(dateEnd);
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, 1);
date = c.getTime();
query = query.lt("startTime", date.getTime());
} catch (ParseException e) {
e.printStackTrace();
}
}
List<JobResult> results = query
.order().desc("analysisTime")
Expand All @@ -57,6 +87,14 @@ public static Result dashboard(int page) {
numJobsAnalyzed = JobResult.find.where()
.gt("analysisTime", now - DAY)
.findRowCount();
numJobsCritical = JobResult.find.where()
.gt("analysisTime", now - DAY)
.eq("severity", Severity.CRITICAL.getValue())
.findRowCount();
numJobsSevere = JobResult.find.where()
.gt("analysisTime", now - DAY)
.eq("severity", Severity.SEVERE.getValue())
.findRowCount();
lastFetch = now;
}
List<JobResult> results = JobResult.find.where()
Expand All @@ -66,6 +104,18 @@ public static Result dashboard(int page) {
.fetch("heuristicResults")
.findList();

return ok(index.render(Integer.toString(numJobsAnalyzed), multijob.render("Latest analysis", results)));
return ok(index.render(numJobsAnalyzed, numJobsSevere, numJobsCritical, multijob.render("Latest analysis", results)));
}

public static Result help() {
DynamicForm form = Form.form().bindFromRequest(request());
String topic = form.get("topic");

if (topic != null && !topic.isEmpty()) {
//TODO
} else {

}
return ok(help.render(multijob.render("Latest analysis", null)));
}
}
5 changes: 5 additions & 0 deletions app/views/help.scala.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@()(content: Html)

@main("Dr. Elephant", "help") {
@content
}
8 changes: 5 additions & 3 deletions app/views/index.scala.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
@(numJobsAnalyzed: String)(results: Html)
@(numJobsAnalyzed: Int, numJobsSevere: Int, numJobsCritical: Int)(results: Html)

@main("Dr. Elephant", "dashboard") {
<div class="jumbotron">
<h2>Dr. Elephant has been busy today!</h2>
<p>We analyzed <b>@numJobsAnalyzed</b> jobs.</p>
<h2>Dr. Elephant has been busy!</h2>
<p>We looked through <b>@numJobsAnalyzed</b> jobs today.<br>
About <b>@numJobsSevere</b> of them could use some tuning.<br>
About <b>@numJobsCritical</b> of them need some serious attention!</p>
</div>
@results
}
Loading

0 comments on commit f070109

Please sign in to comment.