Lightweight Django middleware for profiling SQL queries, detecting performance issues, and analyzing request execution.
Project description
🚀 ami-djAPI-analyzing
A lightweight Django performance analysis tool for monitoring SQL queries, request performance, and detecting common database issues such as:
- N+1 queries
- Duplicate queries
- Slow queries
- Missing indexes
It provides detailed profiling information directly via response headers and API responses.
✨ Features
- 📊 Capture all SQL queries executed during a request
- 🔁 Automatic N+1 query detection
- 🔍 Detect duplicate queries
- ⚡ Identify slow SQL queries
- 📌 Detect potential missing indexes
- ⏱ Analyze DB time vs total response time
- 🧠 Performance scoring system (A–F grading)
- 🗂 Track request history
- 💾 Monitor memory usage
- 📈 Generate EXPLAIN plans for slow queries
- 🔎 Optional step-by-step view execution profiling
- 🔐 Encrypted performance payload in response headers
📦 Installation
pip install ami-djAPI-analyzing
⚙️ Setup
Add the middleware to your Django project:
MIDDLEWARE = [
...
'ami_djapi_analyzing.middleware.PerformanceMiddleware',
]
🔥 Usage Flow
1️⃣ Make an API Request
Call any API endpoint in your Django project.
You will receive additional headers like:
{
"agent_encrypted": "...",
"X-Encryption-Key": "your-encryption-key"
}
🧪 How to Use (Decrypt & Analyze Performance Data)
1️⃣ Install Required Dependencies
pip install requests cryptography
2️⃣ Decrypt the Performance Payload
import json
import base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def decrypt_agent_payload(agent_encrypted: str, key_b64: str) -> dict:
key = base64.b64decode(key_b64)
raw = base64.b64decode(agent_encrypted)
nonce, ciphertext = raw[:12], raw[12:]
aesgcm = AESGCM(key)
plaintext = aesgcm.decrypt(nonce, ciphertext, None)
return json.loads(plaintext)
3️⃣ Make API Requests & Extract Data
import requests
import json
session = requests.Session()
def make_request(req):
try:
response = session.request(
method=req.get("method", "GET"),
url=req.get("url"),
headers=req.get("headers"),
params=req.get("params"),
data=req.get("data"),
json=req.get("json")
)
output = {
"status_code": response.status_code,
"agent_data": None
}
try:
output["json"] = response.json()
except:
pass
if "agent_encrypted" in response.headers and "X-Encryption-Key" in response.headers:
try:
output["agent_data"] = decrypt_agent_payload(
response.headers["agent_encrypted"],
response.headers["X-Encryption-Key"]
)
except Exception as e:
output["agent_data"] = f"Decryption failed: {str(e)}"
return output
except Exception as e:
return {"error": str(e)}
4️⃣ Example Requests
🔹 JSON Request
REQUESTS = [
{
"method": "POST",
"url": "http://127.0.0.1:8000/auth/login/",
"headers": {
"Content-Type": "application/json",
},
"json": {
"emp_id": "112",
"password": "Amit@123"
}
}
]
🔹 Bearer Token + Form Data Request
TOKEN = "your-access-token"
REQUESTS = [
{
"method": "POST",
"url": "http://localhost:8000/auth/register/",
"headers": {
"Accept": "application/json",
"Authorization": f"Bearer {TOKEN}"
},
"data": [
("user_status", "active"),
("first_name", "ac"),
("last_name", "r"),
("emp_id", "1019"),
("email", "ac@gmailc.com"),
("workcenter", "8"),
("workcenter", "9"),
("plant", "37"),
("role_id", "7"),
("password", "Qwe2@1234"),
]
}
]
5️⃣ Run Requests
if __name__ == "__main__":
for i, req in enumerate(REQUESTS, start=1):
print(f"\n========== REQUEST {i} ==========")
result = make_request(req)
print(json.dumps(result, indent=4))
📊 Output Structure
After decryption, you will get detailed performance insights, not just summary.
🔍 Example Output
{
"summary": {
"query_count": 3,
"db_time": 0.003,
"response_time": 0.0167,
"score": 100,
"grade": "A"
},
"sql_queries": [
{
"sql": "SELECT ...",
"time": 0.0012,
"model": "auth_user"
}
],
"top_slow_queries": [
{
"sql": "SELECT ...",
"time": 0.0012
}
],
"sql_analysis": {
"duplicate_queries": [],
"n_plus_one_queries": [],
"slow_query_count": 0
}
}
---
### 📌 Key Sections Explained
- **summary** → Overall performance score (A–F)
- **sql_queries** → All executed SQL queries
- **top_slow_queries** → Slowest queries
- **sql_analysis**
- duplicate_queries
- n_plus_one_queries
- slow_query_count
- **memory_usage** → Memory consumption
- **request_history** → Past request performance
---
## 💡 Best Practices
- Use in **development or staging environments**
- Avoid exposing headers in production without proper security
- Great for:
- Debugging Django ORM issues
- Optimizing API performance
- Identifying database bottlenecks
---
## 🚀 Future Improvements
- CLI tool support
- Web dashboard for visualization
- Postman integration
---
## 🧑💻 Author
Made with ❤️ by Ami
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ami_djapi_analyzing-0.1.1.tar.gz.
File metadata
- Download URL: ami_djapi_analyzing-0.1.1.tar.gz
- Upload date:
- Size: 8.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a82589aad50289efbfea0ea9cbdc6eb365cb000c01765467ba89e5e8ec08e884
|
|
| MD5 |
fdee979446e7fe25a26794ec97e31b2c
|
|
| BLAKE2b-256 |
71e42a8436ebcbbf03ff6fd2f34cf1d6c3a5cbfdd8f6437f54a2b909a9102c97
|
File details
Details for the file ami_djapi_analyzing-0.1.1-py3-none-any.whl.
File metadata
- Download URL: ami_djapi_analyzing-0.1.1-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bd727eabf2a87fda935e4019c4d3b128e85cda16cb5f80c581f16f99d4db687a
|
|
| MD5 |
e23ba290bb0f99f2c0cefe9052427f59
|
|
| BLAKE2b-256 |
4f97be6503e053e8e5269814371cf54bd8b14f8831daabb419a219c311c12702
|