From 8e453f059ad2a7e596280d211f9f614e78a826f7 Mon Sep 17 00:00:00 2001 From: wo_cow Date: Mon, 19 Sep 2022 11:09:02 +0800 Subject: [PATCH] add pg_stat.probe --- config/gala-gopher.conf | 16 ++- src/probes/extends/python.probe/install.sh | 2 + .../pg_stat.probe/pg_stat_probe.conf | 17 +++ .../pg_stat.probe/pg_stat_probe.meta | 51 ++++++++ .../pg_stat.probe/pg_stat_probe.py | 118 ++++++++++++++++++ 5 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.conf create mode 100644 src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.meta create mode 100644 src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.py diff --git a/config/gala-gopher.conf b/config/gala-gopher.conf index c011763b..c70e9880 100644 --- a/config/gala-gopher.conf +++ b/config/gala-gopher.conf @@ -87,6 +87,14 @@ probes = extend_probes = ( + { + name = "pg_stat_probe"; + command = "python3 /opt/gala-gopher/extend_probes/pg_stat_probe.py"; + param = ""; + start_check = "ps -ef | grep gaussdb | grep -v grep | wc -l"; + check_type = "count"; + switch = "auto"; + }, { name = "cadvisor"; command = "python3 /opt/gala-gopher/extend_probes/cadvisor_probe.py"; @@ -159,13 +167,17 @@ extend_probes = name = "ksliprobe"; command = "/opt/gala-gopher/extend_probes/ksliprobe" param = ""; - switch = "on"; + start_check = "ps -ef | grep 'redis\|keydb' | grep -v grep | wc -l"; + check_type = "count"; + switch = "auto"; }, { name = "pgsliprobe"; command = "/opt/gala-gopher/extend_probes/pgsliprobe" param = ""; - switch = "on"; + start_check = "ps -ef | grep gaussdb | grep -v grep | wc -l"; + check_type = "count"; + switch = "auto"; }, { name = "redis_client"; diff --git a/src/probes/extends/python.probe/install.sh b/src/probes/extends/python.probe/install.sh index dcbeefc0..eabbb2d5 100755 --- a/src/probes/extends/python.probe/install.sh +++ b/src/probes/extends/python.probe/install.sh @@ -6,6 +6,8 @@ INSTALL_FILES="redis.probe/redis_probe.py" INSTALL_FILES+=" redis_client.probe/client-async.py" INSTALL_FILES+=" cadvisor.probe/cadvisor_probe.py" INSTALL_FILES+=" cadvisor.probe/cadvisor_probe.conf" +INSTALL_FILES+=" pg_stat.probe/pg_stat_probe.py" +INSTALL_FILES+=" pg_stat.probe/pg_stat_probe.conf" if [ $# -eq 1 ]; then # copy to specify dir diff --git a/src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.conf b/src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.conf new file mode 100644 index 00000000..4c99dfc8 --- /dev/null +++ b/src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.conf @@ -0,0 +1,17 @@ +servers: +( + { + ip: "172.11.0.101", + port: "5432", + dbname: "postgres", + user: "opengauss_exporter", + password: "opengauss_exporter123" + }, + { + ip: "172.12.0.101", + port: "5433", + dbname: "postgres", + user: "opengauss_exporter", + password: "opengauss_exporter123" + }, +) diff --git a/src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.meta b/src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.meta new file mode 100644 index 00000000..3dfd95a3 --- /dev/null +++ b/src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.meta @@ -0,0 +1,51 @@ +version = "1.0.0" +measurements: +( + { + table_name: "pg_tps", + entity_name: "sli", + fields: + ( + { + description: "the tgid of server process", + type: "key", + name: "tgid", + }, + { + description: "OID of a database", + type: "key", + name: "ins_id", + }, + { + description: "the protocol type", + type: "key", + name: "app", + }, + { + description: "the cmd of req", + type: "key", + name: "method", + }, + { + description: "the IP of server", + type: "label", + name: "server_ip", + }, + { + description: "the port of server", + type: "label", + name: "server_port", + }, + { + description: "Name of this database", + type: "label", + name: "datname", + }, + { + description: "Number of transactions in this database that have been committed", + type: "gauge", + name: "tps", + } + ) + } +) diff --git a/src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.py b/src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.py new file mode 100644 index 00000000..a4d75caa --- /dev/null +++ b/src/probes/extends/python.probe/pg_stat.probe/pg_stat_probe.py @@ -0,0 +1,118 @@ +import sys +import time +import signal +import subprocess +import os +import io +import getopt +import libconf +import psycopg2 + + +PROJECT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # /opt/gala-gopher/ +SELECT_PG_STAT_DATABASE = "select * from pg_stat_database where datname NOT IN ('template0','template1');" +g_metric = dict() +g_servers = [] +g_period = 5 + + +def get_tgid(port): + # for host process + command = "netstat -natp | grep LISTEN | grep gaussdb | grep %s | \ + awk -F ' ' 'NR ==1{print $7}' | awk -F '/' '{print $1}'" % (port) + p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + (rawout, serr) = p.communicate(timeout=5) + if len(rawout) != 0: + return rawout.rstrip().decode() + + # for docker process + command = "docker ps -q | xargs docker inspect --format='{{.State.Pid}}, {{range $p, $conf := \ + .HostConfig.PortBindings}}{{$p}}{{end}}' | grep -w %s | awk -F ', ' 'NR ==1{print $1}'" % port + p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + (rawout, serr) = p.communicate(timeout=5) + if len(rawout) != 0: + return rawout.rstrip().decode() + return 0 + + +def init_conns(): + global g_servers + meta_path = os.path.join(PROJECT_PATH, "extend_probes/pg_stat_probe.conf") + with io.open(meta_path, encoding='utf-8') as f: + conf = libconf.load(f) + for server in conf.servers: + conn = psycopg2.connect("host=%s port=%s dbname=%s user=%s password=%s" + % (server.ip, server.port, server.dbname, server.user, server.password)) + print("[pg_stat_probe]connect to %s:%s success!" + % ( server.ip, server.port)) + cursor = conn.cursor() + tgid = get_tgid(server.port) + tgid_num = int(tgid) + server_addr = server.ip + "|" + server.port + g_servers.append(Connection(server.ip, server.port, tgid, conn, cursor, server_addr)) + + +def get_metrics(): + for server in g_servers: + server.cursor.execute(SELECT_PG_STAT_DATABASE, None) + lines = server.cursor.fetchall() + server.conn.commit() + for line in lines: + ''' + the first four item of the line is: + datid + datname + numbackends + xact_commit + ''' + metric_str = "|pg_tps|%s|%s|POSTGRE|0|%s|%s|%s|" % (server.tgid, line[0], server.ip, server.port, line[1]) + metric_new_value = int(line[3]) + hashed_metric_str = hash(metric_str) + if hashed_metric_str in g_metric: + metric_rate = (metric_new_value - g_metric[hashed_metric_str]) / g_period + print(metric_str + str(metric_rate) + "|") + sys.stdout.flush() + g_metric[hashed_metric_str] = metric_new_value + + +def stop_conns(): + for server in g_servers: + if server.cursor: + server.cursor.close() + if server.conn: + server.conn.close() + sys.exit(0) + + +def signal_handler(signum, frame): + stop_conns() + + +class Connection(object): + def __init__(self, ip, port, tgid, conn, cursor, metric_header): + self.ip = ip + self.port = port + self.tgid = tgid + self.conn = conn + self.cursor = cursor + self.metric_header = metric_header + + +def init_param(): + global g_period + argv = sys.argv[1:] + opts, args = getopt.getopt(argv, "-d:") + for opt, arg in opts: + if opt in ["-d"]: + g_period = int(arg) + + +if __name__ == "__main__": + init_param() + signal.signal(signal.SIGINT, signal_handler) + init_conns() + + while True: + time.sleep(g_period) + get_metrics() + -- Gitee