PG-147 Stored Procedure Support add parentid to track caller.
Patch By: Martin Sun Reviewed By: Hamid Akhtarpull/73/head
parent
cba6bbfbd4
commit
ed6fe2d8dc
|
@ -376,3 +376,44 @@ postgres=# SELECT bucket, substr(query,0, 50) AS query, cmd_type FROM pg_stat_mo
|
|||
4 | UPDATE pgbench_branches SET bbalance = bbalance + | UPDATE
|
||||
(14 rows)
|
||||
```
|
||||
|
||||
#### Function Execution Tracking
|
||||
|
||||
**`parentid`**: Outer layer caller's query id.
|
||||
|
||||
```sql
|
||||
postgres=# select prosrc from pg_proc where proname = 'getnum';
|
||||
prosrc
|
||||
--------------------------------
|
||||
select * from t1 where a >= $1
|
||||
(1 row)
|
||||
|
||||
postgresr=# select pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
postgres=# select prosrc from pg_proc where proname = 'getnum';
|
||||
prosrc
|
||||
--------------------------------
|
||||
select * from t1 where a >= $1
|
||||
(1 row)
|
||||
|
||||
postgres=# select * from getnum(2);
|
||||
a
|
||||
---
|
||||
2
|
||||
3
|
||||
4
|
||||
(3 rows)
|
||||
|
||||
postgres=# select queryid,parentid,query,calls from pg_stat_monitor;
|
||||
queryid | parentid | query | calls
|
||||
------------------+------------------+-----------------------------------------------+-------
|
||||
3FEC80684AFE7FC7 | DD2A4843140299C2 | select * from t1 where a >= $1 | 1
|
||||
6ED05FFB78DD52FA | | select pg_stat_monitor_reset() | 1
|
||||
DD2A4843140299C2 | | select * from getnum($1) | 1
|
||||
42517D48FB98ACF7 | | select prosrc from pg_proc where proname = $1 | 1
|
||||
(4 rows)
|
||||
```
|
|
@ -17,7 +17,7 @@ SELECT 1;
|
|||
1
|
||||
(1 row)
|
||||
|
||||
SELECT query FROM pg_stat_monitor ORDER BY query;
|
||||
SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query
|
||||
--------------------------------
|
||||
SELECT $1
|
||||
|
|
|
@ -20,9 +20,9 @@ SELECT * FROM pg_stat_monitor_settings;
|
|||
pg_stat_monitor.pgsm_track_utility | 0 | 0 | Selects whether utility commands are tracked. | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_normalized_query | 1 | 1 | Selects whether save query in normalized format. | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_max_buckets | 10 | 10 | Sets the maximum number of buckets. | 1 | 10 | 1
|
||||
pg_stat_monitor.pgsm_bucket_time | 300 | 60 | Sets the time in seconds per bucket. | 1 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_bucket_time | 300 | 300 | Sets the time in seconds per bucket. | 1 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_histogram_min | 0 | 0 | Sets the time in millisecond. | 0 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_histogram_max | 100000 | 10 | Sets the time in millisecond. | 10 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_histogram_max | 100000 | 100000 | Sets the time in millisecond. | 10 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_histogram_buckets | 10 | 10 | Sets the maximum number of histogram buckets | 2 | 2147483647 | 1
|
||||
(10 rows)
|
||||
|
||||
|
|
4
guc.c
4
guc.c
|
@ -104,7 +104,7 @@ init_guc(void)
|
|||
conf[i] = (GucVariable) {
|
||||
.guc_name = "pg_stat_monitor.pgsm_bucket_time",
|
||||
.guc_desc = "Sets the time in seconds per bucket.",
|
||||
.guc_default = 60,
|
||||
.guc_default = 300,
|
||||
.guc_min = 1,
|
||||
.guc_max = INT_MAX,
|
||||
.guc_restart = true,
|
||||
|
@ -128,7 +128,7 @@ init_guc(void)
|
|||
conf[i] = (GucVariable) {
|
||||
.guc_name = "pg_stat_monitor.pgsm_histogram_max",
|
||||
.guc_desc = "Sets the time in millisecond.",
|
||||
.guc_default = 10,
|
||||
.guc_default = 100000,
|
||||
.guc_min = 10,
|
||||
.guc_max = INT_MAX,
|
||||
.guc_restart = true,
|
||||
|
|
|
@ -31,6 +31,7 @@ CREATE FUNCTION pg_stat_monitor(IN showtext boolean,
|
|||
OUT client_ip int8,
|
||||
|
||||
OUT queryid text,
|
||||
OUT parentid text,
|
||||
OUT query text,
|
||||
OUT application_name text,
|
||||
OUT relations text,
|
||||
|
@ -125,10 +126,12 @@ CREATE VIEW pg_stat_monitor AS SELECT
|
|||
datname,
|
||||
'0.0.0.0'::inet + client_ip AS client_ip,
|
||||
queryid,
|
||||
parentid,
|
||||
query,
|
||||
(SELECT query from pg_stat_monitor(true) s where s.queryid = p.parentid) AS parent_query,
|
||||
application_name,
|
||||
string_to_array(relations, ',') AS relations,
|
||||
cmd_type,
|
||||
cmd_type,
|
||||
get_cmd_type(cmd_type) AS cmd_type_text,
|
||||
elevel,
|
||||
sqlcode,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
PG_MODULE_MAGIC;
|
||||
|
||||
#define BUILD_VERSION "0.7.0"
|
||||
#define PG_STAT_STATEMENTS_COLS 46 /* maximum of above */
|
||||
#define PG_STAT_STATEMENTS_COLS 47 /* maximum of above */
|
||||
#define PGSM_TEXT_FILE "/tmp/pg_stat_monitor_query"
|
||||
|
||||
#define PGUNSIXBIT(val) (((val) & 0x3F) + '0')
|
||||
|
@ -63,6 +63,11 @@ void _PG_fini(void);
|
|||
/* Current nesting depth of ExecutorRun+ProcessUtility calls */
|
||||
static int nested_level = 0;
|
||||
|
||||
/* the current max level a query can nested */
|
||||
int cur_max_nested_level;
|
||||
/* The array to store outer layer query id*/
|
||||
uint64 *nested_queryids;
|
||||
|
||||
#if PG_VERSION_NUM >= 130000
|
||||
static int plan_nested_level = 0;
|
||||
static int exec_nested_level = 0;
|
||||
|
@ -240,6 +245,9 @@ _PG_init(void)
|
|||
prev_ExecutorCheckPerms_hook = ExecutorCheckPerms_hook;
|
||||
ExecutorCheckPerms_hook = pgss_ExecutorCheckPerms;
|
||||
|
||||
cur_max_nested_level = max_stack_depth;
|
||||
nested_queryids = (uint64*)malloc(sizeof(uint64)*cur_max_nested_level);
|
||||
|
||||
system_init = true;
|
||||
}
|
||||
|
||||
|
@ -257,6 +265,9 @@ _PG_fini(void)
|
|||
ExecutorFinish_hook = prev_ExecutorFinish;
|
||||
ExecutorEnd_hook = prev_ExecutorEnd;
|
||||
ProcessUtility_hook = prev_ProcessUtility;
|
||||
|
||||
free(nested_queryids);
|
||||
|
||||
hash_entry_reset();
|
||||
}
|
||||
|
||||
|
@ -389,6 +400,12 @@ static void
|
|||
pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count,
|
||||
bool execute_once)
|
||||
{
|
||||
nested_queryids[nested_level] = queryDesc->plannedstmt->queryId;
|
||||
if(nested_level + 1 >= cur_max_nested_level)
|
||||
{
|
||||
cur_max_nested_level *= 2;
|
||||
nested_queryids = realloc(nested_queryids, cur_max_nested_level);
|
||||
}
|
||||
nested_level++;
|
||||
PG_TRY();
|
||||
{
|
||||
|
@ -397,10 +414,12 @@ pgss_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count,
|
|||
else
|
||||
standard_ExecutorRun(queryDesc, direction, count, execute_once);
|
||||
nested_level--;
|
||||
nested_queryids[nested_level] = UINT64CONST(0);
|
||||
}
|
||||
PG_CATCH();
|
||||
{
|
||||
nested_level--;
|
||||
nested_queryids[nested_level] = UINT64CONST(0);
|
||||
PG_RE_THROW();
|
||||
}
|
||||
PG_END_TRY();
|
||||
|
@ -985,6 +1004,11 @@ static void pgss_store(uint64 queryId,
|
|||
_snprintf(e->counters.error.sqlcode, sqlcode, sqlcode_len, SQLCODE_LEN);
|
||||
_snprintf(e->counters.error.message, message, message_len, ERROR_MESSAGE_LEN);
|
||||
|
||||
if(nested_level > 0)
|
||||
e->counters.info.parentid = nested_queryids[nested_level - 1];
|
||||
else
|
||||
e->counters.info.parentid = UINT64CONST(0);
|
||||
|
||||
e->counters.calls[kind].rows += rows;
|
||||
e->counters.blocks.shared_blks_hit += bufusage->shared_blks_hit;
|
||||
e->counters.blocks.shared_blks_read += bufusage->shared_blks_read;
|
||||
|
@ -1075,6 +1099,7 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
pgssEntry *entry;
|
||||
char *query_txt;
|
||||
char queryid_txt[64];
|
||||
char parentid_txt[64];
|
||||
pgssSharedState *pgss = pgsm_get_ss();
|
||||
HTAB *pgss_hash = pgsm_get_hash();
|
||||
|
||||
|
@ -1179,7 +1204,19 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
tmp = e->counters;
|
||||
SpinLockRelease(&e->mutex);
|
||||
}
|
||||
|
||||
values[i++] = CStringGetTextDatum(queryid_txt);
|
||||
|
||||
if (tmp.info.parentid != UINT64CONST(0))
|
||||
{
|
||||
sprintf(parentid_txt,"%08lX",tmp.info.parentid);
|
||||
values[i++] = CStringGetTextDatum(parentid_txt);
|
||||
}
|
||||
else
|
||||
{
|
||||
nulls[i++] = true;
|
||||
}
|
||||
|
||||
if (is_allowed_role || entry->key.userid == userid)
|
||||
{
|
||||
if (showtext)
|
||||
|
@ -1205,6 +1242,9 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
|
|||
}
|
||||
else
|
||||
{
|
||||
/*skip the query id and parent id*/
|
||||
nulls[i++] = true;
|
||||
nulls[i++] = true;
|
||||
/*
|
||||
* Don't show query text, but hint as to the reason for not doing
|
||||
* so if it was requested
|
||||
|
|
|
@ -120,6 +120,8 @@ typedef enum pgssStoreKind
|
|||
PGSS_NUMKIND /* Must be last value of this enum */
|
||||
} pgssStoreKind;
|
||||
|
||||
/* the assumption of query max nested level */
|
||||
#define DEFAULT_MAX_NESTED_LEVEL 10
|
||||
|
||||
/*
|
||||
* Type of aggregate keys
|
||||
|
@ -161,6 +163,7 @@ typedef struct QueryInfo
|
|||
Oid userid; /* user OID */
|
||||
Oid dbid; /* database OID */
|
||||
uint host; /* client IP */
|
||||
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 relations[REL_LST][REL_LEN]; /* List of relation involved in the query */
|
||||
|
|
|
@ -2,6 +2,6 @@ CREATE EXTENSION pg_stat_monitor;
|
|||
SELECT pg_stat_monitor_reset();
|
||||
select pg_sleep(.5);
|
||||
SELECT 1;
|
||||
SELECT query FROM pg_stat_monitor ORDER BY query;
|
||||
SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
SELECT pg_stat_monitor_reset();
|
||||
DROP EXTENSION pg_stat_monitor;
|
||||
|
|
Loading…
Reference in New Issue