diff --git a/corehq/apps/case_search/templates/case_search/profile_case_search.html b/corehq/apps/case_search/templates/case_search/profile_case_search.html
index 8ef81047a72c..a79e9a6a366f 100644
--- a/corehq/apps/case_search/templates/case_search/profile_case_search.html
+++ b/corehq/apps/case_search/templates/case_search/profile_case_search.html
@@ -47,17 +47,17 @@
Profile Slow Case Searches
- seconds;
+ seconds
- % of total;
+ % of total
% of parent
+ class="list-group">
@@ -66,9 +66,14 @@ Profile Slow Case Searches
diff --git a/corehq/apps/case_search/utils.py b/corehq/apps/case_search/utils.py
index 07e19920f22d..2db2109c1d7d 100644
--- a/corehq/apps/case_search/utils.py
+++ b/corehq/apps/case_search/utils.py
@@ -3,6 +3,7 @@
from collections import defaultdict
from dataclasses import dataclass, field
from functools import wraps
+from io import BytesIO
from django.utils.functional import cached_property
from django.utils.translation import gettext as _
@@ -40,11 +41,13 @@
reverse_index_case_query,
wrap_case_search_hit,
)
+from corehq.apps.hqadmin.utils import get_download_url
from corehq.apps.registry.exceptions import (
RegistryAccessException,
RegistryNotFound,
)
from corehq.apps.registry.helper import DataRegistryHelper
+from corehq.util.dates import get_timestamp_for_filename
from corehq.util.quickcache import quickcache
from corehq.util.timer import TimingContext
@@ -57,24 +60,47 @@ class CaseSearchProfiler:
timing_context: TimingContext = field(
default_factory=lambda: TimingContext('Case Search'))
queries: list = field(default_factory=list)
- profile_results: list = field(default_factory=list)
+ _query_number: int = 0
def run_query(self, slug, es_query):
+ self._query_number += 1
if self.debug_mode:
es_query = es_query.enable_profiling()
- with self.timing_context('run query'):
+ tc = self.timing_context(f'run query #{self._query_number}: {slug}')
+ timer = tc.peek()
+ with tc:
results = es_query.run()
if self.debug_mode:
- self.queries.append({'slug': slug, 'query': es_query.raw_query})
- self.profile_results.append({'slug': slug, 'results': results.raw.get('profile')})
-
+ self.queries.append({
+ 'slug': slug,
+ 'query_number': self._query_number,
+ 'query': es_query.raw_query,
+ 'duration': timer.duration,
+ 'profile_url': self._get_profile_url(slug, self._query_number, results.raw.get('profile')),
+ })
return results
def add_query(self, slug, es_query):
+ self._query_number += 1
if self.debug_mode:
- self.queries.append({'slug': slug, 'query': es_query.raw_query})
+ self.queries.append({
+ 'slug': slug,
+ 'query_number': self._query_number,
+ 'query': es_query.raw_query,
+ 'duration': None,
+ 'profile_url': None,
+ })
+
+ @staticmethod
+ def _get_profile_url(slug, query_number, profile_json):
+ timestamp = get_timestamp_for_filename()
+ name = f'es_profile_{query_number}_{slug}_{timestamp}.json'
+ io = BytesIO()
+ io.write(json.dumps(profile_json).encode('utf-8'))
+ io.seek(0)
+ return get_download_url(io, name, content_type='application/json')
def time_function():
diff --git a/corehq/apps/case_search/views.py b/corehq/apps/case_search/views.py
index f38bb2fb456e..f27170d9aa12 100644
--- a/corehq/apps/case_search/views.py
+++ b/corehq/apps/case_search/views.py
@@ -116,5 +116,4 @@ def post(self, request, *args, **kwargs):
'related_count': profiler.related_count,
'timing_data': profiler.timing_context.to_dict(),
'queries': profiler.queries,
- 'profile_results': profiler.profile_results,
})