| From: | "P(dot) Scott DeVos" <scott(at)countrysidetechnology(dot)com> | 
|---|---|
| To: | pgsql-patches(at)postgresql(dot)org | 
| Subject: | plpython tracebacks | 
| Date: | 2006-02-06 22:05:37 | 
| Message-ID: | 43E7C831.3050207@countrysidetechnology.com | 
| Views: | Whole Thread | Raw Message | Download mbox | Resend email | 
| Thread: | |
| Lists: | pgsql-patches | 
I have been working with plpython for several months and have
been hampered by the lack of a traceback being logged when a
plpython function raises an error.  I have written a patch causes
the PLy_traceback function to fully log the traceback.  The
output looks just like the traceback output provided by the
python interpreter.
Feedback appreciated.
Scott
--- plpython-1.70.c.orig	2006-02-06 14:24:42.000000000 -0600
+++ plpython-1.70.c.patched	2006-02-06 15:34:05.000000000 -0600
@@ -2499,7 +2499,8 @@
  			   *vob = NULL;
  	char	   *vstr,
  			   *estr,
-			   *xstr = NULL;
+			   *xstr = NULL,
+			   *tbstr;
  	/*
  	 * get the current exception
@@ -2523,6 +2524,82 @@
  	else
  		vstr = "Unknown";
+	/* If there is a traceback object, we build a string containing
+	   the traceback information. */
+	if (tb != NULL)
+	{
+		PyObject
+			*cur_tb,  /* traceback (tb) item being handled */
+			*old_tb,  /* holds tb so we can decrement reference to it */
+			*hdr,     /* First line of logged output */
+			*tmpl,    /* PyString template for the logged tb item */
+			*ftr,     /* Last line of logged output */
+			*tb_list, /* Each tb item create a PyString in this list */
+			*ln,      /* The line number of the item in the traceback */
+			*frame,   /* the tb_frame */
+			*code,    /* the f_code this guy has filename and method name*/
+			*fn,      /* the filename of the item in the tb */
+			*nm,      /* the function/method name of the item in the tb */
+			*args,    /* A tuple of the form (fn, ln, nm) */
+			*logline, /* The assembled string with the logged message */
+			*os,      /* points to the os module */
+			*sep,     /* line separator */
+			*tb_log;  /* PyString with the assembled log msg */
+
+		hdr = PyString_FromString("Traceback (most recent call last):");
+		tmpl = PyString_FromString("  File \"%s\", line %s, in %s");
+		ftr = PyString_FromString("");
+
+		tb_list = PyList_New(0);     /* create the list of strings */
+		PyList_Append(tb_list, hdr); /* Append the header to the list */
+
+		/* 1st tb is useless; throw it away */
+		cur_tb = PyObject_GetAttrString(tb, "tb_next");
+		while (cur_tb != Py_None)
+		{
+			
+			ln = PyObject_GetAttrString(cur_tb, "tb_lineno");
+			frame = PyObject_GetAttrString(cur_tb, "tb_frame");
+			code = PyObject_GetAttrString(frame, "f_code");
+			fn = PyObject_GetAttrString(code, "co_filename");
+			nm = PyObject_GetAttrString(code, "co_name");
+
+			args = Py_BuildValue("(OOO)", fn, ln, nm); /* args tuple */
+			logline = PyString_Format(tmpl, args); /* build logged string */
+			PyList_Append(tb_list, logline);       /* append string to list */
+
+			/* decrement references on all our objects */
+			Py_DECREF(logline);
+			Py_DECREF(args);
+			Py_XDECREF(nm);
+			Py_XDECREF(fn);
+			Py_XDECREF(code);
+			Py_XDECREF(frame);
+			Py_XDECREF(ln);
+
+			old_tb = cur_tb;
+			/* get the next traceback item */
+			cur_tb = PyObject_GetAttrString(cur_tb, "tb_next");
+			Py_DECREF(old_tb);    /* we're done with old_tb so decref it */
+		}
+		PyList_Append(tb_list, ftr); /* append the log msg footer */
+
+		os = PyImport_ImportModule("os");
+		sep = PyObject_GetAttrString(os, "linesep"); /* get os EOL char */
+		tb_log = _PyString_Join(sep, tb_list);       /* create tb log msgs */
+		tbstr = PyString_AsString(tb_log);
+
+		Py_DECREF(tb_log);
+		Py_DECREF(sep);
+		Py_DECREF(os);
+		Py_DECREF(tb_list);
+		Py_DECREF(ftr);
+		Py_DECREF(tmpl);
+		Py_DECREF(hdr);
+	}
+	else
+		tbstr = "No Traceback";
+
  	/*
  	 * I'm not sure what to do if eob is NULL here -- we can't call PLy_elog
  	 * because that function calls us, so we could end up with infinite
@@ -2530,7 +2607,7 @@
  	 * Assert() be more appropriate?
  	 */
  	estr = eob ? PyString_AsString(eob) : "Unknown Exception";
-	xstr = PLy_printf("%s: %s", estr, vstr);
+	xstr = PLy_printf("%s%s: %s", tbstr, estr, vstr);
  	Py_DECREF(eob);
  	Py_XDECREF(vob);
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Thomas F. O'Connell | 2006-02-06 23:56:45 | Re: pgbench: Support Multiple Simultaneous Runs (with Mean and Std. Dev.) | 
| Previous Message | Michael Meskes | 2006-02-06 20:33:16 | Re: [BUGS] BUG #2171: Differences compiling plpgsql in ecpg and psql |