From 31d4bf8484ee42690386c6b7a6bd6c7a2be54464 Mon Sep 17 00:00:00 2001 From: Ravi Chintakunta Date: Mon, 17 Feb 2014 23:30:41 -0500 Subject: bitbake: toaster: View detailed information about a task Information about a task is displayed depending on it's execution status and outcome status. Edited to iterate through all possible entries for related setscene tasks. [YOCTO #4282] (Bitbake rev: 62f502b1237d4060df6be1ee4f4865db5fa39a6a) Signed-off-by: Ravi Chintakunta Signed-off-by: Paul Eggleton Signed-off-by: Alexandru DAMIAN Signed-off-by: Richard Purdie --- bitbake/lib/toaster/orm/models.py | 12 + bitbake/lib/toaster/toastergui/templates/task.html | 263 +++++++++++++++++++++ .../lib/toaster/toastergui/templates/tasks.html | 4 +- .../toaster/toastergui/templatetags/projecttags.py | 8 +- bitbake/lib/toaster/toastergui/views.py | 34 ++- 5 files changed, 315 insertions(+), 6 deletions(-) create mode 100644 bitbake/lib/toaster/toastergui/templates/task.html (limited to 'bitbake') diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py index 588e1b9265..abc16d9b88 100644 --- a/bitbake/lib/toaster/orm/models.py +++ b/bitbake/lib/toaster/orm/models.py @@ -111,6 +111,15 @@ class Task(models.Model): (OUTCOME_EMPTY, 'Empty'), ) + TASK_OUTCOME_HELP = { + OUTCOME_SUCCESS:'This task completed successfully', + OUTCOME_COVERED:'This task did not run because its output is provided by another task', + OUTCOME_CACHED:'This task restored output from the sstate-cache directory or mirrors', + OUTCOME_PREBUILT:'This task did not run because its outcome was reused from a previous build', + OUTCOME_FAILED:'This task did not complete', + OUTCOME_NA:'' + } + search_allowed_fields = [ "recipe__name", "recipe__version", "task_name", "logfile" ] objects = TaskManager() @@ -118,6 +127,9 @@ class Task(models.Model): def get_related_setscene(self): return Task.objects.related_setscene(self) + def outcome_help(self): + return Task.TASK_OUTCOME_HELP[self.outcome] + def get_executed_display(self): if self.task_executed: return "Executed" diff --git a/bitbake/lib/toaster/toastergui/templates/task.html b/bitbake/lib/toaster/toastergui/templates/task.html new file mode 100644 index 0000000000..c5d6176b62 --- /dev/null +++ b/bitbake/lib/toaster/toastergui/templates/task.html @@ -0,0 +1,263 @@ +{% extends "basebuilddetailpage.html" %} + +{% load projecttags %} +{% load humanize %} + +{% block localbreadcrumb %} +
  • Tasks
  • +
  • {{task.recipe.name}}_{{task.recipe.version}} {{task.task_name}}
  • +{% endblock %} + +{% block pagedetailinfomain %} + +
    + + +{# Outcome section #} +

    + {{task.get_outcome_display}} + +

    +{%if task.task_executed %} + {# executed tasks outcome #} +
    +
    + Log file +
    +
    + {{task.logfile}} +
    + {# show stack trace for failed task #} + {% if task.outcome == task.OUTCOME_FAILED and log_head %} +

    Python stack trace

    +
    +
    +                    {{log_head}}...
    +                    
    + {{log_body}}
    +
    + {% endif %} +
    +{% else %} +{# not executed tasks outcome #} + {% if task.outcome == task.OUTCOME_PREBUILT %} + {% if not showing_matches %} + Match to tasks in previous builds + {% elif matching_tasks %} +

    Prebuilt task could be based on + +

    + + + + + + + + + + {% for match in matching_tasks %} + + + + + + + + {% endfor %} + +
    + + Recipe + + + Task + + + Executed + + + Outcome + + + Build completed on +
    + {{match.recipe.name}} + + {{match.task_name}} + + {{match.get_executed_display}} + + {{match.get_outcome_display}} + + {{match.build.completed_on|date:"d/m/y H:i"}} +
    + {% else %} +

    + We have found no tasks matching this prebuilt task.
    + The task you are looking for could belong to a build for which Toaster has not data. +

    + {% endif %} + {% elif task.outcome == task.OUTCOME_COVERED %} +
    +
    + Task covered by +
    +
    +
      +
    • TODO:Covering tasks will be displayed here

    • +
    +
    +
    + {%elif task.outcome == task.OUTCOME_CACHED%} +
    +
    + Log file +
    +
    + {% for t in task.get_related_setscene %} {{t.logfile}}
    {% endfor %} +
    +
    +
    + {% endif %} +{% endif %} + +{# Execution section #} +

    + {% if task.task_executed %} + Executed + + {% else %} + Not Executed + + {% endif %} +

    +
    +
    + + Task inputs signature +
    +
    + {{task.sstate_checksum}} +
    +
    + {% if task.sstate_result != task.SSTATE_NA %} +
    Attempting to restore output from sstate cache + +
    +
    +
    + + File searched for +
    +
    {{task.path_to_sstate_obj}}
    +
    + + URI(s) searched +
    +
    {{task.work_directory}}
    +
    + {% endif %} + {% if task.sstate_result == task.SSTATE_MISS %} +
    + File not in sstate cache. Running the real task instead. +
    + {% elif task.sstate_result == task.SSTATE_FAILED%} +
    + Failed to restore output from sstate cache. The file was found but could not be unpacked. +
    +
    +
    + + Log file +
    +
    {{task.logfile}}
    +
    + + Time (secs) +
    +
    {{task.elapsed_time|format_none_and_zero}}
    +
    +
    + Running the real task instead. +
    + {% elif task.sstate_result == task.SSTATE_RESTORED %} +
    + Output successfully restored from sstate cache. +
    + {% endif %} +
    +
    + + Task order +
    +
    {{task.order}}
    + {% if task.task_executed %} +
    + + Task script type +
    +
    {{task.get_script_type_display}}
    + {% endif %} + +
    + + Task depends on +
    +
    + +
    +
    + + Task reverse dependencies +
    +
    + +
    + +{# Performance section - shown only for executed tasks #} +{%if task.task_executed %} +

    Performance

    +
    +
    + + Time (secs) +
    +
    {{task.elapsed_time|format_none_and_zero}}
    +
    + + CPU usage +
    +
    {{task.cpu_usage|format_none_and_zero}}
    +
    + + Disk I/O (ms) +
    +
    {{task.disk_io|format_none_and_zero}}
    +
    +{%endif%} + + +
    +{% endblock %} + diff --git a/bitbake/lib/toaster/toastergui/templates/tasks.html b/bitbake/lib/toaster/toastergui/templates/tasks.html index 7dc2c38b18..ce75b75c94 100644 --- a/bitbake/lib/toaster/toastergui/templates/tasks.html +++ b/bitbake/lib/toaster/toastergui/templates/tasks.html @@ -20,9 +20,9 @@ {% include "basetable_top.html" %} {% for task in objects %} - + - {{task.order}} + {{task.order}} {{task.recipe.name}} diff --git a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py index 7e2c8e98fa..b1e573b16d 100644 --- a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py +++ b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py @@ -70,13 +70,17 @@ def sortcols(tablecols): return sorted(tablecols, key = lambda t: t['name']) @register.filter -def task_color(task_object): - """ Return css class depending on Task execution status and execution outcome +def task_color(task_object, show_green=False): + """ Return css class depending on Task execution status and execution outcome. + By default, green is not returned for executed and successful tasks; + show_green argument should be True to get green color. """ if not task_object.task_executed: return 'class=muted' elif task_object.outcome == task_object.OUTCOME_FAILED: return 'class=error' + elif task_object.outcome == task_object.OUTCOME_SUCCESS and show_green: + return 'class=green' else: return '' diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 11c8fd806e..b77be1a6e7 100644 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py @@ -349,12 +349,36 @@ def builddashboard(request, build_id): return render(request, template, context) def task(request, build_id, task_id): - template = "singletask.html" - if Build.objects.filter(pk=build_id).count() == 0 : + template = "task.html" + if Task.objects.filter(pk=task_id).count() == 0 : return redirect(builds) + task = Task.objects.filter(pk=task_id)[0] + + dependencies = sorted(_find_task_dep(task), key=lambda t:'%s_%s %s'%(t.recipe.name, t.recipe.version, t.task_name)) + reverse_dependencies = sorted(_find_task_revdep(task), key=lambda t:'%s_%s %s'%(t.recipe.name, t.recipe.version, t.task_name)) + + log_head = '' + log_body = '' + if task.outcome == task.OUTCOME_FAILED: + pass +# FIXME: the log should be read from the orm_logmessage table. +# This will be fixed when the backend is done. + context = { 'build' : Build.objects.filter(pk=build_id)[0], + 'object': task, + 'task':task, + 'deps': dependencies, + 'rdeps': reverse_dependencies, + 'log_head':log_head, + 'log_body':log_body, + 'showing_matches':False, } + + if request.GET.get('show_matches', ""): + context['showing_matches'] = True + context['matching_tasks'] = Task.objects.filter(sstate_checksum=task.sstate_checksum).filter(build__completed_on__lt=task.build.completed_on).order_by('-build__completed_on') + return render(request, template, context) def recipe(request, build_id, recipe_id): @@ -388,6 +412,12 @@ def target(request, build_id, target_id): return render(request, template, context) +def _find_task_dep(task): + tp = [] + for p in Task_Dependency.objects.filter(task=task): + tp.append(p.depends_on); + return tp + def _find_task_revdep(task): tp = [] -- cgit v1.2.3-54-g00ecf