PG Jobmon Exception Handling
As a quick review for those unfamiliar with what PG Jobmon is, it’s an extension to allow autonomously logging steps within a function so that if the function fails, the individually logged steps are not rolled back and lost. This provides an audit trail and monitoring capabilities for functions critical to your database infrastructure. See my Projects page for the code and other posts tagged with “pg_jobmon” for more info.
One of the tricker issues I came across when making an extension out of the existing code that PG Jobmon was based on was getting useful errors back, both on the console and in the log tables. If an error happened before you logged the first step, or job logging even started, trying to handle logging the errors in the exception block would cause some rather useless feedback, often hiding the real error. The below has become sort of a template for any function’s exception block where I use jobmon.
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS v_ex_context = PG_EXCEPTION_CONTEXT;
IF v_job_id IS NULL THEN
v_job_id := jobmon.add_job('JOB NAME HERE');
v_step_id := jobmon.add_step(v_job_id, 'Exception occurred before job logging started');
ELSIF v_step_id IS NULL THEN
v_step_id := jobmon.add_step(v_job_id, 'EXCEPTION before first step logged');
END IF;
PERFORM jobmon.update_step(v_step_id, 'CRITICAL', 'ERROR: '||coalesce(SQLERRM,'unknown'));
PERFORM jobmon.fail_job(v_job_id);
RAISE EXCEPTION '%
CONTEXT: %', SQLERRM, v_ex_context;
This accounts for when an error occurs before job logging started (call to add_job) or if it occurs between job logging starting and the first step being logged (between add_job and first call to add_step). Another call to RAISE EXCEPTION with the original SQL error is made after all that to ensure the real error is still reported back normally.
UPDATE (2013-02-07): I’ve added some additional error output to the actual raising of the exception to better show where the error is coming from. If you’d like that in your jobmon log as well, just add the variable into the update_step() call. The only downside to this is that GET STACKED DIAGNOSTIC only works on 9.2.