diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/c77_dbh.iml b/.idea/c77_dbh.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/c77_dbh.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..00e1151 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + postgresql + true + org.postgresql.Driver + jdbc:postgresql://localhost:5432/dbh + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..aac545b --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 0000000..f324872 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/health_functions.sql b/health_functions.sql new file mode 100644 index 0000000..603affa --- /dev/null +++ b/health_functions.sql @@ -0,0 +1,98 @@ +CREATE OR REPLACE FUNCTION public.c77_dbh_get_mv_health() + RETURNS JSON AS $$ +BEGIN + RETURN ( + SELECT json_agg( + json_build_object( + 'metric', 'Materialized View Refresh', + 'mv_name', mv_name, + 'status', CASE + WHEN refresh_mv_time_last > refresh_mv_time_max * 0.9 THEN 'Red' + WHEN refresh_mv_time_last > (refresh_mv_time_total / GREATEST(refresh_count, 1)) * 1.2 THEN 'Yellow' + ELSE 'Green' + END, + 'severity', CASE + WHEN refresh_mv_time_last > refresh_mv_time_max * 0.9 THEN 5 + WHEN refresh_mv_time_last > (refresh_mv_time_total / GREATEST(refresh_count, 1)) * 1.2 THEN 3 + ELSE 1 + END, + 'insight', CASE + WHEN refresh_mv_time_last > refresh_mv_time_max * 0.9 THEN 'Refreshes are critically slow compared to historical max.' + WHEN refresh_mv_time_last > (refresh_mv_time_total / GREATEST(refresh_count, 1)) * 1.2 THEN 'Refreshes are slower than average.' + ELSE 'Refreshes are performing normally.' + END, + 'action', CASE + WHEN refresh_mv_time_last > refresh_mv_time_max * 0.9 THEN 'Investigate immediately; consider optimizing queries or resources.' + WHEN refresh_mv_time_last > (refresh_mv_time_total / GREATEST(refresh_count, 1)) * 1.2 THEN 'Review refresh schedule or resource usage.' + ELSE 'No action needed.' + END, + 'last_refresh_time', refresh_mv_time_last::text, + 'refresh_count', refresh_count + ) + ) + FROM public.c77_dbh_mv_stats + ); +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION public.c77_dbh_get_mv_details(p_mv_name text) + RETURNS JSON AS $$ +BEGIN + RETURN ( + SELECT json_build_object( + 'metric', 'Materialized View Refresh', + 'mv_name', mv_name, + 'status', CASE + WHEN refresh_mv_time_last > refresh_mv_time_max * 0.9 THEN 'Red' + WHEN refresh_mv_time_last > (refresh_mv_time_total / GREATEST(refresh_count, 1)) * 1.2 THEN 'Yellow' + ELSE 'Green' + END, + 'severity', CASE + WHEN refresh_mv_time_last > refresh_mv_time_max * 0.9 THEN 5 + WHEN refresh_mv_time_last > (refresh_mv_time_total / GREATEST(refresh_count, 1)) * 1.2 THEN 3 + ELSE 1 + END, + 'insight', CASE + WHEN io_rate > 50 THEN 'Refreshes are slower due to high I/O load.' + WHEN cpu_usage > 80 THEN 'Refreshes are slower due to high CPU usage.' + WHEN ram_usage > 90 THEN 'Refreshes are slower due to memory constraints.' + ELSE 'Refreshes are performing normally.' + END, + 'action', CASE + WHEN io_rate > 50 THEN 'Optimize I/O or schedule during off-peak hours.' + WHEN cpu_usage > 80 THEN 'Increase CPU capacity or optimize queries.' + WHEN ram_usage > 90 THEN 'Adjust memory settings (e.g., work_mem).' + ELSE 'No action needed.' + END, + 'details', json_build_object( + 'last_refresh_time', refresh_mv_time_last::text, + 'avg_refresh_time', (refresh_mv_time_total / GREATEST(refresh_count, 1))::text, + 'min_refresh_time', refresh_mv_time_min::text, + 'max_refresh_time', refresh_mv_time_max::text, + 'refresh_count', refresh_count, + 'cpu_usage', cpu_usage::text || '%', + 'ram_usage', ram_usage::text || '%', + 'io_rate', io_rate::text || ' MB/s', + 'bottleneck', CASE + WHEN io_rate > 50 THEN 'I/O' + WHEN cpu_usage > 80 THEN 'CPU' + WHEN ram_usage > 90 THEN 'RAM' + ELSE 'None' + END, + 'explanations', json_build_object( + 'last_refresh_time', 'Last refresh duration compared to historical min/max.', + 'io_rate', 'High I/O rate indicates disk operations are limiting performance.', + 'cpu_usage', 'High CPU usage suggests processing power is the bottleneck.', + 'ram_usage', 'High memory usage may cause disk spills, slowing refreshes.' + ) + ) + ) + FROM public.c77_dbh_mv_stats + CROSS JOIN LATERAL ( + -- Placeholder system stats; replace with real data later + SELECT 40 AS cpu_usage, 60 AS ram_usage, 80 AS io_rate + ) AS sys + WHERE mv_name = p_mv_name + ); +END; +$$ LANGUAGE plpgsql; \ No newline at end of file