postgres-monitor/reports/connections

53 lines
2.1 KiB
Python
Executable File

#!/usr/bin/python3
import argparse
import re
ap = argparse.ArgumentParser()
ap.add_argument("files", nargs="+")
args = ap.parse_args()
sessions = {}
summary = {}
for fn in args.files:
with open(fn) as fh:
for ln in fh:
if m := re.match(r".*user=\[unknown\],db=\[unknown\],pid=(\d+) LOG: connection received: host=(\S+)", ln):
pid = int(m.group(1))
host = m.group(2)
sessions[pid] = { "host": host }
elif m := re.match(r".*user=(.*?),db=(.*?),pid=(\d+) LOG: connection authorized:", ln):
user = m.group(1)
db = m.group(2)
pid = int(m.group(3))
sessions[pid]["user"] = user
sessions[pid]["db"] = db
if m := re.match(r".*application_name=(\S+)", ln):
sessions[pid]["application_name"] = m.group(1)
else:
sessions[pid]["application_name"] = "-"
elif m := re.match(r".*user=(.*?),db=(.*?),pid=(\d+) LOG: disconnection: session time: ([0-9:.]+) user=\S+ database=\S+ host=(\S+)", ln):
user = m.group(1)
db = m.group(2)
pid = int(m.group(3))
time_str = m.group(4)
host = m.group(5)
m = re.match("(\d+):(\d{2}):(\d{2})\.(\d{3})", time_str)
time = int(m.group(1)) * 3600 + int(m.group(2)) * 60 + int(m.group(3)) * 1 + int(m.group(4)) * 0.001
assert user == sessions[pid]["user"]
assert db == sessions[pid]["db"]
assert host == sessions[pid]["host"]
s = summary.setdefault((db, user, host, sessions[pid]["application_name"]), { "n_sessions": 0, "session_time": 0 })
s["n_sessions"] += 1
s["session_time"] += time
del sessions[pid]
print("Database", "User", "Client", "Application", "#Sessions", "Session time (s)", sep="\t")
for k, v in summary.items():
print(k[0], k[1], k[2], k[3], v["n_sessions"], v["session_time"], sep="\t")
# vim: tw=0