[SATYR PATCH 4/5] Short text representation for java stacktraces
Martin Milata
mmilata at redhat.com
Fri May 24 15:55:22 UTC 2013
Signed-off-by: Martin Milata <mmilata at redhat.com>
---
lib/java_stacktrace.c | 29 +++++++++++++++++++++++++++++
lib/java_stacktrace.h | 8 ++++++++
python/py_java_stacktrace.c | 27 +++++++++++++++++++++++++++
python/py_java_stacktrace.h | 1 +
tests/python/java.py | 13 +++++++++++++
5 files changed, 78 insertions(+)
diff --git a/lib/java_stacktrace.c b/lib/java_stacktrace.c
index 527e3f4..382da7f 100644
--- a/lib/java_stacktrace.c
+++ b/lib/java_stacktrace.c
@@ -195,3 +195,32 @@ sr_java_stacktrace_get_reason(struct sr_java_stacktrace *stacktrace)
return sr_asprintf("Exception %s occurred in %s:%"PRIu32, exc, file, line);
}
+
+char *
+sr_java_stacktrace_to_short_text(struct sr_java_stacktrace *stacktrace,
+ int max_frames)
+{
+ if (!stacktrace->threads)
+ return NULL;
+
+ struct sr_strbuf *strbuf = sr_strbuf_new();
+
+ /* FIXME: is the first thread the crash (or otherwise interesting) thread?
+ */
+ struct sr_java_thread *thread = stacktrace->threads;
+ struct sr_java_frame *frame;
+ int i = 0;
+
+ for (frame = thread->frames; frame; frame = frame->next)
+ {
+ i++;
+ sr_strbuf_append_strf(strbuf, "#%d ", i);
+ sr_java_frame_append_to_str(frame, strbuf);
+ sr_strbuf_append_char(strbuf, '\n');
+
+ if (max_frames && i >= max_frames)
+ break;
+ }
+
+ return sr_strbuf_free_nobuf(strbuf);
+}
diff --git a/lib/java_stacktrace.h b/lib/java_stacktrace.h
index e267f73..63076de 100644
--- a/lib/java_stacktrace.h
+++ b/lib/java_stacktrace.h
@@ -133,6 +133,14 @@ sr_java_stacktrace_get_reason(struct sr_java_stacktrace *stacktrace);
char *
sr_java_stacktrace_to_json(struct sr_java_stacktrace *stacktrace);
+/**
+ * Returns brief textual representation of the stacktrace, or NULL in case of
+ * failure. Caller has to free it using free().
+ */
+char *
+sr_java_stacktrace_to_short_text(struct sr_java_stacktrace *stacktrace,
+ int max_frames);
+
#ifdef __cplusplus
}
#endif
diff --git a/python/py_java_stacktrace.c b/python/py_java_stacktrace.c
index 53a0100..56f5fdf 100644
--- a/python/py_java_stacktrace.c
+++ b/python/py_java_stacktrace.c
@@ -17,6 +17,10 @@
"Clones the stacktrace object. All new structures are independent " \
"on the original object."
+#define b_to_short_text "Usage: stacktrace.to_short_text([max_frames])\n" \
+ "Returns short text representation of the stacktrace. If max_frames is\n" \
+ "specified, the result includes only that much topmost frames.\n"
+
#define b_normalize_doc "Usage: stacktrace.normalize()\n" \
"Normalizes all threads in the stacktrace."
@@ -28,6 +32,7 @@ java_stacktrace_methods[] =
{
/* methods */
{ "dup", sr_py_java_stacktrace_dup, METH_NOARGS, b_dup_doc },
+ { "to_short_text", sr_py_java_stacktrace_to_short_text, METH_VARARGS, b_to_short_text },
// { "normalize", sr_py_java_stacktrace_normalize, METH_NOARGS, b_normalize_doc },
{ NULL },
};
@@ -272,6 +277,28 @@ sr_py_java_stacktrace_dup(PyObject *self, PyObject *args)
return (PyObject*)bo;
}
+PyObject *
+sr_py_java_stacktrace_to_short_text(PyObject *self, PyObject *args)
+{
+ int max_frames = 0;
+ if (!PyArg_ParseTuple(args, "|i", &max_frames))
+ return NULL;
+
+ struct sr_py_java_stacktrace *this = (struct sr_py_java_stacktrace*)self;
+ if (java_stacktrace_prepare_linked_list(this) < 0)
+ return NULL;
+
+ char *text =
+ sr_java_stacktrace_to_short_text(this->stacktrace, max_frames);
+ if (!text)
+ return NULL;
+
+ PyObject *result = PyString_FromString(text);
+
+ free(text);
+ return result;
+}
+
/*
* Normalization not yet implemente for java stacktraces
*
diff --git a/python/py_java_stacktrace.h b/python/py_java_stacktrace.h
index c92d76e..74996dc 100644
--- a/python/py_java_stacktrace.h
+++ b/python/py_java_stacktrace.h
@@ -62,6 +62,7 @@ PyObject *sr_py_java_stacktrace_str(PyObject *self);
/* methods */
PyObject *sr_py_java_stacktrace_dup(PyObject *self, PyObject *args);
PyObject *sr_py_java_stacktrace_normalize(PyObject *self, PyObject *args);
+PyObject *sr_py_java_stacktrace_to_short_text(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
diff --git a/tests/python/java.py b/tests/python/java.py
index ba0cb49..7b4685e 100755
--- a/tests/python/java.py
+++ b/tests/python/java.py
@@ -12,6 +12,15 @@ except ImportError:
path = '../java_stacktraces/java-02'
threads_expected = 1
frames_expected = 32
+expected_short_text = '''#1 org.hibernate.exception.ConstraintViolationException: could not insert: [com.example.myproject.MyEntity]
+#2 \tat org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) [unknown]
+#3 \tat org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) [unknown]
+#4 \tat org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:64) [unknown]
+#5 com.example.myproject.MyProjectServletException
+#6 \tat com.example.myproject.MyServlet.doPost(MyServlet.java:169) [unknown]
+#7 \tat javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [unknown]
+#8 \tat javax.servlet.http.HttpServlet.service(HttpServlet.java:820) [unknown]
+'''
if not os.path.isfile(path):
path = '../' + path
@@ -52,6 +61,10 @@ class TestJavaStacktrace(BindingsTestCase):
out = str(self.trace)
self.assertTrue(('Java stacktrace with %d threads' % threads_expected) in out)
+ def test_to_short_text(self):
+ self.assertEqual(self.trace.to_short_text(8), expected_short_text)
+
+
class TestJavaThread(BindingsTestCase):
def setUp(self):
self.thread = satyr.JavaStacktrace(contents).threads[0]
--
1.7.11.7
More information about the Crash-catcher
mailing list