Explorar o código

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 %!s(int64=13) %!d(string=hai) anos
pai
achega
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):
   """