Commit Graph

45 Commits (2a5a2f07c47605c4599fe272aa7eed7a135036c4)

Author SHA1 Message Date
Artem Gavrilov 3bb65798fd
Format sources (#475)
* Temporary disable workflows

* Add indent target to makefiel

* Add CI workflow to check if sources formatted

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Fix

* Format sources

* Add comments

* Revert "Temporary disable workflows"

This reverts commit 7e11cf6154.

* Revert "Format sources"

This reverts commit 6ef992d9f0.

* Use PG17 for code formatt

* Format sources

* Revert "Format sources"

This reverts commit 34061e1f82.

* Format sources
2024-08-07 15:12:24 +02:00
Artem Gavrilov dacb41f9e4
[PG-810] PG-17 Support (#463)
* Temporary disable all workflows

* Add build workflow with PG17

* Fix incompatibilities

* Fix 007_settings_pgsm_query_shared_buffer.pl test

* Fix 018_column_names.pl

* Fix 025_compare_pgss.pl

* Remove tuplestore_donestoring usage at all

* Rename I/O timing statistics columns to shared_blk_{read|write}_time

* Fix comments with fileds numbers

* Fix format

* Revert "Temporary disable all workflows"

This reverts commit 12e75beb63.

* Disable all workflows except check and build for PG 15, 16 and 17

* Fix

* Fix comments

* Fix migration

* Use REL_17_BETA1 in CI

* Add timers tests to 028_temp_block.pl

* Add local blocks timing statistics columns local_blk_{write|read}_time

* Fix t/027_local_blocks.pl test for older PG versions

* Fix

* Add jit_deform_{count|time} metrics

* Fix

* Add stats_since and minmax_stats_since fields

* Revert "Disable all workflows except check and build for PG 15, 16 and 17"

This reverts commit 73febf3aee.

* Fix t/028_temp_block.pl for PG14 and below

* Fix build for PG12

* Add pgdg workflow for PG17

* Try to fix PG pgdg workflow

* Fixes and formatting

* Format code

* Add level tracking regression test

* Fix nesting level tracking

* Format code

* Add level tracking test expected result for PG13

* Fix for PG12

* Skip level tracking regression test for PG version less than 14

* Fix toplevel calculation for older PG version

* Fix level tracking test results

* Fix nesting level counting for older PG version

* Revert "Fix nesting level counting for older PG version"

This reverts commit 3e91da8010.

* Fix level tracking for older PG versions once again

* Set REL_17_BETA2 tag for PG

* Add CI badge for PG17

* Use PG17 for examples in readme
2024-07-18 14:59:57 +02:00
Artem Gavrilov 288ec6325f
Add license headers validation (#458)
* Add .licenserc.yaml file

* Fix license headers

* Add github action to check license headers

* Fix workflow

* Fix checkout path

* Rename workflow

* Add debug info

* Disable workflows

* Try fix

* Split check workflow in two jobs

* Try invalid license header

* Comment of failure

* Disable cppcheck job

* Fix licenserc file

* Enable debug logging

* Prevent comments from licence-eye

* Revert "Disable cppcheck job"

This reverts commit 10f55373ea.

* Revert "Disable workflows"

This reverts commit 2e2ead2fa5.

* Fix typo

* Revert "Try invalid license header"

This reverts commit 0cc0c883d2.

* Update year in license headers

* Cleanup

* Fix indention in license header
2024-04-26 10:55:50 +02:00
Hamid Akhtar 39d9419bd0 PG-624: pg_stat_monitor: Possible server crash when running pgbench with pg_stat_monitor loaded (#396)
PG-624: pg_stat_monitor: Possible server crash when running pgbench
with pg_stat_monitor loaded

It appears that this issue was being caused by improper handling of
dynamic number of buckets. This commit resolves the issue.

Also, as part of a larger cleanup, memory context has been moved to
local space from shared storage. Also, some unwanted
and no-longer-needed variables are removed.

Co-authored-by: Muhammad Usama <muhammad.usama@percona.com>
2023-05-24 12:27:40 +05:00
Hamid Akhtar 9ecd2ccbb7 Updating formatting of source code 2023-03-01 19:40:24 +05:00
Hamid Akhtar faa938b8f1 Fixing code indentation with pgindent 2023-02-27 14:47:27 +05:00
Muhammad Usama 05ffcac2fa
PG-606: New GUC required for enabling/disabling of pgsm_query_id calculation… (#383)
* PG-606: New GUC required for enabling/disabling of pgsm_query_id calculation

Adds a new GUC pg_stat_monitor.pgsm_enable_pgsm_query_id to enable/disable
pgsm query id calculation. Apart from that patch also refactors the GUC-related
code to match PostgreSQL conventions.

Moreover, the commit also changes the pgsm_enable_overflow GUC to boolean
instead of enum.
2023-02-23 19:08:09 +05:00
Hamid Akhtar de66ef0fce PG-588: Some queries are not being normalised.
This bug uncovered serious issues with how the data was being stored by PSGM.
So it require a complete redesign.

pg_stat_monitor now stores the data locally within the backend process's local
memory. The data is only stored when the query completes. This reduces the
number of lock acquisitions that were previously needed during various stages
of the execution. Also, this avoids data loss in case the current bucket
changes during execution. Also, the unavailability of jumble state during later
stages of executions was causing pg_stat_monitor to save non-normalized query.
This was a major problem as well.

pg_stat_monitor specific memory context is implemented. It is used for saving
data locally. The context memory callback helps us clear the locally saved data
so that we do not store it multiple times in the shared hash.

As part of this major rewrite, pgss reference in function and variable names
is changed to pgsm. Memory footprint for the entries is reduced, data types
are corrected where needed, and we've removed unused variables, functions and
macros.

This patch was mutually created by:
Co-authored-by: Hamid Akhtar <hamid.akhtar@percona.com>
Co-authored-by: Muhammad Usama <muhammad.usama@percona.com>
2023-02-22 19:31:52 +05:00
Muhammad Usama 5648b99eee
PG-585: pg_stat_monitor: Add code comments to the DSA related funcs.. (#360)
Adding code comments for the DSA related functionality.
2023-01-23 14:36:23 +05:00
Muhammad Usama 2c5e12af0a
PG-488: pg_stat_monitor: Overflow management. (#342)
* PG-488: pg_stat_monitor: Overflow management.

Reimplement the storage mechanism of buckets (for PG-15 onward) and query texts
using Dynamic shared memory. Since the dynamic shared memory can grow into a
swap area, so we get the overflow out of the box.

As PostgreSQL versions prior to V15 does not support sequence scan on dynamic
shared memory hashes, so older versions has to live with the classic shared
memory hash for storing the buckets.

Another noteworthy change with the new design is: it saves the query pointer
inside the bucket, and eventually, the query text gets evicted with the bucket
recycle.

Finally, the dynamic shared memory hash has a built-in locking mechanism, so we
can revisit the whole locking in pg_stat_monitor has the potential for lots of
performance improvements.

* Fixing tap test reported issues and also disabling dynamic hash for all versions

* Updating the expected out file for top_query test case

Co-authored-by: Hamid Akhtar <hamid.akhtar@percona.com>
2023-01-10 17:54:17 +05:00
Ibrar Ahmed 802774a2a7
PG-488: Revert pg_stat_monitor: Overflow management. (#338)
PG-488: Revert pg_stat_monitor: Overflow management.

This patch does not work for  < PostgreSQL - 15. More work required.
2022-12-22 19:15:14 +05:00
Muhammad Usama df0580b741 PG-488: pg_stat_monitor: Overflow management.
Reimplement the storage mechanism of buckets and query texts
using Dynamic shared memory. Since the dynamic shared memory
can grow into a swap area, so we get the overflow out of the box.

oreover the new design saves the query pointer inside the bucket
and eventually, the query text gets evicted with the bucket recycle.

Finally, the dynamic shared memory hash has a built-in locking
mechanism so we can revisit the whole locking in pg_stat_monitor
has potential for lots of performance improvements
2022-12-20 17:29:15 +05:00
Ibrar Ahmed a9187117f9
PG-456: Running pgindent to make source PostgreSQL compatible. (#269)
PG-456: Running pgindent to make source indentation/spacing PostgreSQLCompatible.

PostgreSQL uses pgindent from time to time to make source code PostgreSQL
style guide compatible, it is a very long time since we have not done that.
Commit fixes a lot of indentation and spacing issues.

Co-authored-by: Hamid Akhtar <hamid.akhtar@gmail.com>
2022-06-29 00:42:40 +05:00
Diego Fronza 5db7056840 Resolving compilation failures after cherry-picking of require commits
from the main branch.
2022-03-01 19:25:29 +05:00
Diego Fronza 1881fd737b PG-291: Fix query call count.
The issue with wrong query call count was taking place during transition
to a new bucket, the process is shortly describe bellow:

1. Scan for pending queries in previous bucket.
2. Add pending queries to the new bucket id.
3. Remove pending queries from previous bucket id.

The problem is that when switching to a new bucket, we reset query
statistics for a given entry being processed, so, for example, if the
pending query had a call count of 10 (9 of which were finished, 10th is
the pending one), if we move this query to the new bucket, the entry
will have its stats reseted, clearing the query call count to zero.

To solve the problem, whenever a pending query is detected, if the entry
has a call count > 1, we mark it as finished, and don't remove it from
the previous bucket in order to keep its statistics, then we move just
the pending query (10th in the example) to the new bucket id.

Another issue is that when moving a entry to a new bucket, we missed
copying the query position from the previous entry, which is used to
locate the query text in the query buffer:

hash_entry_dealloc():291
new_entry->query_pos = old_entry->query_pos;
2022-02-17 19:49:13 +05:00
Diego Fronza 258fa7faa4 PG-286: Check for NULL return on hash_search before using object.
Check if hash_search() function returns NULL before attempting to
use the object in hash_entry_alloc().
2022-02-17 19:47:35 +05:00
Diego Fronza c21a3de00d PG-286: Avoid duplicate queries in text buffer.
The memory area reserved for query text (pgsm_query_shared_buffer) was
divided evenly for each bucket, this allowed to have the same query,
e.g. "SELECT 1", duplicated in different buckets, thus wasting space.

This commit fix the query text duplication by adding a new hash table
whose only purpose is to verify if a given query is already added to the
buffer (by using the queryID).

This allows different buckets that share the same query to point to a
unique entry in the query buffer (pgss_qbuf).

When pg_stat_monitor moves to a new bucket id, by avoiding adding a
query that already exists in the buffer it can also save some CPU time.
2022-02-17 19:46:35 +05:00
Diego Fronza 8fdf0946fe PG-254: Add query location to hash table entries.
Whenever a new query is added to a query buffer, record the position
in which the query was inserted, we can then use this information to
locate the query in a faster way later on when required.

This allowed to simplify the logic in hash_entry_dealloc(), after
creating the list of pending queries, as the list is scanned we can copy
the query from the previous query buffer to the new one by using the
query position (query_pos), this avoids scanning the whole query buffer
when looking up for the queryid.

Also, when moving a query to a new buffer (copy_query), we update
the query_pos for the hash table entry, so it points to the right place
in the new query buffer.

read_query() function was updated to allow query position to be passed
as argument, if pos != 0 use it to locate the query directly, otherwise
fallback to the previous mode of scanning the whole buffer.

SaveQueryText() was updated to pass a reference to the query position as
argument, this value is updated after the function finishes with the
position that the query was stored into the buffer.
2021-10-07 10:06:20 -03:00
Diego Fronza fcb70ffed1 PG-254: Removal of pgss_query_hash hash table.
There was no necessity for using a separate hash table to keep track
of queries as all the necessary information is already available in
the pgss_hash table.

The code that moves pending queries' text in hash_query_entry_dealloc
was merged into hash_entry_dealloc.

Couple functions were not necessary anymore, thus were removed:
- hash_create_query_entry
- pgss_store_query_info
- pgss_get_entry (this logic was added directly into pgss_store).

We simplified the logic in pgss_store, it basically works as follows:
1. Create a key (bucketid, queryid, etc...) for the query event.
2. Lookup the key in pgss_hash, if no entry exists for the key, create a
   new one, save the query text into the current query buffer.
3. If jstate == NULL, then update stats counters for the entry.
2021-10-06 14:57:15 -03:00
Diego Fronza a959acb3d5 PG-244: Move pending queries' text to new bucket after bucket expiration.
Added code to move all pending queries text from an expired bucket's query
buffer to the next, active query buffer.

The previous implementation was not very efficient, it worked like this,
as soon as a query is processed and a bucket expires:

1. Allocate memory to save the contents of the next query buffer.
2. Clear the next query buffer.
3. Iterate over pgss_query_hash, then, for each entry:
   - If the entry's bucket id is equal to the next bucket then:
     -- If the query for this entry has finished or ended in error, then
        remove it from the hash table.
     -- Else, if the query is not yet finished, copy the query from the
        backup query buffer to the new query buffer.
	Now, this copy was really expensive, because it was implemented
	using read_query() / SaveQueryText(), and read_query() scans the
	whole query buffer looking for some query ID, since we do this
	extra lookup loop for each pending query we end up with a O(n^2)
	algorithm.
4. Release the backup query buffer.

Since now we always move pending queries from an expired bucket to the
next one, there is no need to scan the next query buffer for pending
queries (the pending queries are always in the current bucket, and when
it expires we move them to the next one).

Taking that into consideration, the new implementation works as follows,
whenever a bucket expires:

1. Clear the next query buffer (all entries).
2. Define an array to store pending query ids from the expired bucket,
   we use this array later on in the algorithm.
3. Iterate over pgss_query_hash, then, for each entry:
   - If the entry's bucket id is equal to the next bucket then:
     -- If the query for this entry has finished or ended in error, then
        remove it from the hash table. This is equal to the previous
	implementation.
   - Else, if the entry's bucket id is equal to the just expired bucket
     id (old bucket id) and the query state is pending (not yet finished),
     then add this query ID to the array of pending query IDs.

     Note: We define the array to hold up to 128 pending entries, if there
     are more entries than this we try to allocate memory in the heap to
     store them, then, if the allocation fails we manually copy every
     pending query past the 128th to the next query buffer, using the
     previous algorithm (read_query() / SaveQueryText), this should be a
     very rare situation.
4. Finally, if there are pending queries, copy them from the previous
   query buffer to the next one using copy_queries.

Now, copy_queries() is better than looping through each query entry and
calling read_query() / SaveQueryText() to copy each of them to the new
buffer, as explained, read_query() scans the whole query buffer for
every call.

copy_queries(), instead, scans the query buffer only once, and for every
element it checks if the current query id is in the list of queries to
be copied, this is an array of uint64 that is small enough to fit in L1
cache.

Another important fix in this commit is the addition of the line 1548 in
pg_stat_monitor.c / pgss_store():
query_entry->state = kind;

Before the addition of this line, all entries in the pgss_query_hash
hash table were not having their status updated when the query entered
execution / finished or ended in error, effectively leaving all entries
as pending, thus whenever a bucket expired all entries were being copied
from the expired bucket to the next one.
2021-10-01 15:27:45 -03:00
Diego Fronza 89743e9243 PG-244: Fix race condition in get_next_wbucket().
The if condition bellow in geta_next_wbucket() was subject to a race
condition:
if ((current_usec - pgss->prev_bucket_usec) > (PGSM_BUCKET_TIME * 1000 *
1000))

Two or more threads/processes could easily evaluate this condition to
true, thus executing more than once the block that would calculate a
new bucket id, clear/move old entries in the pgss_query_hash and
pgss_hash hash tables.

To avoid this problem, we define prev_bucket_usec and current_wbucket
variables as atomic and execute a loop to check if another thread has
updated prev_bucket_usec before the current one.
2021-09-30 17:13:27 -03:00
Diego Fronza 273f23b161 PG-230: Fix duplicated query entries.
A problem during bucket management was allowing some queries to be
duplicated, old entries would sit around without having their statistics
updated.

The problem would arise during the following chain of events:
1. A query goes through pgss_post_parse_analyze, in this stage (PGSS_PARSE)
   we only save the query into the query buffer and create an entry in the
   query hash table.
2. The query then goes through pgss_ExecutorStart (PGSS_EXEC), in this stage
   we create an entry for query statistic counters with default values,
   all time stats equal zero, etc.
3. The query then goes through pgss_ExecutorEnd (PGSS_FINISH), in this stage
   we update the query statistis, no. calls, total time taken, min_time, etc.

The problem is that between steps 2 and 3, the current bucket ID timer may
have been expired.

For example, during steps 1 and 2 the query may have been stored in
bucket ID 1, but when the query is finished (pgss_ExecutorEnd) the
current bucket ID may have been updated to 2.

This is leaving an entry for the query in bucket ID 1 with state ACTIVE,
with time statistics not updated yet.

This is also creating an entry for the query in the bucket ID 2, with all
statistics (time and others) being updated for this entry.

To solve this problem, during transition to a new bucket id, we scan all
pending queries in the previous bucket id and move them to the new
bucket id.

This way finished queries will always be associated with the bucket id
that was active at the time they've finished.
2021-09-28 16:12:34 -03:00
Andrew Pogrebnoy aecfb7a5cd PG-232: remove unused function
and fix a couple of typos
2021-09-21 10:37:10 +03:00
Diego Fronza eafb2e89a8 PG-225: Fix deadlock in pgss_store.
The deadlock scenario is describe below:
1. pgss_store is called, it acquires the lock pgss->lock.
2. An error ocurr, mostly out of memory when accessing internal hash
   tables used to store internal data, on functions
   pgss_store_query_info and pgss_get_entry.
3. Call elog() to report out of memory error.
4. Our pgsm_emit_log_hook is called, it calls pgss_store_error, which in
   turn calls pgss_store.
5. Try to acquire already acquired lock pgss->lock, deadlock happens.

To fix the problem, there are two modifications worth mentioning done by
this commit:
1. We are now passing HASH_ENTER_NULL flag to hash_search, instead of
   HASH_ENTER, as read in postgresql sources, this prevents this
   function from reporting error when out of memory, but instead it will
   only return NULL if we pass HASH_ENTER_NULL, so we can handle the
   error ourselves.
2. In pgss_store, if an error happens after the pgss->lock is acquired,
   we only set a flag, then, after releasing the lock, we check if the
   flag is set and report the error accordingly.
2021-09-03 14:43:32 -04:00
Diego Fronza 775c087fb2 PG-222: Add benchmark support for measuring hook execution time.
Added a new view 'pg_stat_monitor_hook_stats' that provide execution
time statistics for all hooks installed by the module, following is a
description of the fields:
  -       hook: The hook function name.
  -   min_time: The fastest execution time recorded for the given hook.
  -   max_time: The slowest execution time recorded for the given hook.
  - total_time: Total execution time taken by all calls to the hook.
  -   avg_time: Average execution time of a call to the hook.
  -     ncalls: Total number of calls to the hook.
  - load_comparison: A percentual of time taken by an individual hook
                     compared to every other hook.

To enable benchmark, code must be compiled with -DBENCHMARK flag, this
will make the hook functions to be replaced by a function with the same
name plus a '_benchmark' suffix, e.g. hook_function_benchmark.

The hook_function_benchmark will call the original function and
calculate the amount of time it took to execute, than it will update
statistics for that hook.
2021-08-23 11:50:56 -04:00
Diego Fronza 99f01d37e3 PG-200: Add application name to the bucket ID.
Add application name to the key used to identify queries in the hash
table, this allows different applications to have separate entries in
pg_stat_monitor view if they issued the same query.
2021-07-29 15:05:08 -04:00
Ibrar Ahmed 89614e442b PG-190: Does not show query, if query elapsed time is greater than bucket time. 2021-04-08 15:29:42 +05:00
Ibrar Ahmed e0fc683810 PG-186: Add support to monitor query execution plan. 2021-03-17 18:56:39 +05:00
Ibrar Ahmed 066162c3f6 PG-186: Add support to monitor query execution plan.
This requires refactoring of code to add this functionality. Along with
that this patch contains regression test cases.
2021-03-12 18:55:12 +00:00
Ibrar Ahmed a6036b86ac PG-174: Code cleanup. 2021-02-11 12:02:04 +00:00
Ibrar Ahmed bd8c54476f PG-150: Logging CMD Type like SELECT, UPDATE, INSERT, DELETE. 2021-02-10 14:55:40 +00:00
Ibrar Ahmed 401e2b0505 PG-168: "calls" and histogram parameter does not match. 2021-01-19 13:05:54 +00:00
Ibrar Ahmed 9bee6b3690 Copyright Notice update. 2021-01-05 18:56:07 +00:00
Ibrar Ahmed 47ad105011 PG-150: Logging CMD Type like SELECT, UPDATE, INSERT, DELETE. 2020-12-06 16:38:48 +00:00
Ibrar Ahmed bedc2ffc78 PG-154: Add backup option in case of no space left in the bucket. 2020-11-29 20:11:23 +00:00
Ibrar Ahmed 057150c99b Issue - (#21): Show objects(tables) involved in the query.
PG-96
2020-11-24 20:10:49 +00:00
Ibrar Ahmed 7e570378d1 Remove missing code debugging information. 2020-11-24 18:03:41 +00:00
Ibrar Ahmed 3999e28c00 Issue - (#61): Remove unnecessary code previously used for wait_events.
PG-146
2020-11-11 13:52:45 +00:00
Ibrar Ahmed 7b04755037 Issue - (#60): Log error/warning/info and debug messages.
PG-136
2020-11-11 11:47:06 +00:00
Ibrar Ahmed 8918017134 Issue (#59): Build failed using gcc-9 and 10.
The issue only occurs when compiled using -fno-common flag.
2020-11-02 11:21:47 +00:00
Ibrar Ahmed f48a64cc0a Issue - (#53): Fix a bug where the query response time histogram does show proper counters.
PG-143 : Total sum of all the response histograms should be equal to total_calls.
2020-10-12 21:49:35 +00:00
Ibrar Ahmed 166ee0a25b Issue - (#51): Postgres process is taking too much CPU.
Jira: PG-141

There is lock conflict, so used LW_EXCLUSIVE instead of LW_SHARED. This
need to be investigated again and check the possibility to use a shared lock.
2020-10-12 19:41:48 +00:00
Ibrar Ahmed dea16f1878 Issue (#49): Duplicates in pg_stat_monitor.
Jira: PG-139
2020-10-10 22:46:53 +00:00
Ibrar Ahmed d66a079b1b Issue (#47): Default values of setting are not set properly. 2020-09-30 12:49:05 +00:00
Ibrar Ahmed 935d063f13 Issue(30): Code refactoring. 2020-09-14 22:26:19 +00:00