Skip to content

Commit

Permalink
DRILL-5172: Display elapsed time for queries in the UI
Browse files Browse the repository at this point in the history
Displays the elapsed time for running queries and the total duration of completed/failed/cancelled queries in the list of query profiles displayed, and within a query's profile page as well.
The query runtime is  displayed in '[hr] [min] sec'.
e.g. A duration of 25,254,321ms is displayed  7 hr 00 min 54.321 sec

This closes #721
  • Loading branch information
Kunal Khatua authored and parthchandra committed Jan 14, 2017
1 parent a093433 commit 8a4d7a9
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 5 deletions.
Expand Up @@ -68,20 +68,43 @@ public class ProfileResources {
@Inject DrillUserPrincipal principal; @Inject DrillUserPrincipal principal;
@Inject SecurityContext sc; @Inject SecurityContext sc;


/**
* Returns elapsed time a human-readable format. If end time is less than the start time, current epoch time is assumed as the end time.
* e.g. getPrettyDuration(1468368841695,1468394096016) = '7 hr 00 min 54.321 sec'
* @param startTimeMillis Start Time in milliseconds
* @param endTimeMillis End Time in milliseconds
* @return Human-Readable Elapsed Time
*/
public static String getPrettyDuration(long startTimeMillis, long endTimeMillis) {
long durationInMillis = (startTimeMillis > endTimeMillis ? System.currentTimeMillis() : endTimeMillis) - startTimeMillis;
long hours = TimeUnit.MILLISECONDS.toHours(durationInMillis);
long minutes = TimeUnit.MILLISECONDS.toMinutes(durationInMillis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(durationInMillis));
long seconds = TimeUnit.MILLISECONDS.toSeconds(durationInMillis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(durationInMillis));
long milliSeconds = durationInMillis - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(durationInMillis));
String formattedDuration = (hours > 0 ? hours + " hr " : "") +
((minutes + hours) > 0 ? String.format("%02d min ", minutes) : "") +
seconds + "." + String.format("%03d sec", milliSeconds) ;
return formattedDuration;
}

