Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make it possible to control header items display from configuration file #404

Merged
merged 8 commits into from
Feb 28, 2024
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 .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
include:
- python: "3.7"
- python: "3.8"
psycopg: "psycopg2"
- python: "3.12"
psycopg: "psycopg3"
Expand Down
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ repos:
exclude: tests/test_*.txt
- repo: local
hooks:
- id: pyupgrade
name: pyupgrade
entry: pyupgrade --py38-plus --exit-zero-even-if-changed
language: system
types: [python]
- id: black
name: black
entry: black --check .
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
### Added

* The *rollback ratio* is now displayed in the "global" header (#385).
* Make header's sections display configurable through the `[header]` section of
the configuration file.

### Changed

* The help text for `K` action, displayed in the footer, has been rephrased as
"terminate underlying session".
* Rephrase the help text of `--no-{inst,sys,proc}-info` options and group them
into a dedicated section of `--help` output.

### Fixed

Expand All @@ -18,6 +22,10 @@
* Fix retrieval of I/O statistics on BSD systems (#393).
* Fix spelling mistakes in the man page.

### Removed

* Python 3.7 is no longer supported.

### Misc

* Document how to *hack* on pg\_activity in the `README`.
Expand Down
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pg\_activity releases. Before submitting a bug report here:

## From PyPI

pg\_activity can be installed using pip on Python 3.7 or later along with
pg\_activity can be installed using pip on Python 3.8 or later along with
psycopg:

$ python3 -m pip install "pg_activity[psycopg]"
Expand Down Expand Up @@ -130,12 +130,14 @@ ex:
--no-wait Disable W.
--no-app-name Disable App.

Header display options:
--no-inst-info Display instance information.
--no-sys-info Display system information.
--no-proc-info Display workers process information.

Other display options:
--hide-queries-in-logs
Disable log_min_duration_statements and log_min_duration_sample for pg_activity.
--no-inst-info Display instance information in header.
--no-sys-info Display system information in header.
--no-proc-info Display workers process information in header.
--refresh REFRESH Refresh rate. Values: 0.5, 1, 2, 3, 4, 5 (default: 2).

## Configuration
Expand All @@ -144,8 +146,14 @@ ex:
read from `${XDG_CONFIG_HOME:~/.config}/pg_activity.conf` or
`/etc/pg_activity.conf` in that order. Command-line options may override
configuration file settings.
This is used to control how columns in the processes table are rendered, e.g.:
This is used to control how columns in the processes table are rendered or which
items of the header should be displayed, e.g.:
```ini
[header]
show_instance = yes
show_system = yes
show_workers = no

[client]
hidden = yes

Expand Down
14 changes: 8 additions & 6 deletions docs/man/pg_activity.1
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "PG_ACTIVITY 1"
.TH PG_ACTIVITY 1 "2023-06-01" "pg_activity 3.4.2" "Command line tool for PostgreSQL server activity monitoring."
.TH PG_ACTIVITY 1 "2024-02-20" "pg_activity 3.4.2" "Command line tool for PostgreSQL server activity monitoring."
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
Expand Down Expand Up @@ -490,23 +490,25 @@ required by another session. It shows following information:
.Vb 1
\& Disable App.
.Ve
.SS "\s-1OTHER DISPLAY OPTIONS\s0"
.IX Subsection "OTHER DISPLAY OPTIONS"
.SS "\s-1HEADER DISPLAY OPTIONS\s0"
.IX Subsection "HEADER DISPLAY OPTIONS"
.IP "\fB\-\-no\-inst\-info\fR" 2
.IX Item "--no-inst-info"
.Vb 1
\& Display instance information in header.
\& Hide instance information.
.Ve
.IP "\fB\-\-no\-sys\-info\fR" 2
.IX Item "--no-sys-info"
.Vb 1
\& Display system information in header.
\& Hide system information.
.Ve
.IP "\fB\-\-no\-proc\-info\fR" 2
.IX Item "--no-proc-info"
.Vb 1
\& Display workers process information in header.
\& Hide workers process information.
.Ve
.SS "\s-1OTHER DISPLAY OPTIONS\s0"
.IX Subsection "OTHER DISPLAY OPTIONS"
.IP "\fB\-\-refresh\fR" 2
.IX Item "--refresh"
.Vb 1
Expand Down
14 changes: 10 additions & 4 deletions docs/man/pg_activity.pod
Original file line number Diff line number Diff line change
Expand Up @@ -358,21 +358,27 @@ required by another session. It shows following information:

=back

=head2 OTHER DISPLAY OPTIONS
=head2 HEADER DISPLAY OPTIONS

=over 2

=item B<--no-inst-info>

Display instance information in header.
Hide instance information.

=item B<--no-sys-info>

Display system information in header.
Hide system information.

=item B<--no-proc-info>

Display workers process information in header.
Hide workers process information.

=back

=head2 OTHER DISPLAY OPTIONS

=over 2

=item B<--refresh>

Expand Down
19 changes: 11 additions & 8 deletions pgactivity/activities.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from __future__ import annotations

import builtins
import os
import time
from typing import Dict, List, Optional, Sequence, Tuple, TypeVar
from typing import TypeVar
from warnings import catch_warnings, simplefilter

import attr
import psutil

from .compat import Sequence
from .types import (
BlockingProcess,
IOCounter,
Expand All @@ -21,7 +24,7 @@
)


def sys_get_proc(pid: int) -> Optional[SystemProcess]:
def sys_get_proc(pid: int) -> SystemProcess | None:
"""Return a SystemProcess instance matching given pid or None if access with psutil
is not possible.
"""
Expand Down Expand Up @@ -53,9 +56,9 @@ def sys_get_proc(pid: int) -> Optional[SystemProcess]:

def ps_complete(
pg_processes: Sequence[RunningProcess],
processes: Dict[int, SystemProcess],
processes: dict[int, SystemProcess],
fs_blocksize: int,
) -> Tuple[List[LocalRunningProcess], IOCounter, IOCounter]:
) -> tuple[list[LocalRunningProcess], IOCounter, IOCounter]:
"""Transform the sequence of 'pg_processes' (RunningProcess) as LocalRunningProcess
with local system information from the 'processes' map. Return LocalRunningProcess
list, as well as read and write IO counters.
Expand Down Expand Up @@ -139,7 +142,7 @@ def ps_complete(
T = TypeVar("T", RunningProcess, WaitingProcess, BlockingProcess, LocalRunningProcess)


def sorted(processes: List[T], *, key: SortKey, reverse: bool = False) -> List[T]:
def sorted(processes: list[T], *, key: SortKey, reverse: bool = False) -> list[T]:
"""Return processes sorted.

>>> from ipaddress import IPv4Interface, ip_address
Expand Down Expand Up @@ -314,12 +317,12 @@ def update_max_iops(max_iops: int, read_count: float, write_count: float) -> int
return max(int(read_count + write_count), max_iops)


def get_load_average() -> Tuple[float, float, float]:
def get_load_average() -> tuple[float, float, float]:
"""Get load average"""
return os.getloadavg()


def get_mem_swap() -> Tuple[MemoryInfo, SwapInfo]:
def get_mem_swap() -> tuple[MemoryInfo, SwapInfo]:
"""Get memory and swap usage"""
with catch_warnings():
simplefilter("ignore", RuntimeWarning)
Expand All @@ -335,7 +338,7 @@ def get_mem_swap() -> Tuple[MemoryInfo, SwapInfo]:
)


def mem_swap_load() -> Tuple[MemoryInfo, SwapInfo, LoadAverage]:
def mem_swap_load() -> tuple[MemoryInfo, SwapInfo, LoadAverage]:
"""Read memory, swap and load average from Data object."""
memory, swap = get_mem_swap()
load = LoadAverage(*get_load_average())
Expand Down
43 changes: 23 additions & 20 deletions pgactivity/cli.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from __future__ import annotations

import logging
import os
import socket
import sys
import time
from argparse import ArgumentParser
from io import StringIO
from typing import Optional

from blessed import Terminal

Expand All @@ -14,7 +15,7 @@
from .pg import OperationalError


def configure_logger(debug_file: Optional[str] = None) -> StringIO:
def configure_logger(debug_file: str | None = None) -> StringIO:
logger = logging.getLogger("pgactivity")
logger.setLevel(logging.DEBUG)

Expand Down Expand Up @@ -314,38 +315,40 @@ def get_parser() -> ArgumentParser:
default=False,
)

group = parser.add_argument_group("Other display options")
# --hide-queries-in-logs
group.add_argument(
"--hide-queries-in-logs",
dest="hide_queries_in_logs",
action="store_true",
help="Disable log_min_duration_statements and log_min_duration_sample for pg_activity.",
default=False,
)
group = parser.add_argument_group("Header display options")
# --no-inst-info
group.add_argument(
"--no-inst-info",
dest="show_instance_info_in_header",
dest="header_show_instance",
action="store_false",
help="Display instance information in header.",
default=True,
help="Hide instance information.",
default=None,
)
# --no-sys-info
group.add_argument(
"--no-sys-info",
dest="show_system_info_in_header",
dest="header_show_system",
action="store_false",
help="Display system information in header.",
default=True,
help="Hide system information.",
default=None,
)
# --no-proc-info
group.add_argument(
"--no-proc-info",
dest="show_worker_info_in_header",
dest="header_show_workers",
action="store_false",
help="Display workers process information in header.",
default=True,
help="Hide workers process information.",
default=None,
)

group = parser.add_argument_group("Other display options")
# --hide-queries-in-logs
group.add_argument(
"--hide-queries-in-logs",
dest="hide_queries_in_logs",
action="store_true",
help="Disable log_min_duration_statements and log_min_duration_sample for pg_activity.",
default=False,
)
# --refresh
group.add_argument(
Expand Down
32 changes: 27 additions & 5 deletions pgactivity/compat.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
from __future__ import annotations

import operator
import sys
from typing import Any, Dict
from importlib.metadata import version
from typing import Any

import attr
import attr.validators
import blessed

if sys.version_info < (3, 8):
from importlib_metadata import version
__all__ = [
"Callable",
"Dict",
"Iterable",
"Iterator",
"Mapping",
"MutableSet",
"Sequence",
]

if sys.version_info >= (3, 9):
from collections.abc import (
Callable,
Iterable,
Iterator,
Mapping,
MutableSet,
Sequence,
)

Dict = dict
else:
from importlib.metadata import version
from typing import Callable, Dict, Iterable, Iterator, Mapping, MutableSet, Sequence

ATTR_VERSION = tuple(int(x) for x in version("attrs").split(".", 2)[:2])
BLESSED_VERSION = tuple(int(x) for x in version("blessed").split(".", 2)[:2])

if ATTR_VERSION < (18, 1):

def fields_dict(cls: Any) -> Dict[str, Any]:
def fields_dict(cls: Any) -> dict[str, Any]:
return {a.name: a for a in cls.__attrs_attrs__}

else:
Expand Down
Loading
Loading