55from django .db import connection , connections
66from pydantic import ValidationError
77
8+ from kernelCI_app .cache import get_query_cache , set_query_cache
89from kernelCI_app .helpers .database import dict_fetchall
910from kernelCI_app .helpers .logger import out
1011from kernelCI_app .queries .tree import get_tree_listing_query
@@ -644,22 +645,32 @@ def get_issues_summary_data(*, checkout_ids: list[str]) -> list[dict]:
644645 return dict_fetchall (cursor = cursor )
645646
646647
647- def query_fetchone_work (* , query : str , params : dict [str , Any ]):
648+ def query_fetchone_work (* , cache_key : str , query : str , params : dict [str , Any ]):
649+ rows = get_query_cache (key = cache_key , params = params )
650+ if rows is not None :
651+ return rows
648652 try :
649653 with connections ["default" ].cursor () as cursor :
650654 cursor .execute (query , params )
651- return cursor .fetchone ()
655+ rows = cursor .fetchone ()
652656 finally :
653657 connections ["default" ].close ()
658+ set_query_cache (key = cache_key , params = params , rows = rows )
659+ return rows
654660
655661
656- def query_fetchall_work (* , query : str , params : dict [str , Any ]):
662+ def query_fetchall_work (* , cache_key : str , query : str , params : dict [str , Any ]):
663+ rows = get_query_cache (key = cache_key , params = params )
664+ if rows is not None :
665+ return rows
657666 try :
658667 with connections ["default" ].cursor () as cursor :
659668 cursor .execute (query , params )
660- return cursor .fetchall ()
669+ rows = cursor .fetchall ()
661670 finally :
662671 connections ["default" ].close ()
672+ set_query_cache (key = cache_key , params = params , rows = rows )
673+ return rows
663674
664675
665676def get_metrics_data (
@@ -790,6 +801,42 @@ def get_metrics_data(
790801 WHERE r.ranked <= 3 AND n.total_incidents > 0
791802 """
792803
804+ new_build_issues_query = """
805+ WITH time_rank AS (
806+ SELECT
807+ _timestamp,
808+ origin,
809+ issue_id,
810+ ROW_NUMBER() OVER (PARTITION BY issue_id ORDER BY _timestamp) AS rn
811+ FROM incidents
812+ WHERE build_id IS NOT NULL
813+ ),
814+ new_issues AS (
815+ SELECT issue_id, origin
816+ FROM time_rank
817+ WHERE rn = 1
818+ AND _timestamp BETWEEN
819+ NOW() - INTERVAL %(start_days_ago)s
820+ AND NOW() - INTERVAL %(end_days_ago)s
821+ )
822+ SELECT
823+ inc.origin,
824+ inc.issue_id,
825+ inc.issue_version,
826+ i.comment,
827+ COUNT(inc.*) AS total
828+ FROM incidents inc
829+ JOIN issues i ON inc.issue_id = i.id AND inc.issue_version = i.version
830+ JOIN new_issues ni ON inc.issue_id = ni.issue_id AND inc.origin = ni.origin
831+ WHERE
832+ inc.build_id IS NOT NULL
833+ AND inc._timestamp BETWEEN
834+ NOW() - INTERVAL %(start_days_ago)s
835+ AND NOW() - INTERVAL %(end_days_ago)s
836+ GROUP BY inc.origin, inc.issue_id, inc.issue_version, i.comment
837+ ORDER BY inc.origin, total DESC
838+ """
839+
793840 lab_summary_query = """
794841 -- get count of tests of each lab and how many builds are related to those tests
795842 SELECT
@@ -806,32 +853,55 @@ def get_metrics_data(
806853 GROUP BY lab
807854 """
808855
809- with ThreadPoolExecutor (max_workers = 5 ) as executor :
856+ with ThreadPoolExecutor (max_workers = 6 ) as executor :
810857 total_objects_result = executor .submit (
811- query_fetchone_work , query = total_objects_query , params = params
858+ query_fetchone_work ,
859+ cache_key = "metricsTotalObjects" ,
860+ query = total_objects_query ,
861+ params = params ,
812862 )
813863 prev_total_objects_result = executor .submit (
814- query_fetchone_work , query = total_objects_query , params = prev_params
864+ query_fetchone_work ,
865+ cache_key = "metricsTotalObjects" ,
866+ query = total_objects_query ,
867+ params = prev_params ,
815868 )
816869 build_incidents_result = executor .submit (
817- query_fetchall_work , query = build_incidents_query , params = params
870+ query_fetchall_work ,
871+ cache_key = "metricsBuildIncidents" ,
872+ query = build_incidents_query ,
873+ params = params ,
874+ )
875+ new_build_issues_result = executor .submit (
876+ query_fetchall_work ,
877+ cache_key = "metricsNewBuildIssues" ,
878+ query = new_build_issues_query ,
879+ params = params ,
818880 )
819881 lab_summary_results = executor .submit (
820- query_fetchall_work , query = lab_summary_query , params = params
882+ query_fetchall_work ,
883+ cache_key = "metricsLabSummary" ,
884+ query = lab_summary_query ,
885+ params = params ,
821886 )
822887 prev_lab_summary_results = executor .submit (
823- query_fetchall_work , query = lab_summary_query , params = prev_params
888+ query_fetchall_work ,
889+ cache_key = "metricsLabSummary" ,
890+ query = lab_summary_query ,
891+ params = prev_params ,
824892 )
825893
826894 total_objects_result = total_objects_result .result ()
827895 prev_total_objects_result = prev_total_objects_result .result ()
828896 build_incidents_result = build_incidents_result .result ()
897+ new_build_issues_result = new_build_issues_result .result ()
829898 lab_summary_results = lab_summary_results .result ()
830899 prev_lab_summary_results = prev_lab_summary_results .result ()
831900
832901 try :
833902 build_incidents_by_origin : dict [str , BuildIncidentsCount ] = {}
834903 top_issues_by_origin : dict [str , dict [tuple [str , int ], TopIssue ]] = {}
904+ new_issues_by_origin : dict [str , dict [tuple [str , int ], TopIssue ]] = {}
835905 for row in build_incidents_result :
836906 origin = row [0 ]
837907 issue_id = row [4 ]
@@ -851,6 +921,19 @@ def get_metrics_data(
851921 total_incidents = row [7 ],
852922 )
853923
924+ for row in new_build_issues_result :
925+ origin = row [0 ]
926+ issue_id = row [1 ]
927+ issue_version = row [2 ]
928+ if new_issues_by_origin .get (origin ) is None :
929+ new_issues_by_origin [origin ] = {}
930+ new_issues_by_origin [origin ][(issue_id , issue_version )] = TopIssue (
931+ id = issue_id ,
932+ version = issue_version ,
933+ comment = row [3 ],
934+ total_incidents = row [4 ],
935+ )
936+
854937 data = MetricsReportData (
855938 n_trees = total_objects_result [0 ],
856939 n_checkouts = total_objects_result [1 ],
@@ -860,6 +943,7 @@ def get_metrics_data(
860943 n_incidents = total_objects_result [5 ],
861944 build_incidents_by_origin = build_incidents_by_origin ,
862945 top_issues_by_origin = top_issues_by_origin ,
946+ new_issues_by_origin = new_issues_by_origin ,
863947 lab_maps = {
864948 row [0 ]: LabMetricsData (
865949 builds = row [1 ],
0 commit comments