Module: check_mk
Branch: master
Commit: a08c235c0f541d2f9204bfd21cd204ae71767545
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=a08c235c0f541d…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Wed Feb 3 14:32:37 2016 +0100
Improved exception in case of having non json dumpable objects in local vars
---
modules/check_mk_base.py | 46 ++++++++++++++++++++++++++++++++++++++---
web/htdocs/crash_reporting.py | 15 +++++++++-----
2 files changed, 53 insertions(+), 8 deletions(-)
diff --git a/modules/check_mk_base.py b/modules/check_mk_base.py
index 60484bc..4327f22 100644
--- a/modules/check_mk_base.py
+++ b/modules/check_mk_base.py
@@ -1516,10 +1516,42 @@ def is_manual_check(hostname, check_type, item):
return (check_type, item) in manual_checks
+def format_var_for_export(val):
+ if isinstance(val, dict):
+ for item_key, item_val in val.items():
+ val[item_key] = format_var_for_export(item_val)
+
+ elif isinstance(val, list):
+ for index, item in enumerate(val):
+ val[index] = format_var_for_export(item)
+
+ elif isinstance(val, tuple):
+ new_val = ()
+ for item in val:
+ new_val += (format_var_for_export(item),)
+ val = new_val
+
+ # Check and limit size
+ if type(val) in (str, unicode):
+ size_limit = 1024*1024
+ size = len(val)
+ if size > size_limit:
+ val = val[:size_limit] + "... (%d bytes stripped)" % (size -
size_limit)
+
+ return val
+
+
+def get_local_vars_of_last_exception():
+ local_vars = {}
+ import inspect
+ for key, val in inspect.trace()[-1][0].f_locals.items():
+ local_vars[key] = format_var_for_export(val)
+ return local_vars
+
+
def create_crash_dump_info_file(crash_dir, hostname, check_type, item, params,
description, info, text):
exc_type, exc_value, exc_traceback = sys.exc_info()
- import inspect
crash_info = {
"crash_type" : "check",
"time" : time.time(),
@@ -1529,7 +1561,7 @@ def create_crash_dump_info_file(crash_dir, hostname, check_type,
item, params, d
"exc_type" : exc_type.__name__,
"exc_value" : "%s" % exc_value,
"exc_traceback" : traceback.extract_tb(exc_traceback),
- "local_vars" : inspect.trace()[-1][0].f_locals,
+ "local_vars" : get_local_vars_of_last_exception(),
"details" : {
"check_output" : text,
"host" : hostname,
@@ -1549,7 +1581,15 @@ def create_crash_dump_info_file(crash_dir, hostname, check_type,
item, params, d
except ImportError:
import json
- file(crash_dir+"/crash.info",
"w").write(json.dumps(crash_info)+"\n")
+
+ # The default JSON encoder raises an exception when detecting unknown types. For the
crash
+ # reporting it is totally ok to have some string representations of the objects.
+ class RobustJSONEncoder(json.JSONEncoder):
+ # Are there cases where no __str__ is available? if so, we should do something
like %r
+ def default(self, o):
+ return "%s" % o
+
+ file(crash_dir+"/crash.info", "w").write(json.dumps(crash_info,
cls=RobustJSONEncoder)+"\n")
def get_os_info():
diff --git a/web/htdocs/crash_reporting.py b/web/htdocs/crash_reporting.py
index 15dcb9a..5036aaa 100644
--- a/web/htdocs/crash_reporting.py
+++ b/web/htdocs/crash_reporting.py
@@ -393,10 +393,7 @@ def get_local_vars_of_last_exception():
def format_var_for_export(val):
- if inspect.isclass(val) or inspect.isroutine(val) or type(val).__name__ ==
"instance":
- return "%s" % val
-
- elif isinstance(val, dict):
+ if isinstance(val, dict):
for item_key, item_val in val.items():
val[item_key] = format_var_for_export(item_val)
@@ -420,6 +417,14 @@ def format_var_for_export(val):
return val
+# The default JSON encoder raises an exception when detecting unknown types. For the
crash
+# reporting it is totally ok to have some string representations of the objects.
+class RobustJSONEncoder(json.JSONEncoder):
+ # Are there cases where no __str__ is available? if so, we should do something like
%r
+ def default(self, o):
+ return "%s" % o
+
+
# Slightly duplicate code with modules/check_mk_base.py. Maybe create some kind of
central library?
def create_crash_dump_info_file(tar):
exc_type, exc_value, exc_traceback = sys.exc_info()
@@ -448,7 +453,7 @@ def create_crash_dump_info_file(tar):
}
content = cStringIO.StringIO()
- content.write(json.dumps(crash_info))
+ content.write(json.dumps(crash_info, cls=RobustJSONEncoder))
content.seek(0)
tarinfo = tarfile.TarInfo(name="crash.info")