Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ repos:
exclude: tests
- id: codespell
name: codespell
entry: codespell
entry: codespell --ignore-words-list USIN
language: system
types: [file]
11 changes: 11 additions & 0 deletions docs/man/pg_activity.1
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ The running queries panel shows all running queries, transactions or backends
.IX Item "- XMIN: xmin horizon of the backend;"
.IP "\- \fBDATABASE\fR: database specified in the connection string;" 2
.IX Item "- DATABASE: database specified in the connection string;"
.IP "\- \fBQUERYID\fR: query identifier for the statement;" 2
.IX Item "- QUERYID: query identifier for the statement;"
.IP "\- \fBAPP\fR: application name specified in the connection string;" 2
.IX Item "- APP: application name specified in the connection string;"
.IP "\- \fBUSER\fR: user name specified in the connection string;" 2
Expand Down Expand Up @@ -218,6 +220,8 @@ shows the following information:
.PD 0
.IP "\- \fBDATABASE\fR: database specified in the connection string;" 2
.IX Item "- DATABASE: database specified in the connection string;"
.IP "\- \fBQUERYID\fR: query identifier for the statement;" 2
.IX Item "- QUERYID: query identifier for the statement;"
.IP "\- \fBAPP\fR: application name specified in the connection string;" 2
.IX Item "- APP: application name specified in the connection string;"
.IP "\- \fBUSER\fR: user name specified in the connection string;" 2
Expand Down Expand Up @@ -246,6 +250,8 @@ required by another session. It shows following information:
.PD 0
.IP "\- \fBDATABASE\fR: database specified in the connection string;" 2
.IX Item "- DATABASE: database specified in the connection string;"
.IP "\- \fBQUERYID\fR: query identifier for the statement;" 2
.IX Item "- QUERYID: query identifier for the statement;"
.IP "\- \fBAPP\fR: application name specified in the connection string;" 2
.IX Item "- APP: application name specified in the connection string;"
.IP "\- \fBUSER\fR: user name specified in the connection string;" 2
Expand Down Expand Up @@ -419,6 +425,11 @@ required by another session. It shows following information:
.Vb 1
\& Enable/disable APP.
.Ve
.IP "\fB\-\-query\-id\fR, \fB\-\-no\-query\-id\fR" 2
.IX Item "--query-id, --no-query-id"
.Vb 1
\& Enable/disable QUERYID.
.Ve
.SS "HEADER DISPLAY OPTIONS"
.IX Subsection "HEADER DISPLAY OPTIONS"
.IP \fB\-\-no\-inst\-info\fR 2
Expand Down
10 changes: 10 additions & 0 deletions docs/man/pg_activity.pod
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ B<min duration> seconds. It displays the following information:

=item - B<DATABASE>: database specified in the connection string;

=item - B<QUERYID>: query identifier for the statement;

=item - B<APP>: application name specified in the connection string;

=item - B<USER>: user name specified in the connection string;
Expand Down Expand Up @@ -175,6 +177,8 @@ shows the following information:

=item - B<DATABASE>: database specified in the connection string;

=item - B<QUERYID>: query identifier for the statement;

=item - B<APP>: application name specified in the connection string;

=item - B<USER>: user name specified in the connection string;
Expand Down Expand Up @@ -206,6 +210,8 @@ required by another session. It shows following information:

=item - B<DATABASE>: database specified in the connection string;

=item - B<QUERYID>: query identifier for the statement;

=item - B<APP>: application name specified in the connection string;

=item - B<USER>: user name specified in the connection string;
Expand Down Expand Up @@ -370,6 +376,10 @@ required by another session. It shows following information:

Enable/disable APP.

=item B<--query-id>, B<--no-query-id>

Enable/disable QUERYID.

=back

=head2 HEADER DISPLAY OPTIONS
Expand Down
12 changes: 10 additions & 2 deletions pgactivity/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,21 @@ def configure_logger(debug_file: str | None = None) -> StringIO:
return memory_string


