django-devbar 0.6.1__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_devbar-0.6.1 → django_devbar-0.7.0}/PKG-INFO +8 -2
- {django_devbar-0.6.1 → django_devbar-0.7.0}/README.md +5 -0
- {django_devbar-0.6.1 → django_devbar-0.7.0}/pyproject.toml +2 -1
- {django_devbar-0.6.1 → django_devbar-0.7.0}/src/django_devbar/conf.py +12 -0
- {django_devbar-0.6.1 → django_devbar-0.7.0}/src/django_devbar/middleware.py +91 -19
- {django_devbar-0.6.1 → django_devbar-0.7.0}/src/django_devbar/__init__.py +0 -0
- {django_devbar-0.6.1 → django_devbar-0.7.0}/src/django_devbar/templates/django_devbar/devbar.html +0 -0
- {django_devbar-0.6.1 → django_devbar-0.7.0}/src/django_devbar/templates/django_devbar/duplicates.html +0 -0
- {django_devbar-0.6.1 → django_devbar-0.7.0}/src/django_devbar/templates/django_devbar/similar.html +0 -0
- {django_devbar-0.6.1 → django_devbar-0.7.0}/src/django_devbar/tracker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-devbar
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Lightweight performance devbar for Django
|
|
5
5
|
Keywords: django,debug,performance,monitoring,development
|
|
6
6
|
Author: amureki
|
|
@@ -22,11 +22,12 @@ Classifier: Framework :: Django :: 5.2
|
|
|
22
22
|
Classifier: Framework :: Django :: 6.0
|
|
23
23
|
Classifier: Topic :: Software Development
|
|
24
24
|
Classifier: Intended Audience :: Developers
|
|
25
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
25
26
|
Requires-Dist: django>=4.2
|
|
26
27
|
Requires-Python: >=3.10
|
|
27
28
|
Project-URL: Homepage, https://github.com/amureki/django-devbar
|
|
28
|
-
Project-URL: Issues, https://github.com/amureki/django-devbar/issues
|
|
29
29
|
Project-URL: Repository, https://github.com/amureki/django-devbar
|
|
30
|
+
Project-URL: Issues, https://github.com/amureki/django-devbar/issues
|
|
30
31
|
Description-Content-Type: text/markdown
|
|
31
32
|
|
|
32
33
|
# django-devbar
|
|
@@ -95,6 +96,8 @@ DEVBAR = {
|
|
|
95
96
|
"POSITION": "bottom-right", # bottom-right (default), bottom-left, top-right, top-left
|
|
96
97
|
"SHOW_BAR": None, # follows DEBUG; set True/False to override
|
|
97
98
|
"ENABLE_DEVTOOLS_DATA": None, # follows DEBUG; set True/False to override
|
|
99
|
+
"DEVTOOLS_HEADER_MAX_BYTES": 6144, # max bytes for DevBar-Data header payload
|
|
100
|
+
"DEVTOOLS_MAX_QUERIES": None, # optional hard cap for q/dup entries sent to DevTools
|
|
98
101
|
}
|
|
99
102
|
```
|
|
100
103
|
|
|
@@ -107,6 +110,9 @@ Django DevBar adds HTTP response headers with performance metrics:
|
|
|
107
110
|
An additional header is included by default in DEBUG mode:
|
|
108
111
|
|
|
109
112
|
- **DevBar-Data** - JSON header with comprehensive metrics including similar and duplicate query details
|
|
113
|
+
- Query-level flags are embedded in `q` entries (`dup` and `sim`)
|
|
114
|
+
- Payload is automatically truncated to fit `DEVTOOLS_HEADER_MAX_BYTES`
|
|
115
|
+
- When truncated, response includes metadata keys: `tr`, `q_total`, `q_sent`
|
|
110
116
|
|
|
111
117
|
This is useful for:
|
|
112
118
|
|
|
@@ -64,6 +64,8 @@ DEVBAR = {
|
|
|
64
64
|
"POSITION": "bottom-right", # bottom-right (default), bottom-left, top-right, top-left
|
|
65
65
|
"SHOW_BAR": None, # follows DEBUG; set True/False to override
|
|
66
66
|
"ENABLE_DEVTOOLS_DATA": None, # follows DEBUG; set True/False to override
|
|
67
|
+
"DEVTOOLS_HEADER_MAX_BYTES": 6144, # max bytes for DevBar-Data header payload
|
|
68
|
+
"DEVTOOLS_MAX_QUERIES": None, # optional hard cap for q/dup entries sent to DevTools
|
|
67
69
|
}
|
|
68
70
|
```
|
|
69
71
|
|
|
@@ -76,6 +78,9 @@ Django DevBar adds HTTP response headers with performance metrics:
|
|
|
76
78
|
An additional header is included by default in DEBUG mode:
|
|
77
79
|
|
|
78
80
|
- **DevBar-Data** - JSON header with comprehensive metrics including similar and duplicate query details
|
|
81
|
+
- Query-level flags are embedded in `q` entries (`dup` and `sim`)
|
|
82
|
+
- Payload is automatically truncated to fit `DEVTOOLS_HEADER_MAX_BYTES`
|
|
83
|
+
- When truncated, response includes metadata keys: `tr`, `q_total`, `q_sent`
|
|
79
84
|
|
|
80
85
|
This is useful for:
|
|
81
86
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "django-devbar"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "Lightweight performance devbar for Django"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -27,6 +27,7 @@ classifiers = [
|
|
|
27
27
|
"Framework :: Django :: 6.0",
|
|
28
28
|
"Topic :: Software Development",
|
|
29
29
|
"Intended Audience :: Developers",
|
|
30
|
+
"License :: OSI Approved :: MIT License",
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
[project.urls]
|
|
@@ -13,6 +13,8 @@ def get_config():
|
|
|
13
13
|
"POSITION": "bottom-right",
|
|
14
14
|
"SHOW_BAR": None, # None = use settings.DEBUG
|
|
15
15
|
"ENABLE_DEVTOOLS_DATA": None, # None = use settings.DEBUG
|
|
16
|
+
"DEVTOOLS_HEADER_MAX_BYTES": 6144,
|
|
17
|
+
"DEVTOOLS_MAX_QUERIES": None,
|
|
16
18
|
**getattr(settings, "DEVBAR", {}),
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -33,3 +35,13 @@ def get_enable_devtools_data():
|
|
|
33
35
|
config = get_config()
|
|
34
36
|
enable = config["ENABLE_DEVTOOLS_DATA"]
|
|
35
37
|
return settings.DEBUG if enable is None else enable
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_devtools_header_max_bytes():
|
|
41
|
+
config = get_config()
|
|
42
|
+
return config["DEVTOOLS_HEADER_MAX_BYTES"]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_devtools_max_queries():
|
|
46
|
+
config = get_config()
|
|
47
|
+
return config["DEVTOOLS_MAX_QUERIES"]
|
|
@@ -9,6 +9,8 @@ from django.template import Context, Engine
|
|
|
9
9
|
|
|
10
10
|
from . import tracker
|
|
11
11
|
from .conf import (
|
|
12
|
+
get_devtools_header_max_bytes,
|
|
13
|
+
get_devtools_max_queries,
|
|
12
14
|
get_enable_devtools_data,
|
|
13
15
|
get_position,
|
|
14
16
|
get_show_bar,
|
|
@@ -58,34 +60,104 @@ class DevBarMiddleware:
|
|
|
58
60
|
return response
|
|
59
61
|
|
|
60
62
|
def _add_devtools_data_header(self, response, stats):
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
max_bytes = get_devtools_header_max_bytes()
|
|
64
|
+
if max_bytes <= 0:
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
summary_data = {
|
|
63
68
|
"c": stats["count"],
|
|
64
69
|
"db": round(stats["duration"], 2),
|
|
65
70
|
"app": stats["python_time"],
|
|
66
71
|
"full": stats["total_time"],
|
|
67
72
|
}
|
|
73
|
+
if self._json_size(summary_data) > max_bytes:
|
|
74
|
+
return
|
|
68
75
|
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
raw_queries = stats.get("queries", [])
|
|
77
|
+
total_query_count = len(raw_queries)
|
|
78
|
+
max_queries = get_devtools_max_queries()
|
|
79
|
+
all_queries = (
|
|
80
|
+
raw_queries[:max_queries] if max_queries is not None else raw_queries
|
|
81
|
+
)
|
|
82
|
+
processed_queries = [
|
|
83
|
+
{
|
|
84
|
+
"s": truncate_sql(q["sql"]),
|
|
85
|
+
"dur": q["duration"],
|
|
86
|
+
"dup": 1 if q["is_duplicate"] else 0,
|
|
87
|
+
"sim": 1 if q.get("is_similar") else 0,
|
|
88
|
+
}
|
|
89
|
+
for q in all_queries
|
|
90
|
+
]
|
|
91
|
+
is_truncated = len(processed_queries) < total_query_count
|
|
71
92
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"sim": 1 if q.get("is_similar") else 0,
|
|
79
|
-
}
|
|
80
|
-
for q in all_queries
|
|
81
|
-
]
|
|
82
|
-
extension_data["q"] = processed_queries
|
|
93
|
+
full_payload = summary_data.copy()
|
|
94
|
+
if processed_queries:
|
|
95
|
+
full_payload["q"] = processed_queries
|
|
96
|
+
if self._json_size(full_payload) <= max_bytes and not is_truncated:
|
|
97
|
+
response["DevBar-Data"] = self._serialize_payload(full_payload)
|
|
98
|
+
return
|
|
83
99
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
100
|
+
best_count = self._max_queries_that_fit(
|
|
101
|
+
summary_data,
|
|
102
|
+
processed_queries,
|
|
103
|
+
max_bytes,
|
|
104
|
+
total_query_count,
|
|
105
|
+
)
|
|
106
|
+
payload = self._build_truncated_payload(
|
|
107
|
+
summary_data,
|
|
108
|
+
processed_queries,
|
|
109
|
+
best_count,
|
|
110
|
+
total_query_count,
|
|
111
|
+
)
|
|
87
112
|
|
|
88
|
-
|
|
113
|
+
if self._json_size(payload) <= max_bytes:
|
|
114
|
+
response["DevBar-Data"] = self._serialize_payload(payload)
|
|
115
|
+
else:
|
|
116
|
+
response["DevBar-Data"] = self._serialize_payload(summary_data)
|
|
117
|
+
|
|
118
|
+
def _json_size(self, data):
|
|
119
|
+
return len(self._serialize_payload(data).encode("utf-8"))
|
|
120
|
+
|
|
121
|
+
def _serialize_payload(self, payload):
|
|
122
|
+
return json.dumps(payload, separators=(",", ":"))
|
|
123
|
+
|
|
124
|
+
def _build_truncated_payload(
|
|
125
|
+
self,
|
|
126
|
+
summary_data,
|
|
127
|
+
processed_queries,
|
|
128
|
+
query_count,
|
|
129
|
+
queries_total,
|
|
130
|
+
):
|
|
131
|
+
payload = summary_data.copy()
|
|
132
|
+
if query_count:
|
|
133
|
+
payload["q"] = processed_queries[:query_count]
|
|
134
|
+
payload["tr"] = 1
|
|
135
|
+
payload["q_total"] = queries_total
|
|
136
|
+
payload["q_sent"] = query_count
|
|
137
|
+
return payload
|
|
138
|
+
|
|
139
|
+
def _max_queries_that_fit(
|
|
140
|
+
self,
|
|
141
|
+
summary_data,
|
|
142
|
+
processed_queries,
|
|
143
|
+
max_bytes,
|
|
144
|
+
queries_total,
|
|
145
|
+
):
|
|
146
|
+
low = 0
|
|
147
|
+
high = len(processed_queries)
|
|
148
|
+
while low < high:
|
|
149
|
+
mid = (low + high + 1) // 2
|
|
150
|
+
payload = self._build_truncated_payload(
|
|
151
|
+
summary_data,
|
|
152
|
+
processed_queries,
|
|
153
|
+
mid,
|
|
154
|
+
queries_total,
|
|
155
|
+
)
|
|
156
|
+
if self._json_size(payload) <= max_bytes:
|
|
157
|
+
low = mid
|
|
158
|
+
else:
|
|
159
|
+
high = mid - 1
|
|
160
|
+
return low
|
|
89
161
|
|
|
90
162
|
def _add_server_timing_header(self, response, stats):
|
|
91
163
|
parts = [
|
|
File without changes
|
{django_devbar-0.6.1 → django_devbar-0.7.0}/src/django_devbar/templates/django_devbar/devbar.html
RENAMED
|
File without changes
|
|
File without changes
|
{django_devbar-0.6.1 → django_devbar-0.7.0}/src/django_devbar/templates/django_devbar/similar.html
RENAMED
|
File without changes
|
|
File without changes
|