1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-01 12:18:01 +03:00

Add support for tracking call counts and elapsed runtime for user-defined

functions.

Note that because this patch changes FmgrInfo, any external C functions
you might be testing with 8.4 will need to be recompiled.

Patch by Martin Pihlak, some editorialization by me (principally, removing
tracking of getrusage() numbers)
This commit is contained in:
Tom Lane
2008-05-15 00:17:41 +00:00
parent 3bc25384d7
commit 93c701edc6
20 changed files with 830 additions and 67 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.51 2008/05/12 00:00:51 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.52 2008/05/15 00:17:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,6 +39,10 @@ extern Datum pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_function_calls(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_function_time(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_function_self_time(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_activity(PG_FUNCTION_ARGS);
extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
@@ -325,6 +329,39 @@ pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
PG_RETURN_TIMESTAMPTZ(result);
}
Datum
pg_stat_get_function_calls(PG_FUNCTION_ARGS)
{
Oid funcid = PG_GETARG_OID(0);
PgStat_StatFuncEntry *funcentry;
if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
PG_RETURN_NULL();
PG_RETURN_INT64(funcentry->f_numcalls);
}
Datum
pg_stat_get_function_time(PG_FUNCTION_ARGS)
{
Oid funcid = PG_GETARG_OID(0);
PgStat_StatFuncEntry *funcentry;
if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
PG_RETURN_NULL();
PG_RETURN_INT64(funcentry->f_time);
}
Datum
pg_stat_get_function_self_time(PG_FUNCTION_ARGS)
{
Oid funcid = PG_GETARG_OID(0);
PgStat_StatFuncEntry *funcentry;
if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
PG_RETURN_NULL();
PG_RETURN_INT64(funcentry->f_time_self);
}
Datum
pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
{
@@ -401,7 +438,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
}
else
{
/*
/*
* Get one backend - locate by pid.
*
* We lookup the backend early, so we can return zero rows if it doesn't

View File

@@ -1,4 +1,4 @@
$PostgreSQL: pgsql/src/backend/utils/fmgr/README,v 1.12 2008/04/21 00:26:45 tgl Exp $
$PostgreSQL: pgsql/src/backend/utils/fmgr/README,v 1.13 2008/05/15 00:17:40 tgl Exp $
Function Manager
================
@@ -70,6 +70,7 @@ typedef struct
short fn_nargs; /* 0..FUNC_MAX_ARGS, or -1 if variable arg count */
bool fn_strict; /* function is "strict" (NULL in => NULL out) */
bool fn_retset; /* function returns a set (over multiple calls) */
unsigned char fn_stats; /* collect stats if track_functions > this */
void *fn_extra; /* extra space for use by handler */
MemoryContext fn_mcxt; /* memory context to store fn_extra in */
Node *fn_expr; /* expression parse tree for call, or NULL */
@@ -86,10 +87,11 @@ a function handler could set it to avoid making repeated lookups of its
own when the same FmgrInfo is used repeatedly during a query.) fn_nargs
is the number of arguments expected by the function, fn_strict is its
strictness flag, and fn_retset shows whether it returns a set; all of
these values come from the function's pg_proc entry. If the function is
being called as part of a SQL expression, fn_expr will point to the
expression parse tree for the function call; this can be used to extract
parse-time knowledge about the actual arguments.
these values come from the function's pg_proc entry. fn_stats is also
set up to control whether or not to track runtime statistics for calling
this function. If the function is being called as part of a SQL expression,
fn_expr will point to the expression parse tree for the function call; this
can be used to extract parse-time knowledge about the actual arguments.
FmgrInfo already exists in the current code, but has fewer fields. This
change should be transparent at the source-code level.

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.118 2008/05/12 00:00:52 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.119 2008/05/15 00:17:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,6 +21,7 @@
#include "executor/functions.h"
#include "miscadmin.h"
#include "parser/parse_expr.h"
#include "pgstat.h"
#include "utils/builtins.h"
#include "utils/fmgrtab.h"
#include "utils/guc.h"
@@ -165,8 +166,7 @@ fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
/*
* This one does the actual work. ignore_security is ordinarily false
* but is set to true by fmgr_security_definer to avoid infinite
* recursive lookups.
* but is set to true by fmgr_security_definer to avoid recursion.
*/
static void
fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
@@ -197,6 +197,7 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
finfo->fn_nargs = fbp->nargs;
finfo->fn_strict = fbp->strict;
finfo->fn_retset = fbp->retset;
finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
finfo->fn_addr = fbp->func;
finfo->fn_oid = functionId;
return;
@@ -216,13 +217,23 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
/*
* If it has prosecdef set, or non-null proconfig, use
* fmgr_security_definer call handler.
* fmgr_security_definer call handler --- unless we are being called
* again by fmgr_security_definer.
*
* When using fmgr_security_definer, function stats tracking is always
* disabled at the outer level, and instead we set the flag properly
* in fmgr_security_definer's private flinfo and implement the tracking
* inside fmgr_security_definer. This loses the ability to charge the
* overhead of fmgr_security_definer to the function, but gains the
* ability to set the track_functions GUC as a local GUC parameter of
* an interesting function and have the right things happen.
*/
if (!ignore_security &&
(procedureStruct->prosecdef ||
!heap_attisnull(procedureTuple, Anum_pg_proc_proconfig)))
{
finfo->fn_addr = fmgr_security_definer;
finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
finfo->fn_oid = functionId;
ReleaseSysCache(procedureTuple);
return;
@@ -255,18 +266,23 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
pfree(prosrc);
/* Should we check that nargs, strict, retset match the table? */
finfo->fn_addr = fbp->func;
/* note this policy is also assumed in fast path above */
finfo->fn_stats = TRACK_FUNC_ALL; /* ie, never track */
break;
case ClanguageId:
fmgr_info_C_lang(functionId, finfo, procedureTuple);
finfo->fn_stats = TRACK_FUNC_PL; /* ie, track if ALL */
break;
case SQLlanguageId:
finfo->fn_addr = fmgr_sql;
finfo->fn_stats = TRACK_FUNC_PL; /* ie, track if ALL */
break;
default:
fmgr_info_other_lang(functionId, finfo, procedureTuple);
finfo->fn_stats = TRACK_FUNC_OFF; /* ie, track if not OFF */
break;
}
@@ -862,6 +878,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
Oid save_userid;
bool save_secdefcxt;
volatile int save_nestlevel;
PgStat_FunctionCallUsage fcusage;
if (!fcinfo->flinfo->fn_extra)
{
@@ -934,7 +951,19 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
{
fcinfo->flinfo = &fcache->flinfo;
/* See notes in fmgr_info_cxt_security */
pgstat_init_function_usage(fcinfo, &fcusage);
result = FunctionCallInvoke(fcinfo);
/*
* We could be calling either a regular or a set-returning function,
* so we have to test to see what finalize flag to use.
*/
pgstat_end_function_usage(&fcusage,
(fcinfo->resultinfo == NULL ||
!IsA(fcinfo->resultinfo, ReturnSetInfo) ||
((ReturnSetInfo *) fcinfo->resultinfo)->isDone != ExprMultipleResult));
}
PG_CATCH();
{
@@ -2089,7 +2118,7 @@ float4
DatumGetFloat4(Datum X)
{
union {
int32 value;
int32 value;
float4 retval;
} myunion;

View File

@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.453 2008/05/12 08:35:05 mha Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.454 2008/05/15 00:17:40 tgl Exp $
*
*--------------------------------------------------------------------
*/
@@ -169,7 +169,6 @@ static char *config_enum_get_options(struct config_enum *record,
const char *prefix, const char *suffix);
/*
* Options for enum values defined in this module.
*/
@@ -241,6 +240,13 @@ static const struct config_enum_entry syslog_facility_options[] = {
};
#endif
static const struct config_enum_entry track_function_options[] = {
{"none", TRACK_FUNC_OFF},
{"pl", TRACK_FUNC_PL},
{"all", TRACK_FUNC_ALL},
{NULL, 0}
};
static const struct config_enum_entry xmlbinary_options[] = {
{"base64", XMLBINARY_BASE64},
{"hex", XMLBINARY_HEX},
@@ -2524,6 +2530,15 @@ static struct config_enum ConfigureNamesEnum[] =
assign_session_replication_role, NULL
},
{
{"track_functions", PGC_SUSET, STATS_COLLECTOR,
gettext_noop("Collects function-level statistics on database activity."),
gettext_noop("Valid values are: NONE, PL, and ALL.")
},
&pgstat_track_functions,
TRACK_FUNC_OFF, track_function_options, NULL, NULL
},
{
{"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
gettext_noop("Selects the method used for forcing WAL updates to disk."),

View File

@@ -363,6 +363,7 @@
#track_activities = on
#track_counts = on
#track_functions = none # none, pl, all
#update_process_title = on