Reduce the default date range on Overview panel to 1 day

First, the default default date range used on Overview panel is made
configurable (setting OVERVIEW_DAYS_RANGE). Second, its default value
is set to 1 day. Changing the default behavior is aimed to improve
load time of the default page in the presence of large amounts of
data. If OVERVIEW_DAYS_RANGE setting is explicitly set to None, the
behavior remains the same - the default date range is from the
beginning of the current month until today.

Co-Authored-By: Dmitry Sutyagin <dsutyagin@mirantis.com>
Change-Id: I55a0397f69e33ba9c8fb1f27d57838efcd8648af
Closes-Bug: #1508571
This commit is contained in:
Timur Sufiev 2015-10-21 21:31:28 +03:00
parent 482c85db23
commit 5da5fd3196
7 changed files with 118 additions and 29 deletions

View File

@ -815,6 +815,22 @@ Used to customize features related to the image service, such as the list of
supported image formats.
``OVERVIEW_DAYS_RANGE``
-----------------------
.. versionadded:: 10.0.0(Newton)
Default:: ``1``
When set to an integer N (as by default), the start date in the Overview panel
meters will be today minus N days. This setting is used to limit the amount of
data fetched by default when rendering the Overview panel. If set to ``None``
(which corresponds to the behavior in past Horizon versions), the start date
will be from the beginning of the current month until the current date. The
legacy behaviour is not recommended for large deployments as Horizon suffers
significant lags in this case.
``IMAGE_CUSTOM_PROPERTY_TITLES``
--------------------------------

View File

@ -20,6 +20,7 @@ import datetime
from django.core.urlresolvers import reverse
from django import http
from django.test.utils import override_settings
from django.utils import encoding
from django.utils import timezone
@ -52,21 +53,34 @@ class UsageViewTests(test.BaseAdminViewTests):
'SimpleTenantUsage', IsA(http.HttpRequest)) \
.AndReturn(nova_stu_enabled)
@override_settings(OVERVIEW_DAYS_RANGE=None)
def test_usage(self):
self._test_usage(nova_stu_enabled=True, overview_days_range=None)
def test_usage_1_day(self):
self._test_usage(nova_stu_enabled=True)
@override_settings(OVERVIEW_DAYS_RANGE=None)
def test_usage_disabled(self):
self._test_usage(nova_stu_enabled=False)
self._test_usage(nova_stu_enabled=False, overview_days_range=None)
def test_usage_with_deleted_tenant(self):
self._test_usage(tenant_deleted=True)
def _test_usage(self, nova_stu_enabled=True, tenant_deleted=False):
def _get_start_end_range(self, overview_days_range):
now = timezone.now()
if overview_days_range:
start_day = now - datetime.timedelta(days=overview_days_range)
else:
start_day = datetime.date(now.year, now.month, 1)
return start_day, now
def _test_usage(self, nova_stu_enabled=True, tenant_deleted=False,
overview_days_range=1):
self._stub_api_calls(nova_stu_enabled)
api.nova.extension_supported(
'SimpleTenantUsage', IsA(http.HttpRequest)) \
.AndReturn(nova_stu_enabled)
now = timezone.now()
usage_list = [api.nova.NovaUsage(u) for u in self.usages.list()]
if tenant_deleted:
api.keystone.tenant_list(IsA(http.HttpRequest)) \
@ -76,10 +90,11 @@ class UsageViewTests(test.BaseAdminViewTests):
.AndReturn([self.tenants.list(), False])
if nova_stu_enabled:
start_day, now = self._get_start_end_range(overview_days_range)
api.nova.usage_list(IsA(http.HttpRequest),
datetime.datetime(now.year,
now.month,
1, 0, 0, 0, 0),
datetime.datetime(start_day.year,
start_day.month,
start_day.day, 0, 0, 0, 0),
datetime.datetime(now.year,
now.month,
now.day, 23, 59, 59, 0)) \
@ -150,26 +165,32 @@ class UsageViewTests(test.BaseAdminViewTests):
else:
self.assertNotContains(res, usage_table, html=True)
@override_settings(OVERVIEW_DAYS_RANGE=None)
def test_usage_csv(self):
self._test_usage_csv(nova_stu_enabled=True, overview_days_range=None)
def test_usage_csv_1_day(self):
self._test_usage_csv(nova_stu_enabled=True)
@override_settings(OVERVIEW_DAYS_RANGE=None)
def test_usage_csv_disabled(self):
self._test_usage_csv(nova_stu_enabled=False)
self._test_usage_csv(nova_stu_enabled=False, overview_days_range=None)
def _test_usage_csv(self, nova_stu_enabled=True):
def _test_usage_csv(self, nova_stu_enabled=True, overview_days_range=1):
self._stub_api_calls(nova_stu_enabled)
api.nova.extension_supported(
'SimpleTenantUsage', IsA(http.HttpRequest)) \
.AndReturn(nova_stu_enabled)
now = timezone.now()
usage_obj = [api.nova.NovaUsage(u) for u in self.usages.list()]
api.keystone.tenant_list(IsA(http.HttpRequest)) \
.AndReturn([self.tenants.list(), False])
if nova_stu_enabled:
start_day, now = self._get_start_end_range(overview_days_range)
api.nova.usage_list(IsA(http.HttpRequest),
datetime.datetime(now.year,
now.month,
1, 0, 0, 0, 0),
datetime.datetime(start_day.year,
start_day.month,
start_day.day,
0, 0, 0, 0),
datetime.datetime(now.year,
now.month,
now.day, 23, 59, 59, 0)) \

