[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-grid5k] 106/189: viualizer can parse log lines / formatted output
From: |
gnunet |
Subject: |
[taler-grid5k] 106/189: viualizer can parse log lines / formatted output |
Date: |
Thu, 28 Apr 2022 10:47:56 +0200 |
This is an automated email from the git hooks/post-receive script.
marco-boss pushed a commit to branch master
in repository grid5k.
commit 014c5c29fa1a9a4dd788595d707d46ccb083ee16
Author: Boss Marco <bossm8@bfh.ch>
AuthorDate: Tue Mar 22 20:54:09 2022 +0100
viualizer can parse log lines / formatted output
---
additional/explain-visualizer/example.log | 25 ++++++++++
additional/explain-visualizer/explain.py | 83 +++++++++++++++++++++----------
2 files changed, 82 insertions(+), 26 deletions(-)
diff --git a/additional/explain-visualizer/example.log
b/additional/explain-visualizer/example.log
new file mode 100644
index 0000000..653c6a8
--- /dev/null
+++ b/additional/explain-visualizer/example.log
@@ -0,0 +1,25 @@
+2022-03-22 18:43:44.104 UTC [89] LOG: statement: EXPLAIN (ANALYZE, VERBOSE,
BUFFERS, FORMAT JSON) Select * from reserves join reserves_in using
(reserve_pub) where reserve_pub='x';
+2022-03-22 18:44:40.956 UTC [92] LOG: statement: select * from reserves where
reserve_pub='x';
+2022-03-22 18:53:19.795 UTC [92] LOG: statement: select * from reserves where
reserve_pub='x';
+2022-03-22 18:53:20.577 UTC [92] LOG: statement: select * from reserves where
reserve_pub='x';
+2022-03-22 18:53:21.135 UTC [92] LOG: statement: select * from reserves where
reserve_pub='x';
+2022-03-22 18:53:21.646 UTC [92] LOG: statement: select * from reserves where
reserve_pub='x';
+2022-03-22 18:53:31.910 UTC [92] ERROR: syntax error at or near "where" at
character 42
+2022-03-22 18:53:31.910 UTC [92] STATEMENT: select * from reserves join
reserves_out where reserve_pub='x';
+2022-03-22 18:53:35.640 UTC [92] ERROR: syntax error at or near "where" at
character 41
+2022-03-22 18:53:35.640 UTC [92] STATEMENT: select * from reserves join
reserves_in where reserve_pub='x';
+2022-03-22 18:53:43.136 UTC [92] ERROR: syntax error at or near "reserve_pub"
at character 61
+2022-03-22 18:53:43.136 UTC [92] STATEMENT: select * from reserves join
reserves_in on reserve_pubwhere reserve_pub='x';
+2022-03-22 18:53:45.680 UTC [92] LOG: statement: select * from reserves join
reserves_in on reserve_pub where reserve_pub='x';
+2022-03-22 18:53:45.681 UTC [92] ERROR: column reference "reserve_pub" is
ambiguous at character 44
+2022-03-22 18:53:45.681 UTC [92] STATEMENT: select * from reserves join
reserves_in on reserve_pub where reserve_pub='x';
+2022-03-22 18:53:51.504 UTC [92] LOG: statement: select * from reserves join
reserves_in on(reserve_pub) where reserve_pub='x';
+2022-03-22 18:53:51.504 UTC [92] ERROR: column reference "reserve_pub" is
ambiguous at character 44
+2022-03-22 18:53:51.504 UTC [92] STATEMENT: select * from reserves join
reserves_in on(reserve_pub) where reserve_pub='x';
+2022-03-22 18:53:55.042 UTC [92] LOG: statement: select * from reserves join
reserves_in on (reserve_pub) where reserve_pub='x';
+2022-03-22 18:53:55.042 UTC [92] ERROR: column reference "reserve_pub" is
ambiguous at character 45
+2022-03-22 18:53:55.042 UTC [92] STATEMENT: select * from reserves join
reserves_in on (reserve_pub) where reserve_pub='x';
+2022-03-22 18:54:01.883 UTC [92] LOG: statement: select * from reserves join
reserves_in on (reserve_pub) where reserves.reserve_pub='x';
+2022-03-22 18:54:01.883 UTC [92] ERROR: column reference "reserve_pub" is
ambiguous at character 45
+2022-03-22 18:54:01.883 UTC [92] STATEMENT: select * from reserves join
reserves_in on (reserve_pub) where reserves.reserve_pub='x';
+2022-03-22 18:54:06.817 UTC [92] LOG: statement: select * from reserves join
reserves_in using (reserve_pub) where reserves.reserve_pub='x';
diff --git a/additional/explain-visualizer/explain.py
b/additional/explain-visualizer/explain.py
index 5a8e838..21fe580 100755
--- a/additional/explain-visualizer/explain.py
+++ b/additional/explain-visualizer/explain.py
@@ -4,6 +4,7 @@ from json import loads
from re import compile
from subprocess import check_output, CalledProcessError
from enum import Enum
+from textwrap import fill
import argparse
@@ -55,27 +56,33 @@ class Plan:
plans = {}
most_time_consuming = Plan("default", Type.RELATION, 0)
-partitioned_re = compile('(.*)_([0-9]+|default)')
+partitioned_re = compile('.*_([0-9]+|default)')
+log_statement_re = compile('.*LOG: statement: (.*);')
args = None
def get_explain(sql) -> dict:
+ print("\n" + "=" * 80 + "\n")
+ print(fill(text=sql, width=80))
+ print("\n" + "=" * 80 + "\n")
sql = sql.replace("\n", "").replace('"', "")
sql = "EXPLAIN (ANALYZE, VERBOSE, BUFFERS, FORMAT JSON) " + sql + ";"
try:
- analyze_json = check_output(args=['psql',
- '-U', args.db_user,
- '-h', args.db_host,
- '-d', args.db_name,
- '-p', args.db_port,
- '-P', 'pager=off',
- '-qtAXc', sql],
- env={'PGPASSWD': args.db_pw},
- timeout=10)
+ analyze_json = check_output(
+ args=['psql',
+ '-U', args.db_user,
+ '-h', args.db_host,
+ '-d', args.db_name,
+ '-p', args.db_port,
+ '-P', 'pager=off',
+ '-qtAXc', sql],
+ env={'PGPASSWD': args.db_pw},
+ timeout=10
+ )
return loads(analyze_json)[0]
except CalledProcessError as e:
print(e.output)
- exit(1)
+ print("\nQuery returned an error, skipping analyzation\n")
def ensure_partition_added(relation, indent):
@@ -125,7 +132,7 @@ def iterate_plans():
yield plans[plan]
-def parse_plan(plan, indent=0):
+def parse_plan(plan, indent=2):
if 'Plans' in plan:
ensure_plan_added(plan['Node Type'], indent)
for _plan in plan['Plans']:
@@ -140,8 +147,8 @@ def print_summary(attr_name):
if plan.type == Type.RELATION:
attr = getattr(plan, attr_name)
total += attr
- print(f" {plan.name}: {attr}")
- print(f"(Total: {total})")
+ print(" {:<25} {:>10}".format(plan.name + ":", attr))
+ print(f"\n (Total: {total})")
def print_non_indexed():
@@ -150,32 +157,42 @@ def print_non_indexed():
if plan.scan_type == 'Seq Scan':
print(f" {plan.name}")
total += 1
- print(f"(Total: {total})")
+ print(f"\n (Total: {total})")
def visualize(analyze_json):
+ if analyze_json is None:
+ return
+
plan = analyze_json['Plan']
- print("General:\n")
- print(f"Estimated Rows: {plan['Plan Rows']}")
- print(f"Actual Rows Returned: {plan['Actual Rows']}")
- print(f"Actual Execution Time: {plan['Actual Total Time']} ms")
+ print("GENERAL:\n")
+ print(" {:<25} {:>10}".format("Estimated Rows:", plan['Plan Rows']))
+ print(" {:<25} {:>10}".format("Actual Rows Returned:", plan['Actual
Rows']))
+ print(" {:<25} {:>10} ms".format("Actual Execution Time:", plan['Actual
Total Time']))
parse_plan(plan)
- print("\nSummary: \n")
+ print("\n\nSUMMARY: \n")
print(f"Rows Returned by Sub-queries:")
+ print("-----------------------------\n")
print_summary('rows_returned')
print("\nPartitions Hit:")
+ print("---------------\n")
print_summary('partitions_hit')
print("\nNon Indexed Scans on:")
+ print("---------------------\n")
print_non_indexed()
print("\nMost Time Consuming:")
- print(f"{most_time_consuming.name}: {most_time_consuming.time_spent} ms")
+ print("--------------------\n")
+ print(" {:<25} {:>10} ms".format(most_time_consuming.name + ":",
most_time_consuming.time_spent))
+ print("")
- print("\nDetail:\n")
- for plan in iterate_plans():
- plan.print()
+ if args.verbose:
+ print("\nDETAIL:\n")
+ for plan in iterate_plans():
+ plan.print()
+ print("")
def analyze_from_query():
@@ -183,11 +200,20 @@ def analyze_from_query():
visualize(explain)
-def analyze_from_logs():
+def handle_log_line(line):
global plans
plans = {}
+
+ match = log_statement_re.match(line)
+ if match:
+ explain = get_explain(match.group(1))
+ visualize(explain)
+
+
+def analyze_from_logs():
with open(args.file, 'r') as logs:
- print(logs)
+ for line in logs:
+ handle_log_line(line)
def main():
@@ -219,6 +245,10 @@ def main():
type=str,
default="",
help='Database port, default 5432')
+ global_args.add_argument('-v', '--verbose',
+ dest='verbose',
+ action='store_true',
+ help='Print detailed query plan')
s_p = parser.add_subparsers()
@@ -242,6 +272,7 @@ def main():
global args
args = parser.parse_args()
+
args.func()
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-grid5k] 24/189: fix missing with tar, (continued)
- [taler-grid5k] 24/189: fix missing with tar, gnunet, 2022/04/28
- [taler-grid5k] 42/189: hopefully better logging of slow queries with pg_stat_statements, gnunet, 2022/04/28
- [taler-grid5k] 39/189: test do not partition wire_targets, gnunet, 2022/04/28
- [taler-grid5k] 14/189: aggregation tracking cant be sharded, gnunet, 2022/04/28
- [taler-grid5k] 30/189: log nested statements to hopefully get function debug output, gnunet, 2022/04/28
- [taler-grid5k] 16/189: re-enable sharding of aggregation tracking tables, gnunet, 2022/04/28
- [taler-grid5k] 43/189: again without analyze, gnunet, 2022/04/28
- [taler-grid5k] 47/189: add monitor to dahu because of link speed, gnunet, 2022/04/28
- [taler-grid5k] 20/189: fix typos, gnunet, 2022/04/28
- [taler-grid5k] 38/189: test, gnunet, 2022/04/28
- [taler-grid5k] 106/189: viualizer can parse log lines / formatted output,
gnunet <=
- [taler-grid5k] 21/189: generic wire-fee year, fix empty shards when partitioned only, gnunet, 2022/04/28
- [taler-grid5k] 90/189: add doc, gnunet, 2022/04/28
- [taler-grid5k] 77/189: test custom metrics, gnunet, 2022/04/28
- [taler-grid5k] 116/189: fix verbose output, gnunet, 2022/04/28
- [taler-grid5k] 124/189: enable admin api for prometheus in order to test snapshots, gnunet, 2022/04/28
- [taler-grid5k] 75/189: also separate wallet from the main syslog receiver, gnunet, 2022/04/28
- [taler-grid5k] 80/189: change denominations, gnunet, 2022/04/28
- [taler-grid5k] 62/189: fix lookahead sign, gnunet, 2022/04/28
- [taler-grid5k] 84/189: cleaner exchange setup, gnunet, 2022/04/28
- [taler-grid5k] 118/189: add sharding logic, gnunet, 2022/04/28