diff --git a/bitbake/lib/toaster/toastergui/buildtables.py b/bitbake/lib/toaster/toastergui/buildtables.py index dc742b9fe5..51c136f988 100644 --- a/bitbake/lib/toaster/toastergui/buildtables.py +++ b/bitbake/lib/toaster/toastergui/buildtables.py @@ -19,10 +19,13 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -from orm.models import Build -import toastergui.tables as tables +from orm.models import Build, Task +from django.db.models import Q +import toastergui.tables as tables from toastergui.widgets import ToasterTable +from toastergui.tablefilter import TableFilter +from toastergui.tablefilter import TableFilterActionToggle class BuildTablesMixin(ToasterTable): @@ -279,3 +282,223 @@ class BuiltRecipesTable(BuildTablesMixin): self.add_column(title="Layer commit", static_data_name="commit", static_data_template=git_rev_template) + + +class BuildTasksTable(BuildTablesMixin): + """ Table to show the tasks that run in this build """ + + def __init__(self, *args, **kwargs): + super(BuildTasksTable, self).__init__(*args, **kwargs) + self.title = "Tasks" + self.default_orderby = "order" + + # Toggle these columns on off for Time/CPU usage/Disk I/O tables + self.toggle_columns = {} + + def setup_queryset(self, *args, **kwargs): + build = Build.objects.get(pk=kwargs['build_id']) + self.static_context_extra['build'] = build + self.queryset = build.task_build.filter(~Q(order=None)) + self.queryset = self.queryset.order_by(self.default_orderby) + + def setup_filters(self, *args, **kwargs): + # Execution outcome types filter + executed_outcome = TableFilter(name="execution_outcome", + title="Filter Tasks by 'Executed") + + exec_outcome_action_exec = TableFilterActionToggle( + "executed", + "Executed Tasks", + Q(task_executed=True)) + + exec_outcome_action_not_exec = TableFilterActionToggle( + "not_executed", + "Not Executed Tasks", + Q(task_executed=False)) + + executed_outcome.add_action(exec_outcome_action_exec) + executed_outcome.add_action(exec_outcome_action_not_exec) + + # Task outcome types filter + task_outcome = TableFilter(name="task_outcome", + title="Filter Task by 'Outcome'") + + for outcome_enum, title in Task.TASK_OUTCOME: + action = TableFilterActionToggle( + title.replace(" ", "_").lower(), + "%s Tasks" % title, + Q(outcome=outcome_enum)) + + task_outcome.add_action(action) + + # SSTATE outcome types filter + sstate_outcome = TableFilter(name="sstate_outcome", + title="Filter Task by 'Cache attempt'") + + for sstate_result_enum, title in Task.SSTATE_RESULT: + action = TableFilterActionToggle( + title.replace(" ", "_").lower(), + "Tasks with '%s' attempts" % title, + Q(sstate_result=sstate_result_enum)) + + sstate_outcome.add_action(action) + + self.add_filter(sstate_outcome) + self.add_filter(executed_outcome) + self.add_filter(task_outcome) + + def setup_columns(self, *args, **kwargs): + self.toggle_columns['order'] = len(self.columns) + + recipe_name_tmpl =\ + ''\ + '{{data.recipe.name}}'\ + '' + + recipe_version_tmpl =\ + ''\ + '{{data.recipe.version}}'\ + '' + + def task_link_tmpl(val): + return ('' + '%s' + '') % str(val) + + self.add_column(title="Order", + static_data_name="order", + static_data_template=task_link_tmpl('{{data.order}}'), + orderable=True) + + self.add_column(title="Recipe", + static_data_name='recipe__name', + static_data_template=recipe_name_tmpl, + orderable=True) + + self.add_column(title="Recipe version", + static_data_name='recipe__version', + static_data_template=recipe_version_tmpl) + + self.add_column(title="Task", + static_data_name="task_name", + static_data_template=task_link_tmpl( + "{{data.task_name}}"), + orderable=True) + + self.add_column(title="Executed", + static_data_name="task_executed", + static_data_template=task_link_tmpl( + "{{data.get_executed_display}}"), + filter_name='execution_outcome', + orderable=True) + + self.static_context_extra['OUTCOME_FAILED'] = Task.OUTCOME_FAILED + outcome_tmpl = task_link_tmpl("{{data.outcome_text}}") + outcome_tmpl = ('%s ' + '{%% if data.outcome = extra.OUTCOME_FAILED %%}' + '' + ' ' + ' {%% endif %%}' + '' + ) % outcome_tmpl + + self.add_column(title="Outcome", + static_data_name="outcome", + static_data_template=outcome_tmpl, + filter_name="task_outcome", + orderable=True) + + self.add_column(title="Cache attempt", + static_data_name="sstate_result", + static_data_template=task_link_tmpl( + "{{data.sstate_text}}"), + filter_name="sstate_outcome", + orderable=True) + + self.toggle_columns['elapsed_time'] = len(self.columns) + + self.add_column( + title="Time (secs)", + static_data_name="elapsed_time", + static_data_template='{% load projecttags %}{% load humanize %}' + '{{data.elapsed_time|format_none_and_zero|floatformat:2}}', + orderable=True, + hidden=True) + + self.toggle_columns['cpu_time_sys'] = len(self.columns) + + self.add_column( + title="System CPU time (secs)", + static_data_name="cpu_time_system", + static_data_template='{% load projecttags %}{% load humanize %}' + '{{data.cpu_time_system|format_none_and_zero|floatformat:2}}', + hidden=True, + orderable=True) + + self.toggle_columns['cpu_time_user'] = len(self.columns) + + self.add_column( + title="User CPU time (secs)", + static_data_name="cpu_time_user", + static_data_template='{% load projecttags %}{% load humanize %}' + '{{data.cpu_time_user|format_none_and_zero|floatformat:2}}', + hidden=True, + orderable=True) + + self.toggle_columns['disk_io'] = len(self.columns) + + self.add_column( + title="Disk I/O (ms)", + static_data_name="disk_io", + static_data_template='{% load projecttags %}{% load humanize %}' + '{{data.disk_io|format_none_and_zero|filtered_filesizeformat}}', + hidden=True, + orderable=True) + + +class BuildTimeTable(BuildTasksTable): + """ Same as tasks table but the Time column is default displayed""" + + def __init__(self, *args, **kwargs): + super(BuildTimeTable, self).__init__(*args, **kwargs) + self.default_orderby = "-elapsed_time" + + def setup_columns(self, *args, **kwargs): + super(BuildTimeTable, self).setup_columns(**kwargs) + + self.columns[self.toggle_columns['order']]['hidden'] = True + self.columns[self.toggle_columns['elapsed_time']]['hidden'] = False + + +class BuildCPUTimeTable(BuildTasksTable): + """ Same as tasks table but the CPU usage columns are default displayed""" + + def __init__(self, *args, **kwargs): + super(BuildCPUTimeTable, self).__init__(*args, **kwargs) + self.default_orderby = "-cpu_time_system" + + def setup_columns(self, *args, **kwargs): + super(BuildCPUTimeTable, self).setup_columns(**kwargs) + + self.columns[self.toggle_columns['order']]['hidden'] = True + self.columns[self.toggle_columns['cpu_time_sys']]['hidden'] = False + self.columns[self.toggle_columns['cpu_time_user']]['hidden'] = False + + +class BuildIOTable(BuildTasksTable): + """ Same as tasks table but the Disk IO column is default displayed""" + + def __init__(self, *args, **kwargs): + super(BuildIOTable, self).__init__(*args, **kwargs) + self.default_orderby = "-disk_io" + + def setup_columns(self, *args, **kwargs): + super(BuildIOTable, self).setup_columns(**kwargs) + + self.columns[self.toggle_columns['order']]['hidden'] = True + self.columns[self.toggle_columns['disk_io']]['hidden'] = False diff --git a/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html b/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html index 4ce5c4a8a5..52cc0569f7 100644 --- a/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html +++ b/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html @@ -12,12 +12,14 @@ {% block buildinfomain %}
sstate-cache directory or mirrors'),
- ('Prebuilt Tasks', 'outcome:%d'%Task.OUTCOME_PREBUILT, queryset_with_search.filter(outcome=Task.OUTCOME_PREBUILT).count(),'Prebuilt tasks didn\'t need to run because their output was reused from a previous build'),
- ('Covered Tasks', 'outcome:%d'%Task.OUTCOME_COVERED, queryset_with_search.filter(outcome=Task.OUTCOME_COVERED).count(), 'Covered tasks didn\'t need to run because their output is provided by another task in this build'),
- ('Empty Tasks', 'outcome:%d'%Task.OUTCOME_EMPTY, queryset_with_search.filter(outcome=Task.OUTCOME_EMPTY).count(), 'Empty tasks have no executable content'),
- ]
- }
-
- }
-
- tc_cache={
- 'name':'Cache attempt',
- 'qhelp':'This column tells you if a task tried to restore output from the sstate-cache directory or mirrors, and reports the result: Succeeded, Failed or File not in cache',
- 'clclass': 'cache_attempt', 'hidden' : 0,
- 'orderfield': _get_toggle_order(request, "sstate_result"),
- 'ordericon':_get_toggle_order_icon(request, "sstate_result"),
- 'orderkey' : 'sstate_result',
- 'filter' : {
- 'class' : 'cache_attempt',
- 'label': 'Show:',
- 'options' : [
- ('Tasks with cache attempts', 'sstate_result__gt:%d'%Task.SSTATE_NA, queryset_with_search.filter(sstate_result__gt=Task.SSTATE_NA).count(), 'Show all tasks that tried to restore ouput from the sstate-cache directory or mirrors'),
- ("Tasks with 'File not in cache' attempts", 'sstate_result:%d'%Task.SSTATE_MISS, queryset_with_search.filter(sstate_result=Task.SSTATE_MISS).count(), 'Show tasks that tried to restore output, but did not find it in the sstate-cache directory or mirrors'),
- ("Tasks with 'Failed' cache attempts", 'sstate_result:%d'%Task.SSTATE_FAILED, queryset_with_search.filter(sstate_result=Task.SSTATE_FAILED).count(), 'Show tasks that found the required output in the sstate-cache directory or mirrors, but could not restore it'),
- ("Tasks with 'Succeeded' cache attempts", 'sstate_result:%d'%Task.SSTATE_RESTORED, queryset_with_search.filter(sstate_result=Task.SSTATE_RESTORED).count(), 'Show tasks that successfully restored the required output from the sstate-cache directory or mirrors'),
- ]
- }
-
- }
- #if 'tasks' == variant: tc_cache['hidden']='0';
- tc_time={
- 'name':'Time (secs)',
- 'qhelp':'How long it took the task to finish in seconds',
- 'orderfield': _get_toggle_order(request, "elapsed_time", True),
- 'ordericon':_get_toggle_order_icon(request, "elapsed_time"),
- 'orderkey' : 'elapsed_time',
- 'clclass': 'time_taken', 'hidden' : 1,
- }
- if 'buildtime' == variant:
- tc_time['hidden']='0'
- del tc_time['clclass']
- tc_cache['hidden']='1'
-
- tc_cpu_time_system={
- 'name':'System CPU time (secs)',
- 'qhelp':'Total amount of time spent executing in kernel mode, in ' +
- 'seconds. Note that this time can be greater than the task ' +
- 'time due to parallel execution.',
- 'orderfield': _get_toggle_order(request, "cpu_time_system", True),
- 'ordericon':_get_toggle_order_icon(request, "cpu_time_system"),
- 'orderkey' : 'cpu_time_system',
- 'clclass': 'cpu_time_system', 'hidden' : 1,
- }
-
- tc_cpu_time_user={
- 'name':'User CPU time (secs)',
- 'qhelp':'Total amount of time spent executing in user mode, in seconds. ' +
- 'Note that this time can be greater than the task time due to ' +
- 'parallel execution.',
- 'orderfield': _get_toggle_order(request, "cpu_time_user", True),
- 'ordericon':_get_toggle_order_icon(request, "cpu_time_user"),
- 'orderkey' : 'cpu_time_user',
- 'clclass': 'cpu_time_user', 'hidden' : 1,
- }
-
- if 'cputime' == variant:
- tc_cpu_time_system['hidden']='0'
- tc_cpu_time_user['hidden']='0'
- del tc_cpu_time_system['clclass']
- del tc_cpu_time_user['clclass']
- tc_cache['hidden']='1'
-
- tc_diskio={
- 'name':'Disk I/O (bytes)',
- 'qhelp':'Number of bytes written to and read from the disk during the task',
- 'orderfield': _get_toggle_order(request, "disk_io", True),
- 'ordericon':_get_toggle_order_icon(request, "disk_io"),
- 'orderkey' : 'disk_io',
- 'clclass': 'disk_io', 'hidden' : 1,
- }
- if 'diskio' == variant:
- tc_diskio['hidden']='0'
- del tc_diskio['clclass']
- tc_cache['hidden']='1'
-
- build = Build.objects.get(pk=build_id)
-
- context = { 'objectname': variant,
- 'object_search_display': object_search_display,
- 'filter_search_display': filter_search_display,
- 'mainheading': title_variant,
- 'build': build,
- 'project': build.project,
- 'objects': task_objects,
- 'default_orderby' : default_orderby,
- 'search_term': search_term,
- 'total_count': queryset_with_search.count(),
- 'tablecols':[
- tc_order,
- tc_recipe,
- tc_recipe_version,
- tc_task,
- tc_executed,
- tc_outcome,
- tc_cache,
- tc_time,
- tc_cpu_time_system,
- tc_cpu_time_user,
- tc_diskio,
- ]}
-
-
- response = render(request, template, context)
- _set_parameters_values(pagesize, orderby, request)
- return response
-
-def tasks(request, build_id):
- return tasks_common(request, build_id, 'tasks', '')
-
-def tasks_task(request, build_id, task_id):
- return tasks_common(request, build_id, 'tasks', task_id)
-
-def buildtime(request, build_id):
- return tasks_common(request, build_id, 'buildtime', '')
-
-def diskio(request, build_id):
- return tasks_common(request, build_id, 'diskio', '')
-
-def cputime(request, build_id):
- return tasks_common(request, build_id, 'cputime', '')
-
def configuration(request, build_id):
template = 'configuration.html'