View File

@ -1553,14 +1553,23 @@ class UsageViewTests(test.BaseAdminViewTests):
def test_usage_csv_disabled(self):
self._test_usage_csv(nova_stu_enabled=False)
def _test_usage_csv(self, nova_stu_enabled=True):
@override_settings(OVERVIEW_DAYS_RANGE=1)
def test_usage_csv_1_day(self):
self._test_usage_csv(nova_stu_enabled=True, overview_days_range=1)
def _test_usage_csv(self, nova_stu_enabled=True, overview_days_range=None):
now = timezone.now()
usage_obj = api.nova.NovaUsage(self.usages.first())
self._stub_nova_api_calls(nova_stu_enabled)
api.nova.extension_supported(
'SimpleTenantUsage', IsA(http.HttpRequest)) \
.AndReturn(nova_stu_enabled)
start = datetime.datetime(now.year, now.month, 1, 0, 0, 0, 0)
if overview_days_range:
start_day = now - datetime.timedelta(days=overview_days_range)
else:
start_day = datetime.date(now.year, now.month, 1)
start = datetime.datetime(start_day.year, start_day.month,
start_day.day, 0, 0, 0, 0)
end = datetime.datetime(now.year, now.month, now.day, 23, 59, 59, 0)
if nova_stu_enabled:

View File

