You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by de...@apache.org on 2013/04/19 11:48:56 UTC

svn commit: r1469764 - in /uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main: java/org/apache/uima/ducc/ws/server/ java/org/apache/uima/ducc/ws/utils/ webapp/root/

Author: degenaro
Date: Fri Apr 19 09:48:55 2013
New Revision: 1469764

URL: http://svn.apache.org/r1469764
Log:
UIMA-2817 DUCC webserver (WS) should display duration for jobs/reservations, and end time on hover

Added:
    uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/FormatHelper.java
Modified:
    uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccAbstractHandler.java
    uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java
    uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerJsonFormat.java
    uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerLegacy.java
    uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/jobs.jsp
    uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/reservations.jsp

Modified: uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccAbstractHandler.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccAbstractHandler.java?rev=1469764&r1=1469763&r2=1469764&view=diff
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccAbstractHandler.java (original)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccAbstractHandler.java Fri Apr 19 09:48:55 2013
@@ -23,7 +23,6 @@ import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.List;
 import java.util.Properties;
-import java.util.concurrent.TimeUnit;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -46,10 +45,12 @@ import org.apache.uima.ducc.transport.ev
 import org.apache.uima.ducc.transport.event.common.IDuccUnits.MemoryUnits;
 import org.apache.uima.ducc.transport.event.common.IDuccWork;
 import org.apache.uima.ducc.transport.event.common.IDuccWorkJob;
+import org.apache.uima.ducc.transport.event.common.IDuccWorkReservation;
 import org.apache.uima.ducc.ws.DuccMachinesData;
 import org.apache.uima.ducc.ws.registry.IServicesRegistry;
 import org.apache.uima.ducc.ws.registry.ServicesRegistry;
 import org.apache.uima.ducc.ws.server.DuccCookies.DateStyle;
+import org.apache.uima.ducc.ws.utils.FormatHelper;
 import org.eclipse.jetty.server.handler.AbstractHandler;
 
 public abstract class DuccAbstractHandler extends AbstractHandler {
@@ -175,6 +176,24 @@ public abstract class DuccAbstractHandle
 		return sb.toString();
 	}
 	
+	public String getDuration(HttpServletRequest request, DuccId jobId, String millisV2, String millisV1) {
+		String methodName = "getDuration";
+		String retVal = "";
+		try {
+			long d2 = Long.parseLong(millisV2);
+			long d1 = Long.parseLong(millisV1);
+			long diff = d2 - d1;
+			retVal = FormatHelper.duration(diff);
+		}
+		catch(Exception e) {
+			duccLogger.trace(methodName, null, "no worries", e);
+		}
+		catch(Throwable t) {
+			duccLogger.trace(methodName, null, "no worries", t);
+		}
+		return retVal;
+	}
+	
 	public String getTimeStamp(HttpServletRequest request, DuccId jobId, String millis) {
 		return getTimeStamp(DuccCookies.getDateStyle(request),getTimeStamp(jobId, millis));
 	}
@@ -624,8 +643,8 @@ public abstract class DuccAbstractHandle
 		return retVal;
 	}
 
