Permalink
Browse files

pre-flight and post-flight logging hooks

  • Loading branch information...
1 parent 604d4c4 commit 62bb9dfa2d373618f10e46678612720a3a01599a @postwait committed Nov 24, 2011
Showing with 155 additions and 0 deletions.
  1. +5 −0 src/backend/tcop/fastpath.c
  2. +101 −0 src/backend/tcop/postgres.c
  3. +49 −0 src/include/access/hooks.h
@@ -21,6 +21,7 @@
#include <arpa/inet.h>
#include "access/xact.h"
+#include "access/hooks.h"
#include "catalog/pg_proc.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
@@ -333,6 +334,8 @@ HandleFunctionRequest(StringInfo msgBuf)
was_logged = true;
}
+ call_pre_exec_log_hooks(LOG_HOOK_CONTEXT_FASTPATH, fip->fname, NULL, was_logged);
+
/*
* Check permission to access and call function. Since we didn't go
* through a normal name lookup, we need to check schema usage too.
@@ -417,6 +420,8 @@ HandleFunctionRequest(StringInfo msgBuf)
break;
}
+ call_post_exec_log_hooks(LOG_HOOK_CONTEXT_FASTPATH, fip->fname, NULL, was_logged);
+
return 0;
}
View
@@ -42,6 +42,7 @@
#include "access/printtup.h"
#include "access/xact.h"
+#include "access/hooks.h"
#include "catalog/pg_type.h"
#include "commands/async.h"
#include "commands/prepare.h"
@@ -111,6 +112,56 @@ int PostAuthDelay = 0;
* ----------------
*/
+/* a list of hooks for pre and post execution logging */
+static List *pre_exec_log_hooks = NULL;
+static List *post_exec_log_hooks = NULL;
+
+void register_pre_exec_log_hook(pre_exec_log_hook_t f) {
+ MemoryContext oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+ pre_exec_log_hooks = list_append_unique(pre_exec_log_hooks, f);
+ MemoryContextSwitchTo(oldcontext);
+}
+
+void register_post_exec_log_hook(post_exec_log_hook_t f) {
+ MemoryContext oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+ post_exec_log_hooks = list_append_unique(post_exec_log_hooks, f);
+ MemoryContextSwitchTo(oldcontext);
+}
+
+void call_pre_exec_log_hooks(LogHookContext ctx, const char *query,
+ List *tree, bool was_logged)
+{
+ if(list_length(pre_exec_log_hooks) > 0)
+ {
+ ListCell *prelog_item;
+ foreach(prelog_item, pre_exec_log_hooks)
+ {
+ pre_exec_log_hook_t prelog = (pre_exec_log_hook_t)lfirst(prelog_item);
+ prelog(ctx, query, tree, was_logged);
+ }
+ }
+}
+
+void call_post_exec_log_hooks(LogHookContext ctx, const char *query,
+ List *tree, bool was_logged)
+{
+ if(list_length(post_exec_log_hooks) > 0)
+ {
+ ListCell *postlog_item;
+ long secs, usecs;
+ int usecs_part;
+ TimestampDifference(GetCurrentStatementStartTimestamp(),
+ GetCurrentTimestamp(),
+ &secs, &usecs_part);
+ usecs = secs * 1000000 + usecs_part;
+ foreach(postlog_item, post_exec_log_hooks)
+ {
+ post_exec_log_hook_t postlog = (post_exec_log_hook_t)lfirst(postlog_item);
+ postlog(LOG_HOOK_CONTEXT_SIMPLE, query, tree, was_logged, usecs);
+ }
+ }
+}
+
/* max_stack_depth converted to bytes for speed of checking */
static long max_stack_depth_bytes = 100 * 1024L;
@@ -859,6 +910,12 @@ exec_simple_query(const char *query_string)
}
/*
+ * Run all pre-exec log hooks.
+ */
+ call_pre_exec_log_hooks(LOG_HOOK_CONTEXT_SIMPLE, query_string,
+ parsetree_list, was_logged);
+
+ /*
* Switch back to transaction context to enter the loop.
*/
MemoryContextSwitchTo(oldcontext);
@@ -1093,6 +1150,13 @@ exec_simple_query(const char *query_string)
break;
}
+ /*
+ * Run all post-exec log hooks.
+ */
+ call_post_exec_log_hooks(LOG_HOOK_CONTEXT_SIMPLE, query_string,
+ parsetree_list, was_logged);
+
+
if (save_log_statement_stats)
ShowUsage("QUERY STATISTICS");
@@ -1359,6 +1423,12 @@ exec_parse_message(const char *query_string, /* string to execute */
break;
}
+ /*
+ * Run all post-exec log hooks.
+ */
+ call_post_exec_log_hooks(LOG_HOOK_CONTEXT_EXEC_PARSE, query_string,
+ querytree_list, false);
+
if (save_log_statement_stats)
ShowUsage("PARSE MESSAGE STATISTICS");
@@ -1739,6 +1809,12 @@ exec_bind_message(StringInfo input_message)
break;
}
+ /*
+ * Run all post-exec log hooks.
+ */
+ call_post_exec_log_hooks(LOG_HOOK_CONTEXT_BIND, psrc->query_string,
+ portal->stmts, false);
+
if (save_log_statement_stats)
ShowUsage("BIND MESSAGE STATISTICS");
@@ -1875,6 +1951,12 @@ exec_execute_message(const char *portal_name, long max_rows)
}
/*
+ * Run all pre-exec log hooks.
+ */
+ call_pre_exec_log_hooks(LOG_HOOK_CONTEXT_PORTAL, sourceText,
+ portal->stmts, was_logged);
+
+ /*
* If we are in aborted transaction state, the only portals we can
* actually run are those containing COMMIT or ROLLBACK commands.
*/
@@ -1959,6 +2041,25 @@ exec_execute_message(const char *portal_name, long max_rows)
break;
}
+ /*
+ * Run all post-exec log hooks.
+ */
+ if(list_length(post_exec_log_hooks) > 0)
+ {
+ ListCell *postlog_item;
+ long secs, usecs;
+ int usecs_part;
+ TimestampDifference(GetCurrentStatementStartTimestamp(),
+ GetCurrentTimestamp(),
+ &secs, &usecs_part);
+ usecs = secs * 1000000 + usecs_part;
+ foreach(postlog_item, post_exec_log_hooks)
+ {
+ post_exec_log_hook_t postlog = (post_exec_log_hook_t)postlog_item;
+ postlog(LOG_HOOK_CONTEXT_PORTAL, sourceText, portal->stmts, false, usecs);
+ }
+ }
+
if (save_log_statement_stats)
ShowUsage("EXECUTE MESSAGE STATISTICS");
View
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * hooks.h
+ * POSTGRES hooks.
+ *
+ *
+ * Portions Copyright (c) 2011, PostgreSQL Global Development Group
+ *
+ * src/include/access/hooks.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef HOOKS_H
+#define HOOKS_H
+
+#include "nodes/pg_list.h"
+
+/*
+ * Allow arbitrary logging of queries.
+ */
+typedef enum {
+ LOG_HOOK_CONTEXT_SIMPLE = 0,
+ LOG_HOOK_CONTEXT_BIND = 1,
+ LOG_HOOK_CONTEXT_PORTAL = 2,
+ LOG_HOOK_CONTEXT_EXEC_PARSE = 3,
+ LOG_HOOK_CONTEXT_FASTPATH = 4
+} LogHookContext;
+
+typedef void (*pre_exec_log_hook_t)(LogHookContext ctx, const char *query,
+ List *parsetree, bool was_logged);
+typedef void (*post_exec_log_hook_t)(LogHookContext ctx, const char *query,
+ List *parsetree, bool was_logged, long usec_duration);
+
+/*
+ * These functions can be used by modules authors to instrument the
+ * logging process and do arbitrary pre-flight and post-flight logging
+ * of statements.
+ */
+void register_pre_exec_log_hook(pre_exec_log_hook_t f);
+void register_post_exec_log_hook(post_exec_log_hook_t f);
+
+/*
+ * Call the hooks
+ */
+void call_pre_exec_log_hooks(LogHookContext ctx, const char *query,
+ List *tree, bool was_logged);
+void call_post_exec_log_hooks(LogHookContext ctx, const char *query,
+ List *tree, bool was_logged);
+#endif

0 comments on commit 62bb9df

Please sign in to comment.