[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