Module: check_mk
Branch: master
Commit: 1c5fc9cc80357dde879e0a59a4f44feb8de71696
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=1c5fc9cc80357d…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Wed Oct 4 07:56:09 2017 +0200
Removed html.log() call
- logging is not related to html rendering
- method was not aware of log levels
There is now a dedicated "log" module to manage the logging of the GUI.
Use something like this now:
C+:
from log import logger
logger.error(...)
C-:
You can use all the features of the default python logging module
loggers now.
Change-Id: Iaa12a99e4e70b4f4cf7925770d01758d813cdfaa
---
web/htdocs/html_mod_python.py | 7 -------
web/htdocs/htmllib.py | 4 ----
2 files changed, 11 deletions(-)
diff --git a/web/htdocs/html_mod_python.py b/web/htdocs/html_mod_python.py
index 9623666..923f131 100644
--- a/web/htdocs/html_mod_python.py
+++ b/web/htdocs/html_mod_python.py
@@ -229,13 +229,6 @@ class html_mod_python(htmllib.html):
self.javascript('update_header_timer()')
self.top_heading_right()
- def log(self, *args):
- for arg in args:
- if type(arg) in (str, unicode):
- text = arg
- else:
- text = repr(arg)
- logger.warning(text)
def http_redirect(self, url):
self.set_http_header('Location', url)
diff --git a/web/htdocs/htmllib.py b/web/htdocs/htmllib.py
index 721b528..0364e18 100644
--- a/web/htdocs/htmllib.py
+++ b/web/htdocs/htmllib.py
@@ -1735,10 +1735,6 @@ class html(HTMLGenerator, RequestHandler):
self.lowlevel_write("%s" % self.render_pre(formatted))
- def log(self, *args):
- raise NotImplementedError()
-
-
#
# URL building
#
Module: check_mk
Branch: master
Commit: 1f519ce4192a43ba3ad16f2b541393416246b5df
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=1f519ce4192a43…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Wed Oct 4 07:54:21 2017 +0200
Changed html.log calls to use logger directly
Change-Id: Icd880beff95483f5457a124bc71753aaef71a22c
---
.bugs/2970 | 7 +++++--
web/htdocs/metrics.py | 5 ++---
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/.bugs/2970 b/.bugs/2970
index fa0a97c..1aefb29 100644
--- a/.bugs/2970
+++ b/.bugs/2970
@@ -1,9 +1,12 @@
Title: Manually defined log level for web.log is not used
Component: wato
-State: open
+Class: bug
+State: works4me
Date: 2017-09-22 10:36:07
Targetversion: 1.4.0
-Class: bug
If the log level is set manually in WATO nothing changes in the global.mk. It
seems that the setting is not used at all.
+
+2017-10-04 07:49:37: changed state open -> works4me
+The setting "User Interface > Logging" is stored in etc/check_mk/multisite.d/wato/global.mk by saving the option log_levels. It works as expected in 1.4 and master.
diff --git a/web/htdocs/metrics.py b/web/htdocs/metrics.py
index 208b44f..dec841d 100644
--- a/web/htdocs/metrics.py
+++ b/web/htdocs/metrics.py
@@ -411,7 +411,7 @@ def parse_perf_data(perf_data_string, check_command=None):
try:
parts = split_perf_data(perf_data_string)
except ValueError, e:
- html.log("Failed to parse perfdata string: %s" % perf_data_string)
+ logger.exception("Failed to parse perfdata string: %s", perf_data_string)
return [], check_command
if not parts:
@@ -464,8 +464,7 @@ def parse_perf_data(perf_data_string, check_command=None):
perf_data.append(perf_data_tuple)
except:
- html.log("Failed to parse perfdata '%s': %s" %
- (perf_data_string, traceback.format_exc()))
+ logger.exception("Failed to parse perfdata '%s'", perf_data_string)
if config.debug:
raise
Module: check_mk
Branch: master
Commit: 91b50e926ac45537f40f8bef5e82fd3201847d1e
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=91b50e926ac455…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Mon Oct 2 15:49:21 2017 +0200
5360 FIX Improved GUI performance when having a large number of custom views or dashboards
Change-Id: I363390977425d705016df1f145480a1105058569
---
.werks/5360 | 10 +++++
web/htdocs/visuals.py | 105 ++++++++++++++++++++++++++++++++++++++------------
2 files changed, 90 insertions(+), 25 deletions(-)
diff --git a/.werks/5360 b/.werks/5360
new file mode 100644
index 0000000..27e027d
--- /dev/null
+++ b/.werks/5360
@@ -0,0 +1,10 @@
+Title: Improved GUI performance when having a large number of custom views or dashboards
+Level: 1
+Component: multisite
+Compatible: compat
+Edition: cre
+Version: 1.5.0i1
+Date: 1506952133
+Class: fix
+
+
diff --git a/web/htdocs/visuals.py b/web/htdocs/visuals.py
index eabd0ad..731be69 100644
--- a/web/htdocs/visuals.py
+++ b/web/htdocs/visuals.py
@@ -99,6 +99,40 @@ def load_plugins(force):
# | |
# '----------------------------------------------------------------------'
+class UserVisualsCache(object):
+ """Realizes a in memory cache (per apache process). This has been introduced to improve the
+ situation where there are hundrets of custom visuals (views here). These visuals are rarely
+ changed, but read and evaluated(!) during each page request which costs a lot of time."""
+ def __init__(self):
+ super(UserVisualsCache, self).__init__()
+ self._cache = {}
+
+
+ def get(self, path):
+ try:
+ cached_modification_timestamp, cached_user_visuals = self._cache[path]
+
+ try:
+ current_modification_timestamp = os.stat(path).st_mtime
+ except IOError:
+ return None # Invalidate cache (file to readable)
+
+ if os.stat(path).st_mtime <= cached_modification_timestamp:
+ return cached_user_visuals # Use cache
+ else:
+ return None # Cache is outdated
+ except KeyError:
+ return None # Not cached yet
+
+
+ def add(self, path, modification_timestamp, user_visuals):
+ self._cache[path] = modification_timestamp, user_visuals
+
+
+_user_visuals_cache = UserVisualsCache()
+
+
+
def save(what, visuals, user_id = None):
if user_id == None:
user_id = config.user.id
@@ -109,6 +143,7 @@ def save(what, visuals, user_id = None):
uservisuals[name] = visual
config.save_user_file('user_' + what, uservisuals, user = user_id)
+
# FIXME: Currently all user visual files of this type are locked. We could optimize
# this not to lock all files but only lock the files the user is about to modify.
def load(what, builtin_visuals, skip_func = None, lock=False):
@@ -128,6 +163,14 @@ def load(what, builtin_visuals, skip_func = None, lock=False):
visuals[('', name)] = visual
# Now scan users subdirs for files "user_*.mk"
+ visuals.update(load_user_visuals(what, builtin_visuals, skip_func, lock))
+
+ return visuals
+
+
+def load_user_visuals(what, builtin_visuals, skip_func, lock):
+ visuals = {}
+
subdirs = os.listdir(config.config_dir)
for user in subdirs:
try:
@@ -148,39 +191,51 @@ def load(what, builtin_visuals, skip_func = None, lock=False):
if not userdb.user_exists(user):
continue
- user_visuals = store.load_data_from_file(path, {}, lock)
- for name, visual in user_visuals.items():
- visual["owner"] = user
- visual["name"] = name
+ user_visuals = _user_visuals_cache.get(path)
+ if user_visuals is None:
+ modification_timestamp = os.stat(path).st_mtime
+ user_visuals = load_visuals_of_a_user(what, builtin_visuals, skip_func, lock, path, user)
+ _user_visuals_cache.add(path, modification_timestamp, user_visuals)
- if skip_func and skip_func(visual):
- continue
+ visuals.update(user_visuals)
- # Maybe resolve inherited attributes. This was a feature for several versions
- # to make the visual texts localizable. This has been removed because the visual
- # texts can now be localized using the custom localization strings.
- # This is needed for backward compatibility to make the visuals without these
- # attributes get the attributes from their builtin visual.
- builtin_visual = visuals.get(('', name))
- if builtin_visual:
- for attr in [ 'title', 'linktitle', 'topic', 'description' ]:
- if attr not in visual and attr in builtin_visual:
- visual[attr] = builtin_visual[attr]
+ except SyntaxError, e:
+ raise MKGeneralException(_("Cannot load %s from %s: %s") % (what, path, e))
- # Repair visuals with missing 'title' or 'description'
- visual.setdefault("title", name)
- visual.setdefault("description", "")
+ return visuals
- # Declare custom permissions
- declare_visual_permission(what, name, visual)
- visuals[(user, name)] = visual
+def load_visuals_of_a_user(what, builtin_visuals, skip_func, lock, path, user):
+ user_visuals = {}
+ for name, visual in store.load_data_from_file(path, {}, lock).items():
+ visual["owner"] = user
+ visual["name"] = name
+ if skip_func and skip_func(visual):
+ continue
- except SyntaxError, e:
- raise MKGeneralException(_("Cannot load %s from %s: %s") % (what, path, e))
+ # Maybe resolve inherited attributes. This was a feature for several versions
+ # to make the visual texts localizable. This has been removed because the visual
+ # texts can now be localized using the custom localization strings.
+ # This is needed for backward compatibility to make the visuals without these
+ # attributes get the attributes from their builtin visual.
+ builtin_visual = builtin_visuals.get(name)
+ if builtin_visual:
+ for attr in [ 'title', 'linktitle', 'topic', 'description' ]:
+ if attr not in visual and attr in builtin_visual:
+ visual[attr] = builtin_visual[attr]
+
+ # Repair visuals with missing 'title' or 'description'
+ visual.setdefault("title", name)
+ visual.setdefault("description", "")
+
+ # Declare custom permissions
+ declare_visual_permission(what, name, visual)
+
+ user_visuals[(user, name)] = visual
+
+ return user_visuals
- return visuals
def declare_visual_permission(what, name, visual):
permname = "%s.%s" % (what[:-1], name)