From 67b3d961ca726c7b7cfc888ca3f5c17349d59d27 Mon Sep 17 00:00:00 2001 From: Ibrar Ahmed Date: Wed, 19 May 2021 22:15:37 +0500 Subject: [PATCH] PG-193: Comment based tags to identify different parameters. --- Makefile | 2 +- pg_stat_monitor--1.0.sql | 4 +++- pg_stat_monitor.c | 43 +++++++++++++++++++++++++++++++++--- pg_stat_monitor.h | 2 ++ regression/expected/tags.out | 28 +++++++++++++++++++++++ regression/sql/tags.sql | 6 +++++ 6 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 regression/expected/tags.out create mode 100644 regression/sql/tags.sql diff --git a/Makefile b/Makefile index 3d7038b..ef1a66c 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ PGFILEDESC = "pg_stat_monitor - execution statistics of SQL statements" LDFLAGS_SL += $(filter -lm, $(LIBS)) REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_stat_monitor/pg_stat_monitor.conf --inputdir=regression -REGRESS = basic version guc counters relations database top_query application_name cmd_type error state rows +REGRESS = basic version guc counters relations database top_query application_name cmd_type error state rows tags # Disabled because these tests require "shared_preload_libraries=pg_stat_statements", # which typical installcheck users do not have (e.g. buildfarm clients). diff --git a/pg_stat_monitor--1.0.sql b/pg_stat_monitor--1.0.sql index 552801f..73153b5 100644 --- a/pg_stat_monitor--1.0.sql +++ b/pg_stat_monitor--1.0.sql @@ -77,7 +77,8 @@ CREATE FUNCTION pg_stat_monitor_internal(IN showtext boolean, OUT cpu_sys_time float8, OUT wal_records int8, OUT wal_fpi int8, - OUT wal_bytes numeric + OUT wal_bytes numeric, + OUT comments TEXT ) RETURNS SETOF record AS 'MODULE_PATHNAME', 'pg_stat_monitor' @@ -144,6 +145,7 @@ CREATE VIEW pg_stat_monitor AS SELECT queryid, top_queryid, query, + comments, planid, query_plan, (SELECT query from pg_stat_monitor_internal(true) s where s.queryid = p.top_queryid) AS top_query, diff --git a/pg_stat_monitor.c b/pg_stat_monitor.c index 9d9ca6b..9b6df03 100644 --- a/pg_stat_monitor.c +++ b/pg_stat_monitor.c @@ -15,13 +15,14 @@ *------------------------------------------------------------------------- */ #include "postgres.h" +#include #include "commands/explain.h" #include "pg_stat_monitor.h" PG_MODULE_MAGIC; #define BUILD_VERSION "devel" -#define PG_STAT_STATEMENTS_COLS 51 /* maximum of above */ +#define PG_STAT_STATEMENTS_COLS 52 /* maximum of above */ #define PGSM_TEXT_FILE "/tmp/pg_stat_monitor_query" #define PGUNSIXBIT(val) (((val) & 0x3F) + '0') @@ -73,6 +74,7 @@ static struct rusage rusage_end; static unsigned char *pgss_qbuf[MAX_BUCKETS]; static char *pgss_explain(QueryDesc *queryDesc); +static char *extract_query_comments(const char *query); static int get_histogram_bucket(double q_time); static bool IsSystemInitialized(void); static void dump_queries_buffer(int bucket_id, unsigned char *buf, int buf_len); @@ -893,6 +895,7 @@ pgss_update_entry(pgssEntry *entry, int bucketid, uint64 queryid, const char *query, + const char *comments, PlanInfo *plan_info, CmdType cmd_type, SysInfo *sys_info, @@ -910,6 +913,7 @@ pgss_update_entry(pgssEntry *entry, pgssSharedState *pgss = pgsm_get_ss(); double old_mean; int message_len = error_info ? strlen (error_info->message) : 0; + int comments_len = comments ? strlen (comments) : 0; int sqlcode_len = error_info ? strlen (error_info->sqlcode) : 0; int plan_text_len = plan_info ? strlen (plan_info->plan_text) : 0; @@ -922,6 +926,7 @@ pgss_update_entry(pgssEntry *entry, if (reset) memset(&entry->counters, 0, sizeof(Counters)); + _snprintf(e->counters.info.comments, comments, comments_len, COMMENTS_LEN); e->counters.state = kind; if (kind == PGSS_PLAN) { @@ -1204,13 +1209,15 @@ pgss_store(uint64 queryid, uint64 dbid = MyDatabaseId; uint64 ip = pg_get_client_addr(); uint64 planid = plan_info ? plan_info->planid: 0; - + char *comments; /* Monitoring is disabled */ if (!PGSM_ENABLED) return; Assert(query != NULL); + comments = extract_query_comments(query); + /* Safety check... */ if (!IsSystemInitialized() || !pgss_qbuf[pgss->current_wbucket]) return; @@ -1258,6 +1265,7 @@ pgss_store(uint64 queryid, bucketid, /* bucketid */ queryid, /* queryid */ query, /* query */ + comments, /* comments */ plan_info, /* PlanInfo */ cmd_type, /* CmdType */ sys_info, /* SysInfo */ @@ -1364,7 +1372,7 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "pg_stat_monitor: return type must be a row type"); - if (tupdesc->natts != 48) + if (tupdesc->natts != 49) elog(ERROR, "pg_stat_monitor: incorrect number of output arguments, required %d", tupdesc->natts); tupstore = tuplestore_begin_heap(true, false, work_mem); @@ -1658,6 +1666,12 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, Int32GetDatum(-1)); /* wal_bytes at column number 46 */ values[i++] = wal_bytes; + + /* application_name at column number 47 */ + if (strlen(tmp.info.comments) > 0) + values[i++] = CStringGetTextDatum(tmp.info.comments); + else + nulls[i++] = true; } tuplestore_putvalues(tupstore, tupdesc, values, nulls); } @@ -3049,3 +3063,26 @@ get_histogram_timings(PG_FUNCTION_ARGS) return CStringGetTextDatum(text_str); } +char * +extract_query_comments(const char *query) +{ + regex_t preg; + char *pattern = "/\\*.*\\*/"; + int rc; + size_t nmatch = 1; + regmatch_t pmatch; + char *comments = palloc0(512); + + rc = regcomp(&preg, pattern, 0); + if (rc != 0) + { + printf("regcomp() failed, returning nonzero (%d)\n", rc); + return ""; + } + rc = regexec(&preg, query, nmatch, &pmatch, 0); + if (rc != 0) + return ""; + sprintf(comments, "%.*s", pmatch.rm_eo - pmatch.rm_so -4, &query[pmatch.rm_so + 2]); + regfree(&preg); + return comments; +} diff --git a/pg_stat_monitor.h b/pg_stat_monitor.h index 448232e..6af7449 100644 --- a/pg_stat_monitor.h +++ b/pg_stat_monitor.h @@ -78,6 +78,7 @@ #define CMD_LST 10 #define CMD_LEN 20 #define APPLICATIONNAME_LEN 100 +#define COMMENTS_LEN 512 #define PGSM_OVER_FLOW_MAX 10 #define PLAN_TEXT_LEN 1024 /* the assumption of query max nested level */ @@ -211,6 +212,7 @@ typedef struct QueryInfo uint64 parentid; /* parent queryid of current query*/ int64 type; /* type of query, options are query, info, warning, error, fatal */ char application_name[APPLICATIONNAME_LEN]; + char comments[COMMENTS_LEN]; char relations[REL_LST][REL_LEN]; /* List of relation involved in the query */ int num_relations; /* Number of relation in the query */ CmdType cmd_type; /* query command type SELECT/UPDATE/DELETE/INSERT */ diff --git a/regression/expected/tags.out b/regression/expected/tags.out new file mode 100644 index 0000000..9da2b13 --- /dev/null +++ b/regression/expected/tags.out @@ -0,0 +1,28 @@ +CREATE EXTENSION pg_stat_monitor; +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +SELECT 1 AS num /* { "application", psql_app, "real_ip", 192.168.1.3) */; + num +----- + 1 +(1 row) + +SELECT query, comments FROM pg_stat_monitor ORDER BY query COLLATE "C"; + query | comments +-------------------------------------------------------------------------+------------------------------------------------------ + SELECT $1 AS num | { "application", psql_app, "real_ip", 192.168.1.3) + SELECT pg_stat_monitor_reset(); | + SELECT query, comments FROM pg_stat_monitor ORDER BY query COLLATE "C"; | +(3 rows) + +SELECT pg_stat_monitor_reset(); + pg_stat_monitor_reset +----------------------- + +(1 row) + +DROP EXTENSION pg_stat_monitor; diff --git a/regression/sql/tags.sql b/regression/sql/tags.sql new file mode 100644 index 0000000..8325598 --- /dev/null +++ b/regression/sql/tags.sql @@ -0,0 +1,6 @@ +CREATE EXTENSION pg_stat_monitor; +SELECT pg_stat_monitor_reset(); +SELECT 1 AS num /* { "application", psql_app, "real_ip", 192.168.1.3) */; +SELECT query, comments FROM pg_stat_monitor ORDER BY query COLLATE "C"; +SELECT pg_stat_monitor_reset(); +DROP EXTENSION pg_stat_monitor;