git push origin develMerge branch 'darkfronza-devel' into devel
commit
d3fe5edc80
|
@ -1,63 +0,0 @@
|
|||
name: Test-with-pg14-pgdg-packages
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg14-test-with-pgdg-packages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone pg_stat_monitor repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: 'src/pg_stat_monitor'
|
||||
|
||||
- name: Delete old postgresql files
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt purge postgresql-client-common postgresql-common postgresql postgresql*
|
||||
sudo rm -rf /var/lib/postgresql/
|
||||
sudo rm -rf /var/log/postgresql/
|
||||
sudo rm -rf /etc/postgresql/
|
||||
sudo rm -rf /usr/lib/postgresql
|
||||
sudo rm -rf /usr/include/postgresql
|
||||
sudo rm -rf /usr/share/postgresql
|
||||
sudo rm -rf /etc/postgresql
|
||||
sudo rm -f /usr/bin/pg_config
|
||||
|
||||
- name: Install PG Distribution Postgresql 14
|
||||
run: |
|
||||
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main 14" > /etc/apt/sources.list.d/pgdg.list'
|
||||
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install postgresql-14
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install postgresql-client-14
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install postgresql-server-dev-14
|
||||
sudo chown -R postgres:postgres src/
|
||||
|
||||
- name: Build pg_stat_monitor
|
||||
run: |
|
||||
export PATH="/usr/lib/postgresql/14/bin:$PATH"
|
||||
sudo cp /usr/lib/postgresql/14/bin/pg_config /usr/bin
|
||||
sudo make USE_PGXS=1
|
||||
sudo make USE_PGXS=1 install
|
||||
working-directory: src/pg_stat_monitor/
|
||||
|
||||
- name: Start pg_stat_monitor_tests
|
||||
run: |
|
||||
sudo service postgresql stop
|
||||
echo "shared_preload_libraries = 'pg_stat_monitor'" | sudo tee -a /etc/postgresql/14/main/postgresql.conf
|
||||
sudo service postgresql start
|
||||
sudo -u postgres bash -c 'make installcheck USE_PGXS=1'
|
||||
working-directory: src/pg_stat_monitor/
|
||||
|
||||
- name: Report on test fail
|
||||
uses: actions/upload-artifact@v2
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: Regressions diff and postgresql log
|
||||
path: |
|
||||
src/pg_stat_monitor/regression.diffs
|
||||
src/pg_stat_monitor/logfile
|
||||
retention-days: 1
|
|
@ -1,4 +1,4 @@
|
|||
name: Test-with-pg11-build
|
||||
name: postgresql-11-build
|
||||
on: [push]
|
||||
|
||||
jobs:
|
|
@ -1,9 +1,9 @@
|
|||
name: pg11package-test
|
||||
name: postgresql-11-package
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg11package-test
|
||||
name: postgresql-11-package
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Clone pg_stat_monitor repository
|
|
@ -1,9 +1,9 @@
|
|||
name: Test-with-pg11-pgdg-packages
|
||||
name: postgresql-11-pgdg-package
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg11-test-with-pgdg-packages
|
||||
name: postgresql-11-pgdg-package
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Clone pg_stat_monitor repository
|
|
@ -1,9 +1,9 @@
|
|||
name: Test-with-pg12-build
|
||||
name: postgresql-12-build
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg12-test
|
||||
name: postgresql-12-build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone postgres repository
|
|
@ -1,9 +1,9 @@
|
|||
name: pg12package-test
|
||||
name: postgresql-12-package
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg12package-test
|
||||
name: postgresql-12-package
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Clone pg_stat_monitor repository
|
|
@ -1,9 +1,9 @@
|
|||
name: Test-with-pg12-pgdg-packages
|
||||
name: postgresql-12-pgdg-package
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg12-test-with-pgdg-packages
|
||||
name: postgresql-12-pgdg-package
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone pg_stat_monitor repository
|
|
@ -1,9 +1,9 @@
|
|||
name: Test-with-pg13-build
|
||||
name: postgresql-13-build
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg13-test
|
||||
name: postgresql-13-build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone postgres repository
|
|
@ -1,9 +1,9 @@
|
|||
name: pg13package-test
|
||||
name: postgresql-13-package
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg13package-test
|
||||
name: postgresql-13-package
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Clone pg_stat_monitor repository
|
|
@ -1,9 +1,9 @@
|
|||
name: Test-with-pg13-pgdg-packages
|
||||
name: postgresql-13-pgdg-package
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg13-test-with-pgdg-packages
|
||||
name: postgresql-13-pgdg-package
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone pg_stat_monitor repository
|
|
@ -1,9 +1,9 @@
|
|||
name: Test-with-pg14-build
|
||||
name: postgresql-14-build
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: pg14-test
|
||||
name: postgresql-14-build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone postgres repository
|
|
@ -64,6 +64,8 @@ To build `pg_stat_monitor` from source code, you require the following:
|
|||
|
||||
* git
|
||||
* make
|
||||
* gcc
|
||||
* pg_config
|
||||
|
||||
Refer to the [Building from source code](https://github.com/percona/pg_stat_monitor#installing-from-source-code) section for guidelines.
|
||||
|
||||
|
|
24
Makefile
24
Makefile
|
@ -1,7 +1,7 @@
|
|||
# contrib/pg_stat_monitor/Makefile
|
||||
|
||||
MODULE_big = pg_stat_monitor
|
||||
OBJS = hash_query.o guc.o pg_stat_monitor.o $(WIN32RES)
|
||||
OBJS = hash_query.o guc.o pgsm_errors.o pg_stat_monitor.o $(WIN32RES)
|
||||
|
||||
EXTENSION = pg_stat_monitor
|
||||
DATA = pg_stat_monitor--1.0.sql
|
||||
|
@ -17,8 +17,28 @@ REGRESS = basic version guc counters relations database top_query application_na
|
|||
# which typical installcheck users do not have (e.g. buildfarm clients).
|
||||
# NO_INSTALLCHECK = 1
|
||||
|
||||
ifdef USE_PGXS
|
||||
|
||||
PG_CONFIG = pg_config
|
||||
PG_VERSION := $(shell pg_config --version | awk {'print $$1 $$2'})
|
||||
MAJOR := $(shell echo $(PG_VERSION) | sed -e 's/\.[^./]*$$//')
|
||||
|
||||
ifneq (,$(findstring PostgreSQL14,$(MAJOR)))
|
||||
CP := $(shell cp pg_stat_monitor--1.0.14.sql.in pg_stat_monitor--1.0.sql)
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring PostgreSQL13,$(MAJOR)))
|
||||
CP := $(shell cp pg_stat_monitor--1.0.13.sql.in pg_stat_monitor--1.0.sql)
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring PostgreSQL12,$(MAJOR)))
|
||||
CP := $(shell cp pg_stat_monitor--1.0.sql.in pg_stat_monitor--1.0.sql)
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring PostgreSQL11,$(MAJOR)))
|
||||
CP := $(shell cp pg_stat_monitor--1.0.sql.in pg_stat_monitor--1.0.sql)
|
||||
endif
|
||||
|
||||
ifdef USE_PGXS
|
||||
PGXS := $(shell $(PG_CONFIG) --pgxs)
|
||||
include $(PGXS)
|
||||
else
|
||||
|
|
34
README.md
34
README.md
|
@ -1,10 +1,8 @@
|
|||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
   
|
||||
|
||||
  
