Coverage for django_query_capture/presenter/pretty.py: 100%
26 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-11-20 10:20 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-11-20 10:20 +0000
1import sqlparse
2from pygments import highlight
3from pygments.formatters.terminal256 import TerminalTrueColorFormatter
4from pygments.lexers.sql import SqlLexer
5from tabulate import tabulate
7from django_query_capture.presenter.base import BasePresenter
8from django_query_capture.settings import get_config
9from django_query_capture.utils import colorize, get_stack_prefix
12class PrettyPresenter(BasePresenter):
13 """
14 Outputs all elements of [ClassifiedQuery][classify.ClassifiedQuery] with formatting.<br>
15 termscolor: [https://github.com/django/django/blob/main/django/utils/termcolors.py](https://github.com/django/django/blob/main/django/utils/termcolors.py)<br>
16 tabulate: [https://github.com/astanin/python-tabulate#table-format](https://github.com/astanin/python-tabulate#table-format) <br>
17 pygments: [https://pygments.org/styles/](https://pygments.org/styles/)
18 """
20 @staticmethod
21 def print_sql(sql: str) -> None:
22 print(
23 highlight(
24 sqlparse.format(sql, reindent=True, keyword_case="upper"),
25 SqlLexer(),
26 TerminalTrueColorFormatter(
27 style=get_config()["PRETTY"]["SQL_COLOR_FORMAT"]
28 ),
29 )
30 )
32 def get_stats_table(self, is_warning: bool = False) -> str:
33 return colorize(
34 tabulate(
35 [
36 [
37 self.classified_query["read"],
38 self.classified_query["writes"],
39 self.classified_query["total"],
40 f"{self.classified_query['total_duration']:.2f}",
41 self.classified_query["most_common_duplicate"][1]
42 if self.classified_query["most_common_duplicate"]
43 else 0,
44 self.classified_query["most_common_similar"][1]
45 if self.classified_query["most_common_similar"]
46 else 0,
47 ]
48 ],
49 [
50 "read",
51 "writes",
52 "total",
53 "total_duration",
54 "most_common_duplicates",
55 "most_common_similar",
56 ],
57 tablefmt=get_config()["PRETTY"]["TABLE_FORMAT"],
58 ),
59 is_warning,
60 )
62 def print(self) -> None:
63 is_warning = self.classified_query["has_over_threshold"]
64 print("\n" + self.get_stats_table(is_warning))
66 for captured_query in self.classified_query["slow_captured_queries"]:
67 print(
68 f'{get_stack_prefix(captured_query)} Slow {captured_query["duration"]:.2f} seconds'
69 )
70 self.print_sql(captured_query["sql"])
72 for captured_query, count in self.classified_query[
73 "duplicates_counter_over_threshold"
74 ].items():
75 print(f"{get_stack_prefix(captured_query)} Repeated {count} times")
76 self.print_sql(captured_query["sql"])
78 for captured_query, count in self.classified_query[
79 "similar_counter_over_threshold"
80 ].items():
81 print(f"{get_stack_prefix(captured_query)} Similar {count} times")
82 self.print_sql(captured_query["raw_sql"])