Skip to content

Commit

Permalink
6.5.4
Browse files Browse the repository at this point in the history
  • Loading branch information
charles-001 committed Nov 22, 2024
1 parent 9000c71 commit 353e65c
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ $ brew install dolphie
```sh
$ docker pull ghcr.io/charles-001/dolphie:latest
$ docker run -dit --name dolphie ghcr.io/charles-001/dolphie:latest
$ docker exec -it dolphie dolphie -h host.docker.internal -u root --ask-pass
$ docker exec -it dolphie dolphie --tab-setup
```

## Usage
Expand Down
7 changes: 6 additions & 1 deletion dolphie/Dolphie.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,6 @@ def collect_system_utilization(self):
"Uptime": int(time.time() - psutil.boot_time()),
"CPU_Count": psutil.cpu_count(logical=True),
"CPU_Percent": psutil.cpu_percent(interval=0),
"CPU_Load_Avg": os.getloadavg(), # 1, 5, and 15 minute load averages
"Memory_Total": virtual_memory.total,
"Memory_Used": virtual_memory.used,
"Swap_Total": swap_memory.total,
Expand All @@ -273,6 +272,12 @@ def collect_system_utilization(self):
"Network_Down": network_io.bytes_recv,
}

# Include the load average if it's available
try:
self.system_utilization["CPU_Load_Avg"] = psutil.getloadavg() # 1, 5, and 15 minute load averages
except AttributeError:
pass

def get_group_replication_metadata(self):
# Check to get information on what cluster/instance type it is
if self.is_mysql_version_at_least("8.1"):
Expand Down
7 changes: 7 additions & 0 deletions dolphie/Modules/CommandManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ def __init__(self):
"u": {"human_key": "u", "description": "Display active connected users and their statistics"},
"v": {"human_key": "v", "description": "Display variables from SHOW GLOBAL VARIABLES"},
"z": {"human_key": "z", "description": "Display all entries in the host cache"},
"Z": {
"human_key": "Z",
"description": (
"Display table sizes and fragmentation for all databases - "
"[yellow]Heed caution if you have a lot of tables![/yellow]"
),
},
"placeholder_4": {"human_key": "", "description": ""},
"c": {"human_key": "c", "description": "Clear all filters set"},
"f": {"human_key": "f", "description": "Filter threads by field(s)"},
Expand Down
23 changes: 23 additions & 0 deletions dolphie/Modules/Queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,29 @@ class MySQLQueries:
WHERE
host != "background"
"""
table_sizes: str = """
SELECT
CONCAT( t.TABLE_SCHEMA, '.', t.TABLE_NAME ) AS DATABASE_TABLE,
t.ENGINE,
t.ROW_FORMAT,
s.FILE_SIZE,
s.ALLOCATED_SIZE,
t.DATA_LENGTH,
t.INDEX_LENGTH,
t.DATA_FREE,
CONVERT(
ROUND(( t.DATA_FREE / ( t.DATA_LENGTH + t.INDEX_LENGTH )) * 100, 2 ), UNSIGNED
) AS fragmentation_ratio
FROM
information_schema.TABLES t LEFT JOIN
information_schema.$1 s ON CONCAT( t.TABLE_SCHEMA, '/', t.TABLE_NAME ) = s.NAME
WHERE
t.DATA_LENGTH + t.INDEX_LENGTH > 10 * 1024 * 1024
AND t.TABLE_SCHEMA NOT IN ( 'mysql' )
ORDER BY
s.FILE_SIZE DESC,
fragmentation_ratio DESC;
"""
databases: str = """
SELECT
SCHEMA_NAME
Expand Down
7 changes: 4 additions & 3 deletions dolphie/Panels/dashboard_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,10 @@ def format_percent(value, thresholds=(80, 90), colors=("green", "yellow", "red")
table.add_row("[label]CPU", "N/A")

# CPU Load
load_averages = dolphie.system_utilization.get("CPU_Load_Avg", "N/A")
formatted_load = " ".join(f"{avg:.2f}" for avg in load_averages) if load_averages != "N/A" else "N/A"
table.add_row("[label]Load", formatted_load)
load_averages = dolphie.system_utilization.get("CPU_Load_Avg")
if load_averages:
formatted_load = " ".join(f"{avg:.2f}" for avg in load_averages)
table.add_row("[label]Load", formatted_load)

# Memory
memory_used = dolphie.metric_manager.metrics.system_memory.Memory_Used.last_value
Expand Down
16 changes: 6 additions & 10 deletions dolphie/Panels/performance_schema_metrics_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ def create_panel(tab: Tab):

def update_table_io_waits_summary_by_table(tab: Tab) -> DataTable:
dolphie = tab.dolphie
datatable = tab.pfs_metrics_table_io_waits_datatable

if not dolphie.table_io_waits_data or not dolphie.table_io_waits_data.filtered_data:
tab.pfs_metrics_table_io_waits_datatable.display = False
datatable.display = False
tab.pfs_metrics_tabs.get_tab("pfs_metrics_table_io_waits_tab").label = (
"Table I/O Waits ([highlight]0[/highlight])"
)
return

tab.pfs_metrics_table_io_waits_datatable.display = True
datatable.display = True

columns = {
"Table": {"field": "TABLE_NAME", "width": None},
Expand All @@ -46,9 +47,6 @@ def update_table_io_waits_summary_by_table(tab: Tab) -> DataTable:
"wait_time_ps": {"field": "SUM_TIMER_WAIT", "width": 0},
}

# Get the DataTable object
datatable = tab.pfs_metrics_table_io_waits_datatable

# Add columns to the datatable if it is empty
if not datatable.columns:
for column_key, column_data in columns.items():
Expand Down Expand Up @@ -136,13 +134,14 @@ def update_table_io_waits_summary_by_table(tab: Tab) -> DataTable:

def update_file_io_by_instance(tab: Tab) -> DataTable:
dolphie = tab.dolphie
datatable = tab.pfs_metrics_file_io_datatable

if not dolphie.file_io_data or not dolphie.file_io_data.filtered_data:
tab.pfs_metrics_file_io_datatable.display = False
datatable.display = False
tab.pfs_metrics_tabs.get_tab("pfs_metrics_file_io_tab").label = "File I/O ([highlight]0[/highlight])"
return

tab.pfs_metrics_file_io_datatable.display = True
datatable.display = True

columns = {
"File or Table": {"field": "FILE_NAME", "width": None},
Expand All @@ -155,9 +154,6 @@ def update_file_io_by_instance(tab: Tab) -> DataTable:
"wait_time_ps": {"field": "SUM_TIMER_WAIT", "width": 0},
}

# Get the DataTable object
datatable = tab.pfs_metrics_file_io_datatable

# Add columns to the datatable if it is empty
if not datatable.columns:
for column_key, column_data in columns.items():
Expand Down
81 changes: 79 additions & 2 deletions dolphie/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,12 @@ def command_get_input(input_variable):
command_get_input,
)

