Skip to content

Commit

Permalink
Merge pull request #1942 from natoscott/postgres-pmcheck
Browse files Browse the repository at this point in the history
pmcheck: improve redis, add postgresql and uwsgi checks
  • Loading branch information
kmcdonell committed Apr 5, 2024
2 parents c629364 + 716f66b commit 68f08ac
Show file tree
Hide file tree
Showing 13 changed files with 181 additions and 19 deletions.
10 changes: 10 additions & 0 deletions qa/1491
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,21 @@ s/could be activated/OK/
s/cannot be activated/OK/
s/measure overhead of PCP components/.../
s/not currently available for .*/.../
}' \
-e '/^pmda-postgresql /{
s/inactive/OK/
s/could be activated/OK/
s/cannot be activated/OK/
}' \
-e '/^pmda-redis /{
s/inactive/OK/
s/could be activated/OK/
s/cannot be activated/OK/
}' \
-e '/^pmda-uwsgi /{
s/inactive/OK/
s/could be activated/OK/
s/cannot be activated/OK/
}' \
-e '/^zeroconf /{
s/inactive/OK/
Expand Down
8 changes: 8 additions & 0 deletions qa/1491.out
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,43 @@ basic stuff ...
-- no args --
pmcd OK
pmda-overhead OK
pmda-postgresql OK
pmda-redis OK
pmda-sample OK
pmda-uwsgi OK
pmie OK
pmlogger OK
pmproxy OK
zeroconf OK
-- -l --
pmcd
pmda-overhead
pmda-postgresql
pmda-redis
pmda-sample
pmda-uwsgi
pmie
pmlogger
pmproxy
zeroconf
-- -lv --
pmcd Performance Metrics Collection Daemon - local source of performance data
pmda-overhead overhead PMDA - ...
pmda-postgresql PostgreSQL PMDA - metrics from PostgreSQL
pmda-redis Redis PMDA - metrics from redis-server(1)
pmda-sample sample PMDA
pmda-uwsgi uWSGI PMDA - metrics from uWSGI servers
pmie Inference Engine - rule-based monitoring
pmlogger Archive logger - record performance data for subsequent replay
pmproxy Proxy Daemon - proxy, web and redis integration
zeroconf Zeroconf Package ...
-- -s --
pmcd OK
pmda-overhead OK
pmda-postgresql OK
pmda-redis OK
pmda-sample OK
pmda-uwsgi OK
pmie OK
pmlogger OK
pmproxy OK
Expand Down
28 changes: 21 additions & 7 deletions qa/1992
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,39 @@ echo "QA output created by $seq"

[ -d $PCP_PMDAS_DIR/uwsgi ] || _notrun "uwsgi PMDA directory is not installed"

_cleanup()
{
_cleanup_pmda $iam
$sudo rm -f $tmp.*
exit $status
}

iam=uwsgi
status=1 # failure is the default!
$sudo rm -rf $tmp $tmp.* $seq.full
trap "_cleanup" 0 1 2 3 15

pmdauwsgi_remove()
{
echo
echo "=== remove uwsgi agent ==="
echo "=== remove $iam agent ==="
$sudo ./Remove >$tmp.out 2>&1
_filter_pmda_remove <$tmp.out
}

pmdauwsgi_install()
{
# start from known starting points
cd $PCP_PMDAS_DIR/uwsgi
cd $PCP_PMDAS_DIR/$iam
$sudo ./Remove >/dev/null 2>&1
_service pmcd stop | _filter_pcp_stop

echo
echo "=== uwsgi agent installation ==="
echo "=== $iam check post-install ==="
pmcheck pmda-$iam

echo
echo "=== $iam agent installation ==="
$sudo ./Install </dev/null >$tmp.out 2>&1
# Check metrics have appeared ... X metrics and Y values (or)
# Check metrics have appeared ... N warnings, X metrics and 0 values
Expand All @@ -50,14 +63,15 @@ pmdauwsgi_install()
}
}
{ print }' | tr -s ' '
echo
echo "=== $iam check post-install ==="
pmcheck pmda-$iam
}

_prepare_pmda uwsgi
trap "_cleanup_pmda uwsgi; exit \$status" 0 1 2 3 15

# real QA test starts here
_prepare_pmda $iam
_stop_auto_restart pmcd

# real QA test starts here
pmdauwsgi_install
pmdauwsgi_remove

Expand Down
2 changes: 2 additions & 0 deletions src/pmdas/postgresql/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
domain.h
pmns
6 changes: 4 additions & 2 deletions src/pmdas/postgresql/GNUmakefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2018-2020 Red Hat.
# Copyright (c) 2018-2020,2024 Red Hat.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
Expand Down Expand Up @@ -47,9 +47,11 @@ install_pcp install: default
$(INSTALL) -m 755 -d $(LOGCONFDIR)
$(INSTALL) -m 755 -d $(LOGCONFVARDIR)
$(INSTALL) -m 644 -t $(LOGCONFVARDIR)/summary pmlogconf.summary $(LOGCONFDIR)/summary
$(INSTALL) -m 755 $(IAM).pmcheck $(PCP_SHARE_DIR)/lib/pmcheck/pmda-$(IAM)
else
build-me:
install_pcp install:
install_pcp install: $(TOPDIR)/src/pmcheck/pmda.na.template
$(INSTALL) -m 755 $< $(PCP_SHARE_DIR)/lib/pmcheck/pmda-$(IAM)
@$(INSTALL_MAN)
endif