def flag(p: Any, spec: str, *, dest: str, feature: str) -> None:
def flag(
p: Any,
spec: str,
*,
dest: str,
feature: str,
default: bool | None = None,
) -> None:
assert not spec.startswith("--no-") and spec.startswith("--"), spec
p.add_argument(
spec,
dest=dest,
help=f"Enable/disable {feature}.",
action=argparse.BooleanOptionalAction,
default=None,
default=default,
)


Expand Down Expand Up @@ -240,6 +247,7 @@ def get_parser(prog: str | None = None) -> argparse.ArgumentParser:
flag(group, "--time", dest="time", feature="TIME+")
flag(group, "--wait", dest="wait", feature="W")
flag(group, "--app-name", dest="appname", feature="APP")
flag(group, "--query-id", dest="queryid", feature="QUERYID", default=False)

group = parser.add_argument_group("Header display options")
group.add_argument(
Expand Down
7 changes: 5 additions & 2 deletions pgactivity/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ class Flag(enum.Flag):
"""Column flag.

>>> Flag.names()
['database', 'appname', 'client', 'user', 'cpu', 'mem', 'read', 'write', 'time', 'wait', 'relation', 'type', 'mode', 'iowait', 'pid', 'xmin']
['database', 'appname', 'client', 'user', 'cpu', 'mem', 'read', 'write', 'time', 'wait', 'relation', 'type', 'mode', 'iowait', 'pid', 'xmin', 'queryid']
>>> Flag.all() # doctest: +ELLIPSIS
<Flag...: 65535>
<Flag...: 131071>
"""

DATABASE = enum.auto()
Expand All @@ -83,6 +83,7 @@ class Flag(enum.Flag):
IOWAIT = enum.auto()
PID = enum.auto()
XMIN = enum.auto()
QUERYID = enum.auto()

@classmethod
def names(cls) -> list[str]:
Expand Down Expand Up @@ -127,6 +128,7 @@ def load(
database: bool | None,
mem: bool | None,
pid: bool | None,
queryid: bool | None,
read: bool | None,
time: bool | None,
user: bool | None,
Expand All @@ -147,6 +149,7 @@ def load(
(database, cls.DATABASE),
(mem, cls.MEM),
(pid, cls.PID),
(queryid, cls.QUERYID),
(read, cls.READ),
(time, cls.TIME),
(user, cls.USER),
Expand Down
12 changes: 9 additions & 3 deletions pgactivity/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,9 @@ def pg_get_activities(self, duration_mode: int = 1) -> list[RunningProcess]:
"""
Get activity from pg_stat_activity view.
"""
if self.pg_num_version >= 130000:
if self.pg_num_version >= 140000:
qs = queries.get("get_pg_activity_post_140000")
elif self.pg_num_version >= 130000:
qs = queries.get("get_pg_activity_post_130000")
elif self.pg_num_version >= 110000:
qs = queries.get("get_pg_activity_post_110000")
Expand Down Expand Up @@ -427,7 +429,9 @@ def pg_get_waiting(self, duration_mode: int = 1) -> list[WaitingProcess]:
"""
Get waiting queries.
"""
if self.pg_num_version >= 90200:
if self.pg_num_version >= 140000:
qs = queries.get("get_waiting_post_140000")
elif self.pg_num_version >= 90200:
qs = queries.get("get_waiting_post_090200")
else:
qs = queries.get("get_waiting_oldest")
Expand All @@ -454,7 +458,9 @@ def pg_get_blocking(self, duration_mode: int = 1) -> list[BlockingProcess]:
"""
Get blocking queries
"""
if self.pg_num_version >= 90600:
if self.pg_num_version >= 140000:
qs = queries.get("get_blocking_post_140000")
elif self.pg_num_version >= 90600:
qs = queries.get("get_blocking_post_090600")
elif self.pg_num_version >= 90200:
qs = queries.get("get_blocking_post_090200")
Expand Down
3 changes: 2 additions & 1 deletion pgactivity/queries/get_blocking_oldest.sql
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ SELECT
ELSE sq.query
END AS query,
pg_catalog.pg_encoding_to_char(b.encoding) AS encoding,
waiting AS wait
waiting AS wait,
NULL::int8 AS query_id
FROM
(
-- Transaction id lock
Expand Down
3 changes: 2 additions & 1 deletion pgactivity/queries/get_blocking_post_090200.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ SELECT
state,
sq.query AS query,
pg_catalog.pg_encoding_to_char(b.encoding) AS encoding,
waiting as wait
waiting as wait,
NULL::int8 AS query_id
FROM
(
-- Transaction id lock
Expand Down
3 changes: 2 additions & 1 deletion pgactivity/queries/get_blocking_post_090600.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ SELECT
state,
sq.query AS query,
pg_catalog.pg_encoding_to_char(b.encoding) AS encoding,
wait_event as wait
wait_event as wait,
NULL::int8 AS query_id
FROM
(
-- Transaction id lock
Expand Down
130 changes: 130 additions & 0 deletions pgactivity/queries/get_blocking_post_140000.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
-- Get blocking queries >= 14
SELECT
pid,
application_name,
sq.datname AS database,
usename AS user,
client,
relation,
mode,
locktype AS type,
duration,
state,
sq.query AS query,
pg_catalog.pg_encoding_to_char(b.encoding) AS encoding,
wait_event as wait,
query_id
FROM
(
-- Transaction id lock
SELECT
blocking.pid,
pg_stat_activity.application_name,
pg_stat_activity.query,
blocking.mode,
pg_stat_activity.datname,
pg_stat_activity.datid,
pg_stat_activity.usename,
pg_stat_activity.client_addr AS client,
blocking.locktype,
EXTRACT(epoch FROM (NOW() - pg_stat_activity.{duration_column})) AS duration,
pg_stat_activity.state as state,
blocking.relation::regclass AS relation,
pg_stat_activity.wait_event,
pg_stat_activity.query_id
FROM
pg_locks AS blocking
JOIN pg_locks AS blocked ON (blocking.transactionid = blocked.transactionid AND blocking.locktype = blocked.locktype)
JOIN pg_stat_activity ON (blocking.pid = pg_stat_activity.pid)
WHERE
blocking.granted
AND NOT blocked.granted
AND CASE WHEN {min_duration} = 0
THEN true
ELSE extract(epoch from now() - {duration_column}) > %(min_duration)s
END
AND CASE WHEN {dbname_filter} IS NULL THEN true
ELSE datname ~* %(dbname_filter)s
END
UNION ALL
-- VirtualXid Lock
SELECT
blocking.pid,
pg_stat_activity.application_name,
pg_stat_activity.query,
blocking.mode,
pg_stat_activity.datname,
pg_stat_activity.datid,
pg_stat_activity.usename,
pg_stat_activity.client_addr AS client,
blocking.locktype,
EXTRACT(epoch FROM (NOW() - pg_stat_activity.{duration_column})) AS duration,
pg_stat_activity.state as state,
blocking.relation::regclass AS relation,
pg_stat_activity.wait_event,
pg_stat_activity.query_id
FROM
pg_locks AS blocking
JOIN pg_locks AS blocked ON (blocking.virtualxid = blocked.virtualxid AND blocking.locktype = blocked.locktype)
JOIN pg_stat_activity ON (blocking.pid = pg_stat_activity.pid)
WHERE
blocking.granted
AND NOT blocked.granted
AND CASE WHEN {min_duration} = 0
THEN true
ELSE extract(epoch from now() - {duration_column}) > %(min_duration)s
END
AND CASE WHEN {dbname_filter} IS NULL THEN true
ELSE datname ~* %(dbname_filter)s
END
UNION ALL
-- Relation or tuple Lock
SELECT
blocking.pid,
pg_stat_activity.application_name,
pg_stat_activity.query,
blocking.mode,
pg_stat_activity.datname,
pg_stat_activity.datid,
pg_stat_activity.usename,
pg_stat_activity.client_addr AS client,
blocking.locktype,
EXTRACT(epoch FROM (NOW() - pg_stat_activity.{duration_column})) AS duration,
pg_stat_activity.state as state,
blocking.relation::regclass AS relation,
pg_stat_activity.wait_event,
pg_stat_activity.query_id
FROM
pg_locks AS blocking
JOIN pg_locks AS blocked ON (blocking.database = blocked.database AND blocking.relation = blocked.relation AND blocking.locktype = blocked.locktype)
JOIN pg_stat_activity ON (blocking.pid = pg_stat_activity.pid)
WHERE
blocking.granted
AND NOT blocked.granted
AND blocked.relation IS NOT NULL
AND CASE WHEN {min_duration} = 0
THEN true
ELSE extract(epoch from now() - {duration_column}) > %(min_duration)s
END
AND CASE WHEN {dbname_filter} IS NULL THEN true
ELSE datname ~* %(dbname_filter)s
END
) AS sq
LEFT OUTER JOIN pg_database b ON sq.datid = b.oid
GROUP BY
pid,
application_name,
database,
usename,
client,
relation,
mode,
locktype,
duration,
state,
query,
encoding,
wait_event,
query_id
ORDER BY
duration DESC;
3 changes: 2 additions & 1 deletion pgactivity/queries/get_pg_activity_oldest.sql
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ SELECT
END AS query,
pg_catalog.pg_encoding_to_char(b.encoding) AS encoding,
NULL AS query_leader_pid,
false AS is_parallel_worker
false AS is_parallel_worker,
NULL::int8 AS query_id
FROM
pg_stat_activity a
LEFT OUTER JOIN pg_database b ON a.datid = b.oid
Expand Down
3 changes: 2 additions & 1 deletion pgactivity/queries/get_pg_activity_post_090200.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ SELECT
a.query AS query,
pg_catalog.pg_encoding_to_char(b.encoding) AS encoding,
NULL AS query_leader_pid,
false AS is_parallel_worker
false AS is_parallel_worker,
NULL::int8 AS query_id
FROM
pg_stat_activity a
LEFT OUTER JOIN pg_database b ON a.datid = b.oid
Expand Down
3 changes: 2 additions & 1 deletion pgactivity/queries/get_pg_activity_post_090400.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ SELECT
a.query AS query,
pg_catalog.pg_encoding_to_char(b.encoding) AS encoding,
NULL AS query_leader_pid,
false AS is_parallel_worker
false AS is_parallel_worker,
NULL::int8 AS query_id
FROM
pg_stat_activity a
LEFT OUTER JOIN pg_database b ON a.datid = b.oid
Expand Down
3 changes: 2 additions & 1 deletion pgactivity/queries/get_pg_activity_post_090600.sql
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ SELECT
a.query AS query,
pg_catalog.pg_encoding_to_char(b.encoding) AS encoding,
NULL AS query_leader_pid,
false AS is_parallel_worker
false AS is_parallel_worker,
NULL::int8 AS query_id
FROM
pg_stat_activity a
LEFT OUTER JOIN pg_database b ON a.datid = b.oid
Expand Down
3 changes: 2 additions & 1 deletion pgactivity/queries/get_pg_activity_post_100000.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ SELECT
NULL AS query_leader_pid,
( a.backend_type = 'background worker'
AND a.query IS NOT NULL
) AS is_parallel_worker
) AS is_parallel_worker,
NULL::int8 AS query_id
FROM
pg_stat_activity a
LEFT OUTER JOIN pg_database b ON a.datid = b.oid
Expand Down
Loading
Loading