瀏覽代碼

HUE-873 [jb] Direct access to task logs

Added new view to access the 'best' displayable task
Added logs column on jobbrowser landing page
Added logs link to job view page
Enrico Berti 13 年之前
父節點
當前提交
424cf6e

+ 3 - 1
apps/jobbrowser/src/jobbrowser/templates/job.mako

@@ -30,7 +30,7 @@
     <table class="taskTable table table-striped table-condensed">
         <thead>
         <tr>
-            <th>${_('Log')}</th>
+            <th>${_('Logs')}</th>
             <th>${_('Tasks')}</th>
             <th>${_('Type')}</th>
         </tr>
@@ -99,6 +99,8 @@ ${commonheader(_('Job: %(jobId)s - Job Browser') % dict(jobId=job.jobId), "jobbr
                     <li>
                         ${comps.get_status(job)}
                     </li>
+                    <li class="nav-header">${_('Logs')}</li>
+                    <li><a href="${ url('jobbrowser.views.job_single_logs', jobid=job.jobId) }">${_('View logs')}</a></li>
                     % if job.status.lower() == 'running' or job.status.lower() == 'pending':
                         <li class="nav-header">${_('Kill Job')}</li>
                         <li>

+ 5 - 0
apps/jobbrowser/src/jobbrowser/templates/jobs.mako

@@ -76,6 +76,7 @@ ${commonheader(_('Job Browser'), "jobbrowser", user)}
 <table class="datatables table table-striped table-condensed">
     <thead>
         <tr>
+            <th>${_('Logs')}</th>
             <th>${_('ID')}</th>
             <th>${_('Name')}</th>
             <th>${_('Status')}</th>
@@ -92,6 +93,9 @@ ${commonheader(_('Job Browser'), "jobbrowser", user)}
     <tbody>
         % for job in jobs:
         <tr class="job-row">
+            <td data-row-selector-exclude="true">
+                <a href="${ url('jobbrowser.views.job_single_logs', jobid=job.jobId) }" data-row-selector-exclude="true"><i class="icon-tasks"></i></a>
+            </td>
             <td>
                 <a href="${url('jobbrowser.views.single_job', jobid=job.jobId)}" title="${_('View this job')}" data-row-selector="true">${job.jobId_short}</a>
             </td>
@@ -186,6 +190,7 @@ ${commonheader(_('Job Browser'), "jobbrowser", user)}
             "bInfo": false,
             "aaSorting": [[ 0, "desc" ]],
             "aoColumns": [
+                {"bSortable": false},
                 null,
                 null,
                 null,

+ 1 - 1
apps/jobbrowser/src/jobbrowser/templates/task.mako

@@ -56,7 +56,7 @@ ${commonheader(_('Job Task: %(taskId)s - Job Browser') % dict(taskId=task.taskId
                     <table id="attemptsTable" class="table table-striped table-condensed">
                         <thead>
                         <tr>
-                            <th>${_('Log')}</th>
+                            <th>${_('Logs')}</th>
                             <th>${_('Attempt ID')}</th>
                             <th>${_('Progress')}</th>
                             <th>${_('State')}</th>

+ 1 - 1
apps/jobbrowser/src/jobbrowser/templates/tasks.mako

@@ -68,7 +68,7 @@ ${commonheader(_('Task View: Job: %(jobId)s - Job Browser') % dict(jobId=jobid),
         <table class="datatables table table-striped table-condensed">
             <thead>
             <tr>
-                <th>${_('Log')}</th>
+                <th>${_('Logs')}</th>
                 <th>${_('Task ID')}</th>
                 <th>${_('Type')}</th>
                 <th>${_('Progress')}</th>

+ 4 - 0
apps/jobbrowser/src/jobbrowser/tests.py

@@ -263,6 +263,10 @@ class TestJobBrowserWithHadoop(unittest.TestCase, OozieServerProvider):
                           (hadoop_job_id, early_task_id, attempt_id))
     assert_true('syslog' in response.content)
 
+    # Test job single logs page
+    response = self.client.get('/jobbrowser/jobs/%s/job_single_logs' % (hadoop_job_id))
+    assert_true('syslog' in response.content)
+
     # Test dock jobs
     response = self.client.get('/jobbrowser/dock_jobs/')
     assert_false('completed' in response.content)

+ 1 - 0
apps/jobbrowser/src/jobbrowser/urls.py

@@ -28,6 +28,7 @@ urlpatterns = patterns('jobbrowser.views',
   url(r'^jobs/(?P<jobid>\w+)/counters$','job_counters',name='job_counters'),
   url(r'^jobs/(?P<jobid>\w+)/kill$','kill_job',name='kill_job'),
   url(r'^jobs/(?P<jobid>\w+)/setpriority$','set_job_priority',name='set_job_priority'),
+  url(r'^jobs/(?P<jobid>\w+)/single_logs$','job_single_logs',name='job_single_logs'),
   url(r'^jobs/(?P<jobid>\w+)/tasks$','tasks',name='tasks'),
   url(r'^jobs/(?P<jobid>\w+)/tasks/(?P<taskid>\w+)$','single_task',name='single_task'),
   url(r'^jobs/(?P<jobid>\w+)/tasks/(?P<taskid>\w+)/attempts/(?P<attemptid>\w+)$',

+ 32 - 4
apps/jobbrowser/src/jobbrowser/views.py

@@ -40,6 +40,7 @@ from jobbrowser import conf
 from jobbrowser.models import Job, JobLinkage, TaskList, Tracker, Cluster
 
 from django.utils.translation import ugettext as _
+from django.shortcuts import redirect
 
 ##################################
 ## View end-points
@@ -69,12 +70,12 @@ def single_job(request, jobid):
   """
   job = Job.from_id(jt=request.jt, jobid=jobid)
 
-  def cmp_exec_time(foo, bar):
-    return cmp(foo.execStartTimeMs, bar.execStartTimeMs)
+  def cmp_exec_time(task1, task2):
+    return cmp(task1.execStartTimeMs, task2.execStartTimeMs)
 
-  failed_tasks = job.filter_tasks(task_states=set(['failed']))
+  failed_tasks = job.filter_tasks(task_states=('failed',))
   failed_tasks.sort(cmp_exec_time)
-  recent_tasks = job.filter_tasks(task_states=set(['running', 'succeeded']))
+  recent_tasks = job.filter_tasks(task_states=('running', 'succeeded',))
   recent_tasks.sort(cmp_exec_time, reverse=True)
 
   return render("job.mako", request, {
@@ -156,6 +157,33 @@ def kill_job(request, jobid):
 
   raise Exception(_("Job did not appear as killed within 15 seconds"))
 
+@check_job_permission
+def job_single_logs(request, jobid):
+  """
+  We get here from /jobs/jobid/logs
+  """
+  job = Job.from_id(jt=request.jt, jobid=jobid)
+
+  def cmp_exec_time(task1, task2):
+    return cmp(task1.execStartTimeMs, task2.execStartTimeMs)
+
+  task = None
+
+  failed_tasks = job.filter_tasks(task_states=('failed',))
+  failed_tasks.sort(cmp_exec_time)
+  if failed_tasks:
+    task = failed_tasks[0]
+  else:
+    recent_tasks = job.filter_tasks(task_states=('running', 'succeeded',))
+    recent_tasks.sort(cmp_exec_time, reverse=True)
+    if recent_tasks:
+      task = recent_tasks[0]
+
+  if task is None:
+    raise PopupException(_("No tasks found for job %(id)s") % dict(id=jobid))
+
+  return redirect('single_task_attempt_logs', jobid=jobid, taskid= task.taskId, attemptid= task.taskAttemptIds[-1])
+
 @check_job_permission
 def tasks(request, jobid):
   """