Skip to content

add Redis history #1763

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion debug_toolbar/panels/history/panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ def content(self):
Fetch every store for the toolbar and include it in the template.
"""
stores = {}
for id, toolbar in reversed(self.toolbar._store.items()):

list_obj = self.toolbar.fetch_all(self.toolbar)
for id, toolbar in reversed(list_obj.items()):
stores[id] = {
"toolbar": toolbar,
"form": HistoryStoreForm(
Expand Down
7 changes: 5 additions & 2 deletions debug_toolbar/panels/history/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ def history_sidebar(request):

if form.is_valid():
store_id = form.cleaned_data["store_id"]
toolbar = DebugToolbar.fetch(store_id)
tb = DebugToolbar(request, request)
toolbar = DebugToolbar.fetch(tb, store_id)
exclude_history = form.cleaned_data["exclude_history"]
context = {}
if toolbar is None:
Expand Down Expand Up @@ -46,7 +47,9 @@ def history_refresh(request):
if form.is_valid():
requests = []
# Convert to list to handle mutations happening in parallel
for id, toolbar in list(DebugToolbar._store.items()):
tb = DebugToolbar(request, request)
list_obj = DebugToolbar.fetch_all(tb)
for id, toolbar in list(list_obj.items()):
requests.append(
{
"id": id,
Expand Down
1 change: 1 addition & 0 deletions debug_toolbar/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"SQL_WARNING_THRESHOLD": 500, # milliseconds
"OBSERVE_REQUEST_CALLBACK": "debug_toolbar.toolbar.observe_request",
"TOOLBAR_LANGUAGE": None,
"CACHE_TIME": 100,
}


Expand Down
58 changes: 53 additions & 5 deletions debug_toolbar/toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def __init__(self, request, get_response):
self.stats = {}
self.server_timing_stats = {}
self.store_id = None
self.cache_key = "djangodebug_"
self._created.send(request, toolbar=self)

# Manage panels
Expand Down Expand Up @@ -75,6 +76,8 @@ def render_toolbar(self):
"""
if not self.should_render_panels():
self.store()
if self.tests_run():
return ""
try:
context = {"toolbar": self}
lang = self.config["TOOLBAR_LANGUAGE"] or get_language()
Expand All @@ -90,6 +93,9 @@ def render_toolbar(self):
else:
raise

def tests_run(self):
return self.config.get("TESTS_RUN", False)

def should_render_panels(self):
"""Determine whether the panels should be rendered during the request

Expand All @@ -109,13 +115,55 @@ def store(self):
if self.store_id:
return
self.store_id = uuid.uuid4().hex
self._store[self.store_id] = self
for _ in range(self.config["RESULTS_CACHE_SIZE"], len(self._store)):
self._store.popitem(last=False)

from django.core.cache import cache

data = {
"stats": self.stats,
"server_timing_stats": self.server_timing_stats,
}

cache.set(f"{self.cache_key}{self.store_id}", data, self.config["CACHE_TIME"])

@classmethod
def fetch(cls, tb, store_id):
from django.core.cache import cache

data = cache.get(f"{tb.cache_key}{store_id}")
if data:
tb.stats = data.get("stats", {})
tb.server_timing_stats = data.get("server_timing_stats", {})

sql_plugin_data = tb.stats.get("SQLPanel")
if sql_plugin_data:
databases_data = sql_plugin_data.get("databases", [("default", {})])[0][
1
]
tb._panels.get("SQLPanel")._num_queries = databases_data.get(
"num_queries"
)
tb._panels.get("SQLPanel")._sql_time = sql_plugin_data.get("sql_time")
tb.store_id = store_id
return tb

@classmethod
def fetch(cls, store_id):
return cls._store.get(store_id)
def fetch_all(cls, tb):
import copy

from django.core.cache import cache

data_dict = {}
key_list = cache.keys(f"{tb.cache_key}*")
for key in key_list:
store_id = key.split("_")[1]
data = cache.get(key)
new_tb = copy.copy(tb)
new_tb.stats = data["stats"]
new_tb.server_timing_stats = data["server_timing_stats"]
new_tb.store_id = store_id
data_dict[store_id] = new_tb

return data_dict

# Manually implement class-level caching of panel classes and url patterns
# because it's more obvious than going through an abstraction.
Expand Down
3 changes: 2 additions & 1 deletion debug_toolbar/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
@render_with_toolbar_language
def render_panel(request):
"""Render the contents of a panel"""
toolbar = DebugToolbar.fetch(request.GET["store_id"])
tb = DebugToolbar(request, request)
toolbar = DebugToolbar.fetch(tb, request.GET["store_id"])
if toolbar is None:
content = _(
"Data for this panel isn't available anymore. "
Expand Down