Compare commits

...

25 Commits

Author SHA1 Message Date
39c34ee31f
wip 2026-03-15 23:54:27 -04:00
65f01ea826
Implement FUSE interface using pyfuse 2026-02-04 00:36:54 -05:00
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
3ade30c04a
Add script to shot tempalte coverage
* Add a script to compare the defined metrics with those used in the
  Zabbix template.

* Add a Makefile target to run the above script.
2025-10-09 02:21:17 -04:00
ab039dc412
Improve test coverage
* Refactor some functions to improve unit test coverage.

* Use the "coverage" module if available along with unit tests.
2025-10-08 23:53:45 -04:00
75c5d76047
Add a metric for tracking the number of granted locks 2025-09-23 01:14:50 -04:00
43cd162313
Refactor to make pylint happy 2025-09-23 01:12:49 -04:00
29bfd07dad
Run code through black 2025-07-14 01:58:08 -04:00
60589c2058
Update undiscovered item behavior 2025-07-14 01:39:57 -04:00
ea3aca3455
Filter out initial logical replication sync workers
* Slots are crated for each table during the initial sync, which only
  live for the duration of the copy for that table.

* The initial sync backend workers' names are also based on the table
  being copied.

* Filter out the above in Zabbix discovery based on application_name and
  slot_name.
2025-07-07 13:15:03 -04:00
cc71547f5f
Include application_name in replication discovery data 2025-07-07 13:07:11 -04:00
107d5056d6
Merge branch 'main' into develop 2025-07-06 03:37:37 -04:00
16 changed files with 2233 additions and 527 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ missing
__pycache__
venv
build
.coverage

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
}