Expand Down
4 changes: 4 additions & 0 deletions src/pmdas/postgresql/pmdapostgresql.python
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,10 @@ class POSTGRESQLPMDA(PMDA):
# success
return self.cur

def domain_probe(self):
""" return True if postgresql is available and monitorable """
return self.conn is not None

def debug(self, msg):
""" print diagnostic message if verbose logging is enabled """
if self.verbose:
Expand Down
49 changes: 49 additions & 0 deletions src/pmdas/postgresql/postgresql.pmcheck
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/bin/sh
#
# Postgresql PMDA "plugin" for pmcheck
#

. $PCP_DIR/etc/pcp.env || exit 1
. $PCP_SHARE_DIR/lib/checkproc.sh

_do_args "$@"

_check()
{
test -n "$@" && echo "$@" >> $tmp/out
[ "$verbose" -gt 0 -a -s $tmp/out ] && cat $tmp/out
[ $status -eq 0 ] || exit
}

iam=postgresql
iname=postgres

if $lflag
then
[ "$verbose" -gt 0 ] && echo "PostgreSQL PMDA - metrics from PostgreSQL"
elif $sflag
then
status=0 # assume active until proven not to be
_ctl_svc state $iam || status=$?
_check "$iam service status: $status"
_ctl_pmda state $iam || status=$?
_check "$iam PMDA status: $status"
# No longer use probe due to difficulties with the PMDA implementation;
# in particular it switches user to postgres which we cannot easily do.
# Heuristic instead is simply to test to see if a postgres user exists.
#PROBE="$PCP_PYTHON_PROG $PCP_PMDAS_DIR/$iam/pmda$iam.python"
#PCP_PYTHON_PROBE=1 $PROBE || status=2
id $iname >/dev/null 2>&1 || status=2
_check "$iname user status: $status"
elif $aflag
then
_ctl_pmda activate $iam pmda$iam.python || status=1
elif $dflag
then
_ctl_pmda deactivate $iam || status=1
else
[ $verbose -gt 0 ] && echo "botch sflag=$sflag aflag=$aflag dflag=$dflag show_me=$show_me verbose=$verbose"
status=99
fi

exit
4 changes: 3 additions & 1 deletion src/pmdas/redis/redis.pmcheck
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ then
which redis-server >/dev/null 2>&1 || status=2
which redis-cli >/dev/null 2>&1 || status=2
_check "redis install status: $status"
_ctl_svc state redis || status=$?
svc=redis
test -f "$PCP_SYSTEMDUNIT_DIR/redis-server.service" && svc=redis-server
_ctl_svc state $svc || status=$?
_check "redis service status: $status"
pong=`redis-cli PING`
test "$pong" = "PONG" || status=2
Expand Down
4 changes: 3 additions & 1 deletion src/pmdas/uwsgi/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ install_pcp install: default
$(INSTALL) -m 755 -d $(PMLOGCONFVARDIR)
$(INSTALL) -m 644 -t $(PMLOGCONFVARDIR)/summary pmlogconf.summary $(PMLOGCONFDIR)/summary
$(INSTALL) -m 644 -t $(PMDATMPDIR)/$(IAM).conf $(IAM).conf $(PMDACONFIG)/$(IAM).conf
$(INSTALL) -m 755 $(IAM).pmcheck $(PCP_SHARE_DIR)/lib/pmcheck/pmda-$(IAM)
@$(INSTALL_MAN)
else
build-me:
install_pcp install:
install_pcp install: $(TOPDIR)/src/pmcheck/pmda.na.template
$(INSTALL) -m 755 $< $(PCP_SHARE_DIR)/lib/pmcheck/pmda-$(IAM)
@$(INSTALL_MAN)
endif

Expand Down
10 changes: 10 additions & 0 deletions src/pmdas/uwsgi/pmdauwsgi.python
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class UwsgiPMDA(PMDA):
self.timeout = DEFAULT_TIMEOUT
self.host = DEFAULT_HOST
self.port = DEFAULT_PORT
self.get_failed = False
self.read_config()
self.build_url()
self.connect_pmcd()
Expand Down Expand Up @@ -178,8 +179,10 @@ class UwsgiPMDA(PMDA):
def refresh_all(self):
try:
stats = requests.get(self.url, timeout=self.timeout).json()
self.get_failed = False
#self.log("refresh_all stats:", str(stats))
except Exception:
self.get_failed = True
return

avg_response_time_msec = 0
Expand Down Expand Up @@ -301,5 +304,12 @@ class UwsgiPMDA(PMDA):
return self.uwsgi_fetch_worker_callback(item, inst)
return [PM_ERR_PMID, 0]

def domain_probe(self):
"""
check: return True if server is available and monitorable
"""
self.refresh_all()
return self.get_failed

