-
Notifications
You must be signed in to change notification settings - Fork 2
Understanding Reports
Learn to read, interpret, and act on Mercury's performance reports. Every metric tells a story about your application's health.
Mercury reports are designed to be:
- Progressive: Simple overview โ Detailed analysis
- Actionable: Every issue includes a solution
- Educational: Learn while you analyze
- Adaptive: Different details per profile
Every Mercury report starts with a dashboard:
๐จ MERCURY PERFORMANCE DASHBOARD - UserAPITests
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ ๐ Overall Status: NEEDS IMPROVEMENT โ
โ ๐ Overall Grade: C (65/100) โ
โ ๐ Tests Executed: 12 โ
โ โฑ๏ธ Avg Response Time: 105.6ms โ
โ ๐ง Avg Memory Usage: 45.7MB โ
โ ๐๏ธ Total Queries: 567 (47.25 avg) โ
โ ๐จ N+1 Issues: 3/12 tests affected โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
Let's break down each element:
Status levels indicate urgency:
- โ EXCELLENT: Everything is optimized
- โ GOOD: Minor improvements possible
-
โ ๏ธ NEEDS IMPROVEMENT: Notable issues to address - โ CRITICAL: Serious performance problems
Mercury uses an academic grading system:
| Grade | Score | Meaning | Action Required |
|---|---|---|---|
| S | 100 | Perfect | None - celebrate! ๐ |
| A+ | 95-99 | Excellent | Minor tweaks only |
| A | 90-94 | Very Good | Polish for perfection |
| B | 80-89 | Good | Some optimization needed |
| C | 70-79 | Acceptable | Clear room for improvement |
| D | 60-69 | Poor | Significant issues |
| F | <60 | Failing | Critical problems |
# Grade components and weights
Response Time: 40%
Query Count: 30%
Memory Usage: 20%
Cache Performance: 10%
# Example calculation
Response: 85/100 ร 0.4 = 34
Queries: 70/100 ร 0.3 = 21
Memory: 90/100 ร 0.2 = 18
Cache: 60/100 ร 0.1 = 6
โโโโโโโโโโโโโโโโโโโโโโโโโ
Total: 79/100 = Grade CWhat it measures: Time from request to response
Response Time: 156ms
โโ Database: 89ms (57%)
โโ Python Logic: 45ms (29%)
โโ Template Rendering: 12ms (8%)
โโ Other: 10ms (6%)
Thresholds:
- Excellent: <50ms
- Good: 50-100ms
- Acceptable: 100-200ms
- Slow: 200-500ms
- Critical: >500ms
Common Causes of Slow Response:
- Unoptimized queries (most common)
- Complex computations in views
- External API calls without caching
- Large data serialization
What it measures: Number of database queries per request
Query Analysis:
Total Queries: 89
โโ SELECT: 87
โโ INSERT: 1
โโ UPDATE: 1
โโ DELETE: 0
Duplicate Queries: 43 (48%)
N+1 Detected: Yes
Thresholds:
- Excellent: 1-5 queries
- Good: 6-10 queries
- Acceptable: 11-20 queries
- High: 21-50 queries
- Critical: >50 queries
Reading Query Patterns:
# Good pattern (2 queries)
SELECT users...
SELECT profiles WHERE user_id IN (1,2,3...)
# Bad pattern (N+1, 101 queries)
SELECT users...
SELECT profile WHERE user_id = 1
SELECT profile WHERE user_id = 2
... (98 more)
What it measures: RAM consumed during request
Memory Breakdown:
Total: 45.7MB
โโ Django ORM: 28.3MB (62%)
โโ Python Objects: 12.1MB (26%)
โโ Templates: 3.2MB (7%)
โโ Other: 2.1MB (5%)
Peak Usage: 67.8MB
Baseline: 23.4MB
Overhead: 44.4MB
Thresholds:
- Excellent: <10MB overhead
- Good: 10-25MB
- Acceptable: 25-50MB
- High: 50-100MB
- Critical: >100MB
Common Memory Issues:
- Loading entire querysets into memory
- Large serialized responses
- Unbounded caches
- Memory leaks in views
What it measures: Cache hit/miss ratio
Cache Statistics:
Hit Rate: 73%
โโ Database Cache: 45/50 (90%)
โโ Template Cache: 12/20 (60%)
โโ API Cache: 8/15 (53%)
โโ Static Files: 15/15 (100%)
Missed Opportunities: 12
Suggested Cache Keys:
- user_list_page_1
- product_details_5
Target Hit Rates:
- Excellent: >90%
- Good: 80-90%
- Acceptable: 70-80%
- Poor: 50-70%
- Critical: <50%
Mercury identifies N+1 patterns:
๐จ N+1 QUERY PATTERN DETECTED
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Location: UserSerializer.to_representation()
Pattern: Accessing user.profile in loop
Query Pattern Found:
1. SELECT * FROM users (1 query)
2. SELECT * FROM profiles WHERE user_id = ? (N queries)
Impact: 101 queries for 100 users
Solution:
queryset = User.objects.select_related('profile')
Expected Improvement:
101 queries โ 1 query (99% reduction)
๐ SLOW QUERY DETECTED
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Query: SELECT * FROM orders WHERE status = 'pending'
AND created_at > '2024-01-01'
Execution Time: 342ms
Rows Examined: 45,678
Rows Returned: 234
Missing Index: orders.status, orders.created_at
Solution:
class Meta:
indexes = [
models.Index(fields=['status', 'created_at'])
]
Expected Improvement:
342ms โ ~15ms (95% faster)
๐ MEMORY SPIKE DETECTED
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Location: ProductListView.get_queryset()
Spike: 23MB โ 89MB (+66MB)
Cause: Loading all products into memory
products = list(Product.objects.all())
Solution:
Use pagination or iterator():
products = Product.objects.iterator(chunk_size=100)
Expected Improvement:
66MB overhead โ ~5MB (92% reduction)
Educational and detailed:
๐ PERFORMANCE REPORT - EDUCATIONAL MODE
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Test: test_user_list_api
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Grade: D (65/100)
What happened:
โ Response took 234ms (should be under 100ms)
โ Made 89 queries (should be under 10)
โ Memory usage OK at 23MB
Why this matters:
โข Slow pages frustrate users
โข Many queries = database overload
โข This will get worse with more data
How to fix (step by step):
1. Open views.py line 45
2. Find: users = User.objects.all()
3. Change to: users = User.objects.select_related('profile')
4. Run test again to verify
Learn more:
mercury-test --learn n1-queries
You're learning! Every fix makes you better! ๐ช
Concise and technical:
PERFORMANCE METRICS
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
test_user_list 234ms 89q 23MB D N+1@L45
test_user_detail 45ms 3q 12MB B OK
test_user_create 67ms 5q 18MB B OK
test_user_search 456ms 234q 45MB F N+1@L78,L92
Critical: 2 N+1 patterns
Action: select_related on L45, prefetch_related on L78
Structured JSON:
{
"summary": {
"grade": "D",
"score": 65,
"status": "needs_improvement"
},
"metrics": {
"response_time_ms": 234,
"query_count": 89,
"memory_mb": 23,
"cache_hit_ratio": 0.73
},
"issues": [
{
"type": "n_plus_one",
"severity": "high",
"location": "views.py:45",
"impact": {
"queries_excess": 84,
"time_excess_ms": 134
},
"fix": {
"code": "User.objects.select_related('profile')",
"auto_applicable": false,
"requires_review": true
}
}
],
"recommendations": [
"Add database indexes",
"Implement query caching",
"Use pagination"
]
}- Response time >1 second
- 100+ queries per request
- Memory usage >200MB
- Complete cache misses
- Response time 500ms-1s
- 50-100 queries
- Memory usage 100-200MB
- Cache hit rate <50%
- Response time 200-500ms
- 20-50 queries
- Memory usage 50-100MB
- Cache hit rate 50-70%
- Response time 100-200ms
- 10-20 queries
- Memory usage 25-50MB
- Cache hit rate 70-80%
๐ PERFORMANCE COMPARISON
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Baseline โ Current Change Status
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Response: 145ms โ 89ms -38.6% โ
Improved
Queries: 67 โ 45 -32.8% โ
Improved
Memory: 34MB โ 38MB +11.7% โ ๏ธ Increased
Cache: 65% โ 82% +26.1% โ
Improved
Overall: Performance IMPROVED by 27%
Biggest wins:
โข UserListView: 78% faster
โข ProductSearch: 65% fewer queries
New issues:
โข OrderHistoryView: Memory increased 45%
๐ PERFORMANCE TRENDS (Last 7 Days)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Response Time:
Mon โโโโโโโโโโโโโโโโ 156ms
Tue โโโโโโโโโโโโโโโ 145ms
Wed โโโโโโโโโโโโโ 134ms
Thu โโโโโโโโโโโโ 128ms
Fri โโโโโโโโโโ 112ms
Sat โโโโโโโโโ 98ms โ Best
Sun โโโโโโโโโโ 105ms
Pattern: Steady improvement
Recommendation: Current optimizations working
Use this matrix to decide what to fix first:
High Impact
โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ 1 โ 2 โ
โ CriticalโImportantโ
โ & Easy โ & Easy โ
โโโโโโโโโโโผโโโโโโโโโโค
โ 3 โ 4 โ
โCritical โImportantโ
โ & Hard โ & Hard โ
โโโโโโโโโโโดโโโโโโโโโโ
Easy โโโโโโโโโโ Hard
Fix Order:
- High impact, easy fixes (N+1 queries)
- High impact, moderate difficulty (indexes)
- Lower impact, easy fixes (caching)
- Complex architectural changes (last)
Transform report issues into tasks:
# From report
"N+1 in UserSerializer, 89 queries"
# To action item
"""
Task: Fix N+1 in UserSerializer
Priority: High
Estimate: 15 minutes
Steps:
1. Open serializers.py
2. Update queryset in ViewSet
3. Add select_related('profile')
4. Run tests to verify
Expected: 89 queries โ 2 queries
"""Document your fixes:
## Performance Improvements Log
### 2024-01-15
- **Issue**: N+1 in UserListView
- **Fix**: Added select_related
- **Result**: 89 queries โ 2 queries
- **Impact**: 234ms โ 45ms (80% faster)
### 2024-01-16
- **Issue**: Missing index on orders.status
- **Fix**: Added database index
- **Result**: 342ms โ 15ms query time
- **Impact**: Overall 50% speed improvementNo single critical issue, but many small ones:
- 15 queries (not terrible)
- 150ms response (not terrible)
- 35MB memory (not terrible)
- 60% cache hits (not terrible)
Combined: Grade D performance
Fix: Address all small issues systematically
Everything excellent except one critical issue:
- โ
3 queries
- โ 2.5 second response time
- โ
15MB memory
- โ
95% cache hits
Cause: External API call without timeout
Fix: Add timeout and async processing
Seems OK at first:
- 12 queries (acceptable)
- 89ms response (good)
But with more data:
- 120 queries (10x users)
- 890ms response (10x slower)
Classic N+1 scaling problem
# mercury_config.toml
[reporting]
detail_level = "high" # low, medium, high
show_sql_queries = true
show_stack_traces = false
show_suggestions = true
group_by = "test_class" # test_class, endpoint, severity# HTML report for sharing
mercury-test --format=html > report.html
# CSV for spreadsheet analysis
mercury-test --format=csv > metrics.csv
# Markdown for documentation
mercury-test --format=markdown > PERFORMANCE.md# Just show failures
mercury-test --report-failures-only
# Show worst performers
mercury-test --show-worst 5
# Filter by metric
mercury-test --report-filter="queries>50"Look for patterns across tests:
- Same issue in multiple places?
- Issues clustered in one app?
- Certain operations always slow?
Over time, you'll recognize issues instantly:
- "45 queries for 10 items = N+1"
- "500ms for simple list = missing index"
- "Memory spike = loading full queryset"
Share interesting reports with your team:
- "Look at this N+1 I found!"
- "Check out this optimization"
- "Here's a pattern to avoid"
- Take Action: Workflow Best Practices
- Learn More: Educational Mode
- Get Started: Quick Start Guide
- Explore Features: Plugin System
Remember: Reports are not judgments, they're opportunities to improve.