public static class ProfileInfo implements Comparable<ProfileInfo> { public static class ProfileInfo implements Comparable<ProfileInfo> {
public static final SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); public static final SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");


private String queryId; private String queryId;
private long startTime;
private long endTime;
private Date time; private Date time;
private String location; private String location;
private String foreman; private String foreman;
private String query; private String query;
private String state; private String state;
private String user; private String user;


public ProfileInfo(String queryId, long time, String foreman, String query, String state, String user) { public ProfileInfo(String queryId, long startTime, long endTime, String foreman, String query, String state, String user) {
this.queryId = queryId; this.queryId = queryId;
this.time = new Date(time); this.startTime = startTime;
this.endTime = endTime;
this.time = new Date(startTime);
this.foreman = foreman; this.foreman = foreman;
this.location = "http://localhost:8047/profile/" + queryId + ".json"; this.location = "http://localhost:8047/profile/" + queryId + ".json";
this.query = query.substring(0, Math.min(query.length(), 150)); this.query = query.substring(0, Math.min(query.length(), 150));
Expand All @@ -105,6 +128,17 @@ public String getTime() {
return format.format(time); return format.format(time);
} }


public long getStartTime() {
return startTime;
}

public long getEndTime() {
return endTime;
}

public String getDuration() {
return getPrettyDuration(startTime, endTime);
}


public String getState() { public String getState() {
return state; return state;
Expand Down Expand Up @@ -174,7 +208,7 @@ public QProfiles getProfilesJSON() {
final Map.Entry<String, QueryInfo> runningEntry = runningEntries.next(); final Map.Entry<String, QueryInfo> runningEntry = runningEntries.next();
final QueryInfo profile = runningEntry.getValue(); final QueryInfo profile = runningEntry.getValue();
if (principal.canManageProfileOf(profile.getUser())) { if (principal.canManageProfileOf(profile.getUser())) {
runningQueries.add(new ProfileInfo(runningEntry.getKey(), profile.getStart(), profile.getForeman().getAddress(), profile.getQuery(), profile.getState().name(), profile.getUser())); runningQueries.add(new ProfileInfo(runningEntry.getKey(), profile.getStart(), System.currentTimeMillis(), profile.getForeman().getAddress(), profile.getQuery(), profile.getState().name(), profile.getUser()));
} }
} catch (Exception e) { } catch (Exception e) {
errors.add(e.getMessage()); errors.add(e.getMessage());
Expand All @@ -192,7 +226,7 @@ public QProfiles getProfilesJSON() {
final Map.Entry<String, QueryProfile> profileEntry = range.next(); final Map.Entry<String, QueryProfile> profileEntry = range.next();
final QueryProfile profile = profileEntry.getValue(); final QueryProfile profile = profileEntry.getValue();
if (principal.canManageProfileOf(profile.getUser())) { if (principal.canManageProfileOf(profile.getUser())) {
finishedQueries.add(new ProfileInfo(profileEntry.getKey(), profile.getStart(), profile.getForeman().getAddress(), profile.getQuery(), profile.getState().name(), profile.getUser())); finishedQueries.add(new ProfileInfo(profileEntry.getKey(), profile.getStart(), profile.getEnd(), profile.getForeman().getAddress(), profile.getQuery(), profile.getState().name(), profile.getUser()));
} }
} catch (Exception e) { } catch (Exception e) {
errors.add(e.getMessage()); errors.add(e.getMessage());
Expand Down
Expand Up @@ -114,6 +114,10 @@ public QueryProfile getProfile() {
return profile; return profile;
} }


public String getProfileDuration() {
return ProfileResources.getPrettyDuration(profile.getStart(), profile.getEnd());
}

public String getQueryId() { public String getQueryId() {
return id; return id;
} }
Expand Down
9 changes: 8 additions & 1 deletion exec/java-exec/src/main/resources/rest/profile/list.ftl
Expand Up @@ -36,6 +36,7 @@
<td>User</td> <td>User</td>
<td>Query</td> <td>Query</td>
<td>State</td> <td>State</td>
<td>Elapsed</td>
<td>Foreman</td> <td>Foreman</td>
</thead> </thead>
<tbody> <tbody>
Expand All @@ -62,7 +63,9 @@
</a> </a>
</td> </td>
<td> <td>
<div style="height:100%;width:100%">${query.getState()}</div> <div style="height:100%;width:100%">${query.getState()}</div>
<td>
<div style="height:100%;width:100%">${query.getDuration()}</div>
<td> <td>
<div style="height:100%;width:100%"> <div style="height:100%;width:100%">
${query.getForeman()} ${query.getForeman()}
Expand Down Expand Up @@ -91,6 +94,7 @@
<!-- <td>Query Id</td> --> <!-- <td>Query Id</td> -->
<td>Query</td> <td>Query</td>
<td>State</td> <td>State</td>
<td>Duration</td>
<td>Foreman</td> <td>Foreman</td>
</thead> </thead>
<tbody> <tbody>
Expand Down Expand Up @@ -120,6 +124,9 @@
<td> <td>
<div style="height:100%;width:100%">${query.getState()}</div> <div style="height:100%;width:100%">${query.getState()}</div>
</td> </td>
<td>
<div style="height:100%;width:100%">${query.getDuration()}</div>
</td>
<td> <td>
<div style="height:100%;width:100%"> <div style="height:100%;width:100%">
${query.getForeman()} ${query.getForeman()}
Expand Down
1 change: 1 addition & 0 deletions exec/java-exec/src/main/resources/rest/profile/profile.ftl
Expand Up @@ -106,6 +106,7 @@
<p>STATE: ${model.getProfile().getState().name()}</p> <p>STATE: ${model.getProfile().getState().name()}</p>
<p>FOREMAN: ${model.getProfile().getForeman().getAddress()}</p> <p>FOREMAN: ${model.getProfile().getForeman().getAddress()}</p>
<p>TOTAL FRAGMENTS: ${model.getProfile().getTotalFragments()}</p> <p>TOTAL FRAGMENTS: ${model.getProfile().getTotalFragments()}</p>
<p>DURATION: ${model.getProfileDuration()}</p>


<#assign options = model.getOptions()> <#assign options = model.getOptions()>
<#if (options?keys?size > 0)> <#if (options?keys?size > 0)>
Expand Down

0 comments on commit 8a4d7a9

Please sign in to comment.