diff --git a/pg_stat_monitor--1.0--2.0.sql b/pg_stat_monitor--1.0--2.0.sql index 21a1d41..89cdc98 100644 --- a/pg_stat_monitor--1.0--2.0.sql +++ b/pg_stat_monitor--1.0--2.0.sql @@ -69,7 +69,8 @@ CREATE FUNCTION pg_stat_monitor_internal( OUT wal_fpi int8, OUT wal_bytes numeric, OUT comments TEXT, - OUT toplevel BOOLEAN + OUT toplevel BOOLEAN, + OUT bucket_done BOOLEAN ) RETURNS SETOF record AS 'MODULE_PATHNAME', 'pg_stat_monitor_2_0' @@ -124,7 +125,8 @@ CREATE VIEW pg_stat_monitor AS SELECT cpu_sys_time, wal_records, wal_fpi, - wal_bytes + wal_bytes, + bucket_done FROM pg_stat_monitor_internal(TRUE) p, pg_database d WHERE dbid = oid ORDER BY bucket_start_time; RETURN 0; @@ -242,6 +244,7 @@ CREATE VIEW pg_stat_monitor AS SELECT wal_records, wal_fpi, wal_bytes, + bucket_done, plans_calls, total_plan_time, diff --git a/pg_stat_monitor--1.0.sql b/pg_stat_monitor--1.0.sql index 467d6b5..2d8a411 100644 --- a/pg_stat_monitor--1.0.sql +++ b/pg_stat_monitor--1.0.sql @@ -178,7 +178,8 @@ CREATE FUNCTION pg_stat_monitor_internal( OUT wal_fpi int8, OUT wal_bytes numeric, OUT comments TEXT, - OUT toplevel BOOLEAN + OUT toplevel BOOLEAN, + OUT bucket_done BOOLEAN ) RETURNS SETOF record AS 'MODULE_PATHNAME', 'pg_stat_monitor' diff --git a/pg_stat_monitor--2.0.sql b/pg_stat_monitor--2.0.sql index 2d6df69..b98876a 100644 --- a/pg_stat_monitor--2.0.sql +++ b/pg_stat_monitor--2.0.sql @@ -126,7 +126,7 @@ CREATE FUNCTION pg_stat_monitor_internal( OUT elevel int, OUT sqlcode TEXT, OUT message text, - OUT bucket_start_time timestamp, + OUT bucket_start_time timestamptz, OUT calls int8, -- 16 @@ -165,7 +165,8 @@ CREATE FUNCTION pg_stat_monitor_internal( OUT wal_fpi int8, OUT wal_bytes numeric, OUT comments TEXT, - OUT toplevel BOOLEAN + OUT toplevel BOOLEAN, + OUT bucket_done BOOLEAN ) RETURNS SETOF record AS 'MODULE_PATHNAME', 'pg_stat_monitor_2_0' @@ -219,7 +220,8 @@ CREATE VIEW pg_stat_monitor AS SELECT cpu_sys_time, wal_records, wal_fpi, - wal_bytes + wal_bytes, + bucket_done FROM pg_stat_monitor_internal(TRUE) p, pg_database d WHERE dbid = oid ORDER BY bucket_start_time; RETURN 0; @@ -276,6 +278,7 @@ CREATE VIEW pg_stat_monitor AS SELECT wal_records, wal_fpi, wal_bytes, + bucket_done, -- PostgreSQL-13 Specific Coulumns plans_calls, total_plan_time, @@ -338,6 +341,7 @@ CREATE VIEW pg_stat_monitor AS SELECT wal_records, wal_fpi, wal_bytes, + bucket_done, plans_calls, total_plan_time, diff --git a/pg_stat_monitor.c b/pg_stat_monitor.c index 6fddf45..59c88c9 100644 --- a/pg_stat_monitor.c +++ b/pg_stat_monitor.c @@ -36,7 +36,7 @@ PG_MODULE_MAGIC; #define BUILD_VERSION "2.0.0-dev" -#define PG_STAT_STATEMENTS_COLS 52 /* maximum of above */ +#define PG_STAT_STATEMENTS_COLS 53 /* maximum of above */ #define PGSM_TEXT_FILE PGSTAT_STAT_PERMANENT_DIRECTORY "pg_stat_monitor_query" #define roundf(x,d) ((floor(((x)*pow(10,d))+.5))/pow(10,d)) @@ -1613,15 +1613,12 @@ pg_stat_monitor(PG_FUNCTION_ARGS) static bool IsBucketValid(uint64 bucketid) { - struct tm tm; time_t bucket_t, current_t; double diff_t; pgssSharedState *pgss = pgsm_get_ss(); - memset(&tm, 0, sizeof(tm)); - strptime(pgss->bucket_start_time[bucketid], "%Y-%m-%d %H:%M:%S", &tm); - bucket_t = mktime(&tm); + bucket_t = mktime(&pgss->bucket_start_time[bucketid]); time(¤t_t); diff_t = difftime(current_t, bucket_t); @@ -1674,7 +1671,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 != 51) + if (tupdesc->natts != 52) elog(ERROR, "pg_stat_monitor: incorrect number of output arguments, required %d", tupdesc->natts); tupstore = tuplestore_begin_heap(true, false, work_mem); @@ -1749,7 +1746,7 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, { if (read_query(pgss_qbuf, tmp.info.parentid, parent_query_txt, 0) == 0) { - int rc = read_query_buffer(bucketid, tmp.info.parentid, parent_query_txt, 0); + int rc = read_query_buffer(bucketid, tmp.info.parentid, parent_query_txt, 0); if (rc != 1) snprintf(parent_query_txt, 32, "%s", ""); @@ -1892,7 +1889,11 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, values[i++] = CStringGetTextDatum(tmp.error.message); /* bucket_start_time at column number 15 */ - values[i++] = CStringGetDatum(pgss->bucket_start_time[entry->key.bucket_id]); + { + TimestampTz tm; + tm2timestamp((struct pg_tm*) &pgss->bucket_start_time[entry->key.bucket_id], 0, NULL, &tm); + values[i++] = TimestampGetDatum(tm); + } if (tmp.calls.calls == 0) { /* Query of pg_stat_monitor itslef started from zero count */ @@ -2003,6 +2004,9 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, nulls[i++] = true; } values[i++] = BoolGetDatum(toplevel); + values[i++] = BoolGetDatum(pg_atomic_read_u64(&pgss->current_wbucket) != bucketid); + + /* clean up and return the tuplestore */ tuplestore_putvalues(tupstore, tupdesc, values, nulls); } /* clean up and return the tuplestore */ @@ -2086,13 +2090,16 @@ get_next_wbucket(pgssSharedState *pgss) tv.tv_sec = (tv.tv_sec) - (tv.tv_sec % PGSM_BUCKET_TIME); lt = localtime(&tv.tv_sec); + /* + * Year is 1900 behind and month is 0 based, therefore we need to + * adjust that. + */ + lt->tm_year += 1900; + lt->tm_mon += 1; /* Allign the value in prev_bucket_sec to the bucket start time */ pg_atomic_exchange_u64(&pgss->prev_bucket_sec, (uint64)tv.tv_sec); - - snprintf(pgss->bucket_start_time[new_bucket_id], sizeof(pgss->bucket_start_time[new_bucket_id]), - "%04d-%02d-%02d %02d:%02d:%02d", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec); - + memcpy(&pgss->bucket_start_time[new_bucket_id], lt, sizeof(struct tm)); return new_bucket_id; } diff --git a/pg_stat_monitor.h b/pg_stat_monitor.h index fd6c3cd..e816ca3 100644 --- a/pg_stat_monitor.h +++ b/pg_stat_monitor.h @@ -317,11 +317,9 @@ typedef struct pgssSharedState pg_atomic_uint64 current_wbucket; pg_atomic_uint64 prev_bucket_sec; uint64 bucket_entry[MAX_BUCKETS]; - char bucket_start_time[MAX_BUCKETS][60]; /* start time of the - * bucket */ + struct tm bucket_start_time[MAX_BUCKETS]; /* start time of the bucket */ LWLock *errors_lock; /* protects errors hashtable * search/modification */ - /* * These variables are used when pgsm_overflow_target is ON. *