-	public String getCompletionOrProjection(HttpServletRequest request, IDuccWorkJob job) {
-		String methodName = "getCompletionOrProjection";
+	public String getCompletion(HttpServletRequest request, IDuccWorkJob job) {
+		String methodName = "getCompletion";
 		String retVal = "";
 		try {
 			String tVal = job.getStandardInfo().getDateOfCompletion();
@@ -638,64 +657,97 @@ public abstract class DuccAbstractHandle
 		catch(Throwable t) {
 			duccLogger.trace(methodName, null, "no worries", t);
 		}
+		return retVal;
+	}
+
+	public String getCompletion(HttpServletRequest request, IDuccWorkReservation reservation) {
+		String methodName = "getCompletion";
+		String retVal = "";
 		try {
-			if(retVal.trim().length() == 0) {
-				IDuccSchedulingInfo schedulingInfo = job.getSchedulingInfo();
-				IDuccPerWorkItemStatistics perWorkItemStatistics = schedulingInfo.getPerWorkItemStatistics();
-				if (perWorkItemStatistics == null) {
-					return "";
-				}
-				//
-				int total = schedulingInfo.getIntWorkItemsTotal();
-				int completed = schedulingInfo.getIntWorkItemsCompleted();
-				int error = schedulingInfo.getIntWorkItemsError();
-				int remainingWorkItems = total - (completed + error);
-				if(remainingWorkItems > 0) {
-					int usableProcessCount = job.getProcessMap().getUsableProcessCount();
-					if(usableProcessCount > 0) {
-						if(completed > 0) {
-							int threadsPerProcess = schedulingInfo.getIntThreadsPerShare();
-							int totalThreads = usableProcessCount * threadsPerProcess;
-							double remainingIterations = remainingWorkItems / totalThreads;
-							double avgMillis = perWorkItemStatistics.getMean();
-							double projectedTime = 0;
-							if(remainingIterations > 0) {
-								projectedTime = avgMillis * remainingIterations;
-							}
-							else {
-								projectedTime = avgMillis - (Calendar.getInstance().getTimeInMillis() - job.getSchedulingInfo().getMostRecentWorkItemStart());
-							}
-							if(projectedTime < 0) {
-								projectedTime = 0;
-							}
+			String tVal = reservation.getStandardInfo().getDateOfCompletion();
+			duccLogger.trace(methodName, null, tVal);
+			retVal = getTimeStamp(request,reservation.getDuccId(),tVal);
+		}
+		catch(Exception e) {
+			duccLogger.trace(methodName, null, "no worries", e);
+		}
+		catch(Throwable t) {
+			duccLogger.trace(methodName, null, "no worries", t);
+		}
+		return retVal;
+	}
+	
+	public String getDuration(HttpServletRequest request, IDuccWork dw) {
+		String methodName = "getDuration";
+		String retVal = "";
+		try {
+			String v2 = dw.getStandardInfo().getDateOfCompletion();
+			String v1 = dw.getStandardInfo().getDateOfSubmission();
+			duccLogger.trace(methodName, null, "v2:"+v2+" v1:"+v1);
+			retVal = getDuration(request,dw.getDuccId(),v2,v1);
+		}
+		catch(Exception e) {
+			duccLogger.trace(methodName, null, "no worries", e);
+		}
+		catch(Throwable t) {
+			duccLogger.trace(methodName, null, "no worries", t);
+		}
+		return retVal;
+	}
+	
+	public String getDuration(HttpServletRequest request, IDuccWork dw, long now) {
+		String methodName = "getDuration";
+		String retVal = "";
+		try {
+			String v2 = ""+now;
+			String v1 = dw.getStandardInfo().getDateOfSubmission();
+			duccLogger.trace(methodName, null, "v2:"+v2+" v1:"+v1);
+			retVal = getDuration(request,dw.getDuccId(),v2,v1);
+		}
+		catch(Exception e) {
+			duccLogger.trace(methodName, null, "no worries", e);
+		}
+		catch(Throwable t) {
+			duccLogger.trace(methodName, null, "no worries", t);
+		}
+		return retVal;
+	}
+	
+	public String getProjection(HttpServletRequest request, IDuccWorkJob job) {
+		String methodName = "getProjection";
+		String retVal = "";
+		try {
+			IDuccSchedulingInfo schedulingInfo = job.getSchedulingInfo();
+			IDuccPerWorkItemStatistics perWorkItemStatistics = schedulingInfo.getPerWorkItemStatistics();
+			if (perWorkItemStatistics == null) {
+				return "";
+			}
+			int total = schedulingInfo.getIntWorkItemsTotal();
+			int completed = schedulingInfo.getIntWorkItemsCompleted();
+			int error = schedulingInfo.getIntWorkItemsError();
+			int remainingWorkItems = total - (completed + error);
+			if(remainingWorkItems > 0) {
+				int usableProcessCount = job.getProcessMap().getUsableProcessCount();
+				if(usableProcessCount > 0) {
+					if(completed > 0) {
+						int threadsPerProcess = schedulingInfo.getIntThreadsPerShare();
+						int totalThreads = usableProcessCount * threadsPerProcess;
+						double remainingIterations = remainingWorkItems / totalThreads;
+						double avgMillis = perWorkItemStatistics.getMean();
+						double projectedTime = 0;
+						if(remainingIterations > 0) {
+							projectedTime = avgMillis * remainingIterations;
+						}
+						else {
+							projectedTime = avgMillis - (Calendar.getInstance().getTimeInMillis() - job.getSchedulingInfo().getMostRecentWorkItemStart());
+						}
+						if(projectedTime > 0) {
 							long millis = Math.round(projectedTime);
-							long days = TimeUnit.MILLISECONDS.toDays(millis);
-							millis -= TimeUnit.DAYS.toMillis(days);
-							long hours = TimeUnit.MILLISECONDS.toHours(millis);
-							millis -= TimeUnit.HOURS.toMillis(hours);
-							long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
-							millis -= TimeUnit.MINUTES.toMillis(minutes);
-							long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
-							String remainingTime = String.format("%02d", hours)+":"+String.format("%02d", minutes)+":"+String.format("%02d", seconds);
-							if(days > 0) {
-								remainingTime = days+":"+remainingTime;
+							if(millis > 1000) {
+								retVal = FormatHelper.duration(millis);
 							}
-							retVal = "projected +"+remainingTime;
-							double max = Math.round(perWorkItemStatistics.getMax()/100.0)/10.0;
-							double min = Math.round(perWorkItemStatistics.getMin()/100.0)/10.0;
-							double avg = Math.round(perWorkItemStatistics.getMean()/100.0)/10.0;
-							double dev = Math.round(perWorkItemStatistics.getStandardDeviation()/100.0)/10.0;
-							retVal = "<span title=\""+"seconds-per-work-item "+"Max:"+max+" "+"Min:"+min+" "+"Avg:"+avg+" "+"Dev:"+dev+"\""+">"+retVal+"</span>";
 						}
 					}
-					else {
-						if(job.isRunnable()) {
-							retVal = "suspended";
-						}
-					}
-				}
-				else {
-					retVal = "finished";
 				}
 			}
 		}
@@ -704,6 +756,30 @@ public abstract class DuccAbstractHandle
 		}
 		return retVal;
 	}
+	
+	public String decorateDuration(HttpServletRequest request, IDuccWorkJob job, String duration) {
+		String retVal = duration;
+		String cVal = getCompletion(request,job);
+		if(cVal != null) {
+			if(cVal.length() > 0) {
+				String title = "title=\""+"End="+cVal+"\"";
+				retVal = "<span "+title+">"+duration+"</span>";
+			}
+		}
+		return retVal;
+	}
+	
+	public String decorateDuration(HttpServletRequest request, IDuccWorkReservation reservation, String duration) {
+		String retVal = duration;
+		String cVal = getCompletion(request,reservation);
+		if(cVal != null) {
+			if(cVal.length() > 0) {
+				String title = "title=\""+"End="+cVal+"\"";
+				retVal = "<span "+title+">"+duration+"</span>";
+			}
+		}
+		return retVal;
+	}
 
 	@Deprecated
 	public String getDisabled(HttpServletRequest request, IDuccWork duccWork) {

Modified: uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java?rev=1469764&r1=1469763&r2=1469764&view=diff
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java (original)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandler.java Fri Apr 19 09:48:55 2013
@@ -88,6 +88,7 @@ import org.apache.uima.ducc.ws.MachineSu
 import org.apache.uima.ducc.ws.registry.IServicesRegistry;
 import org.apache.uima.ducc.ws.registry.ServicesRegistry;
 import org.apache.uima.ducc.ws.registry.ServicesRegistryMapPayload;
+import org.apache.uima.ducc.ws.utils.FormatHelper;
 import org.eclipse.jetty.server.Request;
 
 public class DuccHandler extends DuccAbstractHandler {
@@ -521,7 +522,7 @@ public class DuccHandler extends DuccAbs
 						IUimaPipelineAEComponent upc = upcIterator.next();
 						String iName = upc.getAeName();
 						String iState = upc.getAeState().toString();
-						String iTime = formatDuration(upc.getInitializationTime());
+						String iTime = FormatHelper.duration(upc.getInitializationTime());
 						loadme.append("<tr>");
 						loadme.append("<td>"+iName);
 						loadme.append("<td>"+iState);
@@ -1076,25 +1077,6 @@ public class DuccHandler extends DuccAbs
 		duccLogger.trace(methodName, null, messages.fetch("exit"));
 	}
 	
-	private static String formatDuration(final long millis) {
-		long seconds = millis / 1000;
-		long dd =   seconds / 86400;
-		long hh =  (seconds % 86400) / 3600;
-		long mm = ((seconds % 86400) % 3600) / 60;
-		long ss = ((seconds % 86400) % 3600) % 60;
-		String text = String.format("%d:%02d:%02d:%02d", dd, hh, mm, ss);
-		if(dd == 0) {
-			text = String.format("%02d:%02d:%02d", hh, mm, ss);
-			if(hh == 0) {
-				text = String.format("%02d:%02d", mm, ss);
-				if(mm == 0) {
-					text = String.format("%02d", ss);
-				}
-			}
-		}
-		return text;
-	}
-	
 	private void handleDuccServletJobPerformanceData(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) 
 	throws IOException, ServletException
 	{
@@ -1189,22 +1171,22 @@ public class DuccHandler extends DuccAbs
 					// Total
 					sb.append("<td align=\"right\">");
 					ltime = (long)time_total;
-					sb.append(formatDuration(ltime));
+					sb.append(FormatHelper.duration(ltime));
 					// % of Total
 					sb.append("<td align=\"right\">");
 					sb.append(formatter.format(100));
 					// Avg
 					sb.append("<td align=\"right\">");
 					ltime = (long)time_avg;
-					sb.append(formatDuration(ltime));
+					sb.append(FormatHelper.duration(ltime));
 					// Min
 					sb.append("<td align=\"right\">");
 					ltime = (long)time_min;
-					sb.append(formatDuration(ltime));
+					sb.append(FormatHelper.duration(ltime));
 					// Max
 					sb.append("<td align=\"right\">");
 					ltime = (long)time_max;
-					sb.append(formatDuration(ltime));
+					sb.append(FormatHelper.duration(ltime));
 				    // pass 2
 				    for (int i = 0; i < numstats; ++i) {
 				    	sb.append(trGet(counter++));
@@ -1215,7 +1197,7 @@ public class DuccHandler extends DuccAbs
 						sb.append("<td align=\"right\">");
 						time = uimaStats.get(i).getAnalysisTime();
 						ltime = (long)time;
-						sb.append(formatDuration(ltime));
+						sb.append(FormatHelper.duration(ltime));
 						// % of Total
 						sb.append("<td align=\"right\">");
 						double dtime = (time/time_total)*100;
@@ -1224,17 +1206,17 @@ public class DuccHandler extends DuccAbs
 						sb.append("<td align=\"right\">");
 						time = time/casCount;
 						ltime = (long)time;
-						sb.append(formatDuration(ltime));
+						sb.append(FormatHelper.duration(ltime));
 						// Min
 						sb.append("<td align=\"right\">");
 						time = uimaStats.get(i).getAnalysisMinTime();
 						ltime = (long)time;
-						sb.append(formatDuration(ltime));
+						sb.append(FormatHelper.duration(ltime));
 						// Max
 						sb.append("<td align=\"right\">");
 						time = uimaStats.get(i).getAnalysisMaxTime();
 						ltime = (long)time;
-						sb.append(formatDuration(ltime));
+						sb.append(FormatHelper.duration(ltime));
 					}
 					sb.append("</table>");
 			    }

Modified: uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerJsonFormat.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerJsonFormat.java?rev=1469764&r1=1469763&r2=1469764&view=diff
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerJsonFormat.java (original)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerJsonFormat.java Fri Apr 19 09:48:55 2013
@@ -60,6 +60,7 @@ import org.apache.uima.ducc.transport.ev
 import org.apache.uima.ducc.transport.event.common.IDuccState.ReservationState;
 import org.apache.uima.ducc.transport.event.common.IDuccTypes.DuccType;
 import org.apache.uima.ducc.transport.event.common.IDuccUnits.MemoryUnits;
+import org.apache.uima.ducc.transport.event.common.IDuccPerWorkItemStatistics;
 import org.apache.uima.ducc.transport.event.common.IDuccProcess;
 import org.apache.uima.ducc.transport.event.common.IDuccWork;
 import org.apache.uima.ducc.transport.event.common.IDuccWorkJob;
@@ -180,7 +181,7 @@ public class DuccHandlerJsonFormat exten
 		return sb;
 	}
 	
-	private JsonArray buildJobRow(HttpServletRequest request, IDuccWorkJob job, DuccData duccData, ServicesRegistry servicesRegistry) {
+	private JsonArray buildJobRow(HttpServletRequest request, IDuccWorkJob job, DuccData duccData, long now, ServicesRegistry servicesRegistry) {
 		String type="Job";
 		JsonArray row = new JsonArray();
 		StringBuffer sb;
@@ -208,11 +209,26 @@ public class DuccHandlerJsonFormat exten
 		sb.append(getTimeStamp(request,job.getDuccId(), job.getStandardInfo().getDateOfSubmission()));
 		sb.append("</span>");
 		row.add(new JsonPrimitive(sb.toString()));
-		// End
+		// Duration
 		sb = new StringBuffer();
-		sb.append("<span title=\""+DuccConstants.hintPreferencesDateStyle+"\">");
-		sb.append(getCompletionOrProjection(request,job));
-		sb.append("</span>");
+		if(job.isCompleted()) {
+			String duration = getDuration(request,job);
+			String decoratedDuration = decorateDuration(request,job, duration);
+			sb.append("<span>");
+			sb.append(decoratedDuration);
+			sb.append("</span>");
+		}
+		else {
+			String duration = getDuration(request,job,now);
+			String decoratedDuration = decorateDuration(request,job, duration);
+			String projection = getProjection(request,job);
+			sb.append("<span class=\"health_green\""+">");
+			sb.append(decoratedDuration);
+			sb.append("</span>");
+			if(projection.length() > 0) {
+				sb.append("+"+"<i title=\"projected time to completion\">"+projection+"</i>");
+			}
+		}
 		row.add(new JsonPrimitive(sb.toString()));
 		// User
 		sb = new StringBuffer();
@@ -302,7 +318,16 @@ public class DuccHandlerJsonFormat exten
 		// Done
 		sb = new StringBuffer();
 		sb.append("<span>");
-		sb.append(job.getSchedulingInfo().getWorkItemsCompleted());
+		IDuccPerWorkItemStatistics perWorkItemStatistics = job.getSchedulingInfo().getPerWorkItemStatistics();
+		String done = job.getSchedulingInfo().getWorkItemsCompleted();
+		if (perWorkItemStatistics != null) {
+			double max = Math.round(perWorkItemStatistics.getMax()/100.0)/10.0;
+			double min = Math.round(perWorkItemStatistics.getMin()/100.0)/10.0;
+			double avg = Math.round(perWorkItemStatistics.getMean()/100.0)/10.0;
+			double dev = Math.round(perWorkItemStatistics.getStandardDeviation()/100.0)/10.0;
+			done = "<span title=\""+"seconds-per-work-item "+"Max:"+max+" "+"Min:"+min+" "+"Avg:"+avg+" "+"Dev:"+dev+"\""+">"+done+"</span>";
+		}
+		sb.append(done);
 		sb.append("</span>");
 		row.add(new JsonPrimitive(sb.toString()));
 		// Error
@@ -374,6 +399,8 @@ public class DuccHandlerJsonFormat exten
 		
 		ServicesRegistry servicesRegistry = new ServicesRegistry();
 		
+		long now = System.currentTimeMillis();
+		
 		int maxRecords = getJobsMax(request);
 		ArrayList<String> users = getJobsUsers(request);
 		DuccData duccData = DuccData.getInstance();
@@ -387,7 +414,7 @@ public class DuccHandlerJsonFormat exten
 				boolean list = DuccWebUtil.isListable(request, users, maxRecords, counter, job);
 				if(list) {
 					counter++;
-					JsonArray row = buildJobRow(request, job, duccData, servicesRegistry);
+					JsonArray row = buildJobRow(request, job, duccData, now, servicesRegistry);
 					data.add(row);
 				}
 			}
@@ -454,7 +481,7 @@ public class DuccHandlerJsonFormat exten
 	}
 	
 	
-	private JsonArray buildReservationRow(HttpServletRequest request, IDuccWork duccwork, DuccData duccData) {
+	private JsonArray buildReservationRow(HttpServletRequest request, IDuccWork duccwork, DuccData duccData, long now) {
 		String type="Reservation";
 		JsonArray row = new JsonArray();
 		String reservationType = "Unmanaged";
@@ -500,17 +527,24 @@ public class DuccHandlerJsonFormat exten
 		sb.append(getTimeStamp(request,duccwork.getDuccId(), duccwork.getStandardInfo().getDateOfSubmission()));
 		sb.append("</span>");
 		row.add(new JsonPrimitive(sb.toString()));
-		// End
+		// Duration
 		sb = new StringBuffer();
 		if(duccwork instanceof DuccWorkReservation) {
 			DuccWorkReservation reservation = (DuccWorkReservation) duccwork;
 			switch(reservation.getReservationState()) {
 			case Completed:
-				sb.append("<span title=\""+DuccConstants.hintPreferencesDateStyle+"\">");
-				sb.append(getTimeStamp(request,duccwork.getDuccId(),duccwork.getStandardInfo().getDateOfCompletion()));
+				sb.append("<span>");
+				String duration = getDuration(request,reservation);
+				String decoratedDuration = decorateDuration(request,reservation, duration);
+				sb.append(decoratedDuration);
 				sb.append("</span>");
 				break;
 			default:
+				sb.append("<span class=\"health_green\""+">");
+				duration = getDuration(request,reservation,now);
+				decoratedDuration = decorateDuration(request,reservation, duration);
+				sb.append(decoratedDuration);
+				sb.append("</span>");
 				break;
 			}
 		}
@@ -518,11 +552,18 @@ public class DuccHandlerJsonFormat exten
 			DuccWorkJob job = (DuccWorkJob) duccwork;
 			switch(job.getJobState()) {
 			case Completed:
-				sb.append("<span title=\""+DuccConstants.hintPreferencesDateStyle+"\">");
-				sb.append(getTimeStamp(request,duccwork.getDuccId(),duccwork.getStandardInfo().getDateOfCompletion()));
+				sb.append("<span>");
+				String duration = getDuration(request,job);
+				String decoratedDuration = decorateDuration(request,job, duration);
+				sb.append(decoratedDuration);
 				sb.append("</span>");
 				break;
 			default:
+				sb.append("<span class=\"health_green\""+">");
+				duration = getDuration(request,job,now);
+				decoratedDuration = decorateDuration(request,job, duration);
+				sb.append(decoratedDuration);
+				sb.append("</span>");
 				break;
 			}
 		}
@@ -788,6 +829,8 @@ public class DuccHandlerJsonFormat exten
 
 		ArrayList<String> users = getReservationsUsers(request);
 		
+		long now = System.currentTimeMillis();
+		
 		if((sortedCombinedReservations.size() > 0)) {
 			int counter = 0;
 			Iterator<Entry<Info, Info>> iR = sortedCombinedReservations.entrySet().iterator();
@@ -799,12 +842,12 @@ public class DuccHandlerJsonFormat exten
 					counter++;
 					if(dw instanceof DuccWorkReservation) {
 						DuccWorkReservation reservation = (DuccWorkReservation) dw;
-						JsonArray row = buildReservationRow(request, reservation, duccData);
+						JsonArray row = buildReservationRow(request, reservation, duccData, now);
 						data.add(row);
 					}
 					else if(dw instanceof DuccWorkJob) {
 						DuccWorkJob job = (DuccWorkJob) dw;
-						JsonArray row = buildReservationRow(request, job, duccData);
+						JsonArray row = buildReservationRow(request, job, duccData, now);
 						data.add(row);
 					}
 					else {

Modified: uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerLegacy.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerLegacy.java?rev=1469764&r1=1469763&r2=1469764&view=diff
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerLegacy.java (original)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/server/DuccHandlerLegacy.java Fri Apr 19 09:48:55 2013
@@ -51,6 +51,7 @@ import org.apache.uima.ducc.transport.ev
 import org.apache.uima.ducc.transport.event.common.IDuccReservationMap;
 import org.apache.uima.ducc.transport.event.common.IDuccTypes.DuccType;
 import org.apache.uima.ducc.transport.event.common.IDuccUnits.MemoryUnits;
+import org.apache.uima.ducc.transport.event.common.IDuccPerWorkItemStatistics;
 import org.apache.uima.ducc.transport.event.common.IDuccProcess;
 import org.apache.uima.ducc.transport.event.common.IDuccWork;
 import org.apache.uima.ducc.transport.event.common.IDuccWorkJob;
@@ -164,7 +165,7 @@ public class DuccHandlerLegacy extends D
 		return sb.toString();
 	}
 	
-	private void buildJobsListEntry(HttpServletRequest request, StringBuffer sb, DuccId duccId, IDuccWorkJob job, DuccData duccData, ServicesRegistry servicesRegistry) {
+	private void buildJobsListEntry(HttpServletRequest request, StringBuffer sb, DuccId duccId, IDuccWorkJob job, DuccData duccData, long now, ServicesRegistry servicesRegistry) {
 		String type="Job";
 		String id = normalize(duccId);
 		// Terminate
@@ -185,11 +186,26 @@ public class DuccHandlerLegacy extends D
 		sb.append(getTimeStamp(request,job.getDuccId(), job.getStandardInfo().getDateOfSubmission()));
 		sb.append("</span>");
 		sb.append("</td>");
-		// End
-		sb.append("<td valign=\"bottom\">");
-		sb.append("<span title=\""+DuccConstants.hintPreferencesDateStyle+"\">");
-		sb.append(getCompletionOrProjection(request,job));
-		sb.append("</span>");
+		// Duration
+		sb.append("<td valign=\"bottom\" align=\"right\">");
+		if(job.isCompleted()) {
+			String duration = getDuration(request,job);
+			String decoratedDuration = decorateDuration(request,job, duration);
+			sb.append("<span>");
+			sb.append(decoratedDuration);
+			sb.append("</span>");
+		}
+		else {
+			String duration = getDuration(request,job,now);
+			String decoratedDuration = decorateDuration(request,job, duration);
+			String projection = getProjection(request,job);
+			sb.append("<span class=\"health_green\""+">");
+			sb.append(decoratedDuration);
+			sb.append("</span>");
+			if(projection.length() > 0) {
+				sb.append("+"+"<i title=\"projected time to completion\">"+projection+"</i>");
+			}
+		}
 		sb.append("</td>");
 		// User
 		String title = "";
@@ -270,7 +286,16 @@ public class DuccHandlerLegacy extends D
 		sb.append("</td>");
 		// Done
 		sb.append("<td valign=\"bottom\" align=\"right\">");
-		sb.append(job.getSchedulingInfo().getWorkItemsCompleted());
+		IDuccPerWorkItemStatistics perWorkItemStatistics = job.getSchedulingInfo().getPerWorkItemStatistics();
+		String done = job.getSchedulingInfo().getWorkItemsCompleted();
+		if (perWorkItemStatistics != null) {
+			double max = Math.round(perWorkItemStatistics.getMax()/100.0)/10.0;
+			double min = Math.round(perWorkItemStatistics.getMin()/100.0)/10.0;
+			double avg = Math.round(perWorkItemStatistics.getMean()/100.0)/10.0;
+			double dev = Math.round(perWorkItemStatistics.getStandardDeviation()/100.0)/10.0;
+			done = "<span title=\""+"seconds-per-work-item "+"Max:"+max+" "+"Min:"+min+" "+"Avg:"+avg+" "+"Dev:"+dev+"\""+">"+done+"</span>";
+		}
+		sb.append(done);
 		sb.append("</td>");
 		// Error
 		sb.append("<td valign=\"bottom\" align=\"right\">");
@@ -330,6 +355,8 @@ public class DuccHandlerLegacy extends D
 		
 		ServicesRegistry servicesRegistry = new ServicesRegistry();
 		
+		long now = System.currentTimeMillis();
+		
 		int maxRecords = getJobsMax(request);
 		ArrayList<String> users = getJobsUsers(request);
 		DuccData duccData = DuccData.getInstance();
@@ -344,7 +371,7 @@ public class DuccHandlerLegacy extends D
 				if(list) {
 					counter++;
 					sb.append(trGet(counter));
-					buildJobsListEntry(request, sb, job.getDuccId(), job, duccData, servicesRegistry);
+					buildJobsListEntry(request, sb, job.getDuccId(), job, duccData, now, servicesRegistry);
 				}
 			}
 		}
@@ -366,7 +393,7 @@ public class DuccHandlerLegacy extends D
 		duccLogger.trace(methodName, jobid, messages.fetch("exit"));
 	}	
 	
-	private void buildReservationsListEntry(HttpServletRequest request, StringBuffer sb, DuccId duccId, IDuccWork duccwork, DuccData duccData) {
+	private void buildReservationsListEntry(HttpServletRequest request, StringBuffer sb, DuccId duccId, IDuccWork duccwork, DuccData duccData, long now) {
 		String type="Reservation";
 		String id = normalize(duccId);
 		String reservationType = "Unmanaged";
@@ -412,17 +439,26 @@ public class DuccHandlerLegacy extends D
 		sb.append(getTimeStamp(request,duccwork.getDuccId(),duccwork.getStandardInfo().getDateOfSubmission()));
 		sb.append("</span>");
 		sb.append("</td>");
-		// End
-		sb.append("<td>");
+		// Duration
+		sb.append("<td align=\"right\">");
 		if(duccwork instanceof DuccWorkReservation) {
 			DuccWorkReservation reservation = (DuccWorkReservation) duccwork;
+			String duration;
+			String decoratedDuration;
 			switch(reservation.getReservationState()) {
 			case Completed:
-				sb.append("<span title=\""+DuccConstants.hintPreferencesDateStyle+"\">");
-				sb.append(getTimeStamp(request,duccwork.getDuccId(),duccwork.getStandardInfo().getDateOfCompletion()));
+				sb.append("<span>");
+				duration = getDuration(request,reservation);
+				decoratedDuration = decorateDuration(request,reservation, duration);
+				sb.append(decoratedDuration);
 				sb.append("</span>");
 				break;
 			default:
+				sb.append("<span class=\"health_green\""+">");
+				duration = getDuration(request,reservation,now);
+				decoratedDuration = decorateDuration(request,reservation, duration);
+				sb.append(decoratedDuration);
+				sb.append("</span>");
 				break;
 			}
 		}
@@ -430,11 +466,18 @@ public class DuccHandlerLegacy extends D
 			DuccWorkJob job = (DuccWorkJob) duccwork;
 			switch(job.getJobState()) {
 			case Completed:
-				sb.append("<span title=\""+DuccConstants.hintPreferencesDateStyle+"\">");
-				sb.append(getTimeStamp(request,duccwork.getDuccId(),duccwork.getStandardInfo().getDateOfCompletion()));
 				sb.append("<span>");
+				String duration = getDuration(request,job);
+				String decoratedDuration = decorateDuration(request,job, duration);
+				sb.append(decoratedDuration);
+				sb.append("</span>");
 				break;
 			default:
+				sb.append("<span class=\"health_green\""+">");
+				duration = getDuration(request,job,now);
+				decoratedDuration = decorateDuration(request,job, duration);
+				sb.append(decoratedDuration);
+				sb.append("</span>");
 				break;
 			}
 		}
@@ -688,6 +731,8 @@ public class DuccHandlerLegacy extends D
 
 		ArrayList<String> users = getReservationsUsers(request);
 		
+		long now = System.currentTimeMillis();
+		
 		if((sortedCombinedReservations.size() > 0)) {
 			int counter = 0;
 			Iterator<Entry<Info, Info>> iR = sortedCombinedReservations.entrySet().iterator();
@@ -700,12 +745,12 @@ public class DuccHandlerLegacy extends D
 					if(dw instanceof DuccWorkReservation) {
 						DuccWorkReservation reservation = (DuccWorkReservation) dw;
 						sb.append(trGet(counter));
-						buildReservationsListEntry(request, sb, reservation.getDuccId(), reservation, duccData);
+						buildReservationsListEntry(request, sb, reservation.getDuccId(), reservation, duccData, now);
 					}
 					else if(dw instanceof DuccWorkJob) {
 						DuccWorkJob job = (DuccWorkJob) dw;
 						sb.append(trGet(counter));
-						buildReservationsListEntry(request, sb, job.getDuccId(), job, duccData);
+						buildReservationsListEntry(request, sb, job.getDuccId(), job, duccData, now);
 					}
 					else {
 						// huh?

Added: uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/FormatHelper.java
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/FormatHelper.java?rev=1469764&view=auto
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/FormatHelper.java (added)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/java/org/apache/uima/ducc/ws/utils/FormatHelper.java Fri Apr 19 09:48:55 2013
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.uima.ducc.ws.utils;
+
+public class FormatHelper {
+	
+	public static String duration(final long millis) {
+		long seconds = millis / 1000;
+		long dd =   seconds / 86400;
+		long hh =  (seconds % 86400) / 3600;
+		long mm = ((seconds % 86400) % 3600) / 60;
+		long ss = ((seconds % 86400) % 3600) % 60;
+		String text = String.format("%d:%02d:%02d:%02d", dd, hh, mm, ss);
+		if(dd == 0) {
+			text = String.format("%02d:%02d:%02d", hh, mm, ss);
+			if(hh == 0) {
+				text = String.format("%02d:%02d", mm, ss);
+				if(mm == 0) {
+					text = String.format("%02d", ss);
+				}
+			}
+		}
+		return text;
+	}
+}

Modified: uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/jobs.jsp
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/jobs.jsp?rev=1469764&r1=1469763&r2=1469764&view=diff
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/jobs.jsp (original)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/jobs.jsp Fri Apr 19 09:48:55 2013
@@ -42,6 +42,7 @@ if (table_style.equals("scroll")) {
 			"fnRowCallback"  : function(nRow,aData,iDisplayIndex) {
 									$('td:eq(0)', nRow).css( "text-align", "right" );
                              		$('td:eq(1)', nRow).css( "text-align", "right" );
+                             		$('td:eq(3)', nRow).css( "text-align", "right" );
                              		$('td:eq(8)', nRow).css( "text-align", "right" );
                              		$('td:eq(9)', nRow).css( "text-align", "right" );
                              		$('td:eq(10)', nRow).css( "text-align", "right" );
@@ -106,7 +107,7 @@ if (table_style.equals("scroll")) {
 	<th class="ducc-col-terminate"></th>
 	<th title="The system assigned id for this job" class="sorttable_numeric">Id</th>
 	<th title="The time this job was submitted">Start</th>
-	<th title="The time this job was finished (or the projected time until finish if presently running)">End</th>
+	<th title="The time this job lasted (or the projected time until finish if presently running), units ddd:hh:mm:ss">Duration</th>
 	<th class="ducc-no-filter" id="user_column_heading" title="The user who submitted this job">User</th>
 	<th title="The user specified class of this job">Class</th>
 	<th title="The current state of this job">State</th>
@@ -144,7 +145,7 @@ if (table_style.equals("classic")) {
 		<th class="ducc-col-terminate"></th>
 		<th title="The system assigned id for this job" class="sorttable_numeric">Id</th>
 		<th title="The time this job was submitted">Start</th>
-		<th title="The time this job was finished (or the projected time until finish if presently running)">End</th>
+		<th title="The time this job lasted (or the projected time until finish if presently running), units ddd:hh:mm:ss">Duration</th>
 		<th class="ducc-no-filter" id="user_column_heading" title="The user who submitted this job">User</th>
 		<th title="The user specified class of this job">Class</th>
 		<th title="The current state of this job">State</th>

Modified: uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/reservations.jsp
URL: http://svn.apache.org/viewvc/uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/reservations.jsp?rev=1469764&r1=1469763&r2=1469764&view=diff
==============================================================================
--- uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/reservations.jsp (original)
+++ uima/sandbox/uima-ducc/trunk/uima-ducc-web/src/main/webapp/root/reservations.jsp Fri Apr 19 09:48:55 2013
@@ -42,6 +42,7 @@ if (table_style.equals("scroll")) {
 			"fnRowCallback"  : function(nRow,aData,iDisplayIndex) {
 									$('td:eq(0)', nRow).css( "text-align", "right" );
                              		$('td:eq(1)', nRow).css( "text-align", "right" );
+                             		$('td:eq(3)', nRow).css( "text-align", "right" );
                              		$('td:eq(9)', nRow).css( "text-align", "right" );
                              		$('td:eq(10)', nRow).css( "text-align", "right" );
                              		$('td:eq(11)', nRow).css( "text-align", "right" );
@@ -104,7 +105,7 @@ if (table_style.equals("scroll")) {
 	<th class="ducc-col-terminate"></th>
 			<th title="The system assigned id for this reservation">Id</th>
 			<th title="The time this reservation was submitted">Start</th>
-			<th title="The time this reservation was finished">End</th>
+			<th title="The time this reservation lasted, units ddd:hh:mm:ss">Duration</th>
 			<th class="ducc-no-filter" id="user_column_heading" title="The user who submitted this reservation">User</th>
 			<th title="The user specified class of this reservation">Class</th>
 			<th title="The type of this reservation">Type</th>
@@ -136,7 +137,7 @@ if (table_style.equals("classic")) {
 		<th class="ducc-col-terminate"></th>
 			<th title="The system assigned id for this reservation">Id</th>
 			<th title="The time this reservation was submitted">Start</th>
-			<th title="The time this reservation was finished">End</th>
+			<th title="The time this reservation lasted, units ddd:hh:mm:ss">Duration</th>
 			<th class="ducc-no-filter" id="user_column_heading" title="The user who submitted this reservation">User</th>
 			<th title="The user specified class of this reservation">Class</th>
 			<th title="The type of this reservation">Type</th>