185
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')
RELEASE := $(shell echo $(FULL_VERSION) | sed -n 's/.*-rc\([0-9]\+\)$$/\1/p')
# Package version formatting
ifeq ($(RELEASE),)
RPM_RELEASE := 1
RPM_VERSION := $(VERSION)-$(RPM_RELEASE)
@ -19,6 +20,12 @@ RPM_VERSION := $(VERSION)-$(RPM_RELEASE)
DEB_VERSION := $(VERSION)~rc$(RELEASE)
endif
# Python stuff
PYTHON ?= python3
PYLINT ?= pylint
BLACK ?= black
HAVE_COVERAGE := $(shell $(PYTHON) -c 'import coverage' 2>/dev/null && echo yes)
# Where packages are built
BUILD_DIR := build
@ -27,68 +34,77 @@ BUILD_DIR := build
SUPPORTED := ubuntu-20.04 \
ubuntu-22.04 \
ubuntu-24.04 \
debian-10 \
debian-11 \
debian-12 \
debian-13 \
rockylinux-8 \
rockylinux-9 \
rockylinux-10 \
oraclelinux-7 \
amazonlinux-2 \
amazonlinux-2023 \
gentoo
##
# These targets are the main ones to use for most things.
##
.PHONY: all clean tgz test query-tests install-common install-openrc install-systemd
.PHONY: all clean tgz lint format test query-tests template-coverage
all: package-all
# Dump information related to the current version
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))
# Clean up the build directory
clean:
rm -rf $(BUILD_DIR)
# 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)
# Check for lint
lint:
$(PYLINT) src/pgmon.py
$(PYLINT) src/test_pgmon.py
$(BLACK) --check --diff src/pgmon.py
$(BLACK) --check --diff src/test_pgmon.py
# Format the code using black
format:
$(BLACK) src/pgmon.py
$(BLACK) src/test_pgmon.py
# 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)"
# Run unit tests for the script (with coverage if it's available)
test:
ifeq ($(HAVE_COVERAGE),yes)
cd src ; $(PYTHON) -m coverage run -m unittest && python3 -m coverage report -m
else
cd src ; $(PYTHON) -m unittest
endif
# Create a tarball
# Run query tests
query-tests:
cd tests ; ./run-tests.sh
# Compare the sample metrics with the Zabbix template
template-coverage:
$(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 .
# Clean up the build directory
clean:
rm -rf $(BUILD_DIR)
# Run unit tests for the script
test:
cd src ; python3 -m unittest
# Run query tests
query-tests:
cd tests ; ./run-tests.sh
##
# 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)
.PHONY: install-common
install-common:
# Set up directories
mkdir -p $(DESTDIR)/etc/$(PACKAGE_NAME)
@ -111,6 +127,7 @@ install-common:
cp logrotate/${PACKAGE_NAME}.logrotate ${DESTDIR}/etc/logrotate.d/${PACKAGE_NAME}
# Install for systemd
.PHONY: install-systemd
install-systemd:
# Install the common stuff
$(MAKE) install-common
@ -122,6 +139,7 @@ install-systemd:
cp systemd/* $(DESTDIR)/lib/systemd/system/
# Install for open-rc
.PHONY: install-openrc
install-openrc:
# Install the common stuff
$(MAKE) install-common
@ -138,10 +156,46 @@ install-openrc:
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
install-tests: $(foreach distro_release, $(SUPPORTED), $(distro_release)-install-test)
##
# Packaging targets
#
# 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
debian-%-install-test:
@ -154,7 +208,7 @@ debian-%-install-test:
rockylinux-%-install-test:
docker run --rm \
-v ./$(BUILD_DIR):/output \
rockylinux:$* \
rockylinux/rockylinux:$* \
bash -c 'dnf makecache && dnf install -y /output/$(PACKAGE_NAME)-$(RPM_VERSION).el$*.noarch.rpm'
# Run an Ubuntu install test
@ -165,19 +219,30 @@ ubuntu-%-install-test:
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)
oraclelinux-%-install-test: MGR=$(intcmp $*, 7, yum, yum, dnf)
oraclelinux-%-install-test:
docker run --rm \
-v ./$(BUILD_DIR):/output \
oraclelinux:7 \
bash -c 'yum makecache && yum install -y /output/$(PACKAGE_NAME)-$(RPM_VERSION).el7.noarch.rpm'
oraclelinux:$* \
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
gentoo-install-test:
# 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
##
@ -186,6 +251,11 @@ gentoo-install-test:
.PHONY: all-package-images
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
# 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
@ -201,11 +271,10 @@ package-image-%:
# Inside-container targets
#
# 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
# /output.
# at /src and the build directory to be mounted at /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
actually-package-debian-%:
@ -229,10 +298,36 @@ actually-package-ubuntu-%:
dpkg-deb -Zgzip --build /output/ubuntu-$* "/output/$(PACKAGE_NAME)-$(DEB_VERSION)-ubuntu-$*.deb"
# 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-%:
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-$*' \
--define 'version $(RPM_VERSION)' \
-bb /output/oraclelinux-$*/SPECS/$(PACKAGE_NAME).spec
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 RELEASE
RUN yum install -y \
RUN if [ ${RELEASE} -le 7 ] ; then MGR=yum ; else MGR=dnf ; fi && \
${MGR} install -y \
rpm-build \
make \
oracle-epel-release-el7 \
&& yum clean all
oracle-epel-release-el${RELEASE} \
&& ${MGR} clean all
RUN echo -e "#!/bin/bash\nmake actually-package-${DISTRO}-${RELEASE}" > /init.sh \
&& chmod 755 /init.sh

View File

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

4
pylintrc Normal file
View File

@ -0,0 +1,4 @@
[MASTER]
py-version=3.5
disable=fixme

View File

@ -1,2 +1,4 @@
psycopg
psycopg2
pyyaml
llfuse
requests

View File

@ -18,6 +18,7 @@ metrics:
query:
0: >
SELECT host(client_addr) || '_' || regexp_replace(application_name, '[ ,]', '_', 'g') AS repid,
application_name,
client_addr,
state
FROM pg_stat_replication
@ -115,6 +116,63 @@ metrics:
FROM pg_stat_io
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
@ -195,12 +253,28 @@ metrics:
type: set
query:
0: >
SELECT
states.state,
COALESCE(a.backend_count, 0) AS backend_count,
COALESCE(a.max_state_time, 0) AS max_state_time
FROM (
SELECT state,
count(*) AS backend_count,
COALESCE(EXTRACT(EPOCH FROM max(now() - state_change)), 0) AS max_state_time
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:
dbname: postgres
@ -229,7 +303,19 @@ metrics:
SELECT COUNT(*) FILTER (WHERE has_sequence_privilege(c.oid, 'SELECT,USAGE')) AS visible_sequences,
COUNT(*) AS total_sequences
FROM pg_class AS c
WHERE relkind = 'S';
WHERE relkind = 'S'
locks:
type: row
query:
0: >
SELECT COUNT(*) AS total,
SUM(CASE WHEN granted THEN 1 ELSE 0 END) AS granted
FROM pg_locks
90400: >
SELECT COUNT(*) AS total,
COUNT(*) FILTER (WHERE granted) AS granted
FROM pg_locks
##
@ -305,3 +391,5 @@ metrics:
type: value
query:
0: SELECT count(*) AS ntables FROM pg_stat_user_tables
#sequence_usage:

View File

@ -1,8 +1,22 @@
# The address the agent binds to
#address: 127.0.0.1
# # The name for this agent instance (controles the FUSE directory name)
#name: pgmon
# The port the agent listens on for requests
#port: 5400
# Mode to set on FUSE files (in octal)
#fuse_mode: 0o400
# Owner to set on FUSE files
#fuse_owner: zabbix
fuse_owner: james
# Group to set on FUSE files
#fuse_group: zabbix
fuse_group: james
# User the agent runs as
agent_user: james
# Groupthe agent runs as
agent_group: james
# Min PostgreSQL connection pool size (per database)
#min_pool_size: 0
@ -16,21 +30,28 @@
# Log level for stderr logging (see https://docs.python.org/3/library/logging.html#logging-levels)
# Possible values are: debug, info, warning, error, critical
#log_level: 'error'
log_level: 'info'
# Base directory for FUSE file system
fuse_base: /tmp/pgmon
# Database user to connect as
#dbuser: 'postgres'
# Database host
#dbhost: '/var/run/postgresql'
dbhost: 127.0.0.1
# Database port
#dbport: 5432
dbport: 54315
# Default database to connect to when none is specified for a metric
#dbname: 'postgres'
# SSL connection mode
#ssl_mode: require
ssl_mode: allow
# Timeout for getting a connection slot from a pool
#pool_slot_timeout: 5

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@ services:
POSTGRES_PASSWORD: secret
healthcheck:
#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
timeout: 2s
retries: 40

View File

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

129
zabbix_templates/coverage.py Executable file
View File

@ -0,0 +1,129 @@
#!/usr/bin/env python3
# Compare the items defined in a Zabbix template with the metrics defined in a config file.
import sys
import yaml
# Special built in metrics
SPECIAL = {
"agent_version",
"latest_version_info"
}
class NonMetricItemError(Exception):
"""
A given item does not directly use a metric
"""
def read_metrics(file):
"""
Read the metrics from a config file and return the list of names
params:
file: the name of the file to read
returns:
list of metric named defined in the file
raises:
yaml.parser.ParserError: invalid yaml file
"""
names = set()
config = None
with open(file, "r", encoding="utf-8") as f:
config = yaml.safe_load(f)
try:
for m in config["metrics"].keys():
names.add(m)
except KeyError:
pass
return names
def extract_metric(item):
"""
Extract the metric from an item definition
params:
item: the item/discovery/prototype definition dict
returns:
the name of the metric used in the item
raises:
NonMetricItemError: the item does not directly use a metric
"""
try:
if item["type"] == "HTTP_AGENT":
url = item["url"]
if url.startswith("http://localhost:{$AGENT_PORT}"):
return url.split("/")[-1]
except KeyError:
raise NonMetricItemError()
raise NonMetricItemError()
def read_template(file):
"""
Read the items from a Zabbix template and return the list of metric names
params:
file: the name of the file to read
returns:
list of metric named used in the file
raises:
yaml.parser.ParserError: invalid yaml file
"""
names = set()
config = None
with open(file, "r", encoding="utf-8") as f:
config = yaml.safe_load(f)
try:
for template in config["zabbix_export"]["templates"]:
for item in template["items"]:
try:
names.add(extract_metric(item))
except NonMetricItemError:
pass
for rule in template["discovery_rules"]:
try:
names.add(extract_metric(rule))
except NonMetricItemError:
pass
for proto in rule["item_prototypes"]:
try:
names.add(extract_metric(proto))
except NonMetricItemError:
pass
except KeyError:
pass
return names
if __name__ == '__main__':
config_file = sys.argv[1]
config_metrics = read_metrics(config_file)
template_file = sys.argv[2]
template_metrics = read_template(template_file) - SPECIAL
config_only = config_metrics - template_metrics
template_only = template_metrics - config_metrics
print("Config only: {}".format(sorted(list(config_only))))
print("Template only: {}".format(sorted(list(template_only))))

View File

@ -49,6 +49,206 @@ zabbix_export:
tags:
- tag: Application
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
name: 'PostgreSQL latest supported version'
type: DEPENDENT
@ -82,6 +282,39 @@ zabbix_export:
expression: 'last(/PostgreSQL by pgmon/pgmon.release.supported)<>1'
name: 'PostgreSQL major release is lo longer supported'
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
name: 'PostgreSQL Agent Version'
type: HTTP_AGENT
@ -95,6 +328,32 @@ zabbix_export:
tags:
- tag: Application
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
name: 'PostgreSQL Backend IO Info'
type: HTTP_AGENT
@ -124,6 +383,21 @@ zabbix_export:
value: PostgreSQL
- tag: Type
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
name: 'PostgreSQL ID Age Info'
type: HTTP_AGENT
@ -139,6 +413,20 @@ zabbix_export:
value: PostgreSQL
- tag: Type
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
name: 'PostgreSQL version'
type: HTTP_AGENT
@ -167,8 +455,286 @@ zabbix_export:
operator: NOT_MATCHES_REGEX
formulaid: A
lifetime: 30d
enabled_lifetime_type: DISABLE_NEVER
enabled_lifetime_type: DISABLE_AFTER
enabled_lifetime: 1d
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
name: 'Time spent executing statements on {#DBNAME}'
type: DEPENDENT
@ -982,6 +1548,9 @@ zabbix_export:
type: DEPENDENT
key: pgmon_discover_io_backend_types
delay: '0'
lifetime: 30d
enabled_lifetime_type: DISABLE_AFTER
enabled_lifetime: 1h
item_prototypes:
- uuid: b1ac2e56b30f4812bf33ce973ef16b10
name: 'I/O Evictions by {#BACKEND_TYPE}'
@ -1572,8 +2141,15 @@ zabbix_export:
type: HTTP_AGENT
key: pgmon_discover_rep
delay: 10m
filter:
conditions:
- macro: '{#APPLICATION_NAME}'
value: '^pg_[0-9]+_sync_[0-9]+_[0-9]+$'
operator: NOT_MATCHES_REGEX
formulaid: A
lifetime: 30d
enabled_lifetime_type: DISABLE_NEVER
enabled_lifetime_type: DISABLE_AFTER
enabled_lifetime: 7d
item_prototypes:
- uuid: 3a5a60620e6a4db694e47251148d82f5
name: 'Flush lag for {#REPID}'
@ -1775,6 +2351,8 @@ zabbix_export:
value: Raw
url: 'http://localhost:{$AGENT_PORT}/discover_rep'
lld_macro_paths:
- lld_macro: '{#APPLICATION_NAME}'
path: $.application_name
- lld_macro: '{#CLIENT_ADDR}'
path: $.client_addr
- lld_macro: '{#REPID}'
@ -1786,6 +2364,15 @@ zabbix_export:
type: HTTP_AGENT
key: pgmon_discover_slots
delay: 10m
filter:
conditions:
- macro: '{#SLOT_NAME}'
value: '^pg_[0-9]+_sync_[0-9]+_[0-9]+$'
operator: NOT_MATCHES_REGEX
formulaid: A
lifetime: 30d
enabled_lifetime_type: DISABLE_AFTER
enabled_lifetime: 7d
item_prototypes:
- uuid: 536c5f82e3074ddfbfd842b3a2e8d46c
name: 'Slot {#SLOT_NAME} - Confirmed Flushed Bytes Lag'