if __name__ == '__main__':
UwsgiPMDA('uwsgi', 161).run()
40 changes: 40 additions & 0 deletions src/pmdas/uwsgi/uwsgi.pmcheck
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/sh
#
# uWSGI PMDA "plugin" for pmcheck
#

. $PCP_DIR/etc/pcp.env || exit 1
. $PCP_SHARE_DIR/lib/checkproc.sh

_do_args "$@"

_check()
{
test -n "$@" && echo "$@" >> $tmp/out
[ "$verbose" -gt 0 -a -s $tmp/out ] && cat $tmp/out
[ $status -eq 0 ] || exit
}

iam=uwsgi
if $lflag
then
[ "$verbose" -gt 0 ] && echo "uWSGI PMDA - metrics from uWSGI servers"
elif $sflag
then
status=0 # assume active until proven not to be
_ctl_pmda state $iam || status=$?
PROBE="$PCP_PMDAS_DIR/$iam/pmda$iam.python --probe"
PCP_PYTHON_PROBE=1 $PCP_PYTHON_PROG $PROBE || status=2
_check "$iam PMDA status: $status"
elif $aflag
then
_ctl_pmda activate $iam pmda$iam.python || status=1
elif $dflag
then
_ctl_pmda deactivate $iam || status=1
else
[ $verbose -gt 0 ] && echo "botch sflag=$sflag aflag=$aflag dflag=$dflag show_me=$show_me verbose=$verbose"
status=99
fi

exit
28 changes: 22 additions & 6 deletions src/python/pcp/pmda.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# pylint: disable=too-many-arguments,consider-using-dict-items,no-member

import os
import sys

import cpmapi
import cpmda
Expand Down Expand Up @@ -455,6 +456,14 @@ def __init__(self, name, domain, logfile=None, helpfile=None):
##
# general PMDA class methods

def domain_probe(self):
"""
Probe the domain to see if the PMDA could be activated
Used by pmcheck(1) - see man page for meaning of (int)
return codes - as part of PMDA specific scripts.
"""
return 99 # unknown, subclasses override to use this.

def domain_write(self):
"""
Write out the domain.h file (used during installation)
Expand Down Expand Up @@ -492,13 +501,18 @@ def pmda_ready(self):
def run(self):
"""
All the real work happens herein; we can be called in one of three
situations, determined by environment variables. First couple are
during the agent Install process, where the domain.h and namespace
files need to be created. The third case is the real mccoy, where
an agent is actually being started by pmcd/dbpmda and makes use of
libpcp_pmda to talk PCP protocol.
situations, determined by environment variables. First one is for
pmcheck(1), next two are part of the agent Install process (where
the domain.h and namespace files need to be created). The fourth
case is the real mccoy, where an agent is actually being started
by pmcd/dbpmda and makes use of libpcp_pmda to talk PCP protocol.
"""
if 'PCP_PYTHON_DOMAIN' in os.environ:
if 'PCP_PYTHON_PROBE' in os.environ:
result = self.domain_probe()
if isinstance(result, int):
sys.exit(int(result))
sys.exit(2)
elif 'PCP_PYTHON_DOMAIN' in os.environ:
self.domain_write()
elif 'PCP_PYTHON_PMNS' in os.environ:
self.pmns_write(os.environ['PCP_PYTHON_PMNS'])
Expand Down Expand Up @@ -568,6 +582,8 @@ def set_notify_change():

@staticmethod
def set_user(username):
if 'PCP_PYTHON_PROBE' in os.environ:
return cpmapi.PM_ERR_NOTCONN
return cpmapi.pmSetProcessIdentity(username)

@staticmethod
Expand Down
7 changes: 5 additions & 2 deletions src/python/pmda.c
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,9 @@ endContextCallBack(int ctx)
static inline int
pmda_generating_pmns(void) { return getenv("PCP_PYTHON_PMNS") != NULL; }

static inline int
pmda_probing_domain(void) { return getenv("PCP_PYTHON_PROBE") != NULL; }

static inline int
pmda_generating_domain(void) { return getenv("PCP_PYTHON_DOMAIN") != NULL; }

Expand Down Expand Up @@ -984,7 +987,7 @@ init_dispatch(PyObject *self, PyObject *args, PyObject *keywords)
pmdaSetFetchCallBack(&dispatch, fetch_callback);
pmdaSetEndContextCallBack(&dispatch, endContextCallBack);

if (!pmda_generating_pmns() && !pmda_generating_domain())
if (!pmda_generating_pmns() && !pmda_generating_domain() && !pmda_probing_domain())
pmdaOpenLog(&dispatch);

Py_INCREF(Py_None);
Expand All @@ -1003,7 +1006,7 @@ connect_pmcd(void)
* channel setup and complete the connection handshake with
* pmcd.
*/
if (!pmda_generating_pmns() && !pmda_generating_domain()) {
if (!pmda_generating_pmns() && !pmda_generating_domain() && !pmda_probing_domain()) {
/*
* On success pmdaConnect sets PMDA_EXT_CONNECTED in e_flags ...
* this used in the guard below to stop pmda_dispatch() calling
Expand Down

0 comments on commit 68f08ac

Please sign in to comment.