elif key == "Z":
if dolphie.is_mysql_version_at_least("5.7"):
self.run_command_in_worker(key=key, dolphie=dolphie)
else:
self.notify("Table size command requires MySQL 5.7+")

elif key == "z":
if dolphie.host_cache:
table = Table(
Expand Down Expand Up @@ -2062,6 +2068,7 @@ def show_thread_screen():
if explain_fetched_json_data:
explain_json_data = explain_fetched_json_data.get("EXPLAIN")
except ManualException as e:
# Error 1054 means unknown column which would result in a truncated query
# Error 1064 means bad syntax which would result in a truncated query
tip = (
":bulb: [b][yellow]Tip![/b][/yellow] If the query is truncated, consider increasing "
Expand All @@ -2071,11 +2078,13 @@ def show_thread_screen():
"[dark_yellow]P[/dark_yellow]. "
"This will switch to using SHOW PROCESSLIST instead of the Performance Schema, "
"which does not truncate queries.\n\n"
if e.code == 1064
if e.code in (1054, 1064)
else ""
)

explain_failure = f"{tip}[b][indian_red]EXPLAIN ERROR:[/b] [indian_red]{e.reason}"
explain_failure = (
f"{tip}[b][indian_red]EXPLAIN ERROR ({e.code}):[/b] [indian_red]{e.reason}"
)

user_thread_attributes_table = None
if dolphie.performance_schema_enabled:
Expand Down Expand Up @@ -2215,6 +2224,74 @@ def show_thread_screen():
Align.center(table),
)

self.call_from_thread(show_command_screen)

elif key == "Z":
query = MySQLQueries.table_sizes.replace("$1", "INNODB_SYS_TABLESPACES")
if dolphie.is_mysql_version_at_least("8.0") and dolphie.connection_source_alt == ConnectionSource.mysql:
query = MySQLQueries.table_sizes.replace("$1", "INNODB_TABLESPACES")

dolphie.secondary_db_connection.execute(query)
database_tables_data = dolphie.secondary_db_connection.fetchall()

columns = {
"Table": {"field": "DATABASE_TABLE", "format_bytes": False},
"Engine": {"field": "ENGINE", "format_bytes": False},
"Row Format": {"field": "ROW_FORMAT", "format_bytes": False},
"File Size": {"field": "FILE_SIZE", "format_bytes": True},
"Allocated Size": {"field": "ALLOCATED_SIZE", "format_bytes": True},
"Clustered Index": {"field": "DATA_LENGTH", "format_bytes": True},
"Secondary Indexes": {"field": "INDEX_LENGTH", "format_bytes": True},
"Free Space": {"field": "DATA_FREE", "format_bytes": True},
"Frag Ratio": {"field": "fragmentation_ratio", "format_bytes": False},
}

table = Table(
header_style="b",
box=box.SIMPLE_HEAVY,
show_edge=False,
style="table_border",
)
for column, data in columns.items():
table.add_column(column, no_wrap=True)

for database_table_row in database_tables_data:
row_values = []

for column, data in columns.items():
value = database_table_row.get(data.get("field"), "N/A")

if data["format_bytes"]:
row_values.append(format_bytes(value) if value else "0")
elif column == "Frag Ratio":
if value:
if value >= 30:
row_values.append(f"[red]{value}%[/red]")
elif value >= 20:
row_values.append(f"[yellow]{value}%[/yellow]")
else:
row_values.append(f"[green]{value}%[/green]")
else:
row_values.append("[green]0%[/green]")

elif column == "Table":
# Color the database name. Format is database/table
database_table = value.split(".")
row_values.append(f"[dark_gray]{database_table[0]}[/dark_gray].{database_table[1]}")

else:
row_values.append(str(value) or "")

table.add_row(*row_values)

screen_data = Group(
Align.center(
"[b light_blue]Table Sizes & Fragmentation[/b light_blue] ([highlight]%s[/highlight])\n"
% len(database_tables_data)
),
Align.center(table),
)

self.call_from_thread(show_command_screen)
except ManualException as e:
self.notify(e.reason, title=f"Error running command '{key}'", severity="error", timeout=10)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "dolphie"
version = "6.5.3"
version = "6.5.4"
license = "GPL-3.0-or-later"
description = "Your single pane of glass for real-time analytics into MySQL/MariaDB & ProxySQL"
authors = ["Charles Thompson <[email protected]>"]
Expand Down

0 comments on commit 353e65c

Please sign in to comment.