|
||||
|
||||
|
||||
|
||||
[](https://coveralls.io/github/percona/pg_stat_monitor)
|
||||
|
||||
|
@ -22,8 +20,10 @@
|
|||
* [Setup](#setup)
|
||||
* [Building from source code](#building-from-source)
|
||||
* [How to contribute](#how-to-contribute)
|
||||
* [Report a Bug](#report-a-bug)
|
||||
* [Support, discussions and forums](#support-discussions-and-forums)
|
||||
* [License](#license)
|
||||
* [Copyright](#copyright)
|
||||
* [Copyright notice](#copyright-notice)
|
||||
|
||||
## Overview
|
||||
|
||||
|
@ -160,7 +160,11 @@ ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_monitor';
|
|||
ALTER SYSTEM
|
||||
```
|
||||
|
||||
**NOTE**: If you’ve added other values to the shared_preload_libraries parameter, list all of them separated by commas for the `ALTER SYSTEM` command. For example, `ALTER SYSTEM SET shared_preload_libraries = 'foo, bar, pg_stat_monitor'`
|
||||
> **NOTE**: If you’ve added other modules to the `shared_preload_libraries` parameter (for example, `pg_stat_statements`), list all of them separated by commas for the `ALTER SYSTEM` command.
|
||||
>
|
||||
>:warning: For PostgreSQL 13 and earlier versions,`pg_stat_monitor` **must** follow `pg_stat_statements`. For example, `ALTER SYSTEM SET shared_preload_libraries = 'foo, pg_stat_statements, pg_stat_monitor'`.
|
||||
>
|
||||
>In PostgreSQL 14, modules can be specified in any order.
|
||||
|
||||
Start or restart the `postgresql` instance to apply the changes.
|
||||
|
||||
|
@ -188,6 +192,7 @@ CREATE EXTENSION
|
|||
|
||||
This allows you to see the stats collected by `pg_stat_monitor`.
|
||||
|
||||
By default, `pg_stat_monitor` is created for the `postgres` database. To access the statistics from other databases, you need to create the extension for every database.
|
||||
|
||||
```
|
||||
-- Select some of the query information, like client_ip, username and application_name etc.
|
||||
|
@ -209,6 +214,13 @@ To learn more about `pg_stat_monitor` features and usage, see [User Guide](https
|
|||
|
||||
### Building from source
|
||||
|
||||
To build `pg_stat_monitor` from source code, you require the following:
|
||||
|
||||
* git
|
||||
* make
|
||||
* gcc
|
||||
* pg_config
|
||||
|
||||
You can download the source code of the latest release of `pg_stat_monitor` from [the releases page on GitHub](https://github.com/Percona/pg_stat_monitor/releases) or using git:
|
||||
|
||||
|
||||
|
@ -230,6 +242,10 @@ We welcome and strongly encourage community participation and contributions, and
|
|||
|
||||
The [Contributing Guide](https://github.com/percona/pg_stat_monitor/blob/master/CONTRIBUTING.md) contains the guidelines on how you can contribute.
|
||||
|
||||
### Report a Bug
|
||||
|
||||
Please report all bugs to Percona's Jira: https://jira.percona.com/projects/PG/issues
|
||||
|
||||
|
||||
### Support, discussions and forums
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
# Comparing pg_stat_monitor and pg_stat_statements
|
||||
|
||||
The `pg_stat_monitor` extension is developed on the basis of `pg_stat_statements` as its more advanced replacement.
|
||||
|
||||
Thus, `pg_stat_monitor` inherits the columns available in `pg_stat_statements` plus provides additional ones.
|
||||
|
||||
To see all available columns, run the following command from the `psql` terminal:
|
||||
|
||||
```sql
|
||||
postgres=# \d pg_stat_monitor;
|
||||
```
|
||||
|
||||
The following table compares the `pg_stat_monitor` view with that of `pg_stat_statements`.
|
||||
|
||||
Note that the column names differ depending on the PostgreSQL version you are running.
|
||||
|
||||
|
||||
| Column name for PostgreSQL 13 and above | Column name for PostgreSQL 11 and 12 | pg_stat_monitor | pg_stat_statements
|
||||
|--------------------|--------------------------|-----------------------------|----------------------
|
||||
bucket | bucket | :heavy_check_mark: | :x:
|
||||
bucket_start_time | bucket_start_time | :heavy_check_mark: | :x:
|
||||
userid | userid | :heavy_check_mark: | :heavy_check_mark:
|
||||
datname | datname | :heavy_check_mark: | :heavy_check_mark:
|
||||
toplevel[^1] | | :heavy_check_mark: | :heavy_check_mark:
|
||||
client_ip | client_ip | :heavy_check_mark:| :x:
|
||||
queryid | queryid | :heavy_check_mark: | :heavy_check_mark:
|
||||
planid | planid | :heavy_check_mark:| :x:
|
||||
query_plan | query_plan | :heavy_check_mark: | :x:
|
||||
top_query | top_query | :heavy_check_mark: | :x:
|
||||
top_queryid | top_queryid | :heavy_check_mark: | :x:
|
||||
query | query | :heavy_check_mark: | :heavy_check_mark:
|
||||
application_name | application_name | :heavy_check_mark:| :x:
|
||||
relations | relations | :heavy_check_mark: | :x:
|
||||
cmd_type | cmd_type | :heavy_check_mark: | :x:
|
||||
elevel | elevel | :heavy_check_mark: | :x:
|
||||
sqlcode | sqlcode | :heavy_check_mark: | :x:
|
||||
message | message | :heavy_check_mark: | :x:
|
||||
plans_calls | plans_calls | :heavy_check_mark: | :heavy_check_mark:
|
||||
total_plan_time | | :heavy_check_mark: | :heavy_check_mark:
|
||||
min_plan_time | | :heavy_check_mark: | :heavy_check_mark:
|
||||
max_plan_time | | :heavy_check_mark: | :heavy_check_mark:
|
||||
mean_plan_time | | :heavy_check_mark: | :heavy_check_mark:
|
||||
stddev_plan_time | | :heavy_check_mark: | :heavy_check_mark:
|
||||
calls | calls | :heavy_check_mark: | :heavy_check_mark:
|
||||
total_exec_time | total_time | :heavy_check_mark: | :heavy_check_mark:
|
||||
min_exec_time | min_time | :heavy_check_mark: | :heavy_check_mark:
|
||||
max_exec_time | max_time | :heavy_check_mark: | :heavy_check_mark:
|
||||
mean_exec_time | mean_time | :heavy_check_mark: | :heavy_check_mark:
|
||||
stddev_exec_time | stddev_time | :heavy_check_mark: | :heavy_check_mark:
|
||||
rows_retrieved | rows_retrieved | :heavy_check_mark: | :heavy_check_mark:
|
||||
shared_blks_hit | shared_blks_hit | :heavy_check_mark: | :heavy_check_mark:
|
||||
shared_blks_read | shared_blks_read | :heavy_check_mark: | :heavy_check_mark:
|
||||
shared_blks_dirtied | shared_blks_dirtied | :heavy_check_mark: | :heavy_check_mark:
|
||||
shared_blks_written | shared_blks_written | :heavy_check_mark: | :heavy_check_mark:
|
||||
local_blks_hit | local_blks_hit | :heavy_check_mark: | :heavy_check_mark:
|
||||
local_blks_read | local_blks_read | :heavy_check_mark: | :heavy_check_mark:
|
||||
local_blks_dirtied | local_blks_dirtied | :heavy_check_mark: | :heavy_check_mark:
|
||||
local_blks_written | local_blks_written | :heavy_check_mark: | :heavy_check_mark:
|
||||
temp_blks_read | temp_blks_read | :heavy_check_mark: | :heavy_check_mark:
|
||||
temp_blks_written | temp_blks_written | :heavy_check_mark: | :heavy_check_mark:
|
||||
blk_read_time | blk_read_time | :heavy_check_mark: | :heavy_check_mark:
|
||||
blk_write_time | blk_write_time | :heavy_check_mark: | :heavy_check_mark:
|
||||
resp_calls | resp_calls | :heavy_check_mark: | :x:
|
||||
cpu_user_time | cpu_user_time | :heavy_check_mark: | :x:
|
||||
cpu_sys_time | cpu_sys_time | :heavy_check_mark: | :x:
|
||||
wal_records | wal_records | :heavy_check_mark: | :heavy_check_mark:
|
||||
wal_fpi | wal_fpi | :heavy_check_mark: | :heavy_check_mark:
|
||||
wal_bytes | wal_bytes | :heavy_check_mark: | :heavy_check_mark:
|
||||
state_code | state_code | :heavy_check_mark: | :x:
|
||||
state | state | :heavy_check_mark: | :x:
|
||||
|
||||
To learn more about the features in `pg_stat_monitor`, please see the [User guide](https://github.com/percona/pg_stat_monitor/blob/master/docs/USER_GUIDE.md).
|
||||
|
||||
|
||||
Additional reading: [pg_stat_statements](https://www.postgresql.org/docs/current/pgstatstatements.html)
|
||||
|
||||
|
||||
|
||||
|
||||
[^1]: Available starting from PostgreSQL 14 and above
|
|
@ -0,0 +1,66 @@
|
|||
# `pg_stat_monitor` view reference
|
||||
|
||||
`pg_stat_monitor` provides a view where the statistics data is displayed. To see all available columns, run the following command from `psql`:
|
||||
|
||||
```sql
|
||||
postgres=# \d pg_stat_monitor
|
||||
```
|
||||
|
||||
Depending on the PostgreSQL version, some column names may differ. The following table describes the `pg_stat_monitor` view for PostgreSQL 14 and higher versions.
|
||||
|
||||
|
||||
| Column | Type | Description
|
||||
|--------------------|--------------------------|------------------
|
||||
bucket | integer | Data collection unit. The number shows what bucket in a chain a record belongs to
|
||||
bucket_start_time | timestamp with time zone | The start time of the bucket|
|
||||
userid | regrole | An ID of the user who run a query |
|
||||
datname | name | The name of a database where the query was executed
|
||||
toplevel | bool | True means that a query was executed as a top-level statement
|
||||
client_ip | inet | The IP address of a client that run the query
|
||||
queryid | text | The internal hash code serving to identify every query in a statement
|
||||
planid | text | An internally generated ID of a query plan
|
||||
query_plan | text | The sequence of steps used to execute a query. This parameter is available only when the `pgsm_enable_query_plan` is enabled.
|
||||
top_query | text | Shows the top query used in a statement |
|
||||
query | text | The actual text of the query |
|
||||
application_name | text | Shows the name of the application connected to the database
|
||||
relations | text[] | The list of tables involved in the query
|
||||
cmd_type | integer | Type of the query executed
|
||||
cmd_type_text | text[] | The description of the query executed
|
||||
elevel | integer | Shows the error level of a query (WARNING, ERROR, LOG)
|
||||
sqlcode | integer | SQL error code
|
||||
message | text | The error message
|
||||
plans_calls | bigint | The number of times the statement was planned
|
||||
total_plan_time | double precision | The total time (in ms) spent on planning the statement
|
||||
min_plan_time | double precision | Minimum time (in ms) spent on planning the statement
|
||||
max_plan_time | double precision | Maximum time (in ms) spent on planning the statement
|
||||
mean_plan_time | double precision | The mean (average) time (in ms) spent on planning the statement
|
||||
stddev_plan_time | double precision | The standard deviation of time (in ms) spent on planning the statement
|
||||
calls | bigint | The number of times a particular query was executed
|
||||
total_exec_time | double precision | The total time (in ms) spent on executing a query
|
||||
min_exec_time | double precision | The minimum time (in ms) it took to execute a query
|
||||
max_exec_time | double precision | The maximum time (in ms) it took to execute a query
|
||||
mean_time | double precision | The mean (average) time (in ms) it took to execute a query
|
||||
stddev_exec_time | double precision | The standard deviation of time (in ms) spent on executing a query
|
||||
rows_retrieved | bigint | The number of rows retrieved when executing a query
|
||||
shared_blks_hit | bigint | Shows the total number of shared memory blocks returned from the cache
|
||||
shared_blks_read | bigint | Shows the total number of shared blocks returned not from the cache
|
||||
shared_blks_dirtied | bigint | Shows the number of shared memory blocks "dirtied" by the query execution (i.e. a query modified at least one tuple in a block and this block must be written to a drive)
|
||||
shared_blks_written | bigint | Shows the number of shared memory blocks written simultaneously to a drive during the query execution
|
||||
local_blks_hit | bigint | The number of blocks which are considered as local by the backend and thus are used for temporary tables
|
||||
local_blks_read | bigint | Total number of local blocks read during the query execution
|
||||
local_blks_dirtied | bigint | Total number of local blocks "dirtied" during the query execution (i.e. a query modified at least one tuple in a block and this block must be written to a drive)
|
||||
local_blks_written | bigint | Total number of local blocks written simultaneously to a drive during the query execution
|
||||
temp_blks_read | bigint | Total number of blocks of temporary files read from a drive. Temporary files are used when there's not enough memory to execute a query
|
||||
temp_blks_written | bigint | Total number of blocks of temporary files written to a drive
|
||||
blk_read_time | double precision | Total waiting time (in ms) for reading blocks
|
||||
blk_write_time | double precision | Total waiting time (in ms) for writing blocks to a drive
|
||||
resp_calls | text[] | Call histogram
|
||||
cpu_user_time | double precision | The time (in ms) the CPU spent on running the query
|
||||
cpu_sys_time | double precision | The time (in ms) the CPU spent on executing the kernel code
|
||||
wal_records | bigint | The total number of WAL (Write Ahead Logs) generated by the query
|
||||
wal_fpi | bigint | The total number of WAL FPI (Full Page Images) generated by the query
|
||||
wal_bytes | numeric | Total number of bytes used for the WAL generated by the query
|
||||
state_code | bigint | Shows the state code of a query
|
||||
state | text | The state message
|
||||
|
||||
|
|
@ -1,170 +1,334 @@
|
|||
# User Guide
|
||||
|
||||
This document describes the configuration, key features and usage of ``pg_stat_monitor`` extension and compares it with ``pg_stat_statements``.
|
||||
* [Introduction](#introduction)
|
||||
* [Features](#features)
|
||||
* [Views](#views)
|
||||
* [Functions](#functions)
|
||||
* [Configuration](#configuration)
|
||||
* [Usage examples](#usage-examples)
|
||||
|
||||
For how to install and set up ``pg_stat_monitor``, see [README](https://github.com/percona/pg_stat_monitor/blob/master/README.md).
|
||||
## Introduction
|
||||
|
||||
After you've installed and enabled ``pg_stat_monitor``, create the ``pg_stat_monitor`` extension using the ``CREATE EXTENSION`` command.
|
||||
This document describes the features, functions and configuration of the ``pg_stat_monitor`` extension and gives some usage examples. For how to install and set up ``pg_stat_monitor``, see [Installation in README](https://github.com/percona/pg_stat_monitor/blob/master/README.md#installation).
|
||||
|
||||
```sql
|
||||
CREATE EXTENSION pg_stat_monitor;
|
||||
CREATE EXTENSION
|
||||
## Features
|
||||
|
||||
The following are the key features of pg_stat_monitor:
|
||||
|
||||
* [Time buckets](#time-buckets),
|
||||
* [Table and index access statistics per statement](#table-and-index-access-statistics-per-statement),
|
||||
* Query statistics:
|
||||
* [Query and client information](#query-and-client-information),
|
||||
* [Query timing information](#query-timing-information),
|
||||
* [Query execution plan information](#query-execution-plan-information),
|
||||
* [Use of actual data or parameters placeholders in queries](#use-of-actual-data-or-parameters-placeholders-in-queries),
|
||||
* [Query type filtering](#query-type-filtering),
|
||||
* [Query metadata supporting Google’s Sqlcommentor](#query-metadata),
|
||||
* [Top query tracking](#top-query-tracking),
|
||||
* [Relations](#relations) - showing tables involved in a query,
|
||||
* [Monitoring of queries terminated with ERROR, WARNING and LOG error levels](#monitoring-of-queries-terminated-with-error-warning-and-log-error-levels),
|
||||
* [Integration with Percona Monitoring and Management (PMM) tool](#integration-with-pmm),
|
||||
* [Histograms](#histogram) - visual representation of query performance.
|
||||
|
||||
|
||||
### Time buckets
|
||||
|
||||
Instead of supplying one set of ever-increasing counts, `pg_stat_monitor` computes stats for a configured number of time intervals; time buckets. This allows for much better data accuracy, especially in the case of high-resolution or unreliable networks.
|
||||
|
||||
### Table and index access statistics per statement
|
||||
|
||||
`pg_stat_monitor` collects the information about what tables were accessed by a statement. This allows you to identify all queries which access a given table easily.
|
||||
|
||||
|
||||
### Query and client information
|
||||
|
||||
`pg_stat_monitor` provides additional metrics for detailed analysis of query performance from various perspectives, including client connection details like user name, application name, IP address to name a few relevant columns.
|
||||
With this information, `pg_stat_monitor` enables users to track a query to the originating application. More details about the application or query may be incorporated in the SQL query in a [Google’s Sqlcommenter](https://google.github.io/sqlcommenter/) format.
|
||||
|
||||
To see how it works, refer to the [usage example](#query-information)
|
||||
|
||||
### Query timing information
|
||||
|
||||
Understanding query execution time stats helps you identify what affects query performance and take measures to optimize it. `pg_stat_monitor` collects the total, min, max and average (mean) time it took to execute a particular query and provides this data in separate columns. See the [Query timing information](#query-timing-information-1) example for the sample output.
|
||||
|
||||
|
||||
### Query execution plan information
|
||||
|
||||
Every query has a plan that was constructed for its executing. Collecting the query plan information as well as monitoring query plan timing helps you understand how you can modify the query to optimize its execution. It also helps make communication about the query clearer when discussing query performance with other DBAs and application developers.
|
||||
|
||||
See the [Query execution plan](##query-execution-plan) example for the sample output.
|
||||
|
||||
### Use of actual data or parameters placeholders in queries
|
||||
|
||||
You can select whether to see queries with parameters placeholders or actual query data. The benefit of having the full query example is in being able to run the [EXPLAIN](https://www.postgresql.org/docs/current/sql-explain.html) command on it to see how its execution was planned. As a result, you can modify the query to make it run better.
|
||||
|
||||
### Query type filtering
|
||||
|
||||
`pg_stat_monitor` monitors queries per type (``SELECT``, `INSERT`, `UPDATE` or `DELETE`) and classifies them accordingly in the `cmd_type` column. This way you can separate the queries you are interested in and focus on identifying the issues and optimizing query performance.
|
||||
|
||||
See the [Query type filtering example](#query-type-filtering-1) for the sample output.
|
||||
|
||||
### Query metadata
|
||||
|
||||
Google’s Sqlcommenter is a useful tool that in a way bridges that gap between ORM libraries and understanding database performance. And ``pg_stat_monitor`` supports it. So, you can now put any key-value data (like what client executed a query or if it is testing vs production query) in the comments in `/* … */` syntax in your SQL statements, and the information will be parsed by `pg_stat_monitor` and made available in the comments column in the `pg_stat_monitor` view. For details on the comments’ syntax, see [Sqlcommenter documentation](https://google.github.io/sqlcommenter/).
|
||||
|
||||
To see how it works, see the [Query metadata](#query-metadata-1) example.
|
||||
|
||||
### Top query tracking
|
||||
|
||||
Using functions is common. While running, functions can execute queries internally. `pg_stat_monitor` not only keeps track of all executed queries within a function, but also marks that function as top query.
|
||||
|
||||
Top query indicates the main query. To illustrate, for the SELECT query that is invoked within a function, the top query is calling this function.
|
||||
|
||||
This enables you to backtrack to the originating function and thus simplifies the tracking and analysis.
|
||||
|
||||
Find more details in the [usage example](#top-query-tracking-1).
|
||||
|
||||
### Relations
|
||||
|
||||
`pg_stat_monitor` provides the list of tables involved in the query in the relations column. This reduces time on identifying the tables and simplifies the analysis. To learn more, see the [usage examples](#relations-1)
|
||||
|
||||
### Monitoring queries terminated with ERROR, WARNING and LOG error levels
|
||||
|
||||
Monitoring queries that terminate with ERROR, WARNING, LOG states can give useful information to debug an issue. Such messages have the error level (`elevel`), error code (`sqlcode`), and error message (`message`). `pg_stat_monitor` collects all this information and aggregates it so that you can measure performance for successful and failed queries separately, as well as understand why a particular query failed to execute successfully.
|
||||
|
||||
Find details in the [usage example](#queries-terminated-with-errors)
|
||||
|
||||
### Integration with PMM
|
||||
|
||||
To timely identify and react on issues, performance should be automated and alerts should be sent when an issue occurs. There are many monitoring tools available for PostgreSQL, some of them (like Nagios) supporting custom metrics provided via extensions. Though you can integrate `pg_stat_monitor` with these tools, it natively supports integration with Percona Management and Monitoring (PMM). This integration allows you to enjoy all the features provided by both solutions: advanced statistics data provided by `pg_stat_monitor` and automated monitoring with data visualization on dashboards, security threat checks and alerting, available in PMM out of the box.
|
||||
|
||||
To learn how to integrate pg_stat_monitor with PMM, see [Configure pg_stat_monitor in PMM](https://www.percona.com/doc/percona-monitoring-and-management/2.x/setting-up/client/postgresql.html#pg_stat_monitor)
|
||||
|
||||
### Histogram
|
||||
|
||||
Histogram (the `resp_calls` parameter) provides a visual representation of query performance. With the help of the histogram function, you can view a timing/calling data histogram in response to an SQL query.
|
||||
|
||||
Learn more about using histograms from the [usage example](#histogram-1).
|
||||
|
||||
## Views
|
||||
|
||||
`pg_stat_monitor` provides the following views:
|
||||
* `pg_stat_monitor` is the view where statistics data is presented.
|
||||
* `pg_stat_monitor_settings` view shows available configuration options which you can change.
|
||||
|
||||
### `pg_stat_monitor` view
|
||||
|
||||
The statistics gathered by the module are made available via the view named `pg_stat_monitor`. This view contains one row for each distinct combination of metrics and whether it is a top-level statement or not (up to the maximum number of distinct statements that the module can track). For details about available counters, refer to the [`pg_stat_monitor` view reference](https://github.com/percona/pg_stat_monitor/blob/master/docs/REFERENCE.md).
|
||||
|
||||
The following are the primary keys for pg_stat_monitor:
|
||||
|
||||
* `bucket`,
|
||||
* `userid`,
|
||||
* `dbid`,
|
||||
* `client_ip`,
|
||||
* `application_name`.
|
||||
|
||||
A new row is created for each key in the `pg_stat_monitor` view.
|
||||
|
||||
`pg_stat_monitor` inherits the metrics available in `pg_stat_statements`, plus provides additional ones. See the [`pg_stat_monitor` vs `pg_stat_statements` comparison](https://github.com/percona/pg_stat_monitor/blob/master/docs/REFERENCE.md) for details.
|
||||
|
||||
For security reasons, only superusers and members of the `pg_read_all_stats` role are allowed to see the SQL text and `queryid` of queries executed by other users. Other users can see the statistics, however, if the view has been installed in their database.
|
||||
|
||||
### pg_stat_monitor_settings view
|
||||
|
||||
The `pg_stat_monitor_settings` view shows one row per `pg_stat_monitor` configuration parameter. It displays configuration parameter name, value, default value, description, minimum and maximum values, and whether a restart is required for a change in value to be effective.
|
||||
|
||||
## Functions
|
||||
|
||||
### pg_stat_monitor_reset()
|
||||
|
||||
This function resets all the statistics and clears the view. Eventually, the function will delete all the previous data.
|
||||
|
||||
### pg_stat_monitor_version()
|
||||
This function provides the build version of `pg_stat_monitor` version.
|
||||
|
||||
```
|
||||
postgres=# select pg_stat_monitor_version();
|
||||
pg_stat_monitor_version
|
||||
-------------------------
|
||||
devel
|
||||
(1 row)
|
||||
```
|
||||
|
||||
### Configuration
|
||||
Here is the complete list of configuration parameters.
|
||||
### histogram(bucket id, query id)
|
||||
|
||||
It is used to generate the histogram, you can refer to histogram sections.
|
||||
|
||||
## Configuration
|
||||
|
||||
Use the following command to view available configuration parameters in the `pg_stat_monitor_settings` view:
|
||||
|
||||
```sql
|
||||
SELECT * FROM pg_stat_monitor_settings;
|
||||
name | value | default_value | description | minimum | maximum | restart
|
||||
------------------------------------------+--------+---------------+----------------------------------------------------------------------------------------------------------+---------+------------+---------
|
||||
pg_stat_monitor.pgsm_max | 100 | 100 | Sets the maximum size of shared memory in (MB) used for statement's metadata tracked by pg_stat_monitor. | 1 | 1000 | 1
|
||||
pg_stat_monitor.pgsm_query_max_len | 1024 | 1024 | Sets the maximum length of query. | 1024 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_enable | 1 | 1 | Enable/Disable statistics collector. | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_track_utility | 1 | 1 | 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 | 60 | 60 | 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 | 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
|
||||
pg_stat_monitor.pgsm_query_shared_buffer | 20 | 20 | Sets the maximum size of shared memory in (MB) used for query tracked by pg_stat_monitor. | 1 | 10000 | 1
|
||||
pg_stat_monitor.pgsm_overflow_target | 1 | 1 | Sets the overflow target for pg_stat_monitor | 0 | 1 | 1
|
||||
pg_stat_monitor.pgsm_track_planning | 0 | 1 | Selects whether planning statistics are tracked. | 0 | 0 | 0
|
||||
(13 rows)
|
||||
|
||||
|
||||
```
|
||||
Some configuration parameters require a server restart and should be set before the server startup. These must be set in the ``postgresql.conf`` file. Other parameters do not require a server restart and can be set permanently either in the ``postgresql.conf`` or from the client (``psql``).
|
||||
|
||||
The table below shows set up options for each configuration parameter and whether the server restart is required to apply the parameter's value:
|
||||
To amend the `pg_stat_monitor` configuration, use the General Configuration Unit (GCU) system. Some configuration parameters require the server restart and should be set before the server startup. These must be set in the `postgresql.conf` file. Other parameters do not require server restart and can be set permanently either in the `postgresql.conf` or from the client (`psql`) using the SET or ALTER SYSTEM SET commands.
|
||||
|
||||
The following table shows setup options for each configuration parameter and whether the server restart is required to apply the parameter's value:
|
||||
|
||||
| Parameter Name | postgresql.conf | SET | ALTER SYSTEM SET | server restart | configuration reload
|
||||
| Parameter Name | postgresql.conf | SET | ALTER SYSTEM SET | server restart | configuration reload
|
||||
| ----------------------------------------------|--------------------|-----|-------------------|-------------------|---------------------
|
||||
| pg_stat_monitor.pgsm_max | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| pg_stat_monitor.pgsm_query_max_len | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| pg_stat_monitor.pgsm_enable | :heavy_check_mark: | :x: |:heavy_check_mark: |:x: | :x:
|
||||
| pg_stat_monitor.pgsm_track_utility | :heavy_check_mark: | :heavy_check_mark: |:heavy_check_mark: |:x: | :heavy_check_mark:
|
||||
| pg_stat_monitor.pgsm_normalized_query | :heavy_check_mark: | :heavy_check_mark: |:heavy_check_mark: |:x: | :heavy_check_mark:
|
||||
| pg_stat_monitor.pgsm_max_buckets | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :heavy_check_mark:
|
||||
| pg_stat_monitor.pgsm_bucket_time | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| pg_stat_monitor.pgsm_object_cache | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| pg_stat_monitor.pgsm_respose_time_lower_bound | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| pg_stat_monitor.pgsm_respose_time_step | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| pg_stat_monitor.pgsm_query_shared_buffer | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
|
||||
| [pg_stat_monitor.pgsm_max](#pg_stat_monitorpgsm_max) | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| [pg_stat_monitor.pgsm_query_max_len](#pg_stat_monitorpgsm_query_max_len) | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| [pg_stat_monitor.pgsm_enable](#pg_stat_monitorpgsm_enable) | :heavy_check_mark: | :x: |:heavy_check_mark: |:x: | :x:
|
||||
| [pg_stat_monitor.pgsm_track_utility](#pg_stat_monitorpgsm_track_utility) | :heavy_check_mark: | :heavy_check_mark: |:heavy_check_mark: |:x: | :heavy_check_mark:
|
||||
| [pg_stat_monitor.pgsm_normalized_query](#pg_stat_monitorpgsm_normalized_query) | :heavy_check_mark: | :heavy_check_mark: |:heavy_check_mark: |:x: | :heavy_check_mark:
|
||||
| [pg_stat_monitor.pgsm_max_buckets](#pg_stat_monitorpgsm_max_buckets) | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :heavy_check_mark:
|
||||
| [pg_stat_monitor.pgsm_bucket_time](#pg_stat_monitorpgsm_bucket_time) | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| [pg_stat_monitor.pgsm_object_cache](#pg-stat-monitorpgsm-object-cache) | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| [pg_stat_monitor.pgsm_histogram_min](#pg_stat_monitorpgsm_histogram_min) | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| [pg_stat_monitor.pgsm_histogram_max](#pg_stat_monitorpgsm_histogram_max) | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| [pg_stat_monitor.pgsm_histogram_buckets](#pg_stat_monitorpgsm_histogram_buckets) | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| [pg_stat_monitor.pgsm_query_shared_buffer](#pg_stat_monitorpgsm_query_shared_buffer) | :heavy_check_mark: | :x: |:x: |:heavy_check_mark: | :x:
|
||||
| [pg_stat_monitor.pgsm_overflow_target](#pg_stat_monitorpgsm_overflow_target) | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :x: |
|
||||
| [pg_stat_monitor.pgsm_enable_query_plan](#pg_stat_monitorpgsm_enable_query_plan) | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :x: |
|
||||
| [pg_stat_monitor.pgsm_track_planning](#pg_stat_monitorpgsm_track_planning) | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | :x: |
|
||||
|
||||
#### Parameters description:
|
||||
|
||||
- **pg_stat_monitor.pgsm_max**: This parameter defines the limit of shared memory for ``pg_stat_monitor``. This memory is used by buckets in a circular manner. The memory is divided between the buckets equally, at the start of the PostgreSQL.
|
||||
- **pg_stat_monitor.pgsm_query_max_len**: Sets the maximum size of the query. This parameter can only be set at the start of PostgreSQL. For long queries, the query is truncated to that particular length. This is to avoid unnecessary usage of shared memory.
|
||||
- **pg_stat_monitor.pgsm_enable**: This parameter enables or disables the monitoring. "Disable" means that ``pg_stat_monitor`` will not collect the statistics for the whole cluster.
|
||||
- **pg_stat_monitor.pgsm_track_utility**: This parameter controls whether utility commands are tracked by the module. Utility commands are all those other than ``SELECT``, ``INSERT``, ``UPDATE``, and ``DELETE``.
|
||||
- **pg_stat_monitor.pgsm_normalized_query**: By default, the query shows the actual parameter instead of the placeholder. It is quite useful when users want to use that query and try to run that query to check the abnormalities. But in most cases users like the queries with a placeholder. This parameter is used to toggle between the two said options.
|
||||
- **pg_stat_monitor.pgsm_max_buckets**: ``pg_stat_monitor`` accumulates the information in the form of buckets. All the aggregated information is bucket based. This parameter is used to set the number of buckets the system can have. For example, if this parameter is set to 2, then the system will create two buckets. First, the system will add all the information into the first bucket. After its lifetime (defined in the pg_stat_monitor.pgsm_bucket_time parameter) expires, it will switch to the second bucket, reset all the counters and repeat the process.
|
||||
- **pg_stat_monitor.pgsm_bucket_time**: This parameter is used to set the lifetime of the bucket. System switches between buckets on the basis of ``pg_stat_monitor.pgsm_bucket_time``.
|
||||
- **pg_stat_monitor.pgsm_respose_time_lower_bound**: ``pg_stat_monitor`` also stores the execution time histogram. This parameter is used to set the lower bound of the histogram.
|
||||
- **pg_stat_monitor.pgsm_respose_time_step:** This parameter is used to set the steps for the histogram.
|
||||
|
||||
##### pg_stat_monitor.pgsm_max
|
||||
|
||||
Values:
|
||||
- Min: 1
|
||||
- Max: 1000
|
||||
- Default: 100
|
||||
|
||||
|
||||
### Usage
|
||||
This parameter defines the limit of shared memory (in MB) for ``pg_stat_monitor``. This memory is used by buckets in a circular manner. The memory is divided between the buckets equally, at the start of the PostgreSQL. Requires the server restart.
|
||||
|
||||
The ``pg_stat_monitor`` extension contains a view called ``pg_stat_monitor``, which containss all the monitoring information. Find the list of columns in ``pg_stat_monitor`` view in the following table. The table also shows whether a particular column is available in ``pg_stat_statements``.
|
||||
##### pg_stat_monitor.pgsm_query_max_len
|
||||
|
||||
Values:
|
||||
- Min: 1024
|
||||
- Max: 2147483647
|
||||
- Default: 1024
|
||||
|
||||
Sets the maximum size of the query. This parameter can only be set at the start of PostgreSQL. For long queries, the query is truncated to that particular length. This is to avoid unnecessary usage of shared memory. Requires the server restart.
|
||||
|
||||
##### pg_stat_monitor.pgsm_enable
|
||||
|
||||
Type: boolean. Default: 1
|
||||
|
||||
Enables or disables the monitoring. "Disable" (0) means that ``pg_stat_monitor`` will not collect the statistics for the whole cluster.
|
||||
|
||||
##### pg_stat_monitor.pgsm_track_utility
|
||||
|
||||
Type: boolean. Default: 1
|
||||
|
||||
This parameter controls whether utility commands are tracked by the module. Utility commands are all those other than ``SELECT``, ``INSERT``, ``UPDATE``, and ``DELETE``.
|
||||
|
||||
##### pg_stat_monitor.pgsm_normalized_query
|
||||
|
||||
Type: boolean. Default: 1
|
||||
|
||||
By default, the query shows the actual parameter instead of the placeholder. It is quite useful when users want to use that query and try to run that query to check the abnormalities. But in most cases users like the queries with a placeholder. This parameter is used to toggle between the two said options.
|
||||
|
||||
##### pg_stat_monitor.pgsm_max_buckets
|
||||
|
||||
Values:
|
||||
- Min: 1
|
||||
- Max: 10
|
||||
- Default: 10
|
||||
|
||||
``pg_stat_monitor`` accumulates the information in the form of buckets. All the aggregated information is bucket based. This parameter is used to set the number of buckets the system can have. For example, if this parameter is set to 2, then the system will create two buckets. First, the system will add all the information into the first bucket. After its lifetime (defined in the [pg_stat_monitor.pgsm_bucket_time](#pg-stat-monitorpgsm-bucket-time) parameter) expires, it will switch to the second bucket, reset all the counters and repeat the process.
|
||||
|
||||
Requires the server restart.
|
||||
|
||||
##### pg_stat_monitor.pgsm_bucket_time
|
||||
|
||||
Values:
|
||||
- Min: 1
|
||||
- Max: 2147483647
|
||||
- Default: 60
|
||||
|
||||
This parameter is used to set the lifetime of the bucket. System switches between buckets on the basis of [pg_stat_monitor.pgsm_bucket_time](#pg-stat-monitorpgsm-bucket-time).
|
||||
|
||||
Requires the server restart.
|
||||
|
||||
##### pg_stat_monitor.pgsm_histogram_min
|
||||
|
||||
Values:
|
||||
- Min: 0
|
||||
- Max: 2147483647
|
||||
- Default: 0
|
||||
|
||||
``pg_stat_monitor`` also stores the execution time histogram. This parameter is used to set the lower bound of the histogram (in ms).
|
||||
|
||||
Requires the server restart.
|
||||
|
||||
##### pg_stat_monitor.pgsm_histogram_max
|
||||
|
||||
Values:
|
||||
- Min: 10
|
||||
- Max: 2147483647
|
||||
- Default: 100000
|
||||
|
||||
This parameter sets the upper bound of the execution time histogram (in ms). Requires the server restart.
|
||||
|
||||
##### pg_stat_monitor.pgsm_histogram_buckets
|
||||
|
||||
Values:
|
||||
- Min: 2
|
||||
- Max: 2147483647
|
||||
- Default: 10
|
||||
|
||||
This parameter sets the maximum number of histogram buckets. Requires the server restart.
|
||||
|
||||
##### pg_stat_monitor.pgsm_query_shared_buffer
|
||||
|
||||
Values:
|
||||
- Min: 1
|
||||
- Max: 10000
|
||||
- Default: 20
|
||||
|
||||
This parameter defines the shared memory limit (in MB) allocated for a query tracked by ``pg_stat_monitor``. Requires the server restart.
|
||||
|
||||
##### pg_stat_monitor.pgsm_overflow_target
|
||||
|
||||
Type: boolean. Default: 1
|
||||
|
||||
Sets the overflow target for the `pg_stat_monitor`. Requires the server restart.
|
||||
|
||||
##### pg_stat_monitor.pgsm_enable_query_plan
|
||||
|
||||
Type: boolean. Default: 1
|
||||
|
||||
Enables or disables query plan monitoring. When the `pgsm_enable_query_plan` is disabled (0), the query plan will not be captured by `pg_stat_monitor`. Enabling it may adversely affect the database performance. Requires the server restart.
|
||||
|
||||
|
||||
| Column | Type | pg_stat_monitor | pg_stat_statements
|
||||
|--------------------|--------------------------|----------------------|------------------
|
||||
bucket | integer | :heavy_check_mark: | :x:
|
||||
bucket_start_time | timestamp with time zone | :heavy_check_mark: | :x:
|
||||
userid | oid | :heavy_check_mark: | :heavy_check_mark:
|
||||
dbid | oid | :heavy_check_mark: | :heavy_check_mark:
|
||||
client_ip | inet | :heavy_check_mark: | :x:
|
||||
queryid | text | :heavy_check_mark: | :heavy_check_mark:
|
||||
planid | text | :heavy_check_mark: | :x:
|
||||
query_plan | text | :heavy_check_mark: | :x:
|
||||
top_query | text | :heavy_check_mark: | :x:
|
||||
query | text | :heavy_check_mark: | :heavy_check_mark:
|
||||
application_name | text | :heavy_check_mark: | :x:
|
||||
relations | text[] | :heavy_check_mark: | :x:
|
||||
cmd_type | text[] | :heavy_check_mark: | :x:
|
||||
elevel | integer | :heavy_check_mark: | :x:
|
||||
sqlcode | integer | :heavy_check_mark: | :x:
|
||||
message | text | :heavy_check_mark: | :x:
|
||||
plans | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
plan_total_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
plan_min_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
plan_max_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
plan_mean_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
plan_stddev_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
calls | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
total_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
min_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
max_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
mean_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
stddev_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
rows_retrieved | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
shared_blks_hit | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
shared_blks_read | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
shared_blks_dirtied | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
shared_blks_written | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
local_blks_hit | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
local_blks_read | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
local_blks_dirtied | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
local_blks_written | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
temp_blks_read | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
temp_blks_written | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
blk_read_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
blk_write_time | double precision | :heavy_check_mark: | :heavy_check_mark:
|
||||
resp_calls | text[] | :heavy_check_mark: | :x:
|
||||
cpu_user_time | double precision | :heavy_check_mark: | :x:
|
||||
cpu_sys_time | double precision | :heavy_check_mark: | :x:
|
||||
wal_records | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
wal_fpi | bigint | :heavy_check_mark: | :heavy_check_mark:
|
||||
wal_bytes | numeric | :heavy_check_mark: | :heavy_check_mark:
|
||||
state_code | bigint | :heavy_check_mark: | :x:
|
||||
state | text | :heavy_check_mark: | :x:
|
||||
##### pg_stat_monitor.pgsm_track_planning
|
||||
|
||||
Type: boolean. Default: 0
|
||||
|
||||
This parameter instructs ``pg_stat_monitor`` to monitor query planning statistics. Requires the server restart.
|
||||
|
||||
The following are some key features of pg_stat_monitor and usage examples.
|
||||
## Usage examples
|
||||
|
||||
#### Buckets
|
||||
Note that the column names differ depending on the PostgreSQL version you are using. The following usage examples are provided for PostgreSQL version 13.
|
||||
For versions 11 and 12, please consult the [pg_stat_monitor reference](https://github.com/percona/pg_stat_monitor/blob/master/docs/REFERENCE.md).
|
||||
|
||||
**`bucket`**: Accumulates the statistics per bucket. All the information and aggregate reset for each bucket. The bucket will be a number showing the number of buckets for which this record belongs.
|
||||
|
||||
**`bucket_start_time`**: shows the start time of the bucket.
|
||||
### Querying buckets
|
||||
|
||||
```sql
|
||||
postgres=# select bucket, bucket_start_time, query,calls from pg_stat_monitor order by bucket;
|
||||
|
||||
bucket | bucket_start_time | query | calls
|
||||
--------+---------------------+---------------------------------------------------------------------------------------------------------------+-------
|
||||
3 | 11-01-2021 17:30:45 | copy pgbench_accounts from stdin | 1
|
||||
3 | 11-01-2021 17:30:45 | alter table pgbench_accounts add primary key (aid) | 1
|
||||
3 | 11-01-2021 17:30:45 | vacuum analyze pgbench_accounts | 1
|
||||
3 | 11-01-2021 17:30:45 | vacuum analyze pgbench_tellers | 1
|
||||
3 | 11-01-2021 17:30:45 | insert into pgbench_branches(bid,bbalance) values($1,$2) | 100
|
||||
5 | 11-01-2021 17:31:15 | vacuum analyze pgbench_branches | 1
|
||||
5 | 11-01-2021 17:31:15 | copy pgbench_accounts from stdin | 1
|
||||
5 | 11-01-2021 17:31:15 | vacuum analyze pgbench_tellers | 1
|
||||
5 | 11-01-2021 17:31:15 | commit | 1
|
||||
6 | 11-01-2021 17:31:30 | alter table pgbench_branches add primary key (bid) | 1
|
||||
6 | 11-01-2021 17:31:30 | vacuum analyze pgbench_accounts | 1
|
||||
-[ RECORD 1 ]-----+------------------------------------------------------------------------------------
|
||||
bucket | 0
|
||||
bucket_start_time | 2021-10-22 11:10:00
|
||||
query | select bucket, bucket_start_time, query,calls from pg_stat_monitor order by bucket;
|
||||
calls | 1
|
||||
```
|
||||
|
||||
#### Query Information
|
||||
The `bucket` parameter shows the number of a bucket for which a given record belongs.
|
||||
The `bucket_start_time` shows the start time of the bucket.
|
||||
`query` shows the actual query text.
|
||||
`calls` shows how many times a given query was called.
|
||||
|
||||
**`userid`**: An ID of the user to whom that query belongs. ``pg_stat_monitor`` collects queries from all the users and uses the `userid` to segregate the queries based on different users.
|
||||
### Query information
|
||||
|
||||
**`dbid`**: The database ID of the query. ``pg_stat_monitor`` accumulates queries from all the databases; therefore, this column is used to identify the database.
|
||||
**Example 1: Shows the usename, database name, unique queryid hash, query, and the total number of calls of that query.**
|
||||
|
||||
**`queryid`**: ``pg_stat_monitor`` generates a unique ID for each query (queryid).
|
||||
|
||||
**`query`**: The query column contains the actual text of the query. This parameter depends on the **`pg_stat_monitor.pgsm_normalized_query`** configuration parameters, in which format to show the query.
|
||||
|
||||
**`calls`**: Number of calls of that particular query.
|
||||
|
||||
|
||||
##### Example: Shows the usename, database name, unique queryid hash, query, and the total number of calls of that query.
|
||||
```sql
|
||||
postgres=# SELECT userid, datname, queryid, substr(query,0, 50) AS query, calls FROM pg_stat_monitor;
|
||||
userid | datname | queryid | query | calls
|
||||
|
@ -186,219 +350,43 @@ postgres=# SELECT userid, datname, queryid, substr(query,0, 50) AS query, calls
|
|||
|
||||
```
|
||||
|
||||
##### Example: Shows the connected application_name.
|
||||
**Example 2: Shows the connected application details.**
|
||||
|
||||
```sql
|
||||
SELECT application_name, query FROM pg_stat_monitor;
|
||||
application_name | query
|
||||
------------------+------------------------------------------------------------------------------------------------------
|
||||
pgbench | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2
|
||||
pgbench | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2
|
||||
pgbench | vacuum pgbench_tellers
|
||||
pgbench | SELECT abalance FROM pgbench_accounts WHERE aid = $1
|
||||
pgbench | END
|
||||
pgbench | select count(*) from pgbench_branches
|
||||
pgbench | BEGIN
|
||||
pgbench | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP)
|
||||
psql | select application_name, query from pg_stat_monitor
|
||||
pgbench | vacuum pgbench_branches
|
||||
psql | select application_name query from pg_stat_monitor
|
||||
pgbench | truncate pgbench_history
|
||||
pgbench | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2
|
||||
postgres=# SELECT application_name, client_ip, substr(query,0,100) as query FROM pg_stat_monitor;
|
||||
application_name | client_ip | query
|
||||
------------------+-----------+-----------------------------------------------------------------------------------------------------
|
||||
pgbench | 127.0.0.1 | truncate pgbench_history
|
||||
pgbench | 127.0.0.1 | SELECT abalance FROM pgbench_accounts WHERE aid = $1
|
||||
pgbench | 127.0.0.1 | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2
|
||||
pgbench | 127.0.0.1 | BEGIN;
|
||||
pgbench | 127.0.0.1 | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP
|
||||
pgbench | 127.0.0.1 | END;
|
||||
pgbench | 127.0.0.1 | vacuum pgbench_branches
|
||||
pgbench | 127.0.0.1 | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2
|
||||
pgbench | 127.0.0.1 | vacuum pgbench_tellers
|
||||
pgbench | 127.0.0.1 | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2
|
||||
pgbench | 127.0.0.1 | select o.n, p.partstrat, pg_catalog.count(i.inhparent) from pg_catalog.pg_class as c join pg_catalo
|
||||
psql | 127.0.0.1 | SELECT application_name, client_ip, substr(query,$1,$2) as query FROM pg_stat_monitor
|
||||
pgbench | 127.0.0.1 | select count(*) from pgbench_branches
|
||||
(13 rows)
|
||||
|
||||
```
|
||||
|
||||
#### Error Messages / Error Codes and Error Level
|
||||
|
||||
**`elevel`**, **`sqlcode`**,**`message`**,: error level / sql code and log/warning/ error message
|
||||
### Query timing information
|
||||
|
||||
```sql
|
||||
SELECT substr(query,0,50) AS query, decode_error_level(elevel) AS elevel,sqlcode, calls, substr(message,0,50) message
|
||||
FROM pg_stat_monitor;
|
||||
query | elevel | sqlcode | calls | message
|
||||
---------------------------------------------------+--------+---------+-------+---------------------------------------------------
|
||||
select substr(query,$1,$2) as query, decode_error | | 0 | 1 |
|
||||
select bucket,substr(query,$1,$2),decode_error_le | | 0 | 3 |
|
||||
| LOG | 0 | 1 | database system is ready to accept connections
|
||||
select 1/0; | ERROR | 130 | 1 | division by zero
|
||||
| LOG | 0 | 1 | database system was shut down at 2020-11-11 11:37
|
||||
select $1/$2 | | 0 | 1 |
|
||||
(6 rows)
|
||||
```
|
||||
|
||||
#### Query Timing Information
|
||||
|
||||
**`total_time`**, **`min_time`**, **`max_time`**, **`mean_time`**: The total / minimum / maximum and mean time spent for the same query.
|
||||
|
||||
|
||||
```
|
||||
SELECT userid, total_time, min_time, max_time, mean_time, query FROM pg_stat_monitor;
|
||||
userid | total_time | min_time | max_time | mean_time | query
|
||||
SELECT userid, total_time, min_time, max_time, mean_time, query FROM pg_stat_monitor;
|
||||
userid | total_time | min_time | max_time | mean_time | query
|
||||
--------+--------------------+--------------------+--------------------+--------------------+------------------------------------------------------------------
|
||||
10 | 0.14 | 0.14 | 0.14 | 0.14 | select * from pg_stat_monitor_reset()
|
||||
10 | 0.19 | 0.19 | 0.19 | 0.19 | select userid, dbid, queryid, query from pg_stat_monitor
|
||||
10 | 0.30 | 0.13 | 0.16 | 0.15 | select bucket, bucket_start_time, query from pg_stat_monitor
|
||||
10 | 0.29 | 0.29 | 0.29 | 0.29 | select userid, dbid, queryid, query, calls from pg_stat_monitor
|
||||
10 | 11277.79 | 11277.79 | 11277.79 | 11277.79 | SELECT * FROM foo
|
||||
10 | 0.14 | 0.14 | 0.14 | 0.14 | select * from pg_stat_monitor_reset()
|
||||
10 | 0.19 | 0.19 | 0.19 | 0.19 | select userid, dbid, queryid, query from pg_stat_monitor
|
||||
10 | 0.30 | 0.13 | 0.16 | 0.15 | select bucket, bucket_start_time, query from pg_stat_monitor
|
||||
10 | 0.29 | 0.29 | 0.29 | 0.29 | select userid, dbid, queryid, query, calls from pg_stat_monitor
|
||||
10 | 11277.79 | 11277.79 | 11277.79 |
|
||||
```
|
||||
|
||||
#### Client IP address
|
||||
|
||||
**`client_ip`**: The IP address of the client that originated the query.
|
||||
|
||||
```sql
|
||||
SELECT userid::regrole, datname, substr(query,0, 50) AS query, calls, client_ip
|
||||
FROM pg_stat_monitor, pg_database
|
||||
WHERE dbid = oid;
|
||||
userid | datname | query | calls | client_ip
|
||||
---------+----------+---------------------------------------------------+-------+-----------
|
||||
vagrant | postgres | UPDATE pgbench_branches SET bbalance = bbalance + | 1599 | 10.0.2.15
|
||||
vagrant | postgres | select userid::regrole, datname, substr(query,$1, | 5 | 10.0.2.15
|
||||
vagrant | postgres | UPDATE pgbench_accounts SET abalance = abalance + | 1599 | 10.0.2.15
|
||||
vagrant | postgres | select userid::regrole, datname, substr(query,$1, | 1 | 127.0.0.1
|
||||
vagrant | postgres | vacuum pgbench_tellers | 1 | 10.0.2.15
|
||||
vagrant | postgres | SELECT abalance FROM pgbench_accounts WHERE aid = | 1599 | 10.0.2.15
|
||||
vagrant | postgres | END | 1599 | 10.0.2.15
|
||||
vagrant | postgres | select count(*) from pgbench_branches | 1 | 10.0.2.15
|
||||
vagrant | postgres | BEGIN | 1599 | 10.0.2.15
|
||||
vagrant | postgres | INSERT INTO pgbench_history (tid, bid, aid, delta | 1599 | 10.0.2.15
|
||||
vagrant | postgres | vacuum pgbench_branches | 1 | 10.0.2.15
|
||||
vagrant | postgres | truncate pgbench_history | 1 | 10.0.2.15
|
||||
vagrant | postgres | UPDATE pgbench_tellers SET tbalance = tbalance + | 1599 | 10.0.2.15
|
||||
```
|
||||
|
||||
#### Call Timings Histogram
|
||||
|
||||
**`resp_calls`**: Call histogram
|
||||
|
||||
```sql
|
||||
SELECT resp_calls, query FROM pg_stat_monitor;
|
||||
resp_calls | query
|
||||
--------------------------------------------------+----------------------------------------------
|
||||
{1," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 0"} | select client_ip, query from pg_stat_monitor
|
||||
{3," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 1"} | select * from pg_stat_monitor_reset()
|
||||
{3," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 1"} | SELECT * FROM foo
|
||||
|
||||
postgres=# SELECT * FROM histogram(0, 'F44CD1B4B33A47AF') AS a(range TEXT, freq INT, bar TEXT);
|
||||
range | freq | bar
|
||||
--------------------+------+--------------------------------
|
||||
(0 - 3)} | 2 | ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
|
||||
(3 - 10)} | 0 |
|
||||
(10 - 31)} | 1 | ■■■■■■■■■■■■■■■
|
||||
(31 - 100)} | 0 |
|
||||
(100 - 316)} | 0 |
|
||||
(316 - 1000)} | 0 |
|
||||
(1000 - 3162)} | 0 |
|
||||
(3162 - 10000)} | 0 |
|
||||
(10000 - 31622)} | 0 |
|
||||
(31622 - 100000)} | 0 |
|
||||
(10 rows)
|
||||
```
|
||||
|
||||
There are 10 timebase buckets of the time **`pg_stat_monitor.pgsm_respose_time_step`** in the field ``resp_calls``. The field's value shows how many queries run in that period of time.
|
||||
|
||||
|
||||
#### Object Information.
|
||||
|
||||
**`relations`**: The list of tables involved in the query
|
||||
|
||||
##### Example 1: List all the table names involved in the query.
|
||||
```sql
|
||||
postgres=# SELECT relations,query FROM pg_stat_monitor;
|
||||
relations | query
|
||||
-------------------------------+------------------------------------------------------------------------------------------------------
|
||||
| END
|
||||
{pgbench_accounts} | SELECT abalance FROM pgbench_accounts WHERE aid = $1
|
||||
| vacuum pgbench_branches
|
||||
{pgbench_branches} | select count(*) from pgbench_branches
|
||||
{pgbench_accounts} | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2
|
||||
| truncate pgbench_history
|
||||
{pgbench_history} | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP)
|
||||
{pg_stat_monitor,pg_database} | SELECT relations query FROM pg_stat_monitor
|
||||
| vacuum pgbench_tellers
|
||||
| BEGIN
|
||||
{pgbench_tellers} | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2
|
||||
{pgbench_branches} | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2
|
||||
(12 rows)
|
||||
```
|
||||
|
||||
##### Example 2: List all the views and the name of the table in the view. Here we have a view "test_view"
|
||||
```sql
|
||||
\d+ test_view
|
||||
View "public.test_view"
|
||||
Column | Type | Collation | Nullable | Default | Storage | Description
|
||||
--------+---------+-----------+----------+---------+---------+-------------
|
||||
foo_a | integer | | | | plain |
|
||||
bar_a | integer | | | | plain |
|
||||
View definition:
|
||||
SELECT f.a AS foo_a,
|
||||
b.a AS bar_a
|
||||
FROM foo f,
|
||||
bar b;
|
||||
```
|
||||
|
||||
Now when we query ``pg_stat_monitor``, it will show the view name and also all the table names in the view.
|
||||
```sql
|
||||
SELECT relations, query FROM pg_stat_monitor;
|
||||
relations | query
|
||||
---------------------+------------------------------------------------------------------------------------------------------
|
||||
{test_view,foo,bar} | select * from test_view
|
||||
{foo,bar} | select * from foo,bar
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
#### Query command Type (SELECT, INSERT, UPDATE OR DELETE)
|
||||
|
||||
**`cmd_type`**: List the command type of the query.
|
||||
|
||||
```sql
|
||||
postgres=# SELECT bucket, substr(query,0, 50) AS query, cmd_type FROM pg_stat_monitor WHERE elevel = 0;
|
||||
bucket | query | cmd_type
|
||||
--------+---------------------------------------------------+----------
|
||||
4 | END |
|
||||
4 | SELECT abalance FROM pgbench_accounts WHERE aid = | SELECT
|
||||
4 | vacuum pgbench_branches |
|
||||
4 | select count(*) from pgbench_branches | SELECT
|
||||
4 | UPDATE pgbench_accounts SET abalance = abalance + | UPDATE
|
||||
4 | truncate pgbench_history |
|
||||
4 | INSERT INTO pgbench_history (tid, bid, aid, delta | INSERT
|
||||
5 | SELECT relations query FROM pg_stat_monitor | SELECT
|
||||
9 | SELECT bucket, substr(query,$1, $2) AS query, cmd |
|
||||
4 | vacuum pgbench_tellers |
|
||||
4 | BEGIN |
|
||||
5 | SELECT relations,query FROM pg_stat_monitor | SELECT
|
||||
4 | UPDATE pgbench_tellers SET tbalance = tbalance + | UPDATE
|
||||
4 | UPDATE pgbench_branches SET bbalance = bbalance + | UPDATE
|
||||
(14 rows)
|
||||
```
|
||||
|
||||
#### Function Execution Tracking
|
||||
|
||||
**`top_queryid`**: Outer layer caller's query id.
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as
|
||||
$$
|
||||
BEGIN
|
||||
return (select $1 + $2);
|
||||
END;
|
||||
$$ language plpgsql;
|
||||
|
||||
SELECT add2(1,2);
|
||||
add2
|
||||
-----
|
||||
3
|
||||
(1 row)
|
||||
|
||||
postgres=# SELECT queryid, top_queryid, query, top_query FROM pg_stat_monitor;
|
||||
queryid | top_queryid | query. | top_query
|
||||
------------------+------------------+-------------------------------------------------------------------------+-------------------
|
||||
3408CA84B2353094 | | select add2($1,$2) |
|
||||
762B99349F6C7F31 | 3408CA84B2353094 | SELECT (select $1 + $2) | select add2($1,$2)
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
#### Monitor Query Execution Plan.
|
||||
### Query execution plan
|
||||
|
||||
```sql
|
||||
postgres=# SELECT substr(query,0,50), query_plan from pg_stat_monitor limit 10;
|
||||
|
@ -445,9 +433,38 @@ postgres=# SELECT substr(query,0,50), query_plan from pg_stat_monitor limit 10;
|
|||
vacuum pgbench_tellers |
|
||||
UPDATE pgbench_accounts SET abalance = abalance + |
|
||||
(10 rows)
|
||||
|
||||
```
|
||||
#### SQL Commenter / tags.
|
||||
|
||||
The `plan` column does not contain costing, width and other values. This is an expected behavior as each row is an accumulation of statistics based on `plan` and amongst other key columns. Plan is only available when the `pgsm_enable_query_plan` configuration parameter is enabled.
|
||||
|
||||
### Query type filtering
|
||||
|
||||
``pg_stat_monitor`` monitors queries per type (SELECT, INSERT, UPDATE OR DELETE) and classifies them accordingly in the ``cmd_type`` column thus reducing your efforts.
|
||||
|
||||
```sql
|
||||
postgres=# SELECT bucket, substr(query,0, 50) AS query, cmd_type FROM pg_stat_monitor WHERE elevel = 0;
|
||||
bucket | query | cmd_type
|
||||
--------+---------------------------------------------------+----------
|
||||
4 | END |
|
||||
4 | SELECT abalance FROM pgbench_accounts WHERE aid = | SELECT
|
||||
4 | vacuum pgbench_branches |
|
||||
4 | select count(*) from pgbench_branches | SELECT
|
||||
4 | UPDATE pgbench_accounts SET abalance = abalance + | UPDATE
|
||||
4 | truncate pgbench_history |
|
||||
4 | INSERT INTO pgbench_history (tid, bid, aid, delta | INSERT
|
||||
5 | SELECT relations query FROM pg_stat_monitor | SELECT
|
||||
9 | SELECT bucket, substr(query,$1, $2) AS query, cmd |
|
||||
4 | vacuum pgbench_tellers |
|
||||
4 | BEGIN |
|
||||
5 | SELECT relations,query FROM pg_stat_monitor | SELECT
|
||||
4 | UPDATE pgbench_tellers SET tbalance = tbalance + | UPDATE
|
||||
4 | UPDATE pgbench_branches SET bbalance = bbalance + | UPDATE
|
||||
(14 rows)
|
||||
```
|
||||
|
||||
### Query metadata
|
||||
|
||||
The `comments` column contains any text wrapped in `“/*”` and `“*/”` comment tags. The `pg_stat_monitor` extension picks up these comments and makes them available in the comments column. Please note that only the latest comment value is preserved per row. The comments may be put in any format that can be parsed by a tool.
|
||||
|
||||
```sql
|
||||
CREATE EXTENSION hstore;
|
||||
|
@ -524,3 +541,131 @@ postgres=# select query, text_to_hstore(comments)->'real_ip' as real_ip from pg_
|
|||
SELECT $1 AS num1,$2 AS num2, $3 AS num3, $4 AS num4 /* { "application", psql_app, "real_ip", 192.168.1.3} */ | 192.168.1.3
|
||||
(10 rows)
|
||||
```
|
||||
|
||||
### Top query tracking
|
||||
|
||||
In the following example we create a function `add2` that adds one parameter value to another one and call this function to calculate 1+2.
|
||||
|
||||
|
||||
```sql
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as
|
||||
$$
|
||||
BEGIN
|
||||
return (select $1 + $2);
|
||||
END;
|
||||
$$ language plpgsql;
|
||||
|
||||
SELECT add2(1,2);
|
||||
add2
|
||||
-----
|
||||
3
|
||||
(1 row)
|
||||
|
||||
The ``pg_stat_monitor`` view shows all executed queries and shows the very first query in a row - calling the `add2` function.
|
||||
|
||||
postgres=# SELECT queryid, top_queryid, query, top_query FROM pg_stat_monitor;
|
||||
queryid | top_queryid | query. | top_query
|
||||
------------------+------------------+-------------------------------------------------------------------------+-------------------
|
||||
3408CA84B2353094 | | select add2($1,$2) |
|
||||
762B99349F6C7F31 | 3408CA84B2353094 | SELECT (select $1 + $2) | select add2($1,$2)
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
### Relations
|
||||
|
||||
**Example 1: List all the table names involved in the query.**
|
||||
|
||||
```sql
|
||||
postgres=# SELECT relations,query FROM pg_stat_monitor;
|
||||
relations | query
|
||||
-------------------------------+------------------------------------------------------------------------------------------------------
|
||||
| END
|
||||
{public.pgbench_accounts} | SELECT abalance FROM pgbench_accounts WHERE aid = $1
|
||||
| vacuum pgbench_branches
|
||||
{public.pgbench_branches} | select count(*) from pgbench_branches
|
||||
{public.pgbench_accounts} | UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2
|
||||
| truncate pgbench_history
|
||||
{public.pgbench_history} | INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP)
|
||||
{public.pg_stat_monitor,pg_catalog.pg_database} | SELECT relations query FROM pg_stat_monitor
|
||||
| vacuum pgbench_tellers
|
||||
| BEGIN
|
||||
{public.pgbench_tellers} | UPDATE pgbench_tellers SET tbalance = tbalance + $1 WHERE tid = $2
|
||||
{public.pgbench_branches} | UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2
|
||||
(12 rows)
|
||||
```
|
||||
|
||||
**Example 2: List all the views and the name of the table in the view. Here we have a view "test_view"**
|
||||
|
||||
```sql
|
||||
\d+ test_view
|
||||
View "public.test_view"
|
||||
Column | Type | Collation | Nullable | Default | Storage | Description
|
||||
--------+---------+-----------+----------+---------+---------+-------------
|
||||
foo_a | integer | | | | plain |
|
||||
bar_a | integer | | | | plain |
|
||||
View definition:
|
||||
SELECT f.a AS foo_a,
|
||||
b.a AS bar_a
|
||||
FROM foo f,
|
||||
bar b;
|
||||
```
|
||||
|
||||
Now when we query the ``pg_stat_monitor``, it will show the view name and also all the table names in the view. Note that the view name is followed by an asterisk (*).
|
||||
|
||||
```sql
|
||||
SELECT relations, query FROM pg_stat_monitor;
|
||||
relations | query
|
||||
---------------------+----------------------------------------------------
|
||||
{test_view*,foo,bar} | select * from test_view
|
||||
{foo,bar} | select * from foo,bar
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
### Queries terminated with errors
|
||||
|
||||
```sql
|
||||
SELECT substr(query,0,50) AS query, decode_error_level(elevel) AS elevel,sqlcode, calls, substr(message,0,50) message
|
||||
FROM pg_stat_monitor;
|
||||
query | elevel | sqlcode | calls | message
|
||||
---------------------------------------------------+--------+---------+-------+---------------------------------------------------
|
||||
select substr(query,$1,$2) as query, decode_error | | 0 | 1 |
|
||||
select bucket,substr(query,$1,$2),decode_error_le | | 0 | 3 |
|
||||
| LOG | 0 | 1 | database system is ready to accept connections
|
||||
select 1/0; | ERROR | 130 | 1 | division by zero
|
||||
| LOG | 0 | 1 | database system was shut down at 2020-11-11 11:37
|
||||
select $1/$2 | | 0 | 1 |
|
||||
(6 rows)
|
||||
11277.79 | SELECT * FROM foo
|
||||
```
|
||||
|
||||
### Histogram
|
||||
|
||||
Histogram (the `resp_calls` parameter) provides a visual representation of query performance. With the help of the histogram function, you can view a timing/calling data histogram in response to a SQL query.
|
||||
|
||||
|
||||
```sql
|
||||
SELECT resp_calls, query FROM pg_stat_monitor;
|
||||
resp_calls | query
|
||||
--------------------------------------------------+----------------------------------------------
|
||||
{1," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 0"} | select client_ip, query from pg_stat_monitor
|
||||
{3," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 1"} | select * from pg_stat_monitor_reset()
|
||||
{3," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 0"," 1"} | SELECT * FROM foo
|
||||
|
||||
postgres=# SELECT * FROM histogram(0, 'F44CD1B4B33A47AF') AS a(range TEXT, freq INT, bar TEXT);
|
||||
range | freq | bar
|
||||
--------------------+------+--------------------------------
|
||||
(0 - 3)} | 2 | ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
|
||||
(3 - 10)} | 0 |
|
||||
(10 - 31)} | 1 | ■■■■■■■■■■■■■■■
|
||||
(31 - 100)} | 0 |
|
||||
(100 - 316)} | 0 |
|
||||
(316 - 1000)} | 0 |
|
||||
(1000 - 3162)} | 0 |
|
||||
(3162 - 10000)} | 0 |
|
||||
(10000 - 31622)} | 0 |
|
||||
(31622 - 100000)} | 0 |
|
||||
(10 rows)
|
||||
```
|
||||
|
||||
There are 10 time based buckets of the time generated automatically based on total buckets in the field ``resp_calls``. The value in the field shows how many queries run in that period of time.
|
||||
|
||||
|
|
64
guc.c
64
guc.c
|
@ -21,6 +21,7 @@
|
|||
GucVariable conf[MAX_SETTINGS];
|
||||
static void DefineIntGUC(GucVariable *conf);
|
||||
static void DefineBoolGUC(GucVariable *conf);
|
||||
static void DefineEnumGUC(GucVariable *conf, const struct config_enum_entry *options);
|
||||
|
||||
/*
|
||||
* Define (or redefine) custom GUC variables.
|
||||
|
@ -29,6 +30,7 @@ void
|
|||
init_guc(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
conf[i] = (GucVariable) {
|
||||
.guc_name = "pg_stat_monitor.pgsm_max",
|
||||
.guc_desc = "Sets the maximum size of shared memory in (MB) used for statement's metadata tracked by pg_stat_monitor.",
|
||||
|
@ -53,18 +55,6 @@ init_guc(void)
|
|||
};
|
||||
DefineIntGUC(&conf[i++]);
|
||||
|
||||
conf[i] = (GucVariable) {
|
||||
.guc_name = "pg_stat_monitor.pgsm_enable",
|
||||
.guc_desc = "Enable/Disable statistics collector.",
|
||||
.guc_default = 1,
|
||||
.guc_min = 0,
|
||||
.guc_max = 0,
|
||||
.guc_restart = false,
|
||||
.guc_unit = 0,
|
||||
.guc_value = &PGSM_ENABLED
|
||||
};
|
||||
DefineBoolGUC(&conf[i++]);
|
||||
|
||||
conf[i] = (GucVariable) {
|
||||
.guc_name = "pg_stat_monitor.pgsm_track_utility",
|
||||
.guc_desc = "Selects whether utility commands are tracked.",
|
||||
|
@ -185,12 +175,39 @@ init_guc(void)
|
|||
};
|
||||
DefineBoolGUC(&conf[i++]);
|
||||
|
||||
conf[i] = (GucVariable) {
|
||||
.guc_name = "pg_stat_monitor.track",
|
||||
.guc_desc = "Selects which statements are tracked by pg_stat_monitor.",
|
||||
.n_options = 3,
|
||||
.guc_default = PGSM_TRACK_TOP,
|
||||
.guc_min = PSGM_TRACK_NONE,
|
||||
.guc_max = PGSM_TRACK_ALL,
|
||||
.guc_restart = false,
|
||||
.guc_unit = 0,
|
||||
.guc_value = &PGSM_TRACK
|
||||
};
|
||||
for (int j = 0; j < conf[i].n_options; ++j) {
|
||||
strlcpy(conf[i].guc_options[j], track_options[j].name, sizeof(conf[i].guc_options[j]));
|
||||
}
|
||||
DefineEnumGUC(&conf[i++], track_options);
|
||||
|
||||
conf[i] = (GucVariable) {
|
||||
.guc_name = "pg_stat_monitor.extract_comments",
|
||||
.guc_desc = "Enable/Disable extracting comments from queries.",
|
||||
.guc_default = 0,
|
||||
.guc_min = 0,
|
||||
.guc_max = 0,
|
||||
.guc_restart = false,
|
||||
.guc_unit = 0,
|
||||
.guc_value = &PGSM_EXTRACT_COMMENTS
|
||||
};
|
||||
DefineBoolGUC(&conf[i++]);
|
||||
|
||||
#if PG_VERSION_NUM >= 130000
|
||||
conf[i] = (GucVariable) {
|
||||
.guc_name = "pg_stat_monitor.pgsm_track_planning",
|
||||
.guc_desc = "Selects whether planning statistics are tracked.",
|
||||
.guc_default = 1,
|
||||
.guc_default = 0,
|
||||
.guc_min = 0,
|
||||
.guc_max = 0,
|
||||
.guc_restart = false,
|
||||
|
@ -204,6 +221,7 @@ init_guc(void)
|
|||
static void
|
||||
DefineIntGUC(GucVariable *conf)
|
||||
{
|
||||
conf->type = PGC_INT;
|
||||
DefineCustomIntVariable(conf->guc_name,
|
||||
conf->guc_desc,
|
||||
NULL,
|
||||
|
@ -220,6 +238,7 @@ DefineIntGUC(GucVariable *conf)
|
|||
static void
|
||||
DefineBoolGUC(GucVariable *conf)
|
||||
{
|
||||
conf->type = PGC_BOOL;
|
||||
DefineCustomBoolVariable(conf->guc_name,
|
||||
conf->guc_desc,
|
||||
NULL,
|
||||
|
@ -232,9 +251,26 @@ DefineBoolGUC(GucVariable *conf)
|
|||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
DefineEnumGUC(GucVariable *conf, const struct config_enum_entry *options)
|
||||
{
|
||||
conf->type = PGC_ENUM;
|
||||
DefineCustomEnumVariable(conf->guc_name,
|
||||
conf->guc_desc,
|
||||
NULL,
|
||||
conf->guc_value,
|
||||
PGSM_TRACK_TOP,
|
||||
options,
|
||||
conf->guc_restart ? PGC_POSTMASTER : PGC_USERSET,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GucVariable*
|
||||
get_conf(int i)
|
||||
{
|
||||
return &conf[i];
|
||||
return &conf[i];
|
||||
}
|
||||
|
||||
|
|
146
hash_query.c
146
hash_query.c
|
@ -17,24 +17,14 @@
|
|||
#include "postgres.h"
|
||||
#include "nodes/pg_list.h"
|
||||
|
||||
#include "pgsm_errors.h"
|
||||
#include "pg_stat_monitor.h"
|
||||
|
||||
|
||||
static pgssSharedState *pgss;
|
||||
static HTAB *pgss_hash;
|
||||
static HTAB *pgss_query_hash;
|
||||
|
||||
static HTAB* hash_init(const char *hash_name, int key_size, int entry_size, int hash_size);
|
||||
/*
|
||||
* Copy query from src_buffer to dst_buff.
|
||||
* Use query_id and query_pos to fast locate query in source buffer.
|
||||
* Store updated query position in the destination buffer into param query_pos.
|
||||
*/
|
||||
static bool copy_query(uint64 bucket_id,
|
||||
uint64 query_id,
|
||||
uint64 query_pos,
|
||||
unsigned char *dst_buf,
|
||||
unsigned char *src_buf,
|
||||
size_t *new_query_pos);
|
||||
|
||||
static HTAB*
|
||||
hash_init(const char *hash_name, int key_size, int entry_size, int hash_size)
|
||||
|
@ -50,7 +40,6 @@ void
|
|||
pgss_startup(void)
|
||||
{
|
||||
bool found = false;
|
||||
int32 i;
|
||||
|
||||
/* reset in case this is a restart within the postmaster */
|
||||
|
||||
|
@ -66,7 +55,9 @@ pgss_startup(void)
|
|||
if (!found)
|
||||
{
|
||||
/* First time through ... */
|
||||
pgss->lock = &(GetNamedLWLockTranche("pg_stat_monitor"))->lock;
|
||||
LWLockPadded *pgsm_locks = GetNamedLWLockTranche("pg_stat_monitor");
|
||||
pgss->lock = &(pgsm_locks[0].lock);
|
||||
pgss->errors_lock = &(pgsm_locks[1].lock);
|
||||
SpinLockInit(&pgss->mutex);
|
||||
ResetSharedState(pgss);
|
||||
}
|
||||
|
@ -75,16 +66,12 @@ pgss_startup(void)
|
|||
init_hook_stats();
|
||||
#endif
|
||||
|
||||
pgss->query_buf_size_bucket = MAX_QUERY_BUF / PGSM_MAX_BUCKETS;
|
||||
|
||||
for (i = 0; i < PGSM_MAX_BUCKETS; i++)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)ShmemAlloc(pgss->query_buf_size_bucket);
|
||||
set_qbuf(i, buf);
|
||||
memset(buf, 0, sizeof (uint64));
|
||||
}
|
||||
set_qbuf((unsigned char *)ShmemAlloc(MAX_QUERY_BUF));
|
||||
|
||||
pgss_hash = hash_init("pg_stat_monitor: bucket hashtable", sizeof(pgssHashKey), sizeof(pgssEntry), MAX_BUCKET_ENTRIES);
|
||||
pgss_query_hash = hash_init("pg_stat_monitor: queryID hashtable", sizeof(uint64), sizeof(pgssQueryEntry), MAX_BUCKET_ENTRIES);
|
||||
|
||||
psgm_errors_init();
|
||||
|
||||
LWLockRelease(AddinShmemInitLock);
|
||||
|
||||
|
@ -107,6 +94,12 @@ pgsm_get_hash(void)
|
|||
return pgss_hash;
|
||||
}
|
||||
|
||||
HTAB*
|
||||
pgsm_get_query_hash(void)
|
||||
{
|
||||
return pgss_query_hash;
|
||||
}
|
||||
|
||||
/*
|
||||
* shmem_shutdown hook: Dump statistics into file.
|
||||
*
|
||||
|
@ -144,15 +137,21 @@ hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding)
|
|||
{
|
||||
pgssEntry *entry = NULL;
|
||||
bool found = false;
|
||||
long bucket_entries_cnt;
|
||||
|
||||
if (hash_get_num_entries(pgss_hash) >= MAX_BUCKET_ENTRIES)
|
||||
bucket_entries_cnt = hash_get_num_entries(pgss_hash);
|
||||
|
||||
if (bucket_entries_cnt >= MAX_BUCKET_ENTRIES)
|
||||
{
|
||||
elog(DEBUG1, "%s", "pg_stat_monitor: out of memory");
|
||||
pgsm_log_error("hash_entry_alloc: BUCKET OVERFLOW. entries(%d) >= max_entries(%d)",
|
||||
bucket_entries_cnt, MAX_BUCKET_ENTRIES);
|
||||
return NULL;
|
||||
}
|
||||
/* Find or create an entry with desired hash code */
|
||||
entry = (pgssEntry *) hash_search(pgss_hash, key, HASH_ENTER_NULL, &found);
|
||||
if (!found)
|
||||
if (entry == NULL)
|
||||
pgsm_log_error("hash_entry_alloc: OUT OF MEMORY");
|
||||
else if (!found)
|
||||
{
|
||||
pgss->bucket_entry[pg_atomic_read_u64(&pgss->current_wbucket)]++;
|
||||
/* New entry, initialize it */
|
||||
|
@ -164,8 +163,7 @@ hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding)
|
|||
/* ... and don't forget the query text metadata */
|
||||
entry->encoding = encoding;
|
||||
}
|
||||
if (entry == NULL)
|
||||
elog(DEBUG1, "%s", "pg_stat_monitor: out of memory");
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -182,22 +180,15 @@ hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding)
|
|||
* Caller must hold an exclusive lock on pgss->lock.
|
||||
*/
|
||||
void
|
||||
hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer[])
|
||||
hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer)
|
||||
{
|
||||
HASH_SEQ_STATUS hash_seq;
|
||||
pgssEntry *entry = NULL;
|
||||
pgssSharedState *pgss = pgsm_get_ss();
|
||||
|
||||
/* Store pending query ids from the previous bucket. */
|
||||
List *pending_entries = NIL;
|
||||
ListCell *pending_entry;
|
||||
|
||||
if (new_bucket_id != -1)
|
||||
{
|
||||
/* Clear all queries in the query buffer for the new bucket. */
|
||||
memset(query_buffer[new_bucket_id], 0, pgss->query_buf_size_bucket);
|
||||
}
|
||||
|
||||
/* Iterate over the hash table. */
|
||||
hash_seq_init(&hash_seq, pgss_hash);
|
||||
while ((entry = hash_seq_search(&hash_seq)) != NULL)
|
||||
|
@ -210,6 +201,11 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_bu
|
|||
(entry->key.bucket_id == new_bucket_id &&
|
||||
(entry->counters.state == PGSS_FINISHED || entry->counters.state == PGSS_ERROR)))
|
||||
{
|
||||
if (new_bucket_id == -1) {
|
||||
/* pg_stat_monitor_reset(), remove entry from query hash table too. */
|
||||
hash_search(pgss_query_hash, &(entry->key.queryid), HASH_REMOVE, NULL);
|
||||
}
|
||||
|
||||
entry = hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL);
|
||||
}
|
||||
|
||||
|
@ -229,9 +225,21 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_bu
|
|||
pgssEntry *bkp_entry = malloc(sizeof(pgssEntry));
|
||||
if (!bkp_entry)
|
||||
{
|
||||
/* No memory, remove pending query entry from the previous bucket. */
|
||||
elog(ERROR, "hash_entry_dealloc: out of memory");
|
||||
entry = hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL);
|
||||
pgsm_log_error("hash_entry_dealloc: out of memory");
|
||||
/*
|
||||
* No memory, If the entry has calls > 1 then we change the state to finished,
|
||||
* as the pending query will likely finish execution during the new bucket
|
||||
* time window. The pending query will vanish in this case, can't list it
|
||||
* until it completes.
|
||||
*
|
||||
* If there is only one call to the query and it's pending, remove the
|
||||
* entry from the previous bucket and allow it to finish in the new bucket,
|
||||
* in order to avoid the query living in the old bucket forever.
|
||||
*/
|
||||
if (entry->counters.calls.calls > 1)
|
||||
entry->counters.state = PGSS_FINISHED;
|
||||
else
|
||||
entry = hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -244,8 +252,20 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_bu
|
|||
/* Add the entry to a list of nodes to be processed later. */
|
||||
pending_entries = lappend(pending_entries, bkp_entry);
|
||||
|
||||
/* Finally remove the pending query from the expired bucket id. */
|
||||
entry = hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL);
|
||||
/*
|
||||
* If the entry has calls > 1 then we change the state to finished in
|
||||
* the previous bucket, as the pending query will likely finish execution
|
||||
* during the new bucket time window. Can't remove it from the previous bucket
|
||||
* as it may have many calls and we would lose the query statistics.
|
||||
*
|
||||
* If there is only one call to the query and it's pending, remove the entry
|
||||
* from the previous bucket and allow it to finish in the new bucket,
|
||||
* in order to avoid the query living in the old bucket forever.
|
||||
*/
|
||||
if (entry->counters.calls.calls > 1)
|
||||
entry->counters.state = PGSS_FINISHED;
|
||||
else
|
||||
entry = hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -261,20 +281,14 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_bu
|
|||
|
||||
new_entry = (pgssEntry *) hash_search(pgss_hash, &old_entry->key, HASH_ENTER_NULL, &found);
|
||||
if (new_entry == NULL)
|
||||
elog(DEBUG1, "%s", "pg_stat_monitor: out of memory");
|
||||
pgsm_log_error("hash_entry_dealloc: out of memory");
|
||||
else if (!found)
|
||||
{
|
||||
/* Restore counters and other data. */
|
||||
new_entry->counters = old_entry->counters;
|
||||
SpinLockInit(&new_entry->mutex);
|
||||
new_entry->encoding = old_entry->encoding;
|
||||
/* copy query's text from previous bucket to the new one. */
|
||||
copy_query(new_bucket_id,
|
||||
new_entry->key.queryid, /* query id */
|
||||
old_entry->query_pos, /* query position in buffer */
|
||||
query_buffer[new_bucket_id], /* destination query buffer */
|
||||
query_buffer[old_bucket_id], /* source query buffer */
|
||||
&new_entry->query_pos); /* position in which query was inserted into destination buffer */
|
||||
new_entry->query_pos = old_entry->query_pos;
|
||||
}
|
||||
|
||||
free(old_entry);
|
||||
|
@ -310,39 +324,3 @@ IsHashInitialize(void)
|
|||
return (pgss != NULL &&
|
||||
pgss_hash != NULL);
|
||||
}
|
||||
|
||||
static bool copy_query(uint64 bucket_id,
|
||||
uint64 query_id,
|
||||
uint64 query_pos,
|
||||
unsigned char *dst_buf,
|
||||
unsigned char *src_buf,
|
||||
size_t *new_query_pos)
|
||||
{
|
||||
uint64 query_len = 0;
|
||||
uint64 buf_len = 0;
|
||||
|
||||
memcpy(&buf_len, src_buf, sizeof (uint64));
|
||||
if (buf_len <= 0)
|
||||
return false;
|
||||
|
||||
/* Try to locate the query directly. */
|
||||
if (query_pos != 0 && (query_pos + sizeof(uint64) + sizeof(uint64)) < buf_len)
|
||||
{
|
||||
if (*(uint64 *)&src_buf[query_pos] != query_id)
|
||||
return false;
|
||||
|
||||
query_pos += sizeof(uint64);
|
||||
|
||||
memcpy(&query_len, &src_buf[query_pos], sizeof(uint64)); /* query len */
|
||||
query_pos += sizeof(uint64);
|
||||
|
||||
if (query_pos + query_len > buf_len) /* avoid reading past buffer's length. */
|
||||
return false;
|
||||
|
||||
return SaveQueryText(bucket_id, query_id, dst_buf,
|
||||
(const char *)&src_buf[query_pos],
|
||||
query_len, new_query_pos);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -12,18 +12,17 @@ export USE_PGXS=1
|
|||
dh $@
|
||||
|
||||
override_dh_auto_build:
|
||||
+pg_buildext build build-%v
|
||||
+pg_buildext clean . build-%v
|
||||
+pg_buildext build . build-%v
|
||||
|
||||
override_dh_auto_test:
|
||||
# nothing to do here
|
||||
|
||||
override_dh_auto_install:
|
||||
+pg_buildext install build-%v percona-pg-stat-monitor@@PG_REL@@
|
||||
+pg_buildext install . build-%v percona-pg-stat-monitor@@PG_REL@@
|
||||
|
||||
override_dh_installdocs:
|
||||
dh_installdocs --all README.*
|
||||
|
||||
override_dh_auto_clean:
|
||||
+pg_buildext clean build-%v
|
||||
rm -rf results regression.*
|
||||
mkdir results
|
||||
rm -rf results/* regression.*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
%global sname percona-pg-stat-monitor
|
||||
%global sname percona-pg_stat_monitor
|
||||
%global pgrel @@PG_REL@@
|
||||
%global rpm_release @@RPM_RELEASE@@
|
||||
%global pginstdir /usr/pgsql-@@PG_REL@@/
|
||||
|
@ -8,12 +8,16 @@ Name: %{sname}%{pgrel}
|
|||
Version: @@VERSION@@
|
||||
Release: %{rpm_release}%{?dist}
|
||||
License: PostgreSQL
|
||||
Source0: %{sname}%{pgrel}-%{version}.tar.gz
|
||||
Source0: percona-pg-stat-monitor%{pgrel}-%{version}.tar.gz
|
||||
URL: https://github.com/Percona-Lab/pg_stat_monitor
|
||||
BuildRequires: percona-postgresql%{pgrel}-devel
|
||||
Requires: postgresql-server
|
||||
Provides: percona-pg-stat-monitor%{pgrel}
|
||||
Conflicts: percona-pg-stat-monitor%{pgrel}
|
||||
Obsoletes: percona-pg-stat-monitor%{pgrel}
|
||||
Epoch: 1
|
||||
|
||||
Packager: Percona Development Team <https://jira.percona.com>
|
||||
Vendor: Percona, Inc
|
||||
|
||||
%description
|
||||
The pg_stat_monitor is statistics collector tool
|
||||
|
@ -25,7 +29,7 @@ It provides all the features of pg_stat_statment plus its own feature set.
|
|||
|
||||
|
||||
%prep
|
||||
%setup -q -n %{sname}%{pgrel}-%{version}
|
||||
%setup -q -n percona-pg-stat-monitor%{pgrel}-%{version}
|
||||
|
||||
|
||||
%build
|
||||
|
@ -61,5 +65,5 @@ sed -i 's:PG_CONFIG = pg_config:PG_CONFIG = /usr/pgsql-%{pgrel}/bin/pg_config:'
|
|||
|
||||
|
||||
%changelog
|
||||
* Thu Dec 19 2019 Oleksandr Miroshnychenko <alex.miroshnychenko@percona.com> - 1.0.0-1
|
||||
* Wed Nov 17 2021 Evgeniy Patlan <evgeniy.patlan@percona.com> - 1.0.0-1
|
||||
- Initial build
|
||||
|
|
|
@ -333,10 +333,10 @@ build_rpm(){
|
|||
echo "It is not possible to build rpm here"
|
||||
exit 1
|
||||
fi
|
||||
SRC_RPM=$(basename $(find $WORKDIR/srpm -name 'percona-pg-stat-monitor*.src.rpm' | sort | tail -n1))
|
||||
SRC_RPM=$(basename $(find $WORKDIR/srpm -name 'percona-pg_stat_monitor*.src.rpm' | sort | tail -n1))
|
||||
if [ -z $SRC_RPM ]
|
||||
then
|
||||
SRC_RPM=$(basename $(find $CURDIR/srpm -name 'percona-pg-stat-monitor*.src.rpm' | sort | tail -n1))
|
||||
SRC_RPM=$(basename $(find $CURDIR/srpm -name 'percona-pg_stat_monitor*.src.rpm' | sort | tail -n1))
|
||||
if [ -z $SRC_RPM ]
|
||||
then
|
||||
echo "There is no src rpm for build"
|
||||
|
|
|
@ -47,19 +47,22 @@ CREATE FUNCTION pg_stat_monitor_internal(IN showtext boolean,
|
|||
OUT bucket_start_time text,
|
||||
|
||||
OUT calls int8, -- 16
|
||||
OUT total_time float8,
|
||||
OUT min_time float8,
|
||||
OUT max_time float8,
|
||||
OUT mean_time float8,
|
||||
OUT stddev_time float8,
|
||||
OUT rows_retrieved int8,
|
||||
|
||||
OUT total_exec_time float8,
|
||||
OUT min_exec_time float8,
|
||||
OUT max_exec_time float8,
|
||||
OUT mean_exec_time float8,
|
||||
OUT stddev_exec_time float8,
|
||||
|
||||
OUT rows_retrieved int8,
|
||||
|
||||
OUT plans_calls int8, -- 23
|
||||
OUT plan_total_time float8,
|
||||
OUT plan_min_time float8,
|
||||
OUT plan_max_time float8,
|
||||
OUT plan_mean_time float8,
|
||||
OUT plan_stddev_time float8,
|
||||
|
||||
OUT total_plan_time float8,
|
||||
OUT min_plan_time float8,
|
||||
OUT max_plan_time float8,
|
||||
OUT mean_plan_time float8,
|
||||
OUT stddev_plan_time float8,
|
||||
|
||||
OUT shared_blks_hit int8, -- 29
|
||||
OUT shared_blks_read int8,
|
||||
|
@ -79,7 +82,8 @@ CREATE FUNCTION pg_stat_monitor_internal(IN showtext boolean,
|
|||
OUT wal_records int8,
|
||||
OUT wal_fpi int8,
|
||||
OUT wal_bytes numeric,
|
||||
OUT comments TEXT
|
||||
OUT comments TEXT,
|
||||
OUT toplevel BOOLEAN
|
||||
)
|
||||
RETURNS SETOF record
|
||||
AS 'MODULE_PATHNAME', 'pg_stat_monitor'
|
||||
|
@ -158,17 +162,21 @@ CREATE VIEW pg_stat_monitor AS SELECT
|
|||
sqlcode,
|
||||
message,
|
||||
calls,
|
||||
total_time,
|
||||
min_time,
|
||||
max_time,
|
||||
mean_time,
|
||||
stddev_time,
|
||||
total_exec_time,
|
||||
min_exec_time,
|
||||
max_exec_time,
|
||||
mean_exec_time,
|
||||
stddev_exec_time,
|
||||
|
||||
rows_retrieved,
|
||||
plans_calls,
|
||||
plan_total_time,
|
||||
plan_min_time,
|
||||
plan_max_time,
|
||||
plan_mean_time,
|
||||
|
||||
plans_calls,
|
||||
|
||||
total_plan_time,
|
||||
min_plan_time,
|
||||
max_plan_time,
|
||||
mean_plan_time,
|
||||
stddev_plan_time,
|
||||
|
||||
shared_blks_hit,
|
||||
shared_blks_read,
|
||||
|
@ -228,26 +236,26 @@ end loop;
|
|||
END
|
||||
$$ language plpgsql;
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_hook_stats(
|
||||
OUT hook text,
|
||||
OUT min_time float8,
|
||||
OUT max_time float8,
|
||||
OUT total_time float8,
|
||||
OUT ncalls int8
|
||||
)
|
||||
RETURNS SETOF record
|
||||
AS 'MODULE_PATHNAME', 'pg_stat_monitor_hook_stats'
|
||||
LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
--CREATE FUNCTION pg_stat_monitor_hook_stats(
|
||||
-- OUT hook text,
|
||||
-- OUT min_time float8,
|
||||
-- OUT max_time float8,
|
||||
-- OUT total_time float8,
|
||||
-- OUT ncalls int8
|
||||
--)
|
||||
--RETURNS SETOF record
|
||||
--AS 'MODULE_PATHNAME', 'pg_stat_monitor_hook_stats'
|
||||
--LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
|
||||
CREATE VIEW pg_stat_monitor_hook_stats AS SELECT
|
||||
hook,
|
||||
min_time,
|
||||
max_time,
|
||||
total_time,
|
||||
total_time / greatest(ncalls, 1) as avg_time,
|
||||
ncalls,
|
||||
ROUND(CAST(total_time / greatest(sum(total_time) OVER(), 0.00000001) * 100 as numeric), 2)::text || '%' as load_comparison
|
||||
FROM pg_stat_monitor_hook_stats();
|
||||
--CREATE VIEW pg_stat_monitor_hook_stats AS SELECT
|
||||
-- hook,
|
||||
-- min_time,
|
||||
-- max_time,
|
||||
-- total_time,
|
||||
-- total_time / greatest(ncalls, 1) as avg_time,
|
||||
-- ncalls,
|
||||
-- ROUND(CAST(total_time / greatest(sum(total_time) OVER(), 0.00000001) * 100 as numeric), 2)::text || '%' as load_comparison
|
||||
--FROM pg_stat_monitor_hook_stats();
|
||||
|
||||
GRANT SELECT ON pg_stat_monitor TO PUBLIC;
|
||||
GRANT SELECT ON pg_stat_monitor_settings TO PUBLIC;
|
|
@ -0,0 +1,264 @@
|
|||
/* contrib/pg_stat_monitor/pg_stat_monitor--1.1.sql */
|
||||
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION pg_stat_monitor" to load this file. \quit
|
||||
|
||||
-- Register functions.
|
||||
CREATE FUNCTION pg_stat_monitor_reset()
|
||||
RETURNS void
|
||||
AS 'MODULE_PATHNAME'
|
||||
LANGUAGE C PARALLEL SAFE;
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_version()
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME'
|
||||
LANGUAGE C PARALLEL SAFE;
|
||||
|
||||
CREATE FUNCTION get_histogram_timings()
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME'
|
||||
LANGUAGE C PARALLEL SAFE;
|
||||
|
||||
CREATE FUNCTION range()
|
||||
RETURNS text[] AS $$
|
||||
SELECT string_to_array(get_histogram_timings(), ',');
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_internal(IN showtext boolean,
|
||||
OUT bucket int8, -- 0
|
||||
OUT userid oid,
|
||||
OUT dbid oid,
|
||||
OUT client_ip int8,
|
||||
|
||||
OUT queryid text, -- 4
|
||||
OUT planid text,
|
||||
OUT query text,
|
||||
OUT query_plan text,
|
||||
OUT state_code int8,
|
||||
OUT top_queryid text,
|
||||
OUT top_query text,
|
||||
OUT application_name text,
|
||||
|
||||
OUT relations text, -- 11
|
||||
OUT cmd_type int,
|
||||
OUT elevel int,
|
||||
OUT sqlcode TEXT,
|
||||
OUT message text,
|
||||
OUT bucket_start_time text,
|
||||
|
||||
OUT calls int8, -- 16
|
||||
|
||||
OUT total_exec_time float8,
|
||||
OUT min_exec_time float8,
|
||||
OUT max_exec_time float8,
|
||||
OUT mean_exec_time float8,
|
||||
OUT stddev_exec_time float8,
|
||||
|
||||
OUT rows_retrieved int8,
|
||||
|
||||
OUT plans_calls int8, -- 23
|
||||
|
||||
OUT total_plan_time float8,
|
||||
OUT min_plan_time float8,
|
||||
OUT max_plan_time float8,
|
||||
OUT mean_plan_time float8,
|
||||
OUT stddev_plan_time float8,
|
||||
|
||||
OUT shared_blks_hit int8, -- 29
|
||||
OUT shared_blks_read int8,
|
||||
OUT shared_blks_dirtied int8,
|
||||
OUT shared_blks_written int8,
|
||||
OUT local_blks_hit int8,
|
||||
OUT local_blks_read int8,
|
||||
OUT local_blks_dirtied int8,
|
||||
OUT local_blks_written int8,
|
||||
OUT temp_blks_read int8,
|
||||
OUT temp_blks_written int8,
|
||||
OUT blk_read_time float8,
|
||||
OUT blk_write_time float8,
|
||||
OUT resp_calls text, -- 41
|
||||
OUT cpu_user_time float8,
|
||||
OUT cpu_sys_time float8,
|
||||
OUT wal_records int8,
|
||||
OUT wal_fpi int8,
|
||||
OUT wal_bytes numeric,
|
||||
OUT comments TEXT,
|
||||
OUT toplevel BOOLEAN
|
||||
)
|
||||
RETURNS SETOF record
|
||||
AS 'MODULE_PATHNAME', 'pg_stat_monitor'
|
||||
LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION get_state(state_code int8) RETURNS TEXT AS
|
||||
$$
|
||||
SELECT
|
||||
CASE
|
||||
WHEN state_code = 0 THEN 'PARSING'
|
||||
WHEN state_code = 1 THEN 'PLANNING'
|
||||
WHEN state_code = 2 THEN 'ACTIVE'
|
||||
WHEN state_code = 3 THEN 'FINISHED'
|
||||
WHEN state_code = 4 THEN 'FINISHED WITH ERROR'
|
||||
END
|
||||
$$
|
||||
LANGUAGE SQL PARALLEL SAFE;
|
||||
|
||||
CREATE or REPLACE FUNCTION get_cmd_type (cmd_type INTEGER) RETURNS TEXT AS
|
||||
$$
|
||||
SELECT
|
||||
CASE
|
||||
WHEN cmd_type = 0 THEN ''
|
||||
WHEN cmd_type = 1 THEN 'SELECT'
|
||||
WHEN cmd_type = 2 THEN 'UPDATE'
|
||||
WHEN cmd_type = 3 THEN 'INSERT'
|
||||
WHEN cmd_type = 4 THEN 'DELETE'
|
||||
WHEN cmd_type = 5 THEN 'UTILITY'
|
||||
WHEN cmd_type = 6 THEN 'NOTHING'
|
||||
END
|
||||
$$
|
||||
LANGUAGE SQL PARALLEL SAFE;
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_settings(
|
||||
OUT name text,
|
||||
OUT value INTEGER,
|
||||
OUT default_value INTEGER,
|
||||
OUT description text,
|
||||
OUT minimum INTEGER,
|
||||
OUT maximum INTEGER,
|
||||
OUT restart INTEGER
|
||||
)
|
||||
RETURNS SETOF record
|
||||
AS 'MODULE_PATHNAME', 'pg_stat_monitor_settings'
|
||||
LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
|
||||
CREATE VIEW pg_stat_monitor_settings AS SELECT
|
||||
name,
|
||||
value,
|
||||
default_value,
|
||||
description,
|
||||
minimum,
|
||||
maximum,
|
||||
restart
|
||||
FROM pg_stat_monitor_settings();
|
||||
|
||||
-- Register a view on the function for ease of use.
|
||||
CREATE VIEW pg_stat_monitor AS SELECT
|
||||
bucket,
|
||||
bucket_start_time AS bucket_start_time,
|
||||
userid::regrole,
|
||||
datname,
|
||||
'0.0.0.0'::inet + client_ip AS client_ip,
|
||||
queryid,
|
||||
toplevel,
|
||||
top_queryid,
|
||||
query,
|
||||
comments,
|
||||
planid,
|
||||
query_plan,
|
||||
top_query,
|
||||
application_name,
|
||||
string_to_array(relations, ',') AS relations,
|
||||
cmd_type,
|
||||
get_cmd_type(cmd_type) AS cmd_type_text,
|
||||
elevel,
|
||||
sqlcode,
|
||||
message,
|
||||
calls,
|
||||
total_exec_time,
|
||||
min_exec_time,
|
||||
max_exec_time,
|
||||
mean_exec_time,
|
||||
stddev_exec_time,
|
||||
|
||||
rows_retrieved,
|
||||
|
||||
plans_calls,
|
||||
|
||||
total_plan_time,
|
||||
min_plan_time,
|
||||
max_plan_time,
|
||||
mean_plan_time,
|
||||
stddev_plan_time,
|
||||
|
||||
shared_blks_hit,
|
||||
shared_blks_read,
|
||||
shared_blks_dirtied,
|
||||
shared_blks_written,
|
||||
local_blks_hit,
|
||||
local_blks_read,
|
||||
local_blks_dirtied,
|
||||
local_blks_written,
|
||||
temp_blks_read,
|
||||
temp_blks_written,
|
||||
blk_read_time,
|
||||
blk_write_time,
|
||||
(string_to_array(resp_calls, ',')) resp_calls,
|
||||
cpu_user_time,
|
||||
cpu_sys_time,
|
||||
wal_records,
|
||||
wal_fpi,
|
||||
wal_bytes,
|
||||
state_code,
|
||||
get_state(state_code) as state
|
||||
FROM pg_stat_monitor_internal(TRUE) p, pg_database d WHERE dbid = oid
|
||||
ORDER BY bucket_start_time;
|
||||
|
||||
CREATE FUNCTION decode_error_level(elevel int)
|
||||
RETURNS text
|
||||
AS
|
||||
$$
|
||||
SELECT
|
||||
CASE
|
||||
WHEN elevel = 0 THEN ''
|
||||
WHEN elevel = 10 THEN 'DEBUG5'
|
||||
WHEN elevel = 11 THEN 'DEBUG4'
|
||||
WHEN elevel = 12 THEN 'DEBUG3'
|
||||
WHEN elevel = 13 THEN 'DEBUG2'
|
||||
WHEN elevel = 14 THEN 'DEBUG1'
|
||||
WHEN elevel = 15 THEN 'LOG'
|
||||
WHEN elevel = 16 THEN 'LOG_SERVER_ONLY'
|
||||
WHEN elevel = 17 THEN 'INFO'
|
||||
WHEN elevel = 18 THEN 'NOTICE'
|
||||
WHEN elevel = 19 THEN 'WARNING'
|
||||
WHEN elevel = 20 THEN 'ERROR'
|
||||
END
|
||||
$$
|
||||
LANGUAGE SQL PARALLEL SAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION histogram(_bucket int, _quryid text)
|
||||
RETURNS SETOF RECORD AS $$
|
||||
DECLARE
|
||||
rec record;
|
||||
BEGIN
|
||||
for rec in
|
||||
with stat as (select queryid, bucket, unnest(range()) as range, unnest(resp_calls)::int freq from pg_stat_monitor) select range, freq, repeat('■', (freq::float / max(freq) over() * 30)::int) as bar from stat where queryid = _quryid and bucket = _bucket
|
||||
loop
|
||||
return next rec;
|
||||
end loop;
|
||||
END
|
||||
$$ language plpgsql;
|
||||
|
||||
--CREATE FUNCTION pg_stat_monitor_hook_stats(
|
||||
-- OUT hook text,
|
||||
-- OUT min_time float8,
|
||||
-- OUT max_time float8,
|
||||
-- OUT total_time float8,
|
||||
-- OUT ncalls int8
|
||||
--)
|
||||
--RETURNS SETOF record
|
||||
--AS 'MODULE_PATHNAME', 'pg_stat_monitor_hook_stats'
|
||||
--LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
--
|
||||
--CREATE VIEW pg_stat_monitor_hook_stats AS SELECT
|
||||
-- hook,
|
||||
-- min_time,
|
||||
-- max_time,
|
||||
-- total_time,
|
||||
-- total_time / greatest(ncalls, 1) as avg_time,
|
||||
-- ncalls,
|
||||
-- ROUND(CAST(total_time / greatest(sum(total_time) OVER(), 0.00000001) * 100 as numeric), 2)::text || '%' as load_comparison
|
||||
--FROM pg_stat_monitor_hook_stats();
|
||||
|
||||
GRANT SELECT ON pg_stat_monitor TO PUBLIC;
|
||||
GRANT SELECT ON pg_stat_monitor_settings TO PUBLIC;
|
||||
-- Don't want this to be available to non-superusers.
|
||||
REVOKE ALL ON FUNCTION pg_stat_monitor_reset() FROM PUBLIC;
|
|
@ -0,0 +1,285 @@
|
|||
/* contrib/pg_stat_monitor/pg_stat_monitor--1.1.sql */
|
||||
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION pg_stat_monitor" to load this file. \quit
|
||||
|
||||
-- Register functions.
|
||||
CREATE FUNCTION pg_stat_monitor_reset()
|
||||
RETURNS void
|
||||
AS 'MODULE_PATHNAME'
|
||||
LANGUAGE C PARALLEL SAFE;
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_version()
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME'
|
||||
LANGUAGE C PARALLEL SAFE;
|
||||
|
||||
CREATE FUNCTION get_histogram_timings()
|
||||
RETURNS text
|
||||
AS 'MODULE_PATHNAME'
|
||||
LANGUAGE C PARALLEL SAFE;
|
||||
|
||||
CREATE FUNCTION range()
|
||||
RETURNS text[] AS $$
|
||||
SELECT string_to_array(get_histogram_timings(), ',');
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_internal(IN showtext boolean,
|
||||
OUT bucket int8, -- 0
|
||||
OUT userid oid,
|
||||
OUT dbid oid,
|
||||
OUT client_ip int8,
|
||||
|
||||
OUT queryid text, -- 4
|
||||
OUT planid text,
|
||||
OUT query text,
|
||||
OUT query_plan text,
|
||||
OUT state_code int8,
|
||||
OUT top_queryid text,
|
||||
OUT top_query text,
|
||||
OUT application_name text,
|
||||
|
||||
OUT relations text, -- 11
|
||||
OUT cmd_type int,
|
||||
OUT elevel int,
|
||||
OUT sqlcode TEXT,
|
||||
OUT message text,
|
||||
OUT bucket_start_time text,
|
||||
|
||||
OUT calls int8, -- 16
|
||||
OUT total_time float8,
|
||||
OUT min_time float8,
|
||||
OUT max_time float8,
|
||||
OUT mean_time float8,
|
||||
OUT stddev_time float8,
|
||||
OUT rows_retrieved int8,
|
||||
|
||||
OUT plans_calls int8, -- 23
|
||||
OUT plan_total_time float8,
|
||||
OUT plan_min_time float8,
|
||||
OUT plan_max_time float8,
|
||||
OUT plan_mean_time float8,
|
||||
OUT plan_stddev_time float8,
|
||||
|
||||
OUT shared_blks_hit int8, -- 29
|
||||
OUT shared_blks_read int8,
|
||||
OUT shared_blks_dirtied int8,
|
||||
OUT shared_blks_written int8,
|
||||
OUT local_blks_hit int8,
|
||||
OUT local_blks_read int8,
|
||||
OUT local_blks_dirtied int8,
|
||||
OUT local_blks_written int8,
|
||||
OUT temp_blks_read int8,
|
||||
OUT temp_blks_written int8,
|
||||
OUT blk_read_time float8,
|
||||
OUT blk_write_time float8,
|
||||
OUT resp_calls text, -- 41
|
||||
OUT cpu_user_time float8,
|
||||
OUT cpu_sys_time float8,
|
||||
OUT wal_records int8,
|
||||
OUT wal_fpi int8,
|
||||
OUT wal_bytes numeric,
|
||||
OUT comments TEXT,
|
||||
OUT toplevel BOOLEAN
|
||||
)
|
||||
RETURNS SETOF record
|
||||
AS 'MODULE_PATHNAME', 'pg_stat_monitor'
|
||||
LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION get_state(state_code int8) RETURNS TEXT AS
|
||||
$$
|
||||
SELECT
|
||||
CASE
|
||||
WHEN state_code = 0 THEN 'PARSING'
|
||||
WHEN state_code = 1 THEN 'PLANNING'
|
||||
WHEN state_code = 2 THEN 'ACTIVE'
|
||||
WHEN state_code = 3 THEN 'FINISHED'
|
||||
WHEN state_code = 4 THEN 'FINISHED WITH ERROR'
|
||||
END
|
||||
$$
|
||||
LANGUAGE SQL PARALLEL SAFE;
|
||||
|
||||
CREATE or REPLACE FUNCTION get_cmd_type (cmd_type INTEGER) RETURNS TEXT AS
|
||||
$$
|
||||
SELECT
|
||||
CASE
|
||||
WHEN cmd_type = 0 THEN ''
|
||||
WHEN cmd_type = 1 THEN 'SELECT'
|
||||
WHEN cmd_type = 2 THEN 'UPDATE'
|
||||
WHEN cmd_type = 3 THEN 'INSERT'
|
||||
WHEN cmd_type = 4 THEN 'DELETE'
|
||||
WHEN cmd_type = 5 THEN 'UTILITY'
|
||||
WHEN cmd_type = 6 THEN 'NOTHING'
|
||||
END
|
||||
$$
|
||||
LANGUAGE SQL PARALLEL SAFE;
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_settings(
|
||||
OUT name text,
|
||||
OUT value text,
|
||||
OUT default_value text,
|
||||
OUT description text,
|
||||
OUT minimum INTEGER,
|
||||
OUT maximum INTEGER,
|
||||
OUT options text,
|
||||
OUT restart text
|
||||
)
|
||||
RETURNS SETOF record
|
||||
AS 'MODULE_PATHNAME', 'pg_stat_monitor_settings'
|
||||
LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
|
||||
CREATE VIEW pg_stat_monitor_settings AS SELECT
|
||||
name,
|
||||
value,
|
||||
default_value,
|
||||
description,
|
||||
minimum,
|
||||
maximum,
|
||||
options,
|
||||
restart
|
||||
FROM pg_stat_monitor_settings();
|
||||
|
||||
-- Register a view on the function for ease of use.
|
||||
CREATE VIEW pg_stat_monitor AS SELECT
|
||||
bucket,
|
||||
bucket_start_time AS bucket_start_time,
|
||||
userid::regrole,
|
||||
datname,
|
||||
'0.0.0.0'::inet + client_ip AS client_ip,
|
||||
queryid,
|
||||
top_queryid,
|
||||
query,
|
||||
comments,
|
||||
planid,
|
||||
query_plan,
|
||||
top_query,
|
||||
application_name,
|
||||
string_to_array(relations, ',') AS relations,
|
||||
cmd_type,
|
||||
get_cmd_type(cmd_type) AS cmd_type_text,
|
||||
elevel,
|
||||
sqlcode,
|
||||
message,
|
||||
calls,
|
||||
total_time,
|
||||
min_time,
|
||||
max_time,
|
||||
mean_time,
|
||||
stddev_time,
|
||||
rows_retrieved,
|
||||
shared_blks_hit,
|
||||
shared_blks_read,
|
||||
shared_blks_dirtied,
|
||||
shared_blks_written,
|
||||
local_blks_hit,
|
||||
local_blks_read,
|
||||
local_blks_dirtied,
|
||||
local_blks_written,
|
||||
temp_blks_read,
|
||||
temp_blks_written,
|
||||
blk_read_time,
|
||||
blk_write_time,
|
||||
(string_to_array(resp_calls, ',')) resp_calls,
|
||||
cpu_user_time,
|
||||
cpu_sys_time,
|
||||
wal_records,
|
||||
wal_fpi,
|
||||
wal_bytes,
|
||||
state_code,
|
||||
get_state(state_code) as state
|
||||
FROM pg_stat_monitor_internal(TRUE) p, pg_database d WHERE dbid = oid
|
||||
ORDER BY bucket_start_time;
|
||||
|
||||
CREATE FUNCTION decode_error_level(elevel int)
|
||||
RETURNS text
|
||||
AS
|
||||
$$
|
||||
SELECT
|
||||
CASE
|
||||
WHEN elevel = 0 THEN ''
|
||||
WHEN elevel = 10 THEN 'DEBUG5'
|
||||
WHEN elevel = 11 THEN 'DEBUG4'
|
||||
WHEN elevel = 12 THEN 'DEBUG3'
|
||||
WHEN elevel = 13 THEN 'DEBUG2'
|
||||
WHEN elevel = 14 THEN 'DEBUG1'
|
||||
WHEN elevel = 15 THEN 'LOG'
|
||||
WHEN elevel = 16 THEN 'LOG_SERVER_ONLY'
|
||||
WHEN elevel = 17 THEN 'INFO'
|
||||
WHEN elevel = 18 THEN 'NOTICE'
|
||||
WHEN elevel = 19 THEN 'WARNING'
|
||||
WHEN elevel = 20 THEN 'ERROR'
|
||||
END
|
||||
$$
|
||||
LANGUAGE SQL PARALLEL SAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION histogram(_bucket int, _quryid text)
|
||||
RETURNS SETOF RECORD AS $$
|
||||
DECLARE
|
||||
rec record;
|
||||
BEGIN
|
||||
for rec in
|
||||
with stat as (select queryid, bucket, unnest(range()) as range, unnest(resp_calls)::int freq from pg_stat_monitor) select range, freq, repeat('■', (freq::float / max(freq) over() * 30)::int) as bar from stat where queryid = _quryid and bucket = _bucket
|
||||
loop
|
||||
return next rec;
|
||||
end loop;
|
||||
END
|
||||
$$ language plpgsql;
|
||||
|
||||
-- CREATE FUNCTION pg_stat_monitor_hook_stats(
|
||||
-- OUT hook text,
|
||||
-- OUT min_time float8,
|
||||
-- OUT max_time float8,
|
||||
-- OUT total_time float8,
|
||||
-- OUT ncalls int8
|
||||
--)
|
||||
--RETURNS SETOF record
|
||||
--AS 'MODULE_PATHNAME', 'pg_stat_monitor_hook_stats'
|
||||
--LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
|
||||
--CREATE VIEW pg_stat_monitor_hook_stats AS SELECT
|
||||
-- hook,
|
||||
-- min_time,
|
||||
-- max_time,
|
||||
-- total_time,
|
||||
-- total_time / greatest(ncalls, 1) as avg_time,
|
||||
-- ncalls,
|
||||
-- ROUND(CAST(total_time / greatest(sum(total_time) OVER(), 0.00000001) * 100 as numeric), 2)::text || '%' as load_comparison
|
||||
-- FROM pg_stat_monitor_hook_stats();
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_errors(
|
||||
OUT severity int,
|
||||
OUT message text,
|
||||
OUT msgtime text,
|
||||
OUT calls int8
|
||||
)
|
||||
RETURNS SETOF record
|
||||
AS 'MODULE_PATHNAME', 'pg_stat_monitor_errors'
|
||||
LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION pgsm_log_severity_as_text(severity int) RETURNS TEXT AS
|
||||
$$
|
||||
SELECT
|
||||
CASE
|
||||
WHEN severity = 0 THEN 'INFO'
|
||||
WHEN severity = 1 THEN 'WARNING'
|
||||
WHEN severity = 2 THEN 'ERROR'
|
||||
END
|
||||
$$
|
||||
LANGUAGE SQL PARALLEL SAFE;
|
||||
|
||||
CREATE VIEW pg_stat_monitor_errors AS SELECT
|
||||
pgsm_log_severity_as_text(severity) as severity, message, msgtime, calls
|
||||
FROM pg_stat_monitor_errors();
|
||||
|
||||
CREATE FUNCTION pg_stat_monitor_reset_errors()
|
||||
RETURNS void
|
||||
AS 'MODULE_PATHNAME'
|
||||
LANGUAGE C PARALLEL SAFE;
|
||||
|
||||
GRANT SELECT ON pg_stat_monitor TO PUBLIC;
|
||||
GRANT SELECT ON pg_stat_monitor_settings TO PUBLIC;
|
||||
|
||||
GRANT SELECT ON pg_stat_monitor_errors TO PUBLIC;
|
||||
-- Don't want this to be available to non-superusers.
|
||||
REVOKE ALL ON FUNCTION pg_stat_monitor_reset() FROM PUBLIC;
|
||||
REVOKE ALL ON FUNCTION pg_stat_monitor_reset_errors() FROM PUBLIC;
|
1175
pg_stat_monitor.c
1175
pg_stat_monitor.c
File diff suppressed because it is too large
Load Diff
|
@ -52,6 +52,7 @@
|
|||
#include "utils/timestamp.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/guc_tables.h"
|
||||
|
||||
#define MAX_BACKEND_PROCESES (MaxBackends + NUM_AUXILIARY_PROCS + max_prepared_xacts)
|
||||
#define IntArrayGetTextDatum(x,y) intarray_get_datum(x,y)
|
||||
|
@ -87,21 +88,23 @@
|
|||
#define MAX_QUERY_BUF (PGSM_QUERY_SHARED_BUFFER * 1024 * 1024)
|
||||
#define MAX_BUCKETS_MEM (PGSM_MAX * 1024 * 1024)
|
||||
#define BUCKETS_MEM_OVERFLOW() ((hash_get_num_entries(pgss_hash) * sizeof(pgssEntry)) >= MAX_BUCKETS_MEM)
|
||||
#define MAX_QUERY_BUFFER_BUCKET MAX_QUERY_BUF / PGSM_MAX_BUCKETS
|
||||
#define MAX_BUCKET_ENTRIES (MAX_BUCKETS_MEM / sizeof(pgssEntry))
|
||||
#define QUERY_BUFFER_OVERFLOW(x,y) ((x + y + sizeof(uint64) + sizeof(uint64)) > MAX_QUERY_BUFFER_BUCKET)
|
||||
#define QUERY_BUFFER_OVERFLOW(x,y) ((x + y + sizeof(uint64) + sizeof(uint64)) > MAX_QUERY_BUF)
|
||||
#define QUERY_MARGIN 100
|
||||
#define MIN_QUERY_LEN 10
|
||||
#define SQLCODE_LEN 20
|
||||
|
||||
#if PG_VERSION_NUM >= 130000
|
||||
#define MAX_SETTINGS 14
|
||||
#define MAX_SETTINGS 15
|
||||
#else
|
||||
#define MAX_SETTINGS 13
|
||||
#define MAX_SETTINGS 14
|
||||
#endif
|
||||
|
||||
/* Update this if need a enum GUC with more options. */
|
||||
#define MAX_ENUM_OPTIONS 6
|
||||
typedef struct GucVariables
|
||||
{
|
||||
enum config_type type; /* PGC_BOOL, PGC_INT, PGC_REAL, PGC_STRING, PGC_ENUM */
|
||||
int guc_variable;
|
||||
char guc_name[TEXT_LEN];
|
||||
char guc_desc[TEXT_LEN];
|
||||
|
@ -111,6 +114,8 @@ typedef struct GucVariables
|
|||
int guc_unit;
|
||||
int *guc_value;
|
||||
bool guc_restart;
|
||||
int n_options;
|
||||
char guc_options[MAX_ENUM_OPTIONS][32];
|
||||
} GucVariable;
|
||||
|
||||
#if PG_VERSION_NUM < 130000
|
||||
|
@ -161,7 +166,7 @@ typedef enum AGG_KEY
|
|||
|
||||
#define MAX_QUERY_LEN 1024
|
||||
|
||||
/* shared nenory storage for the query */
|
||||
/* shared memory storage for the query */
|
||||
typedef struct CallTime
|
||||
{
|
||||
double total_time; /* total execution time, in msec */
|
||||
|
@ -171,27 +176,26 @@ typedef struct CallTime
|
|||
double sum_var_time; /* sum of variances in execution time in msec */
|
||||
} CallTime;
|
||||
|
||||
typedef struct pgssQueryHashKey
|
||||
{
|
||||
uint64 bucket_id; /* bucket number */
|
||||
uint64 queryid; /* query identifier */
|
||||
uint64 userid; /* user OID */
|
||||
uint64 dbid; /* database OID */
|
||||
uint64 ip; /* client ip address */
|
||||
uint64 appid; /* hash of application name */
|
||||
} pgssQueryHashKey;
|
||||
|
||||
/*
|
||||
* Entry type for queries hash table (query ID).
|
||||
*
|
||||
* We use a hash table to keep track of query IDs that have their
|
||||
* corresponding query text added to the query buffer (pgsm_query_shared_buffer).
|
||||
*
|
||||
* This allow us to avoid adding duplicated queries to the buffer, therefore
|
||||
* leaving more space for other queries and saving some CPU.
|
||||
*/
|
||||
typedef struct pgssQueryEntry
|
||||
{
|
||||
pgssQueryHashKey key; /* hash key of entry - MUST BE FIRST */
|
||||
uint64 pos; /* bucket number */
|
||||
uint64 state;
|
||||
uint64 queryid; /* query identifier, also the key. */
|
||||
size_t query_pos; /* query location within query buffer */
|
||||
} pgssQueryEntry;
|
||||
|
||||
typedef struct PlanInfo
|
||||
{
|
||||
uint64 planid; /* plan identifier */
|
||||
char plan_text[PLAN_TEXT_LEN]; /* plan text */
|
||||
size_t plan_len; /* strlen(plan_text) */
|
||||
} PlanInfo;
|
||||
|
||||
typedef struct pgssHashKey
|
||||
|
@ -203,14 +207,11 @@ typedef struct pgssHashKey
|
|||
uint64 ip; /* client ip address */
|
||||
uint64 planid; /* plan identifier */
|
||||
uint64 appid; /* hash of application name */
|
||||
uint64 toplevel; /* query executed at top level */
|
||||
} pgssHashKey;
|
||||
|
||||
typedef struct QueryInfo
|
||||
{
|
||||
uint64 queryid; /* query identifier */
|
||||
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];
|
||||
|
@ -310,8 +311,22 @@ typedef struct pgssSharedState
|
|||
pg_atomic_uint64 current_wbucket;
|
||||
pg_atomic_uint64 prev_bucket_usec;
|
||||
uint64 bucket_entry[MAX_BUCKETS];
|
||||
int64 query_buf_size_bucket;
|
||||
char bucket_start_time[MAX_BUCKETS][60]; /* start time of the bucket */
|
||||
LWLock *errors_lock; /* protects errors hashtable search/modification */
|
||||
/*
|
||||
* These variables are used when pgsm_overflow_target is ON.
|
||||
*
|
||||
* overflow is set to true when the query buffer overflows.
|
||||
*
|
||||
* n_bucket_cycles counts the number of times we changed bucket
|
||||
* since the query buffer overflowed. When it reaches pgsm_max_buckets
|
||||
* we remove the dump file, also reset the counter.
|
||||
*
|
||||
* This allows us to avoid having a large file on disk that would also
|
||||
* slowdown queries to the pg_stat_monitor view.
|
||||
*/
|
||||
bool overflow;
|
||||
size_t n_bucket_cycles;
|
||||
} pgssSharedState;
|
||||
|
||||
#define ResetSharedState(x) \
|
||||
|
@ -373,6 +388,7 @@ bool SaveQueryText(uint64 bucketid,
|
|||
void init_guc(void);
|
||||
GucVariable *get_conf(int i);
|
||||
|
||||
bool IsSystemInitialized(void);
|
||||
/* hash_create.c */
|
||||
bool IsHashInitialize(void);
|
||||
void pgss_shmem_startup(void);
|
||||
|
@ -381,39 +397,55 @@ int pgsm_get_bucket_size(void);
|
|||
pgssSharedState* pgsm_get_ss(void);
|
||||
HTAB *pgsm_get_plan_hash(void);
|
||||
HTAB *pgsm_get_hash(void);
|
||||
HTAB *pgsm_get_query_hash(void);
|
||||
HTAB *pgsm_get_plan_hash(void);
|
||||
void hash_entry_reset(void);
|
||||
void hash_query_entryies_reset(void);
|
||||
void hash_query_entries();
|
||||
void hash_query_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer[]);
|
||||
void hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer[]);
|
||||
void hash_entry_dealloc(int new_bucket_id, int old_bucket_id, unsigned char *query_buffer);
|
||||
pgssEntry* hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding);
|
||||
Size hash_memsize(void);
|
||||
|
||||
int read_query_buffer(int bucket_id, uint64 queryid, char *query_txt);
|
||||
int read_query_buffer(int bucket_id, uint64 queryid, char *query_txt, size_t pos);
|
||||
uint64 read_query(unsigned char *buf, uint64 queryid, char * query, size_t pos);
|
||||
pgssQueryEntry* hash_find_query_entry(uint64 bucket_id, uint64 queryid, uint64 dbid, uint64 userid, uint64 ip, uint64 appid);
|
||||
pgssQueryEntry* hash_create_query_entry(uint64 bucket_id, uint64 queryid, uint64 dbid, uint64 userid, uint64 ip, uint64 appid);
|
||||
void pgss_startup(void);
|
||||
void set_qbuf(int i, unsigned char *);
|
||||
void set_qbuf(unsigned char *);
|
||||
|
||||
/* hash_query.c */
|
||||
void pgss_startup(void);
|
||||
|
||||
/*---- GUC variables ----*/
|
||||
typedef enum {
|
||||
PSGM_TRACK_NONE, /* track no statements */
|
||||
PGSM_TRACK_TOP, /* only top level statements */
|
||||
PGSM_TRACK_ALL /* all statements, including nested ones */
|
||||
} PGSMTrackLevel;
|
||||
|
||||
static const struct config_enum_entry track_options[] =
|
||||
{
|
||||
{"none", PSGM_TRACK_NONE, false},
|
||||
{"top", PGSM_TRACK_TOP, false},
|
||||
{"all", PGSM_TRACK_ALL, false},
|
||||
{NULL, 0, false}
|
||||
};
|
||||
|
||||
#define PGSM_MAX get_conf(0)->guc_variable
|
||||
#define PGSM_QUERY_MAX_LEN get_conf(1)->guc_variable
|
||||
#define PGSM_ENABLED get_conf(2)->guc_variable
|
||||
#define PGSM_TRACK_UTILITY get_conf(3)->guc_variable
|
||||
#define PGSM_NORMALIZED_QUERY get_conf(4)->guc_variable
|
||||
#define PGSM_MAX_BUCKETS get_conf(5)->guc_variable
|
||||
#define PGSM_BUCKET_TIME get_conf(6)->guc_variable
|
||||
#define PGSM_HISTOGRAM_MIN get_conf(7)->guc_variable
|
||||
#define PGSM_HISTOGRAM_MAX get_conf(8)->guc_variable
|
||||
#define PGSM_HISTOGRAM_BUCKETS get_conf(9)->guc_variable
|
||||
#define PGSM_QUERY_SHARED_BUFFER get_conf(10)->guc_variable
|
||||
#define PGSM_OVERFLOW_TARGET get_conf(12)->guc_variable
|
||||
#define PGSM_QUERY_PLAN get_conf(12)->guc_variable
|
||||
#define PGSM_TRACK_PLANNING get_conf(13)->guc_variable
|
||||
#define PGSM_TRACK_UTILITY get_conf(2)->guc_variable
|
||||
#define PGSM_NORMALIZED_QUERY get_conf(3)->guc_variable
|
||||
#define PGSM_MAX_BUCKETS get_conf(4)->guc_variable
|
||||
#define PGSM_BUCKET_TIME get_conf(5)->guc_variable
|
||||
#define PGSM_HISTOGRAM_MIN get_conf(6)->guc_variable
|
||||
#define PGSM_HISTOGRAM_MAX get_conf(7)->guc_variable
|
||||
#define PGSM_HISTOGRAM_BUCKETS get_conf(8)->guc_variable
|
||||
#define PGSM_QUERY_SHARED_BUFFER get_conf(9)->guc_variable
|
||||
#define PGSM_OVERFLOW_TARGET get_conf(10)->guc_variable
|
||||
#define PGSM_QUERY_PLAN get_conf(11)->guc_variable
|
||||
#define PGSM_TRACK get_conf(12)->guc_variable
|
||||
#define PGSM_EXTRACT_COMMENTS get_conf(13)->guc_variable
|
||||
#define PGSM_TRACK_PLANNING get_conf(14)->guc_variable
|
||||
|
||||
|
||||
/*---- Benchmarking ----*/
|
||||
#ifdef BENCHMARK
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgsm_errors.c
|
||||
* Track pg_stat_monitor internal error messages.
|
||||
*
|
||||
* Copyright © 2021, Percona LLC and/or its affiliates
|
||||
*
|
||||
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
|
||||
*
|
||||
* Portions Copyright (c) 1994, The Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* contrib/pg_stat_monitor/pgsm_errors.c
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <postgres.h>
|
||||
#include <access/hash.h>
|
||||
#include <storage/shmem.h>
|
||||
#include <utils/hsearch.h>
|
||||
|
||||
#include "pg_stat_monitor.h"
|
||||
#include "pgsm_errors.h"
|
||||
|
||||
|
||||
PG_FUNCTION_INFO_V1(pg_stat_monitor_errors);
|
||||
PG_FUNCTION_INFO_V1(pg_stat_monitor_reset_errors);
|
||||
|
||||
|
||||
/*
|
||||
* Maximum number of error messages tracked.
|
||||
* This should be set to a sensible value in order to track
|
||||
* the different type of errors that pg_stat_monitor may
|
||||
* report, e.g. out of memory.
|
||||
*/
|
||||
#define PSGM_ERRORS_MAX 128
|
||||
|
||||
static HTAB *pgsm_errors_ht = NULL;
|
||||
|
||||
void psgm_errors_init(void)
|
||||
{
|
||||
HASHCTL info;
|
||||
#if PG_VERSION_NUM >= 140000
|
||||
int flags = HASH_ELEM | HASH_STRINGS;
|
||||
#else
|
||||
int flags = HASH_ELEM | HASH_BLOBS;
|
||||
#endif
|
||||
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.keysize = ERROR_MSG_MAX_LEN;
|
||||
info.entrysize = sizeof(ErrorEntry);
|
||||
pgsm_errors_ht = ShmemInitHash("pg_stat_monitor: errors hashtable",
|
||||
PSGM_ERRORS_MAX, /* initial size */
|
||||
PSGM_ERRORS_MAX, /* maximum size */
|
||||
&info,
|
||||
flags);
|
||||
}
|
||||
|
||||
size_t pgsm_errors_size(void)
|
||||
{
|
||||
return hash_estimate_size(PSGM_ERRORS_MAX, sizeof(ErrorEntry));
|
||||
}
|
||||
|
||||
void pgsm_log(PgsmLogSeverity severity, const char *format, ...)
|
||||
{
|
||||
char key[ERROR_MSG_MAX_LEN];
|
||||
ErrorEntry *entry;
|
||||
bool found = false;
|
||||
va_list ap;
|
||||
int n;
|
||||
struct timeval tv;
|
||||
struct tm *lt;
|
||||
pgssSharedState *pgss;
|
||||
|
||||
va_start(ap, format);
|
||||
n = vsnprintf(key, ERROR_MSG_MAX_LEN, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (n < 0)
|
||||
return;
|
||||
|
||||
pgss = pgsm_get_ss();
|
||||
LWLockAcquire(pgss->errors_lock, LW_EXCLUSIVE);
|
||||
|
||||
entry = (ErrorEntry *) hash_search(pgsm_errors_ht, key, HASH_ENTER_NULL, &found);
|
||||
if (!entry)
|
||||
{
|
||||
LWLockRelease(pgss->errors_lock);
|
||||
/*
|
||||
* We're out of memory, can't track this error message.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
entry->severity = severity;
|
||||
entry->calls = 0;
|
||||
}
|
||||
|
||||
/* Update message timestamp. */
|
||||
gettimeofday(&tv, NULL);
|
||||
lt = localtime(&tv.tv_sec);
|
||||
snprintf(entry->time, sizeof(entry->time),
|
||||
"%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);
|
||||
|
||||
entry->calls++;
|
||||
|
||||
LWLockRelease(pgss->errors_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all entries from the hash table.
|
||||
*/
|
||||
Datum
|
||||
pg_stat_monitor_reset_errors(PG_FUNCTION_ARGS)
|
||||
{
|
||||
HASH_SEQ_STATUS hash_seq;
|
||||
ErrorEntry *entry;
|
||||
pgssSharedState *pgss = pgsm_get_ss();
|
||||
|
||||
/* Safety check... */
|
||||
if (!IsSystemInitialized())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("pg_stat_monitor: must be loaded via shared_preload_libraries")));
|
||||
|
||||
LWLockAcquire(pgss->errors_lock, LW_EXCLUSIVE);
|
||||
|
||||
hash_seq_init(&hash_seq, pgsm_errors_ht);
|
||||
while ((entry = hash_seq_search(&hash_seq)) != NULL)
|
||||
entry = hash_search(pgsm_errors_ht, &entry->message, HASH_REMOVE, NULL);
|
||||
|
||||
LWLockRelease(pgss->errors_lock);
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked when users query the view pg_stat_monitor_errors.
|
||||
* This function creates tuples with error messages from data present in
|
||||
* the hash table, then return the dataset to the caller.
|
||||
*/
|
||||
Datum
|
||||
pg_stat_monitor_errors(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
TupleDesc tupdesc;
|
||||
Tuplestorestate *tupstore;
|
||||
MemoryContext per_query_ctx;
|
||||
MemoryContext oldcontext;
|
||||
HASH_SEQ_STATUS hash_seq;
|
||||
ErrorEntry *error_entry;
|
||||
pgssSharedState *pgss = pgsm_get_ss();
|
||||
|
||||
/* Safety check... */
|
||||
if (!IsSystemInitialized())
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
||||
errmsg("pg_stat_monitor: must be loaded via shared_preload_libraries")));
|
||||
|
||||
/* check to see if caller supports us returning a tuplestore */
|
||||
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("pg_stat_monitor: set-valued function called in context that cannot accept a set")));
|
||||
|
||||
/* Switch into long-lived context to construct returned data structures */
|
||||
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
|
||||
oldcontext = MemoryContextSwitchTo(per_query_ctx);
|
||||
|
||||
/* Build a tuple descriptor for our result type */
|
||||
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 != 4)
|
||||
elog(ERROR, "pg_stat_monitor: incorrect number of output arguments, required 3, found %d", tupdesc->natts);
|
||||
|
||||
tupstore = tuplestore_begin_heap(true, false, work_mem);
|
||||
rsinfo->returnMode = SFRM_Materialize;
|
||||
rsinfo->setResult = tupstore;
|
||||
rsinfo->setDesc = tupdesc;
|
||||
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
||||
LWLockAcquire(pgss->errors_lock, LW_SHARED);
|
||||
|
||||
hash_seq_init(&hash_seq, pgsm_errors_ht);
|
||||
while ((error_entry = hash_seq_search(&hash_seq)) != NULL)
|
||||
{
|
||||
Datum values[4];
|
||||
bool nulls[4];
|
||||
int i = 0;
|
||||
memset(values, 0, sizeof(values));
|
||||
memset(nulls, 0, sizeof(nulls));
|
||||
|
||||
values[i++] = Int64GetDatumFast(error_entry->severity);
|
||||
values[i++] = CStringGetTextDatum(error_entry->message);
|
||||
values[i++] = CStringGetTextDatum(error_entry->time);
|
||||
values[i++] = Int64GetDatumFast(error_entry->calls);
|
||||
|
||||
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
|
||||
}
|
||||
|
||||
LWLockRelease(pgss->errors_lock);
|
||||
/* clean up and return the tuplestore */
|
||||
tuplestore_donestoring(tupstore);
|
||||
|
||||
return (Datum)0;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pgsm_errors.h
|
||||
* Track pg_stat_monitor internal error messages.
|
||||
*
|
||||
* Copyright © 2021, Percona LLC and/or its affiliates
|
||||
*
|
||||
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
|
||||
*
|
||||
* Portions Copyright (c) 1994, The Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* contrib/pg_stat_monitor/pgsm_errors.h
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef PGSM_ERRORS_H
|
||||
#define PGSM_ERRORS_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <postgres.h>
|
||||
|
||||
|
||||
/* Maximum allowed error message length. */
|
||||
#define ERROR_MSG_MAX_LEN 128
|
||||
|
||||
/* Log message severity. */
|
||||
typedef enum {
|
||||
PSGM_LOG_INFO,
|
||||
PGSM_LOG_WARNING,
|
||||
PGSM_LOG_ERROR
|
||||
} PgsmLogSeverity;
|
||||
|
||||
typedef struct {
|
||||
char message[ERROR_MSG_MAX_LEN]; /* message is also the hash key (MUST BE FIRST). */
|
||||
PgsmLogSeverity severity;
|
||||
char time[60]; /* last timestamp in which this error was reported. */
|
||||
int64 calls; /* how many times this error was reported. */
|
||||
} ErrorEntry;
|
||||
|
||||
/*
|
||||
* Must be called during module startup, creates the hash table
|
||||
* used to store pg_stat_monitor error messages.
|
||||
*/
|
||||
void psgm_errors_init(void);
|
||||
|
||||
/*
|
||||
* Returns an estimate of the hash table size.
|
||||
* Used to reserve space on Postmaster's shared memory.
|
||||
*/
|
||||
size_t pgsm_errors_size(void);
|
||||
|
||||
/*
|
||||
* Add a message to the hash table.
|
||||
* Increment no. of calls if message already exists.
|
||||
*/
|
||||
void pgsm_log(PgsmLogSeverity severity, const char *format, ...);
|
||||
|
||||
#define pgsm_log_info(msg, ...) pgsm_log(PGSM_LOG_INFO, msg, ##__VA_ARGS__)
|
||||
#define pgsm_log_warning(msg, ...) pgsm_log(PGSM_LOG_WARNING, msg, ##__VA_ARGS__)
|
||||
#define pgsm_log_error(msg, ...) pgsm_log(PGSM_LOG_ERROR, msg, ##__VA_ARGS__)
|
||||
|
||||
#endif /* PGSM_ERRORS_H */
|
|
@ -12,11 +12,11 @@ SELECT 1 AS num;
|
|||
(1 row)
|
||||
|
||||
SELECT query,application_name FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | application_name
|
||||
--------------------------------------------------------------------------------+-----------------------------
|
||||
SELECT $1 AS num | pg_regress/application_name
|
||||
SELECT pg_stat_monitor_reset(); | pg_regress/application_name
|
||||
SELECT query,application_name FROM pg_stat_monitor ORDER BY query COLLATE "C"; | pg_regress/application_name
|
||||
query | application_name
|
||||
-------------------------------------------------------------------------------+-----------------------------
|
||||
SELECT $1 AS num | pg_regress/application_name
|
||||
SELECT pg_stat_monitor_reset() | pg_regress/application_name
|
||||
SELECT query,application_name FROM pg_stat_monitor ORDER BY query COLLATE "C" | pg_regress/application_name
|
||||
(3 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
|
|
@ -12,11 +12,11 @@ SELECT 1 AS num;
|
|||
(1 row)
|
||||
|
||||
SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query
|
||||
---------------------------------------------------------------
|
||||
query
|
||||
--------------------------------------------------------------
|
||||
SELECT $1 AS num
|
||||
SELECT pg_stat_monitor_reset();
|
||||
SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
SELECT pg_stat_monitor_reset()
|
||||
SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C"
|
||||
(3 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
|
|
@ -23,21 +23,23 @@ SELECT b FROM t2 FOR UPDATE;
|
|||
|
||||
TRUNCATE t1;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
SELECT query, cmd_type, cmd_type_text FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | cmd_type | cmd_type_text
|
||||
-----------------------------------------------------------------------------------------+----------+---------------
|
||||
CREATE TABLE t1 (a INTEGER); | 0 |
|
||||
CREATE TABLE t2 (b INTEGER); | 0 |
|
||||
DELETE FROM t1; | 4 | DELETE
|
||||
DROP TABLE t1; | 0 |
|
||||
INSERT INTO t1 VALUES($1) | 3 | INSERT
|
||||
SELECT a FROM t1; | 1 | SELECT
|
||||
SELECT b FROM t2 FOR UPDATE; | 1 | SELECT
|
||||
SELECT pg_stat_monitor_reset(); | 1 | SELECT
|
||||
SELECT query, cmd_type, cmd_type_text FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 1 | SELECT
|
||||
TRUNCATE t1; | 0 |
|
||||
UPDATE t1 SET a = $1 | 2 | UPDATE
|
||||
(11 rows)
|
||||
query | cmd_type | cmd_type_text
|
||||
----------------------------------------------------------------------------------------+----------+---------------
|
||||
CREATE TABLE t1 (a INTEGER) | 0 |
|
||||
CREATE TABLE t2 (b INTEGER) | 0 |
|
||||
DELETE FROM t1 | 4 | DELETE
|
||||
DROP TABLE t1 | 0 |
|
||||
DROP TABLE t2 | 0 |
|
||||
INSERT INTO t1 VALUES($1) | 3 | INSERT
|
||||
SELECT a FROM t1 | 1 | SELECT
|
||||
SELECT b FROM t2 FOR UPDATE | 1 | SELECT
|
||||
SELECT pg_stat_monitor_reset() | 1 | SELECT
|
||||
SELECT query, cmd_type, cmd_type_text FROM pg_stat_monitor ORDER BY query COLLATE "C" | 1 | SELECT
|
||||
TRUNCATE t1 | 0 |
|
||||
UPDATE t1 SET a = $1 | 2 | UPDATE
|
||||
(12 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
|
|
|
@ -36,11 +36,11 @@ SELECT a,b,c,d FROM t1, t2, t3, t4 WHERE t1.a = t2.b AND t3.c = t4.d ORDER BY a;
|
|||
(0 rows)
|
||||
|
||||
SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | calls
|
||||
----------------------------------------------------------------------------------+-------
|
||||
SELECT a,b,c,d FROM t1, t2, t3, t4 WHERE t1.a = t2.b AND t3.c = t4.d ORDER BY a; | 4
|
||||
SELECT pg_stat_monitor_reset(); | 1
|
||||
SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 1
|
||||
query | calls
|
||||
---------------------------------------------------------------------------------+-------
|
||||
SELECT a,b,c,d FROM t1, t2, t3, t4 WHERE t1.a = t2.b AND t3.c = t4.d ORDER BY a | 4
|
||||
SELECT pg_stat_monitor_reset() | 1
|
||||
SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C" | 1
|
||||
(3 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
@ -69,8 +69,8 @@ SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
|||
query | calls
|
||||
---------------------------------------------------------------------------------------------------+-------
|
||||
SELECT a,b,c,d FROM t1, t2, t3, t4 WHERE t1.a = t2.b AND t3.c = t4.d ORDER BY a | 1000
|
||||
SELECT pg_stat_monitor_reset(); | 1
|
||||
SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 1
|
||||
SELECT pg_stat_monitor_reset() | 1
|
||||
SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C" | 1
|
||||
do $$ +| 1
|
||||
declare +|
|
||||
n integer:= 1; +|
|
||||
|
@ -80,7 +80,7 @@ SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
|||
exit when n = 1000; +|
|
||||
n := n + 1; +|
|
||||
end loop; +|
|
||||
end $$; |
|
||||
end $$ |
|
||||
(4 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
|
|
@ -29,11 +29,11 @@ SELECT * FROM t3,t4 WHERE t3.c = t4.d;
|
|||
\c contrib_regression
|
||||
SELECT datname, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
datname | query
|
||||
--------------------+------------------------------------------------------------------------
|
||||
db1 | SELECT * FROM t1,t2 WHERE t1.a = t2.b;
|
||||
db2 | SELECT * FROM t3,t4 WHERE t3.c = t4.d;
|
||||
contrib_regression | SELECT datname, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
contrib_regression | SELECT pg_stat_monitor_reset();
|
||||
--------------------+-----------------------------------------------------------------------
|
||||
db1 | SELECT * FROM t1,t2 WHERE t1.a = t2.b
|
||||
db2 | SELECT * FROM t3,t4 WHERE t3.c = t4.d
|
||||
contrib_regression | SELECT datname, query FROM pg_stat_monitor ORDER BY query COLLATE "C"
|
||||
contrib_regression | SELECT pg_stat_monitor_reset()
|
||||
(4 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
|
|
@ -21,18 +21,22 @@ RAISE WARNING 'warning message';
|
|||
END $$;
|
||||
WARNING: warning message
|
||||
SELECT query, elevel, sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C",elevel;
|
||||
query | elevel | sqlcode | message
|
||||
------------------------------------------------------------------------------------------------+--------+---------+-----------------------------------
|
||||
ELECET * FROM unknown; | 20 | 42601 | syntax error at or near "ELECET"
|
||||
SELECT * FROM unknown; | 20 | 42P01 | relation "unknown" does not exist
|
||||
SELECT 1/0; | 20 | 22012 | division by zero
|
||||
SELECT pg_stat_monitor_reset(); | 0 | |
|
||||
SELECT query, elevel, sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C",elevel; | 0 | |
|
||||
do $$ +| 19 | 01000 | warning message
|
||||
BEGIN +| | |
|
||||
RAISE WARNING 'warning message'; +| | |
|
||||
END $$; | | |
|
||||
(6 rows)
|
||||
query | elevel | sqlcode | message
|
||||
-----------------------------------------------------------------------------------------------+--------+---------+-----------------------------------
|
||||
ELECET * FROM unknown; | 20 | 42601 | syntax error at or near "ELECET"
|
||||
SELECT * FROM unknown; | 20 | 42P01 | relation "unknown" does not exist
|
||||
SELECT 1/0; | 20 | 22012 | division by zero
|
||||
SELECT pg_stat_monitor_reset() | 0 | |
|
||||
SELECT query, elevel, sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C",elevel | 0 | |
|
||||
do $$ +| 0 | |
|
||||
BEGIN +| | |
|
||||
RAISE WARNING 'warning message'; +| | |
|
||||
END $$ | | |
|
||||
do $$ +| 19 | 01000 | warning message
|
||||
BEGIN +| | |
|
||||
RAISE WARNING 'warning message'; +| | |
|
||||
END $$; | | |
|
||||
(7 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
|
|
|
@ -21,18 +21,22 @@ RAISE WARNING 'warning message';
|
|||
END $$;
|
||||
WARNING: warning message
|
||||
SELECT query, elevel, sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C",elevel;
|
||||
query | elevel | sqlcode | message
|
||||
------------------------------------------------------------------------------------------------+--------+---------+-----------------------------------
|
||||
ELECET * FROM unknown; | 21 | 42601 | syntax error at or near "ELECET"
|
||||
SELECT * FROM unknown; | 21 | 42P01 | relation "unknown" does not exist
|
||||
SELECT 1/0; | 21 | 22012 | division by zero
|
||||
SELECT pg_stat_monitor_reset(); | 0 | |
|
||||
SELECT query, elevel, sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C",elevel; | 0 | |
|
||||
do $$ +| 19 | 01000 | warning message
|
||||
BEGIN +| | |
|
||||
RAISE WARNING 'warning message'; +| | |
|
||||
END $$; | | |
|
||||
(6 rows)
|
||||
query | elevel | sqlcode | message
|
||||
-----------------------------------------------------------------------------------------------+--------+---------+-----------------------------------
|
||||
ELECET * FROM unknown; | 21 | 42601 | syntax error at or near "ELECET"
|
||||
SELECT * FROM unknown; | 21 | 42P01 | relation "unknown" does not exist
|
||||
SELECT 1/0; | 21 | 22012 | division by zero
|
||||
SELECT pg_stat_monitor_reset() | 0 | |
|
||||
SELECT query, elevel, sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C",elevel | 0 | |
|
||||
do $$ +| 0 | |
|
||||
BEGIN +| | |
|
||||
RAISE WARNING 'warning message'; +| | |
|
||||
END $$ | | |
|
||||
do $$ +| 19 | 01000 | warning message
|
||||
BEGIN +| | |
|
||||
RAISE WARNING 'warning message'; +| | |
|
||||
END $$; | | |
|
||||
(7 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
|
|
|
@ -12,23 +12,24 @@ select pg_sleep(.5);
|
|||
(1 row)
|
||||
|
||||
SELECT * FROM pg_stat_monitor_settings ORDER BY name COLLATE "C";
|
||||
name | value | default_value | description | minimum | maximum | restart
|
||||
------------------------------------------+--------+---------------+----------------------------------------------------------------------------------------------------------+---------+------------+---------
|
||||
pg_stat_monitor.pgsm_bucket_time | 60 | 60 | Sets the time in seconds per bucket. | 1 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_enable | 1 | 1 | Enable/Disable statistics collector. | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_enable_query_plan | 0 | 0 | Enable/Disable query plan monitoring | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_histogram_buckets | 10 | 10 | Sets the maximum number of histogram buckets | 2 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_histogram_max | 100000 | 100000 | Sets the time in millisecond. | 10 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_histogram_min | 0 | 0 | Sets the time in millisecond. | 0 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_max | 100 | 100 | Sets the maximum size of shared memory in (MB) used for statement's metadata tracked by pg_stat_monitor. | 1 | 1000 | 1
|
||||
pg_stat_monitor.pgsm_max_buckets | 10 | 10 | Sets the maximum number of buckets. | 1 | 10 | 1
|
||||
pg_stat_monitor.pgsm_normalized_query | 1 | 1 | Selects whether save query in normalized format. | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_overflow_target | 0 | 1 | Sets the overflow target for pg_stat_monitor | 0 | 1 | 1
|
||||
pg_stat_monitor.pgsm_query_max_len | 1024 | 1024 | Sets the maximum length of query. | 1024 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_query_shared_buffer | 20 | 20 | Sets the maximum size of shared memory in (MB) used for query tracked by pg_stat_monitor. | 1 | 10000 | 1
|
||||
pg_stat_monitor.pgsm_track_planning | 1 | 1 | Selects whether planning statistics are tracked. | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_track_utility | 1 | 1 | Selects whether utility commands are tracked. | 0 | 0 | 0
|
||||
(14 rows)
|
||||
name | value | default_value | description | minimum | maximum | options | restart
|
||||
------------------------------------------+--------+---------------+----------------------------------------------------------------------------------------------------------+---------+------------+----------------+---------
|
||||
pg_stat_monitor.extract_comments | no | no | Enable/Disable extracting comments from queries. | | | yes, no | no
|
||||
pg_stat_monitor.pgsm_bucket_time | 60 | 60 | Sets the time in seconds per bucket. | 1 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_enable_query_plan | no | no | Enable/Disable query plan monitoring | | | yes, no | no
|
||||
pg_stat_monitor.pgsm_histogram_buckets | 10 | 10 | Sets the maximum number of histogram buckets | 2 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_histogram_max | 100000 | 100000 | Sets the time in millisecond. | 10 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_histogram_min | 0 | 0 | Sets the time in millisecond. | 0 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_max | 100 | 100 | Sets the maximum size of shared memory in (MB) used for statement's metadata tracked by pg_stat_monitor. | 1 | 1000 | | yes
|
||||
pg_stat_monitor.pgsm_max_buckets | 10 | 10 | Sets the maximum number of buckets. | 1 | 10 | | yes
|
||||
pg_stat_monitor.pgsm_normalized_query | yes | yes | Selects whether save query in normalized format. | | | yes, no | no
|
||||
pg_stat_monitor.pgsm_overflow_target | 1 | 1 | Sets the overflow target for pg_stat_monitor | 0 | 1 | | yes
|
||||
pg_stat_monitor.pgsm_query_max_len | 1024 | 1024 | Sets the maximum length of query. | 1024 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_query_shared_buffer | 20 | 20 | Sets the maximum size of shared memory in (MB) used for query tracked by pg_stat_monitor. | 1 | 10000 | | yes
|
||||
pg_stat_monitor.pgsm_track_planning | no | no | Selects whether planning statistics are tracked. | | | yes, no | no
|
||||
pg_stat_monitor.pgsm_track_utility | yes | yes | Selects whether utility commands are tracked. | | | yes, no | no
|
||||
pg_stat_monitor.track | top | top | Selects which statements are tracked by pg_stat_monitor. | | | none, top, all | no
|
||||
(15 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
|
|
|
@ -12,22 +12,23 @@ select pg_sleep(.5);
|
|||
(1 row)
|
||||
|
||||
SELECT * FROM pg_stat_monitor_settings ORDER BY name COLLATE "C";
|
||||
name | value | default_value | description | minimum | maximum | restart
|
||||
------------------------------------------+--------+---------------+----------------------------------------------------------------------------------------------------------+---------+------------+---------
|
||||
pg_stat_monitor.pgsm_bucket_time | 60 | 60 | Sets the time in seconds per bucket. | 1 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_enable | 1 | 1 | Enable/Disable statistics collector. | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_enable_query_plan | 0 | 0 | Enable/Disable query plan monitoring | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_histogram_buckets | 10 | 10 | Sets the maximum number of histogram buckets | 2 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_histogram_max | 100000 | 100000 | Sets the time in millisecond. | 10 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_histogram_min | 0 | 0 | Sets the time in millisecond. | 0 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_max | 100 | 100 | Sets the maximum size of shared memory in (MB) used for statement's metadata tracked by pg_stat_monitor. | 1 | 1000 | 1
|
||||
pg_stat_monitor.pgsm_max_buckets | 10 | 10 | Sets the maximum number of buckets. | 1 | 10 | 1
|
||||
pg_stat_monitor.pgsm_normalized_query | 1 | 1 | Selects whether save query in normalized format. | 0 | 0 | 0
|
||||
pg_stat_monitor.pgsm_overflow_target | 0 | 1 | Sets the overflow target for pg_stat_monitor | 0 | 1 | 1
|
||||
pg_stat_monitor.pgsm_query_max_len | 1024 | 1024 | Sets the maximum length of query. | 1024 | 2147483647 | 1
|
||||
pg_stat_monitor.pgsm_query_shared_buffer | 20 | 20 | Sets the maximum size of shared memory in (MB) used for query tracked by pg_stat_monitor. | 1 | 10000 | 1
|
||||
pg_stat_monitor.pgsm_track_utility | 1 | 1 | Selects whether utility commands are tracked. | 0 | 0 | 0
|
||||
(13 rows)
|
||||
name | value | default_value | description | minimum | maximum | options | restart
|
||||
------------------------------------------+--------+---------------+----------------------------------------------------------------------------------------------------------+---------+------------+----------------+---------
|
||||
pg_stat_monitor.extract_comments | no | no | Enable/Disable extracting comments from queries. | | | yes, no | no
|
||||
pg_stat_monitor.pgsm_bucket_time | 60 | 60 | Sets the time in seconds per bucket. | 1 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_enable_query_plan | no | no | Enable/Disable query plan monitoring | | | yes, no | no
|
||||
pg_stat_monitor.pgsm_histogram_buckets | 10 | 10 | Sets the maximum number of histogram buckets | 2 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_histogram_max | 100000 | 100000 | Sets the time in millisecond. | 10 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_histogram_min | 0 | 0 | Sets the time in millisecond. | 0 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_max | 100 | 100 | Sets the maximum size of shared memory in (MB) used for statement's metadata tracked by pg_stat_monitor. | 1 | 1000 | | yes
|
||||
pg_stat_monitor.pgsm_max_buckets | 10 | 10 | Sets the maximum number of buckets. | 1 | 10 | | yes
|
||||
pg_stat_monitor.pgsm_normalized_query | yes | yes | Selects whether save query in normalized format. | | | yes, no | no
|
||||
pg_stat_monitor.pgsm_overflow_target | 1 | 1 | Sets the overflow target for pg_stat_monitor | 0 | 1 | | yes
|
||||
pg_stat_monitor.pgsm_query_max_len | 1024 | 1024 | Sets the maximum length of query. | 1024 | 2147483647 | | yes
|
||||
pg_stat_monitor.pgsm_query_shared_buffer | 20 | 20 | Sets the maximum size of shared memory in (MB) used for query tracked by pg_stat_monitor. | 1 | 10000 | | yes
|
||||
pg_stat_monitor.pgsm_track_utility | yes | yes | Selects whether utility commands are tracked. | | | yes, no | no
|
||||
pg_stat_monitor.track | top | top | Selects which statements are tracked by pg_stat_monitor. | | | none, top, all | no
|
||||
(14 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
|
|
|
@ -37,14 +37,14 @@ SELECT * FROM foo1, foo2, foo3, foo4;
|
|||
(0 rows)
|
||||
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query collate "C";
|
||||
query | relations
|
||||
--------------------------------------------------------------------------+---------------------------------------------------
|
||||
SELECT * FROM foo1, foo2, foo3, foo4; | {public.foo1,public.foo2,public.foo3,public.foo4}
|
||||
SELECT * FROM foo1, foo2, foo3; | {public.foo1,public.foo2,public.foo3}
|
||||
SELECT * FROM foo1, foo2; | {public.foo1,public.foo2}
|
||||
SELECT * FROM foo1; | {public.foo1}
|
||||
SELECT pg_stat_monitor_reset(); |
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query collate "C"; | {public.pg_stat_monitor*,pg_catalog.pg_database}
|
||||
query | relations
|
||||
-------------------------------------------------------------------------+---------------------------------------------------
|
||||
SELECT * FROM foo1 | {public.foo1}
|
||||
SELECT * FROM foo1, foo2 | {public.foo1,public.foo2}
|
||||
SELECT * FROM foo1, foo2, foo3 | {public.foo1,public.foo2,public.foo3}
|
||||
SELECT * FROM foo1, foo2, foo3, foo4 | {public.foo1,public.foo2,public.foo3,public.foo4}
|
||||
SELECT pg_stat_monitor_reset() |
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query collate "C" | {public.pg_stat_monitor*,pg_catalog.pg_database}
|
||||
(6 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
@ -89,14 +89,14 @@ SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3, sch4.foo4;
|
|||
(0 rows)
|
||||
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query collate "C";
|
||||
query | relations
|
||||
--------------------------------------------------------------------------+--------------------------------------------------
|
||||
SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3, sch4.foo4; | {sch1.foo1,sch2.foo2,sch3.foo3,sch4.foo4}
|
||||
SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3; | {sch1.foo1,sch2.foo2,sch3.foo3}
|
||||
SELECT * FROM sch1.foo1, sch2.foo2; | {sch1.foo1,sch2.foo2}
|
||||
SELECT * FROM sch1.foo1; | {sch1.foo1}
|
||||
SELECT pg_stat_monitor_reset(); |
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query collate "C"; | {public.pg_stat_monitor*,pg_catalog.pg_database}
|
||||
query | relations
|
||||
-------------------------------------------------------------------------+--------------------------------------------------
|
||||
SELECT * FROM sch1.foo1 | {sch1.foo1}
|
||||
SELECT * FROM sch1.foo1, sch2.foo2 | {sch1.foo1,sch2.foo2}
|
||||
SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3 | {sch1.foo1,sch2.foo2,sch3.foo3}
|
||||
SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3, sch4.foo4 | {sch1.foo1,sch2.foo2,sch3.foo3,sch4.foo4}
|
||||
SELECT pg_stat_monitor_reset() |
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query collate "C" | {public.pg_stat_monitor*,pg_catalog.pg_database}
|
||||
(6 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
@ -122,12 +122,12 @@ SELECT * FROM sch1.foo1, sch2.foo2, foo1, foo2;
|
|||
(0 rows)
|
||||
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query;
|
||||
query | relations
|
||||
--------------------------------------------------------------+--------------------------------------------------
|
||||
SELECT * FROM sch1.foo1, foo1; | {sch1.foo1,public.foo1}
|
||||
SELECT * FROM sch1.foo1, sch2.foo2, foo1, foo2; | {sch1.foo1,sch2.foo2,public.foo1,public.foo2}
|
||||
SELECT pg_stat_monitor_reset(); |
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query; | {public.pg_stat_monitor*,pg_catalog.pg_database}
|
||||
query | relations
|
||||
-------------------------------------------------------------+--------------------------------------------------
|
||||
SELECT * FROM sch1.foo1, foo1 | {sch1.foo1,public.foo1}
|
||||
SELECT * FROM sch1.foo1, sch2.foo2, foo1, foo2 | {sch1.foo1,sch2.foo2,public.foo1,public.foo2}
|
||||
SELECT pg_stat_monitor_reset() |
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query | {public.pg_stat_monitor*,pg_catalog.pg_database}
|
||||
(4 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
@ -168,14 +168,14 @@ SELECT * FROM v1,v2,v3,v4;
|
|||
(0 rows)
|
||||
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query collate "C";
|
||||
query | relations
|
||||
--------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------
|
||||
SELECT * FROM v1,v2,v3,v4; | {public.v1*,public.foo1,public.v2*,public.foo2,public.v3*,public.foo3,public.v4*,public.foo4}
|
||||
SELECT * FROM v1,v2,v3; | {public.v1*,public.foo1,public.v2*,public.foo2,public.v3*,public.foo3}
|
||||
SELECT * FROM v1,v2; | {public.v1*,public.foo1,public.v2*,public.foo2}
|
||||
SELECT * FROM v1; | {public.v1*,public.foo1}
|
||||
SELECT pg_stat_monitor_reset(); |
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query collate "C"; | {public.pg_stat_monitor*,pg_catalog.pg_database}
|
||||
query | relations
|
||||
-------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------
|
||||
SELECT * FROM v1 | {public.v1*,public.foo1}
|
||||
SELECT * FROM v1,v2 | {public.v1*,public.foo1,public.v2*,public.foo2}
|
||||
SELECT * FROM v1,v2,v3 | {public.v1*,public.foo1,public.v2*,public.foo2,public.v3*,public.foo3}
|
||||
SELECT * FROM v1,v2,v3,v4 | {public.v1*,public.foo1,public.v2*,public.foo2,public.v3*,public.foo3,public.v4*,public.foo4}
|
||||
SELECT pg_stat_monitor_reset() |
|
||||
SELECT query, relations from pg_stat_monitor ORDER BY query collate "C" | {public.pg_stat_monitor*,pg_catalog.pg_database}
|
||||
(6 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
CREATE EXTENSION pg_stat_monitor;
|
||||
CREATE TABLE t1(a int);
|
||||
CREATE TABLE t2(b int);
|
||||
ERROR: relation "t2" already exists
|
||||
INSERT INTO t1 VALUES(generate_series(1,1000));
|
||||
INSERT INTO t2 VALUES(generate_series(1,5000));
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
@ -8541,14 +8540,14 @@ SELECt * FROM t2 WHERE b % 2 = 0;
|
|||
(2500 rows)
|
||||
|
||||
SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | rows_retrieved
|
||||
-------------------------------------------------------------------------------+----------------
|
||||
SELECT * FROM t1 LIMIT $1 | 10
|
||||
SELECT * FROM t1; | 1000
|
||||
SELECT * FROM t2; | 5000
|
||||
SELECT pg_stat_monitor_reset(); | 1
|
||||
SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 0
|
||||
SELECt * FROM t2 WHERE b % $1 = $2 | 2500
|
||||
query | rows_retrieved
|
||||
------------------------------------------------------------------------------+----------------
|
||||
SELECT * FROM t1 | 1000
|
||||
SELECT * FROM t1 LIMIT $1 | 10
|
||||
SELECT * FROM t2 | 5000
|
||||
SELECT pg_stat_monitor_reset() | 1
|
||||
SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C" | 0
|
||||
SELECt * FROM t2 WHERE b % $1 = $2 | 2500
|
||||
(6 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
@ -8558,4 +8557,5 @@ SELECT pg_stat_monitor_reset();
|
|||
(1 row)
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP EXTENSION pg_stat_monitor;
|
||||
|
|
|
@ -8541,14 +8541,14 @@ SELECt * FROM t2 WHERE b % 2 = 0;
|
|||
(2500 rows)
|
||||
|
||||
SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | rows_retrieved
|
||||
-------------------------------------------------------------------------------+----------------
|
||||
SELECT * FROM t1 LIMIT $1 | 10
|
||||
SELECT * FROM t1; | 1000
|
||||
SELECT b FROM t2 FOR UPDATE; | 5000
|
||||
SELECT pg_stat_monitor_reset(); | 1
|
||||
SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 0
|
||||
SELECt * FROM t2 WHERE b % $1 = $2 | 2500
|
||||
query | rows_retrieved
|
||||
------------------------------------------------------------------------------+----------------
|
||||
SELECT * FROM t1 | 1000
|
||||
SELECT * FROM t1 LIMIT $1 | 10
|
||||
SELECT b FROM t2 FOR UPDATE | 5000
|
||||
SELECT pg_stat_monitor_reset() | 1
|
||||
SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C" | 0
|
||||
SELECt * FROM t2 WHERE b % $1 = $2 | 2500
|
||||
(6 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
|
|
@ -14,12 +14,12 @@ SELECT 1;
|
|||
SELECT 1/0; -- divide by zero
|
||||
ERROR: division by zero
|
||||
SELECT query, state_code, state FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | state_code | state
|
||||
----------------------------------------------------------------------------------+------------+---------------------
|
||||
SELECT $1 | 3 | FINISHED
|
||||
SELECT 1/0; | 4 | FINISHED WITH ERROR
|
||||
SELECT pg_stat_monitor_reset(); | 3 | FINISHED
|
||||
SELECT query, state_code, state FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 2 | ACTIVE
|
||||
query | state_code | state
|
||||
---------------------------------------------------------------------------------+------------+---------------------
|
||||
SELECT $1 | 3 | FINISHED
|
||||
SELECT 1/0; | 4 | FINISHED WITH ERROR
|
||||
SELECT pg_stat_monitor_reset() | 3 | FINISHED
|
||||
SELECT query, state_code, state FROM pg_stat_monitor ORDER BY query COLLATE "C" | 2 | ACTIVE
|
||||
(4 rows)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
|
|
@ -11,14 +11,54 @@ SELECT 1 AS num /* { "application", psql_app, "real_ip", 192.168.1.3) */;
|
|||
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)
|
||||
|
||||
ALTER SYSTEM SET pg_stat_monitor.extract_comments TO 'yes';
|
||||
SELECT pg_reload_conf();
|
||||
pg_reload_conf
|
||||
----------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
select pg_sleep(1);
|
||||
pg_sleep
|
||||
----------
|
||||
|
||||
(1 row)
|
||||
|
||||
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) */ | /* { "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"; |
|
||||
SELECT pg_stat_monitor_reset() |
|
||||
SELECT query, comments FROM pg_stat_monitor ORDER BY query COLLATE "C" |
|
||||
(3 rows)
|
||||
|
||||
ALTER SYSTEM SET pg_stat_monitor.extract_comments TO 'no';
|
||||
SELECT pg_reload_conf();
|
||||
pg_reload_conf
|
||||
----------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
|
|
@ -23,25 +23,93 @@ SELECT add2(1,2);
|
|||
(1 row)
|
||||
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | top_query
|
||||
--------------------------------------------------------------------------+--------------------
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return (select $1 + $2); +|
|
||||
END; $$ language plpgsql; |
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return add($1,$2); +|
|
||||
END; +|
|
||||
$$ language plpgsql; |
|
||||
SELECT (select $1 + $2) | SELECT add2($1,$2)
|
||||
SELECT add2($1,$2) |
|
||||
SELECT pg_stat_monitor_reset(); |
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C"; |
|
||||
query | top_query
|
||||
-------------------------------------------------------------------------+-----------
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return (select $1 + $2); +|
|
||||
END; $$ language plpgsql |
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return add($1,$2); +|
|
||||
END; +|
|
||||
$$ language plpgsql |
|
||||
SELECT add2($1,$2) |
|
||||
SELECT pg_stat_monitor_reset() |
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C" |
|
||||
(5 rows)
|
||||
|
||||
ALTER SYSTEM SET pg_stat_monitor.track TO 'all';
|
||||
SELECT pg_reload_conf();
|
||||
pg_reload_conf
|
||||
----------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT pg_sleep(1);
|
||||
pg_sleep
|
||||
----------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS
|
||||
$$
|
||||
BEGIN
|
||||
return (select $1 + $2);
|
||||
END; $$ language plpgsql;
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as
|
||||
$$
|
||||
BEGIN
|
||||
return add($1,$2);
|
||||
END;
|
||||
$$ language plpgsql;
|
||||
SELECT add2(1,2);
|
||||
add2
|
||||
------
|
||||
3
|
||||
(1 row)
|
||||
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | top_query
|
||||
-------------------------------------------------------------------------+--------------------
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return (select $1 + $2); +|
|
||||
END; $$ language plpgsql |
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return add($1,$2); +|
|
||||
END; +|
|
||||
$$ language plpgsql |
|
||||
SELECT (select $1 + $2) | SELECT add2($1,$2)
|
||||
SELECT add2($1,$2) |
|
||||
SELECT pg_stat_monitor_reset() |
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C" |
|
||||
(6 rows)
|
||||
|
||||
ALTER SYSTEM SET pg_stat_monitor.track TO 'top';
|
||||
SELECT pg_reload_conf();
|
||||
pg_reload_conf
|
||||
----------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT pg_sleep(1);
|
||||
pg_sleep
|
||||
----------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
|
|
@ -23,25 +23,93 @@ SELECT add2(1,2);
|
|||
(1 row)
|
||||
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | top_query
|
||||
--------------------------------------------------------------------------+--------------------
|
||||
(select $1 + $2) | SELECT add2($1,$2)
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return (select $1 + $2); +|
|
||||
END; $$ language plpgsql; |
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return add($1,$2); +|
|
||||
END; +|
|
||||
$$ language plpgsql; |
|
||||
SELECT add2($1,$2) |
|
||||
SELECT pg_stat_monitor_reset(); |
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C"; |
|
||||
query | top_query
|
||||
-------------------------------------------------------------------------+-----------
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return (select $1 + $2); +|
|
||||
END; $$ language plpgsql |
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return add($1,$2); +|
|
||||
END; +|
|
||||
$$ language plpgsql |
|
||||
SELECT add2($1,$2) |
|
||||
SELECT pg_stat_monitor_reset() |
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C" |
|
||||
(5 rows)
|
||||
|
||||
ALTER SYSTEM SET pg_stat_monitor.track TO 'all';
|
||||
SELECT pg_reload_conf();
|
||||
pg_reload_conf
|
||||
----------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT pg_sleep(1);
|
||||
pg_sleep
|
||||
----------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS
|
||||
$$
|
||||
BEGIN
|
||||
return (select $1 + $2);
|
||||
END; $$ language plpgsql;
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as
|
||||
$$
|
||||
BEGIN
|
||||
return add($1,$2);
|
||||
END;
|
||||
$$ language plpgsql;
|
||||
SELECT add2(1,2);
|
||||
add2
|
||||
------
|
||||
3
|
||||
(1 row)
|
||||
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
query | top_query
|
||||
-------------------------------------------------------------------------+--------------------
|
||||
(select $1 + $2) | SELECT add2($1,$2)
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return (select $1 + $2); +|
|
||||
END; $$ language plpgsql |
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as +|
|
||||
$$ +|
|
||||
BEGIN +|
|
||||
return add($1,$2); +|
|
||||
END; +|
|
||||
$$ language plpgsql |
|
||||
SELECT add2($1,$2) |
|
||||
SELECT pg_stat_monitor_reset() |
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C" |
|
||||
(6 rows)
|
||||
|
||||
ALTER SYSTEM SET pg_stat_monitor.track TO 'top';
|
||||
SELECT pg_reload_conf();
|
||||
pg_reload_conf
|
||||
----------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT pg_sleep(1);
|
||||
pg_sleep
|
||||
----------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT pg_stat_monitor_reset();
|
||||
pg_stat_monitor_reset
|
||||
-----------------------
|
||||
|
|
|
@ -2,7 +2,7 @@ CREATE EXTENSION pg_stat_monitor;
|
|||
SELECT pg_stat_monitor_version();
|
||||
pg_stat_monitor_version
|
||||
-------------------------
|
||||
1.0.0 - Beta 2
|
||||
1.0.0-rc.1
|
||||
(1 row)
|
||||
|
||||
DROP EXTENSION pg_stat_monitor;
|
||||
|
|
|
@ -10,6 +10,7 @@ DELETE FROM t1;
|
|||
SELECT b FROM t2 FOR UPDATE;
|
||||
TRUNCATE t1;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
SELECT query, cmd_type, cmd_type_text FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
|
|
|
@ -16,4 +16,5 @@ SELECT query, rows_retrieved FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
|||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP EXTENSION pg_stat_monitor;
|
||||
|
|
|
@ -2,5 +2,13 @@ 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";
|
||||
ALTER SYSTEM SET pg_stat_monitor.extract_comments TO 'yes';
|
||||
SELECT pg_reload_conf();
|
||||
select pg_sleep(1);
|
||||
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";
|
||||
ALTER SYSTEM SET pg_stat_monitor.extract_comments TO 'no';
|
||||
SELECT pg_reload_conf();
|
||||
SELECT pg_stat_monitor_reset();
|
||||
DROP EXTENSION pg_stat_monitor;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
CREATE EXTENSION pg_stat_monitor;
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS
|
||||
$$
|
||||
BEGIN
|
||||
|
@ -15,5 +16,30 @@ $$ language plpgsql;
|
|||
|
||||
SELECT add2(1,2);
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
|
||||
ALTER SYSTEM SET pg_stat_monitor.track TO 'all';
|
||||
SELECT pg_reload_conf();
|
||||
SELECT pg_sleep(1);
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS
|
||||
$$
|
||||
BEGIN
|
||||
return (select $1 + $2);
|
||||
END; $$ language plpgsql;
|
||||
|
||||
CREATE OR REPLACE function add2(int, int) RETURNS int as
|
||||
$$
|
||||
BEGIN
|
||||
return add($1,$2);
|
||||
END;
|
||||
$$ language plpgsql;
|
||||
|
||||
SELECT add2(1,2);
|
||||
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C";
|
||||
ALTER SYSTEM SET pg_stat_monitor.track TO 'top';
|
||||
SELECT pg_reload_conf();
|
||||
SELECT pg_sleep(1);
|
||||
SELECT pg_stat_monitor_reset();
|
||||
|
||||
DROP EXTENSION pg_stat_monitor;
|
||||
|
|
Loading…
Reference in New Issue