mirror of
https://github.com/odoo/runbot.git
synced 2025-03-15 15:35:46 +07:00
[IMP] runbot: add total load time on builds
This commit is contained in:
parent
336e9525d5
commit
60dbbcb72e
@ -12,7 +12,7 @@ import os
|
||||
|
||||
from collections import OrderedDict
|
||||
from datetime import timedelta
|
||||
from babel.dates import format_timedelta
|
||||
from babel.dates import LC_TIME, Locale, TIMEDELTA_UNITS
|
||||
from markupsafe import Markup
|
||||
|
||||
from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT, html_escape, file_open
|
||||
@ -80,11 +80,61 @@ def time_delta(time):
|
||||
return time
|
||||
return timedelta(seconds=-time)
|
||||
|
||||
from babel.dates import format_timedelta as _format_timedelta
|
||||
|
||||
|
||||
def format_timedelta(delta, granularity='second', max_unit=None, threshold=.85,
|
||||
add_direction=False, format='long',
|
||||
locale=LC_TIME):
|
||||
"""
|
||||
Modified version of Dates.format_timedelta
|
||||
"""
|
||||
if format not in ('narrow', 'short', 'long'):
|
||||
raise TypeError('Format must be one of "narrow", "short" or "long"')
|
||||
if isinstance(delta, timedelta):
|
||||
seconds = int((delta.days * 86400) + delta.seconds)
|
||||
else:
|
||||
seconds = delta
|
||||
locale = Locale.parse(locale)
|
||||
|
||||
def _iter_patterns(a_unit):
|
||||
if add_direction:
|
||||
unit_rel_patterns = locale._data['date_fields'][a_unit]
|
||||
if seconds >= 0:
|
||||
yield unit_rel_patterns['future']
|
||||
else:
|
||||
yield unit_rel_patterns['past']
|
||||
a_unit = 'duration-' + a_unit
|
||||
yield locale._data['unit_patterns'].get(a_unit, {}).get(format)
|
||||
|
||||
for unit, secs_per_unit in TIMEDELTA_UNITS:
|
||||
if max_unit and unit != max_unit:
|
||||
continue
|
||||
max_unit = None
|
||||
value = abs(seconds) / secs_per_unit
|
||||
if value >= threshold or unit == granularity:
|
||||
if unit == granularity and value > 0:
|
||||
value = max(1, value)
|
||||
value = int(round(value))
|
||||
plural_form = locale.plural_form(value)
|
||||
pattern = None
|
||||
for patterns in _iter_patterns(unit):
|
||||
if patterns is not None:
|
||||
pattern = patterns[plural_form]
|
||||
break
|
||||
# This really should not happen
|
||||
if pattern is None:
|
||||
return u''
|
||||
return pattern.replace('{0}', str(value))
|
||||
|
||||
return u''
|
||||
|
||||
|
||||
def s2human(time):
|
||||
"""Convert a time in second into an human readable string"""
|
||||
return format_timedelta(
|
||||
time_delta(time),
|
||||
max_unit='hour',
|
||||
format="narrow",
|
||||
threshold=2.1,
|
||||
)
|
||||
|
@ -190,6 +190,9 @@ class BuildResult(models.Model):
|
||||
docker_start = fields.Datetime('Docker start')
|
||||
job_time = fields.Integer(compute='_compute_job_time', string='Job time')
|
||||
build_time = fields.Integer(compute='_compute_build_time', string='Build time')
|
||||
wait_time = fields.Integer(compute='_compute_wait_time', string='Wait time')
|
||||
load_time = fields.Integer(compute='_compute_load_time', string='Load time')
|
||||
last_update = fields.Datetime(compute='_compute_last_update', string='Last update')
|
||||
|
||||
gc_date = fields.Datetime('Local cleanup date', compute='_compute_gc_date')
|
||||
gc_delay = fields.Integer('Cleanup Delay', help='Used to compute gc_date')
|
||||
@ -465,6 +468,24 @@ class BuildResult(models.Model):
|
||||
else:
|
||||
build.build_time = 0
|
||||
|
||||
#@api.depends('create_date', 'last_update')
|
||||
def _compute_wait_time(self):
|
||||
for build in self:
|
||||
build.wait_time = dt2time(build.last_update) - dt2time(build.create_date)
|
||||
|
||||
#@api.depends('build_end', 'children_ids.last_update')
|
||||
def _compute_last_update(self):
|
||||
for build in self:
|
||||
if not build.build_end:
|
||||
build.last_update = datetime.datetime.now()
|
||||
else:
|
||||
build.last_update = max([child.last_update for child in build.children_ids] + [build.build_end])
|
||||
|
||||
#@api.depends('build_time', 'children_ids.load_time')
|
||||
def _compute_load_time(self):
|
||||
for build in self:
|
||||
build.load_time = sum([build.build_time] + [child.load_time for child in build.children_ids])
|
||||
|
||||
@api.depends('job_start')
|
||||
def _compute_build_age(self):
|
||||
"""Return the time between job start and now"""
|
||||
@ -1163,9 +1184,6 @@ class BuildResult(models.Model):
|
||||
self._log('write_file', 'exception: %s' % e)
|
||||
return False
|
||||
|
||||
def _get_formated_build_time(self):
|
||||
return s2human(self.build_time)
|
||||
|
||||
def _get_color_class(self):
|
||||
|
||||
if self.global_result == 'ko':
|
||||
|
@ -325,7 +325,7 @@ class ConfigStep(models.Model):
|
||||
if not self:
|
||||
return False
|
||||
self.ensure_one()
|
||||
return self.job_type in ('install_odoo', 'run_odoo', 'restore', 'test_upgrade') or (self.job_type == 'python' and ('docker_params =' in self.python_code or '_run_' in self.python_code))
|
||||
return self.job_type in ('install_odoo', 'run_odoo', 'restore', 'test_upgrade') or (self.job_type == 'python' and ('docker_params =' in self.python_code or '_run_' in self.python_code or 'cmd' in self.python_code))
|
||||
|
||||
def _run_run_odoo(self, build, force=False):
|
||||
if not force:
|
||||
|
@ -11,7 +11,7 @@
|
||||
<td>
|
||||
<a t-esc="batch.bundle_id.name" t-attf-href="/runbot/bundle/{{batch.bundle_id.id}}"/>
|
||||
&emsp;
|
||||
<a groups="runbot.group_runbot_advanced_user" t-attf-href="/web/#id={{batch.id}}&view_type=form&model=runbot.batch&menu_id={{env.ref('runbot.runbot_menu_root').id}}" class="btn btn-default btn-sm" target="new" title="View Batch in Backend">
|
||||
<a groups="runbot.group_runbot_advanced_user" t-attf-href="/web/#id={{batch.id}}&view_type=form&model=runbot.batch&menu_id={{env['ir.model.data']._xmlid_to_res_id('runbot.runbot_menu_root')}}" class="btn btn-default btn-sm" target="new" title="View Batch in Backend">
|
||||
<i class="fa fa-list"/>
|
||||
</a>
|
||||
</td>
|
||||
|
@ -156,16 +156,35 @@
|
||||
</t>
|
||||
<b>Host:</b>
|
||||
<t t-esc="build.host"/>
|
||||
<br/>
|
||||
</t>
|
||||
<b>Total time:</b>
|
||||
<t t-esc="build._get_formated_build_time()"/>
|
||||
<br/>
|
||||
<t t-if="build.stat_ids">
|
||||
<b>Stats:</b>
|
||||
<a t-attf-href="/runbot/build/stats/{{build.id}}">Build <t t-esc="build.id"/></a>
|
||||
<br/>
|
||||
</t>
|
||||
<div>
|
||||
<b title="Execution time of this build, without child time">
|
||||
Build time:
|
||||
</b>
|
||||
<t t-att-tile='build.build_time' t-esc="s2human(build.build_time)"/>
|
||||
<i t-if='more'>(<t t-esc="build.build_time"/>s)</i>
|
||||
</div>
|
||||
<div>
|
||||
<b title='Time from creation to finish (queue time + completion time)'>
|
||||
Wait time:
|
||||
</b>
|
||||
<t t-att-tile='build.wait_time' t-esc="s2human(build.wait_time)"/>
|
||||
<i t-if='more'>(<t t-esc="build.wait_time"/>s)</i>
|
||||
</div>
|
||||
<div>
|
||||
<b title='Total time '>
|
||||
Load time:
|
||||
</b>
|
||||
<t t-att-tile='build.load_time' t-esc="s2human(build.load_time)"/>
|
||||
<i t-if='more'>(<t t-esc="build.load_time"/>s)</i>
|
||||
</div>
|
||||
<div>
|
||||
<t t-if="build.stat_ids">
|
||||
<b>Stats:</b>
|
||||
<a t-attf-href="/runbot/build/stats/{{build.id}}">Build <t t-esc="build.id"/></a>
|
||||
<br/>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6" t-if="build.children_ids">
|
||||
@ -204,7 +223,7 @@
|
||||
</t>
|
||||
</td>
|
||||
<td>
|
||||
<span t-attf-class="badge badge-info" t-esc="child._get_formated_build_time()"/>
|
||||
<span t-attf-class="badge badge-info" t-esc="s2human(child.build_time)"/>
|
||||
</td>
|
||||
<td>
|
||||
<t t-call="runbot.build_button">
|
||||
@ -336,7 +355,7 @@
|
||||
<td/><td/><td/>
|
||||
<td t-attf-class="bg-{{'info' if error.active else 'success'}}-light {{size}}" colspan="2">
|
||||
This error is already <a href="#" t-attf-title="{{'Was detected by runbot in nightly builds.' if error.active else 'Either the error is not properly fixed or the branch does not contain the fix.'}}"><t t-esc="'known' if error.active else 'fixed'"/></a>.
|
||||
<a groups="runbot.group_user" t-attf-href="/web#id={{l.error_id.id}}&view_type=form&model=runbot.build.error&menu_id={{env.ref('runbot.runbot_menu_root').id}}" title="View in Backend" target="new">
|
||||
<a groups="runbot.group_user" t-attf-href="/web#id={{l.error_id.id}}&view_type=form&model=runbot.build.error&menu_id={{env['ir.model.data']._xmlid_to_res_id('runbot.runbot_menu_root')}}" title="View in Backend" target="new">
|
||||
<i t-attf-class="fa fa-{{icon}}"/>
|
||||
</a>
|
||||
<span groups="runbot.group_runbot_admin" t-if="error.responsible or error.responsible.id == uid">(<i t-esc="error.responsible.name"/>)</span>
|
||||
@ -387,7 +406,7 @@
|
||||
<span t-esc="build.params_id.version_id.name"/>
|
||||
</td>
|
||||
<td>
|
||||
<span t-esc="build._get_formated_build_time()"/>
|
||||
<span t-esc="s2human(build.build_time)"/>
|
||||
</td>
|
||||
<td>
|
||||
<t t-call="runbot.build_button">
|
||||
|
@ -38,7 +38,7 @@
|
||||
</div>
|
||||
<div class="col">
|
||||
<a t-att-href="build_error.last_seen_build_id.build_url" t-attf-title="View last affected build ({{build_error.last_seen_build_id.id}})"><i class="fa fa-external-link"/></a>
|
||||
<a groups="base.group_user" t-attf-href="/web/#id={{build_error.id}}&view_type=form&model=runbot.build.error&menu_id={{env.ref('runbot.runbot_menu_root').id}}" target="new" title="View in Backend">
|
||||
<a groups="base.group_user" t-attf-href="/web/#id={{build_error.id}}&view_type=form&model=runbot.build.error&menu_id={{env['ir.model.data']._xmlid_to_res_id('runbot.runbot_menu_root')}}" target="new" title="View in Backend">
|
||||
<span class="badge badge-info" t-esc="build_error.build_count" t-attf-title="This error was seen {{build_error.build_count}} View in backend"/>
|
||||
</a>
|
||||
<span groups="!base.group_user" class="badge badge-info" t-esc="build_error.build_count" t-attf-title="This error was seen {{build_error.build_count}}"/>
|
||||
@ -114,7 +114,7 @@
|
||||
<div t-if="team" class='col-md-12'>
|
||||
<div class="col-lg-12 text-center mb16">
|
||||
<h2>Team <t t-esc="team.name.capitalize()"/>
|
||||
<a groups="base.group_user" t-attf-href="/web/#id={{team.id}}&view_type=form&model=runbot.team&menu_id={{env.ref('runbot.runbot_menu_root').id}}" target="new" title="View in Backend">
|
||||
<a groups="base.group_user" t-attf-href="/web/#id={{team.id}}&view_type=form&model=runbot.team&menu_id={{env['ir.model.data']._xmlid_to_res_id('runbot.runbot_menu_root')}}" target="new" title="View in Backend">
|
||||
<i class="fa fa-list"/>
|
||||
</a>
|
||||
</h2>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<t t-esc="bundle.name"/>
|
||||
<i t-if="bundle.sticky" class="fa fa-star" style="color: #f0ad4e" />
|
||||
<div class="btn-group" role="group">
|
||||
<a groups="runbot.group_runbot_advanced_user" t-attf-href="/web/#id={{bundle.id}}&view_type=form&model=runbot.bundle&menu_id={{env.ref('runbot.runbot_menu_root').id}}" class="btn btn-default btn-sm" target="new" title="View in Backend">
|
||||
<a groups="runbot.group_runbot_advanced_user" t-attf-href="/web/#id={{bundle.id}}&view_type=form&model=runbot.bundle&menu_id={{env['ir.model.data']._xmlid_to_res_id('runbot.runbot_menu_root')}}" class="btn btn-default btn-sm" target="new" title="View in Backend">
|
||||
<i class="fa fa-list"/>
|
||||
</a>
|
||||
<a groups="runbot.group_runbot_advanced_user" class="btn btn-default" t-attf-href="/runbot/bundle/{{bundle.id}}/force" title="Force A New Batch">
|
||||
|
@ -325,7 +325,7 @@
|
||||
<i class="fa fa-search"/>
|
||||
Find similar builds
|
||||
</a>
|
||||
<a class="dropdown-item" t-attf-href="/web/#id={{bu['id']}}&view_type=form&model=runbot.build&menu_id={{env.ref('runbot.runbot_menu_root').id}}" target="new">
|
||||
<a class="dropdown-item" t-attf-href="/web/#id={{bu['id']}}&view_type=form&model=runbot.build&menu_id={{env['ir.model.data']._xmlid_to_res_id('runbot.runbot_menu_root')}}" target="new">
|
||||
<i class="fa fa-list"/>
|
||||
View in backend
|
||||
</a>
|
||||
|
Loading…
Reference in New Issue
Block a user