14 Commits

Author SHA1 Message Date
17b55d3c46 Merge branch 'dev/tmpfiles' into develop 2025-12-03 01:45:50 -05:00
9b48535a09 Add archive ready and temp file items to template
- Add the initital item definitions to the template for archive ready
  files and temp files.

- Fix the temp file query to be able to return both columns in all
  cases.
2025-12-02 01:43:24 -05:00
590425fae7 Handle situations where directories don't exist
- The pgsql_tmp and archive_ready directories don't always exist.  Since
  PG <=9.4 doesn't have the "missing_ok" parameter, we have to work
  around the missing directories explicitly.
2025-12-02 01:05:16 -05:00
174cac4ca6 Add queries for tmp and ready files 2025-11-29 02:42:04 -05:00
f740c4012d Merge branch 'main' into develop 2025-11-29 00:35:05 -05:00
c1dcc6c87b Merge branch 'rel/1.1.0' into develop 2025-11-29 00:34:17 -05:00
4fa3a7b669 Merge branch 'rel/1.1.0' 2025-11-29 00:30:33 -05:00
8182ad75b9 Fix activity query
* Modify the activity query to ensure each state is always reported.

* Fix the activity preprocessor to unwrap the value from the array
  containing it.
2025-10-18 12:49:09 -04:00
175fd85f9f Remove Debian 10
* The Debain 10 Docker image may have been removed.  Remove it from the
  list of supported distros until a source can be found.
2025-10-18 02:47:50 -04:00
e9c97d65cb Fix OEL7 and AL2 targets 2025-10-18 02:42:02 -04:00
af5d9cf186 Add Amazon Linux 2 support, prepare for PG18
* Add Amazon Linux 2 as a supported OS.

* Dynamically select the package manager for Amazon and Oracle Linux.

* Prepare for supporting PostgreSQL 18.  Specifically, the Docker image
  seems to have moved the data directory, so get that dynamically.
2025-10-18 02:11:08 -04:00
17c15e7e48 Add support for Amazon Linux 2023, bump version to 1.1.0-rc1
* Add support for packaging for Amazon Linux 2023

* Bump version to 1.1.0-rc1

* Tidy up the Makefile a bit
2025-10-18 01:00:30 -04:00
f55bcdcfae Merge branch 'dev/locks' into develop 2025-10-17 01:35:43 -04:00
e7b97a9e88 Add items to template
* Add items to the Zabbix template for:
    - Backgroubd writer / checkpoint stats
    - Lock stats
    - Connection states
2025-10-17 01:24:33 -04:00
10 changed files with 865 additions and 59 deletions

View File

@@ -0,0 +1,74 @@
# Copyright 2024 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
PYTHON_COMPAT=( python3_{6..13} )
inherit python-r1 systemd
DESCRIPTION="PostgreSQL monitoring bridge"
HOMEPAGE="None"
LICENSE="BSD"
SLOT="0"
KEYWORDS="amd64"
SRC_URI="https://code2.shh-dot-com.org/james/${PN}/releases/download/v${PV}/${P}.tar.bz2"
IUSE="-systemd"
DEPEND="
${PYTHON_DEPS}
dev-python/psycopg:2
dev-python/pyyaml
dev-python/requests
app-admin/logrotate
"
RDEPEND="${DEPEND}"
BDEPEND=""
#RESTRICT="fetch"
#S="${WORKDIR}/${PN}"
#pkg_nofetch() {
# einfo "Please download"
# einfo " - ${P}.tar.bz2"
# einfo "from ${HOMEPAGE} and place it in your DISTDIR directory."
# einfo "The file should be owned by portage:portage."
#}
src_compile() {
true
}
src_install() {
# Install init script
if ! use systemd ; then
newinitd "openrc/pgmon.initd" pgmon
newconfd "openrc/pgmon.confd" pgmon
fi
# Install systemd unit
if use systemd ; then
systemd_dounit "systemd/pgmon.service"
fi
# Install script
exeinto /usr/bin
newexe "src/pgmon.py" pgmon
# Install default config
diropts -o root -g root -m 0755
insinto /etc/pgmon
doins "sample-config/pgmon.yml"
doins "sample-config/pgmon-metrics.yml"
# Install logrotate config
insinto /etc/logrotate.d
newins "logrotate/pgmon.logrotate" pgmon
# Install man page
doman manpages/pgmon.1
}

160
Makefile
View File