@ -23,6 +23,7 @@ from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME # noqa
from django.core.urlresolvers import reverse
from django import http
from django.test.utils import override_settings
from django.utils import timezone
from mox3.mox import IsA # noqa
@ -42,7 +43,7 @@ class UsageViewTests(test.TestCase):
'extension_supported')})
def _stub_nova_api_calls(self, nova_stu_enabled=True,
tenant_limits_exception=False,
stu_exception=False):
stu_exception=False, overview_days_range=None):
api.nova.extension_supported(
'SimpleTenantUsage', IsA(http.HttpRequest)) \
.AndReturn(nova_stu_enabled)
@ -58,7 +59,8 @@ class UsageViewTests(test.TestCase):
.AndReturn(self.limits['absolute'])
if nova_stu_enabled:
self._nova_stu_enabled(stu_exception)
self._nova_stu_enabled(stu_exception,
overview_days_range=overview_days_range)
@test.create_stubs({api.cinder: ('tenant_absolute_limits',)})
def _stub_cinder_api_calls(self):
@ -81,9 +83,14 @@ class UsageViewTests(test.TestCase):
api.network.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.q_secgroups.list())
def _nova_stu_enabled(self, exception=False):
def _nova_stu_enabled(self, exception=False, overview_days_range=1):
now = timezone.now()
start = datetime.datetime(now.year, now.month, 1, 0, 0, 0, 0)
if overview_days_range:
start_day = now - datetime.timedelta(days=overview_days_range)
else:
start_day = datetime.date(now.year, now.month, 1)
start = datetime.datetime(start_day.year, start_day.month,
start_day.day, 0, 0, 0, 0)
end = datetime.datetime(now.year, now.month, now.day, 23, 59, 59, 0)
if exception:
@ -110,14 +117,20 @@ class UsageViewTests(test.TestCase):
self.assertEqual(usages.limits['maxTotalFloatingIps'],
maxTotalFloatingIps)
@override_settings(OVERVIEW_DAYS_RANGE=None)
def test_usage(self):
self._test_usage(nova_stu_enabled=True, overview_days_range=None)
def test_usage_1_day(self):
self._test_usage(nova_stu_enabled=True)
@override_settings(OVERVIEW_DAYS_RANGE=None)
def test_usage_disabled(self):
self._test_usage(nova_stu_enabled=False)
self._test_usage(nova_stu_enabled=False, overview_days_range=None)
def _test_usage(self, nova_stu_enabled):
self._stub_nova_api_calls(nova_stu_enabled)
def _test_usage(self, nova_stu_enabled, overview_days_range=1):
self._stub_nova_api_calls(nova_stu_enabled,
overview_days_range=overview_days_range)
self._stub_neutron_api_calls()
self._stub_cinder_api_calls()
self.mox.ReplayAll()
@ -174,11 +187,16 @@ class UsageViewTests(test.TestCase):
def test_usage_csv(self):
self._test_usage_csv(nova_stu_enabled=True)
@override_settings(OVERVIEW_DAYS_RANGE=1)
def test_usage_csv_1_day(self):
self._test_usage_csv(nova_stu_enabled=True, overview_days_range=1)
def test_usage_csv_disabled(self):
self._test_usage_csv(nova_stu_enabled=False)
def _test_usage_csv(self, nova_stu_enabled=True):
self._stub_nova_api_calls(nova_stu_enabled)
def _test_usage_csv(self, nova_stu_enabled=True, overview_days_range=None):
self._stub_nova_api_calls(nova_stu_enabled,
overview_days_range=overview_days_range)
self._stub_neutron_api_calls()
self._stub_cinder_api_calls()
self.mox.ReplayAll()

View File

@ -771,3 +771,8 @@ REST_API_REQUIRED_SETTINGS = ['OPENSTACK_HYPERVISOR_FEATURES',
# " [%(http_status)s] [%(param)s]"),
#}
# The default date range in the Overview panel meters - either <today> minus N
# days (if the value is integer N), or from the beginning of the current month
# until today (if set to None). This setting should be used to limit the amount
# of data fetched by default when rendering the Overview panel.
#OVERVIEW_DAYS_RANGE = 1

View File

@ -14,6 +14,7 @@ from __future__ import division
import datetime
from django.conf import settings
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
@ -40,6 +41,14 @@ class BaseUsage(object):
def today(self):
return timezone.now()
@property
def first_day(self):
days_range = getattr(settings, 'OVERVIEW_DAYS_RANGE', 1)
if days_range:
return self.today.date() - datetime.timedelta(days=days_range)
else:
return datetime.date(self.today.year, self.today.month, 1)
@staticmethod
def get_start(year, month, day):
start = datetime.datetime(year, month, day, 0, 0, 0)
@ -57,7 +66,8 @@ class BaseUsage(object):
def get_date_range(self):
if not hasattr(self, "start") or not hasattr(self, "end"):
args_start = (self.today.year, self.today.month, 1)
args_start = (self.first_day.year, self.first_day.month,
self.first_day.day)
args_end = (self.today.year, self.today.month, self.today.day)
form = self.get_form()
if form.is_valid():
@ -73,14 +83,13 @@ class BaseUsage(object):
messages.error(self.request,
_("Invalid date format: "
"Using today as default."))
self.start = self.get_start(*args_start)
self.end = self.get_end(*args_end)
self.start = self.get_start(*args_start)
self.end = self.get_end(*args_end)
return self.start, self.end
def init_form(self):
today = datetime.date.today()
self.start = datetime.date(day=1, month=today.month, year=today.year)
self.end = today
self.start = self.first_day
self.end = self.today.date()
return self.start, self.end

View File

@ -0,0 +1,11 @@
---
features:
- Add a new setting OVERVIEW_DAYS_RANGE.
It defines the default date range in the Overview panel meters - either
today minus N days (if the value is integer N), or from the beginning of
the current month until today (if set to None). This setting is be used to
limit the amount of data fetched by default when rendering the Overview
panel. The default value is 1, which differs from the past behaviour, since
it caused serious lags on large deployments.
fixes:
- https://bugs.launchpad.net/horizon/+bug/1508571