@@ -9,6 +9,7 @@ FULL_VERSION := $(shell grep -m 1 '^VERSION = ' "$(SCRIPT)" | sed -ne 's/.*"\(.*
VERSION := $(shell echo $(FULL_VERSION) | sed -n 's/\(.*\)\(-rc.*\|$$\)/\1/p') VERSION := $(shell echo $(FULL_VERSION) | sed -n 's/\(.*\)\(-rc.*\|$$\)/\1/p')
RELEASE := $(shell echo $(FULL_VERSION) | sed -n 's/.*-rc\([0-9]\+\)$$/\1/p') RELEASE := $(shell echo $(FULL_VERSION) | sed -n 's/.*-rc\([0-9]\+\)$$/\1/p')
# Package version formatting
ifeq ($(RELEASE),) ifeq ($(RELEASE),)
RPM_RELEASE := 1 RPM_RELEASE := 1
RPM_VERSION := $(VERSION)-$(RPM_RELEASE) RPM_VERSION := $(VERSION)-$(RPM_RELEASE)
@@ -33,55 +34,29 @@ BUILD_DIR := build
SUPPORTED := ubuntu-20.04 \ SUPPORTED := ubuntu-20.04 \
ubuntu-22.04 \ ubuntu-22.04 \
ubuntu-24.04 \ ubuntu-24.04 \
debian-10 \
debian-11 \ debian-11 \
debian-12 \
debian-13 \
rockylinux-8 \ rockylinux-8 \
rockylinux-9 \ rockylinux-9 \
rockylinux-10 \
oraclelinux-7 \ oraclelinux-7 \
amazonlinux-2 \
amazonlinux-2023 \
gentoo gentoo
## ##
# These targets are the main ones to use for most things. # These targets are the main ones to use for most things.
## ##
.PHONY: all clean tgz lint format test query-tests install-common install-openrc install-systemd .PHONY: all clean tgz lint format test query-tests template-coverage
all: package-all all: package-all
# Dump information related to the current version
version: version:
@echo "full version=$(FULL_VERSION) version=$(VERSION) rel=$(RELEASE) rpm=$(RPM_VERSION) deb=$(DEB_VERSION)" @echo "full version=$(FULL_VERSION) version=$(VERSION) rel=$(RELEASE) rpm=$(RPM_VERSION) deb=$(DEB_VERSION)"
# Build all packages
.PHONY: package-all
package-all: $(foreach distro_release, $(SUPPORTED), package-$(distro_release))
# Gentoo package (tar.gz) creation
.PHONY: package-gentoo
package-gentoo:
mkdir -p $(BUILD_DIR)/gentoo
tar --transform "s,^,$(PACKAGE_NAME)-$(FULL_VERSION)/," -acjf $(BUILD_DIR)/gentoo/$(PACKAGE_NAME)-$(FULL_VERSION).tar.bz2 --exclude .gitignore $(shell git ls-tree --full-tree --name-only -r HEAD)
# Create a deb package
.PHONY: package-%
package-%: PARTS=$(subst -, ,$*)
package-%: DISTRO=$(word 1, $(PARTS))
package-%: RELEASE=$(word 2, $(PARTS))
package-%:
mkdir -p $(BUILD_DIR)
docker run --rm \
-v .:/src:ro \
-v ./$(BUILD_DIR):/output \
--user $(shell id -u):$(shell id -g) \
"$(DISTRO)-packager:$(RELEASE)"
# Create a tarball
tgz:
rm -rf $(BUILD_DIR)/tgz/root
mkdir -p $(BUILD_DIR)/tgz/root
$(MAKE) install-openrc DESTDIR=$(BUILD_DIR)/tgz/root
tar -cz -f $(BUILD_DIR)/tgz/$(PACKAGE_NAME)-$(FULL_VERSION).tgz -C $(BUILD_DIR)/tgz/root .
# Clean up the build directory # Clean up the build directory
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
@@ -98,7 +73,7 @@ format:
$(BLACK) src/pgmon.py $(BLACK) src/pgmon.py
$(BLACK) src/test_pgmon.py $(BLACK) src/test_pgmon.py
# Run unit tests for the script # Run unit tests for the script (with coverage if it's available)
test: test:
ifeq ($(HAVE_COVERAGE),yes) ifeq ($(HAVE_COVERAGE),yes)
cd src ; $(PYTHON) -m coverage run -m unittest && python3 -m coverage report -m cd src ; $(PYTHON) -m coverage run -m unittest && python3 -m coverage report -m
@@ -114,8 +89,22 @@ query-tests:
template-coverage: template-coverage:
$(PYTHON) zabbix_templates/coverage.py sample-config/pgmon-metrics.yml zabbix_templates/pgmon_templates.yaml $(PYTHON) zabbix_templates/coverage.py sample-config/pgmon-metrics.yml zabbix_templates/pgmon_templates.yaml
# Create a tarball (openrc version)
tgz:
rm -rf $(BUILD_DIR)/tgz/root
mkdir -p $(BUILD_DIR)/tgz/root
$(MAKE) install-openrc DESTDIR=$(BUILD_DIR)/tgz/root
tar -cz -f $(BUILD_DIR)/tgz/$(PACKAGE_NAME)-$(FULL_VERSION).tgz -C $(BUILD_DIR)/tgz/root .
##
# Install targets
#
# These are mostly used by the various package building images to actually install the script
##
# Install the script at the specified base directory (common components) # Install the script at the specified base directory (common components)
.PHONY: install-common
install-common: install-common:
# Set up directories # Set up directories
mkdir -p $(DESTDIR)/etc/$(PACKAGE_NAME) mkdir -p $(DESTDIR)/etc/$(PACKAGE_NAME)
@@ -138,6 +127,7 @@ install-common:
cp logrotate/${PACKAGE_NAME}.logrotate ${DESTDIR}/etc/logrotate.d/${PACKAGE_NAME} cp logrotate/${PACKAGE_NAME}.logrotate ${DESTDIR}/etc/logrotate.d/${PACKAGE_NAME}
# Install for systemd # Install for systemd
.PHONY: install-systemd
install-systemd: install-systemd:
# Install the common stuff # Install the common stuff
$(MAKE) install-common $(MAKE) install-common
@@ -149,6 +139,7 @@ install-systemd:
cp systemd/* $(DESTDIR)/lib/systemd/system/ cp systemd/* $(DESTDIR)/lib/systemd/system/
# Install for open-rc # Install for open-rc
.PHONY: install-openrc
install-openrc: install-openrc:
# Install the common stuff # Install the common stuff
$(MAKE) install-common $(MAKE) install-common
@@ -165,10 +156,46 @@ install-openrc:
cp openrc/pgmon.confd $(DESTDIR)/etc/conf.d/pgmon cp openrc/pgmon.confd $(DESTDIR)/etc/conf.d/pgmon
# Run all of the install tests ##
.PHONY: install-tests debian-%-install-test rockylinux-%-install-test ubuntu-%-install-test gentoo-install-test # Packaging targets
install-tests: $(foreach distro_release, $(SUPPORTED), $(distro_release)-install-test) #
# These targets create packages for the supported distro versions
##
# Build all packages
.PHONY: package-all
package-all: all-package-images $(foreach distro_release, $(SUPPORTED), package-$(distro_release))
# Gentoo package (tar.bz2) creation
.PHONY: package-gentoo
package-gentoo:
mkdir -p $(BUILD_DIR)/gentoo
tar --transform "s,^,$(PACKAGE_NAME)-$(FULL_VERSION)/," -acjf $(BUILD_DIR)/gentoo/$(PACKAGE_NAME)-$(FULL_VERSION).tar.bz2 --exclude .gitignore $(shell git ls-tree --full-tree --name-only -r HEAD)
cp $(BUILD_DIR)/gentoo/$(PACKAGE_NAME)-$(FULL_VERSION).tar.bz2 $(BUILD_DIR)/
# Create a deb/rpm package
.PHONY: package-%
package-%: PARTS=$(subst -, ,$*)
package-%: DISTRO=$(word 1, $(PARTS))
package-%: RELEASE=$(word 2, $(PARTS))
package-%:
mkdir -p $(BUILD_DIR)
docker run --rm \
-v .:/src:ro \
-v ./$(BUILD_DIR):/output \
--user $(shell id -u):$(shell id -g) \
"$(DISTRO)-packager:$(RELEASE)"
##
# Install test targets
#
# These targets test installing the package on the supported distro versions
##
# Run all of the install tests
.PHONY: install-tests debian-%-install-test rockylinux-%-install-test ubuntu-%-install-test amazonlinux-%-install-test gentoo-install-test
install-tests: $(foreach distro_release, $(SUPPORTED), $(distro_release)-install-test)
# Run a Debian install test # Run a Debian install test
debian-%-install-test: debian-%-install-test:
@@ -181,7 +208,7 @@ debian-%-install-test:
rockylinux-%-install-test: rockylinux-%-install-test:
docker run --rm \ docker run --rm \
-v ./$(BUILD_DIR):/output \ -v ./$(BUILD_DIR):/output \
rockylinux:$* \ rockylinux/rockylinux:$* \
bash -c 'dnf makecache && dnf install -y /output/$(PACKAGE_NAME)-$(RPM_VERSION).el$*.noarch.rpm' bash -c 'dnf makecache && dnf install -y /output/$(PACKAGE_NAME)-$(RPM_VERSION).el$*.noarch.rpm'
# Run an Ubuntu install test # Run an Ubuntu install test
@@ -192,19 +219,30 @@ ubuntu-%-install-test:
bash -c 'apt-get update && apt-get install -y /output/$(PACKAGE_NAME)-$(DEB_VERSION)-ubuntu-$*.deb' bash -c 'apt-get update && apt-get install -y /output/$(PACKAGE_NAME)-$(DEB_VERSION)-ubuntu-$*.deb'
# Run an OracleLinux install test (this is for EL7 since CentOS7 images no longer exist) # Run an OracleLinux install test (this is for EL7 since CentOS7 images no longer exist)
oraclelinux-%-install-test: MGR=$(intcmp $*, 7, yum, yum, dnf)
oraclelinux-%-install-test: oraclelinux-%-install-test:
docker run --rm \ docker run --rm \
-v ./$(BUILD_DIR):/output \ -v ./$(BUILD_DIR):/output \
oraclelinux:7 \ oraclelinux:$* \
bash -c 'yum makecache && yum install -y /output/$(PACKAGE_NAME)-$(RPM_VERSION).el7.noarch.rpm' bash -c '$(MGR) makecache && $(MGR) install -y /output/$(PACKAGE_NAME)-$(RPM_VERSION).el7.noarch.rpm'
# Run a Amazon Linux install test
# Note: AL2 is too old for dnf
amazonlinux-%-install-test: MGR=$(intcmp $*, 2, yum, yum, dnf)
amazonlinux-%-install-test:
docker run --rm \
-v ./$(BUILD_DIR):/output \
amazonlinux:$* \
bash -c '$(MGR) makecache && $(MGR) install -y /output/$(PACKAGE_NAME)-$(RPM_VERSION).amzn$*.noarch.rpm'
# Run a Gentoo install test # Run a Gentoo install test
gentoo-install-test: gentoo-install-test:
# May impliment this in the future, but would require additional headaches to set up a repo # May impliment this in the future, but would require additional headaches to set up a repo
true echo "This would take a while ... skipping for now"
## ##
# Container targets # Packaging image targets
# #
# These targets build the docker images used to create packages # These targets build the docker images used to create packages
## ##
@@ -213,6 +251,11 @@ gentoo-install-test:
.PHONY: all-package-images .PHONY: all-package-images
all-package-images: $(foreach distro_release, $(SUPPORTED), package-image-$(distro_release)) all-package-images: $(foreach distro_release, $(SUPPORTED), package-image-$(distro_release))
# Nothing needs to be created to build te tarballs for Gentoo
.PHONY: package-image-gentoo
package-image-gentoo:
echo "Noting to do"
# Generic target for creating images that actually build the packages # Generic target for creating images that actually build the packages
# The % is expected to be: distro-release # The % is expected to be: distro-release
# The build/.package-image-% target actually does the work and touches a state file to avoid excessive building # The build/.package-image-% target actually does the work and touches a state file to avoid excessive building
@@ -228,11 +271,10 @@ package-image-%:
# Inside-container targets # Inside-container targets
# #
# These targets are used inside containers. They expect the repo to be mounted # These targets are used inside containers. They expect the repo to be mounted
# at /src and the package manager specific build directory to be mounted at # at /src and the build directory to be mounted at /output.
# /output.
## ##
.PHONY: actually-package-debian-% actually-package-rockylinux-% actually-package-ubuntu-% actually-package-oraclelinux-% .PHONY: actually-package-debian-% actually-package-rockylinux-% actually-package-ubuntu-% actually-package-oraclelinux-% actually-package-amazonlinux-%
# Debian package creation # Debian package creation
actually-package-debian-%: actually-package-debian-%:
@@ -256,10 +298,36 @@ actually-package-ubuntu-%:
dpkg-deb -Zgzip --build /output/ubuntu-$* "/output/$(PACKAGE_NAME)-$(DEB_VERSION)-ubuntu-$*.deb" dpkg-deb -Zgzip --build /output/ubuntu-$* "/output/$(PACKAGE_NAME)-$(DEB_VERSION)-ubuntu-$*.deb"
# OracleLinux package creation # OracleLinux package creation
# Note: This needs to work inside OEL7, so we can't use intcmp
actually-package-oraclelinux-7:
mkdir -p /output/oraclelinux-7/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
sed -e "s/@@VERSION@@/$(VERSION)/g" -e "s/@@RELEASE@@/$(RPM_RELEASE)/g" RPM/$(PACKAGE_NAME)-el7.spec > /output/oraclelinux-7/SPECS/$(PACKAGE_NAME).spec
rpmbuild --define '_topdir /output/oraclelinux-7' \
--define 'version $(RPM_VERSION)' \
-bb /output/oraclelinux-7/SPECS/$(PACKAGE_NAME).spec
cp /output/oraclelinux-7/RPMS/noarch/$(PACKAGE_NAME)-$(RPM_VERSION).el7.noarch.rpm /output/
actually-package-oraclelinux-%: actually-package-oraclelinux-%:
mkdir -p /output/oraclelinux-$*/{BUILD,RPMS,SOURCES,SPECS,SRPMS} mkdir -p /output/oraclelinux-$*/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
sed -e "s/@@VERSION@@/$(VERSION)/g" -e "s/@@RELEASE@@/$(RPM_RELEASE)/g" RPM/$(PACKAGE_NAME)-el7.spec > /output/oraclelinux-$*/SPECS/$(PACKAGE_NAME).spec sed -e "s/@@VERSION@@/$(VERSION)/g" -e "s/@@RELEASE@@/$(RPM_RELEASE)/g" RPM/$(PACKAGE_NAME).spec > /output/oraclelinux-$*/SPECS/$(PACKAGE_NAME).spec
rpmbuild --define '_topdir /output/oraclelinux-$*' \ rpmbuild --define '_topdir /output/oraclelinux-$*' \
--define 'version $(RPM_VERSION)' \ --define 'version $(RPM_VERSION)' \
-bb /output/oraclelinux-$*/SPECS/$(PACKAGE_NAME).spec -bb /output/oraclelinux-$*/SPECS/$(PACKAGE_NAME).spec
cp /output/oraclelinux-$*/RPMS/noarch/$(PACKAGE_NAME)-$(RPM_VERSION).el$*.noarch.rpm /output/ cp /output/oraclelinux-$*/RPMS/noarch/$(PACKAGE_NAME)-$(RPM_VERSION).el$*.noarch.rpm /output/
# Amazon Linux package creation
# Note: This needs to work inside AL2, so we can't use intcmp
actually-package-amazonlinux-2:
mkdir -p /output/amazonlinux-2/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
sed -e "s/@@VERSION@@/$(VERSION)/g" -e "s/@@RELEASE@@/$(RPM_RELEASE)/g" RPM/$(PACKAGE_NAME)-el7.spec > /output/amazonlinux-2/SPECS/$(PACKAGE_NAME).spec
rpmbuild --define '_topdir /output/amazonlinux-2' \
--define 'version $(RPM_VERSION)' \
-bb /output/amazonlinux-2/SPECS/$(PACKAGE_NAME).spec
cp /output/amazonlinux-2/RPMS/noarch/$(PACKAGE_NAME)-$(RPM_VERSION).amzn2.noarch.rpm /output/
actually-package-amazonlinux-%:
mkdir -p /output/amazonlinux-$*/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
sed -e "s/@@VERSION@@/$(VERSION)/g" -e "s/@@RELEASE@@/$(RPM_RELEASE)/g" RPM/$(PACKAGE_NAME).spec > /output/amazonlinux-$*/SPECS/$(PACKAGE_NAME).spec
rpmbuild --define '_topdir /output/amazonlinux-$*' \
--define 'version $(RPM_VERSION)' \
-bb /output/amazonlinux-$*/SPECS/$(PACKAGE_NAME).spec
cp /output/amazonlinux-$*/RPMS/noarch/$(PACKAGE_NAME)-$(RPM_VERSION).amzn$*.noarch.rpm /output/

View File

@@ -0,0 +1,22 @@
# Dockerfile.rpm
ARG DISTRO=amazonlinux
ARG RELEASE=2023
FROM ${DISTRO}:${RELEASE}
ARG DISTRO
ARG RELEASE
RUN if [ ${RELEASE} -le 2 ] ; then MGR=yum ; else MGR=dnf ; fi && \
${MGR} install -y \
rpm-build \
make \
&& ${MGR} clean all
RUN echo -e "#!/bin/bash\nmake actually-package-${DISTRO}-${RELEASE}" > /init.sh \
&& chmod 755 /init.sh
WORKDIR /src
CMD ["/bin/bash", "/init.sh"]

View File

@@ -8,11 +8,12 @@ FROM ${DISTRO}:${RELEASE}
ARG DISTRO ARG DISTRO
ARG RELEASE ARG RELEASE
RUN yum install -y \ RUN if [ ${RELEASE} -le 7 ] ; then MGR=yum ; else MGR=dnf ; fi && \
${MGR} install -y \
rpm-build \ rpm-build \
make \ make \
oracle-epel-release-el7 \ oracle-epel-release-el${RELEASE} \
&& yum clean all && ${MGR} clean all
RUN echo -e "#!/bin/bash\nmake actually-package-${DISTRO}-${RELEASE}" > /init.sh \ RUN echo -e "#!/bin/bash\nmake actually-package-${DISTRO}-${RELEASE}" > /init.sh \
&& chmod 755 /init.sh && chmod 755 /init.sh

View File

@@ -3,7 +3,7 @@
ARG DISTRO=rockylinux ARG DISTRO=rockylinux
ARG RELEASE=9 ARG RELEASE=9
FROM ${DISTRO}:${RELEASE} FROM rockylinux/${DISTRO}:${RELEASE}
ARG DISTRO ARG DISTRO
ARG RELEASE ARG RELEASE

View File

@@ -116,6 +116,63 @@ metrics:
FROM pg_stat_io FROM pg_stat_io
GROUP BY backend_type GROUP BY backend_type
temp_files:
type: row
query:
120000: >
SELECT count(*) AS count,
coalesce(sum(size), 0) AS size
FROM pg_ls_tmpdir()
WHERE name LIKE 'pgsql_tmp%%'
90500: >
SELECT count(*) AS count,
coalesce(sum((pg_stat_file(name)).size), 0) AS size
FROM pg_ls_dir('base/pgsql_tmp/', true, false) AS name
WHERE name LIKE 'pgsql_tmp%%'
0: >
SELECT count(*) AS count,
coalesce(sum((pg_stat_file(files.name)).size), 0) AS size
FROM (
SELECT name
FROM pg_ls_dir('base') AS name
WHERE name = 'pgsql_tmp') AS dir
LEFT JOIN (
SELECT name
FROM pg_ls_dir('base/pgsql_tmp/') AS name
WHERE name LIKE 'pgsql_tmp%%') AS files
ON dir.name IS NOT NULL
ready_archive_files:
type: value
query:
120000: >
SELECT count(*) AS count
FROM pg_ls_archive_statusdir()
WHERE name LIKE '%%.ready'
100000: >
SELECT count(*) AS count
FROM pg_ls_dir('pg_wal/archive_status/', true, false) AS name
WHERE name LIKE '%%.ready'
90500: >
SELECT count(*) AS count
FROM pg_ls_dir('pg_xlog/archive_status/', true, false) AS name
WHERE name LIKE '%%.ready'
0: >
SELECT
CASE WHEN (
SELECT count(*)
FROM pg_ls_dir('pg_xlog/') AS f
WHERE f = 'archive_status') = 0
THEN (
SELECT 0 AS count
)
ELSE (
SELECT count(*) AS count
FROM pg_ls_dir('pg_xlog/archive_status/') AS name
WHERE name LIKE '%%.ready')
END
## ##
# Per-database metrics # Per-database metrics
@@ -196,12 +253,28 @@ metrics:
type: set type: set
query: query:
0: > 0: >
SELECT state, SELECT
count(*) AS backend_count, states.state,
COALESCE(EXTRACT(EPOCH FROM max(now() - state_change)), 0) AS max_state_time COALESCE(a.backend_count, 0) AS backend_count,
FROM pg_stat_activity COALESCE(a.max_state_time, 0) AS max_state_time
WHERE datname = %(dbname)s FROM (
GROUP BY state SELECT state,
count(*) AS backend_count,
COALESCE(EXTRACT(EPOCH FROM now() - min(state_change)), 0) AS max_state_time
FROM pg_stat_activity
WHERE datname = %(dbname)s
GROUP BY state
) AS a
RIGHT JOIN
unnest(ARRAY[
'active',
'idle',
'idle in transaction',
'idle in transaction (aborted)',
'fastpath function call',
'disabled'
]) AS states(state)
USING (state);
test_args: test_args:
dbname: postgres dbname: postgres
@@ -235,7 +308,7 @@ metrics:
locks: locks:
type: row type: row
query: query:
0: 0: >
SELECT COUNT(*) AS total, SELECT COUNT(*) AS total,
SUM(CASE WHEN granted THEN 1 ELSE 0 END) AS granted SUM(CASE WHEN granted THEN 1 ELSE 0 END) AS granted
FROM pg_locks FROM pg_locks
@@ -318,3 +391,5 @@ metrics:
type: value type: value
query: query:
0: SELECT count(*) AS ntables FROM pg_stat_user_tables 0: SELECT count(*) AS ntables FROM pg_stat_user_tables
#sequence_usage:

View File

@@ -37,7 +37,7 @@ from psycopg2.pool import ThreadedConnectionPool
import requests import requests
VERSION = "1.0.4" VERSION = "1.1.0-rc1"
class Context: class Context:

View File

@@ -20,7 +20,7 @@ services:
POSTGRES_PASSWORD: secret POSTGRES_PASSWORD: secret
healthcheck: healthcheck:
#test: [ "CMD", "pg_isready", "-U", "postgres" ] #test: [ "CMD", "pg_isready", "-U", "postgres" ]
test: [ "CMD-SHELL", "pg_controldata /var/lib/postgresql/data/ | grep -q 'in production'" ] test: [ "CMD-SHELL", "pg_controldata $(psql -At -U postgres -c 'show data_directory') | grep -q 'in production'" ]
interval: 5s interval: 5s
timeout: 2s timeout: 2s
retries: 40 retries: 40

View File

@@ -24,6 +24,7 @@ images["14"]='14-bookworm'
images["15"]='15-bookworm' images["15"]='15-bookworm'
images["16"]='16-bookworm' images["16"]='16-bookworm'
images["17"]='17-bookworm' images["17"]='17-bookworm'
images["18"]='18-trixie'
declare -A results=() declare -A results=()

View File

@@ -49,6 +49,206 @@ zabbix_export:
tags: tags:
- tag: Application - tag: Application
value: PostgreSQL value: PostgreSQL
- uuid: 1dd74025ca0e463bb9eee5cb473f30db
name: 'Total buffers allocated'
type: DEPENDENT
key: 'pgmon.bgwriter[buffers_alloc,total]'
delay: '0'
history: 90d
description: 'Total number of shared buffers that have been allocated'
preprocessing:
- type: JSONPATH
parameters:
- $.buffers_alloc
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: 4ab405996e71444a8113b95c65d73be2
name: 'Total buffers written by backends'
type: DEPENDENT
key: 'pgmon.bgwriter[buffers_backend,total]'
delay: '0'
history: 90d
description: 'Total number of shared buffers written by backends'
preprocessing:
- type: JSONPATH
parameters:
- $.buffers_backend
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: e8b440a1d6ff4ca6b3cb27e2e76f9d06
name: 'Total number of fsyncs from backends'
type: DEPENDENT
key: 'pgmon.bgwriter[buffers_backend_fsync,total]'
delay: '0'
history: 90d
description: 'Total number of times backends have issued their own fsync calls'
preprocessing:
- type: JSONPATH
parameters:
- $.buffers_backend_fsync
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: f8a14885edf34b5cbf2e92432e8fa4c2
name: 'Total buffers written during checkpoints'
type: DEPENDENT
key: 'pgmon.bgwriter[buffers_checkpoint,total]'
delay: '0'
history: 90d
description: 'Total number of shared buffers written during checkpoints'
preprocessing:
- type: JSONPATH
parameters:
- $.buffers_checkpoint
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: f09956f7aaad4b99b0d67339edf26dcf
name: 'Total buffers written by the background writer'
type: DEPENDENT
key: 'pgmon.bgwriter[buffers_clean,total]'
delay: '0'
history: 90d
description: 'Total number of shared buffers written by the background writer'
preprocessing:
- type: JSONPATH
parameters:
- $.buffers_clean
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: f1c6bd9346b14964bd492d7ccf8baf50
name: 'Total checkpoints due to changes'
type: DEPENDENT
key: 'pgmon.bgwriter[checkpoints_changes,total]'
delay: '0'
history: 90d
description: 'Total number of checkpoints that have occurred due to the number of row changes'
preprocessing:
- type: JSONPATH
parameters:
- $.checkpoints_req
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: 04c4587d2f2f4f5fbad866d70938cbb3
name: 'Total checkpoints due to time limit'
type: DEPENDENT
key: 'pgmon.bgwriter[checkpoints_timed,total]'
delay: '0'
history: 90d
description: 'Total number of checkpoints that have occurred due to the configured time limit'
preprocessing:
- type: JSONPATH
parameters:
- $.checkpoints_timed
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: 580a7e632b644aafa1166c534185ba92
name: 'Total time spent syncing files for checkpoints'
type: DEPENDENT
key: 'pgmon.bgwriter[checkpoint_sync_time,total]'
delay: '0'
history: 90d
units: s
description: 'Total time spent syncing files for checkpoints'
preprocessing:
- type: JSONPATH
parameters:
- $.checkpoint_sync_time
- type: MULTIPLIER
parameters:
- '0.001'
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: 4faa33b55fae4fc68561020636573a46
name: 'Total time spent writing checkpoints'
type: DEPENDENT
key: 'pgmon.bgwriter[checkpoint_write_time,total]'
delay: '0'
history: 90d
units: s
description: 'Total time spent writing checkpoints'
preprocessing:
- type: JSONPATH
parameters:
- $.checkpoint_write_time
- type: MULTIPLIER
parameters:
- '0.001'
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: c0c829c6cdc046a4b5d216e10362e4bb
name: 'Total number of times the background writer stopped'
type: DEPENDENT
key: 'pgmon.bgwriter[maxwritten_clean,total]'
delay: '0'
history: 90d
description: 'Total number of times the background writer stopped due to reaching the maximum number of buffers it''s allowed to write in a single scan'
preprocessing:
- type: JSONPATH
parameters:
- $.maxwritten_clean
master_item:
key: 'pgmon[bgwriter]'
tags:
- tag: Application
value: PostgreSQL
- uuid: 645fef7b55cd48c69b11de3201e88d78
name: 'Number of locks'
type: DEPENDENT
key: pgmon.locks.count
delay: '0'
history: 90d
description: 'Total number of locks in any database'
preprocessing:
- type: JSONPATH
parameters:
- $.total
master_item:
key: 'pgmon[locks]'
tags:
- tag: Application
value: PostgreSQL
- uuid: a56ad753b1f341928867a47b14ed8b77
name: 'Number of granted locks'
type: DEPENDENT
key: pgmon.locks.granted
delay: '0'
history: 90d
description: 'Total number of granted locks in any database'
preprocessing:
- type: JSONPATH
parameters:
- $.granted
master_item:
key: 'pgmon[locks]'
tags:
- tag: Application
value: PostgreSQL
- uuid: de1fa757395440118026f4c7a7c4ebbe - uuid: de1fa757395440118026f4c7a7c4ebbe
name: 'PostgreSQL latest supported version' name: 'PostgreSQL latest supported version'
type: DEPENDENT type: DEPENDENT
@@ -82,6 +282,39 @@ zabbix_export:
expression: 'last(/PostgreSQL by pgmon/pgmon.release.supported)<>1' expression: 'last(/PostgreSQL by pgmon/pgmon.release.supported)<>1'
name: 'PostgreSQL major release is lo longer supported' name: 'PostgreSQL major release is lo longer supported'
priority: INFO priority: INFO
- uuid: d0651ffc203949e3a24b1e1a2beb3dd7
name: 'Temp file size'
type: DEPENDENT
key: 'pgmon.temp_files[bytes]'
delay: '0'
history: 90d
units: b
description: 'Total size of all temp files'
preprocessing:
- type: JSONPATH
parameters:
- $.size
master_item:
key: 'pgmon[temp_files]'
tags:
- tag: Application
value: PostgreSQL
- uuid: deb355b26c37441189c85ac82465f21e
name: 'Temp file count'
type: DEPENDENT
key: 'pgmon.temp_files[count]'
delay: '0'
history: 90d
description: 'Total number of temp flies'
preprocessing:
- type: JSONPATH
parameters:
- $.count
master_item:
key: 'pgmon[temp_files]'
tags:
- tag: Application
value: PostgreSQL
- uuid: 763920af8da84db8a9a2667d9653cb21 - uuid: 763920af8da84db8a9a2667d9653cb21
name: 'PostgreSQL Agent Version' name: 'PostgreSQL Agent Version'
type: HTTP_AGENT type: HTTP_AGENT
@@ -95,6 +328,32 @@ zabbix_export:
tags: tags:
- tag: Application - tag: Application
value: PostgreSQL value: PostgreSQL
- uuid: a0bd4a987b7643c5a86e160dd9f9afcb
name: 'PostgreSQL Archive ready count'
type: HTTP_AGENT
key: 'pgmon[archive_ready]'
history: 90d
trends: '0'
description: 'Number of WAL files ready and waiting to be archived'
url: 'http://localhost:{$AGENT_PORT}/ready_archive_files'
tags:
- tag: Application
value: PostgreSQL
- uuid: 91baea76ebb240b19c5a5d3913d0b989
name: 'PostgreSQL BGWriter Info'
type: HTTP_AGENT
key: 'pgmon[bgwriter]'
delay: 5m
history: '0'
value_type: TEXT
trends: '0'
description: 'Maximum age of any frozen XID and MXID in any database'
url: 'http://localhost:{$AGENT_PORT}/bgwriter'
tags:
- tag: Application
value: PostgreSQL
- tag: Type
value: Raw
- uuid: 06b1d082ed1e4796bc31cc25f7db6326 - uuid: 06b1d082ed1e4796bc31cc25f7db6326
name: 'PostgreSQL Backend IO Info' name: 'PostgreSQL Backend IO Info'
type: HTTP_AGENT type: HTTP_AGENT
@@ -124,6 +383,21 @@ zabbix_export:
value: PostgreSQL value: PostgreSQL
- tag: Type - tag: Type
value: Raw value: Raw
- uuid: 4627c156923f4d53bc04789b9b88c133
name: 'PostgreSQL Lock Info'
type: HTTP_AGENT
key: 'pgmon[locks]'
delay: 5m
history: '0'
value_type: TEXT
trends: '0'
description: 'Maximum age of any frozen XID and MXID in any database'
url: 'http://localhost:{$AGENT_PORT}/locks'
tags:
- tag: Application
value: PostgreSQL
- tag: Type
value: Raw
- uuid: 8706eccb7edc4fa394f552fc31f401a9 - uuid: 8706eccb7edc4fa394f552fc31f401a9
name: 'PostgreSQL ID Age Info' name: 'PostgreSQL ID Age Info'
type: HTTP_AGENT type: HTTP_AGENT
@@ -139,6 +413,20 @@ zabbix_export:
value: PostgreSQL value: PostgreSQL
- tag: Type - tag: Type
value: Raw value: Raw
- uuid: bd3026ef3b82419d8a004e2d4684554a
name: 'PostgreSQL Temp Ffle info'
type: HTTP_AGENT
key: 'pgmon[temp_files]'
history: '0'
value_type: TEXT
trends: '0'
description: 'PostgreSQL temp file stats'
url: 'http://localhost:{$AGENT_PORT}/temp_files'
tags:
- tag: Application
value: PostgreSQL
- tag: Type
value: Raw
- uuid: ee88f5f4d2384f97946d049af5af4502 - uuid: ee88f5f4d2384f97946d049af5af4502
name: 'PostgreSQL version' name: 'PostgreSQL version'
type: HTTP_AGENT type: HTTP_AGENT
@@ -170,6 +458,283 @@ zabbix_export:
enabled_lifetime_type: DISABLE_AFTER enabled_lifetime_type: DISABLE_AFTER
enabled_lifetime: 1d enabled_lifetime: 1d
item_prototypes: item_prototypes:
- uuid: 28d5fe3a4f6848149afed33aa645f677
name: 'Max connection age: active on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[active,age,{#DBNAME}]'
delay: '0'
history: 90d
value_type: FLOAT
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "active")].max_state_time.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: ff1b817c3d1f43dc8b49bfd0dcb0d10a
name: 'Connection count: active on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[active,count,{#DBNAME}]'
delay: '0'
history: 90d
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "active")].backend_count.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 4c0b9ca43adb45b895e3ba2e200e501e
name: 'Max connection age: disabled on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[disabled,age,{#DBNAME}]'
delay: '0'
history: 90d
value_type: FLOAT
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "disabled")].max_state_time.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 280dfc9a84e8425399164e6f3e91cf92
name: 'Connection count: disabled on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[disabled,count,{#DBNAME}]'
delay: '0'
history: 90d
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "disabled")].backend_count.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 63e62108657f47aaa29f7ec6499e45fc
name: 'Max connection age: fastpath function call on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[fastpath_function,age,{#DBNAME}]'
delay: '0'
history: 90d
value_type: FLOAT
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "fastpath function call")].max_state_time.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 33193e62f1ad4da5b2e30677581e5305
name: 'Connection count: fastpath function call on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[fastpath_function,count,{#DBNAME}]'
delay: '0'
history: 90d
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "fastpath function call")].backend_count.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 92e2366a56424bc18a88606417eae6e4
name: 'Max connection age: idle on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[idle,age,{#DBNAME}]'
delay: '0'
history: 90d
value_type: FLOAT
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "idle")].max_state_time.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 505bbbb4c7b745d8bab8f3b33705b76b
name: 'Connection count: idle on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[idle,count,{#DBNAME}]'
delay: '0'
history: 90d
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "idle")].backend_count.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 282494d5900c4c2e8abd298160c7cbb6
name: 'Max connection age: idle in transaction (aborted) on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[idle_aborted,age,{#DBNAME}]'
delay: '0'
history: 90d
value_type: FLOAT
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "idle in transaction (aborted)")].max_state_time.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 0da5075d79234602836fc7967a31f1cc
name: 'Connection count: idle in transaction (aborted) on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[idle_aborted,count,{#DBNAME}]'
delay: '0'
history: 90d
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "idle in transaction (aborted)")].backend_count.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 47aa3f7f4ff1473aae425b4c89472ab4
name: 'Max connection age: idle in transaction on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[idle_transaction,age,{#DBNAME}]'
delay: '0'
history: 90d
value_type: FLOAT
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "idle in transaction")].max_state_time.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 95519bf0aefd49799601e1bbb488ec90
name: 'Connection count: idle in transaction on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[idle_transaction,count,{#DBNAME}]'
delay: '0'
history: 90d
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "idle in transaction")].backend_count.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: b2ae38a5733d49ceb1a31e774c11785b
name: 'Max connection age: starting on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[starting,age,{#DBNAME}]'
delay: '0'
history: 90d
value_type: FLOAT
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "starting")].max_state_time.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: c1890f2d7ce84a7ebaaadf266d3ffc51
name: 'Connection count: starting on {#DBNAME}'
type: DEPENDENT
key: 'pgmon_connection_states[starting,count,{#DBNAME}]'
delay: '0'
history: 90d
description: 'Number of disk blocks read in this database'
preprocessing:
- type: JSONPATH
parameters:
- '$[?(@.state == "starting")].backend_count.first()'
master_item:
key: 'pgmon_connection_states[{#DBNAME}]'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- uuid: 131653f883f448a7b861b16bc4366dfd
name: 'Database Connection States for {#DBNAME}'
type: HTTP_AGENT
key: 'pgmon_connection_states[{#DBNAME}]'
history: '0'
value_type: TEXT
trends: '0'
url: 'http://localhost:{$AGENT_PORT}/activity'
query_fields:
- name: dbname
value: '{#DBNAME}'
tags:
- tag: Application
value: PostgreSQL
- tag: Database
value: '{#DBNAME}'
- tag: Type
value: Raw
- uuid: a30babe4a6f4440bba2a3ee46eff7ce2 - uuid: a30babe4a6f4440bba2a3ee46eff7ce2
name: 'Time spent executing statements on {#DBNAME}' name: 'Time spent executing statements on {#DBNAME}'
type: DEPENDENT type: DEPENDENT