WIP:
- [x] Basic working feature
- [ ] Make this optional, this has insanely high overhead.
- [ ] Specify requests/function filter to profile/record. This will
allow better recording in production sites.
- [ ] Make SQL profiling optional too
* Revert "fix(test_recorder): get the correct request (#24143)"
This reverts commit 745080c56e.
* test: disable recording before running assertions
* test: Dont set emails in test for broken email setup
* fix: Show server script name in traceback
* chore: typo
Co-authored-by: Sagar Vora <sagar@resilient.tech>
---------
Co-authored-by: Sagar Vora <sagar@resilient.tech>
Attempt to normalize query by removing "variables"
This gives a different view of similar duplicate queries.
These two are distinct queries:
```sql
select * from user where name = 'x'
select * from user where name = 'z'
```
But their "normalized" form would be same:
```sql
select * from user where name = ?
```
This helps highlight queries ran in loop which might not register as
duplicate but are possibly "duplicate".
By processing `EXPLAIN` of queries in background after recording is
completed, the overhead reduces significantly and hence can be used
"more" in production environment too.
Currently frappe recorder can be enabled globally and profiles every
request. This is often way too much info. If you already know where
problem lies you use this decorator sparingly to only profile relevant
functions.
Usage:
```py
from frappe.recorder import record_queries
@record_queries
def sus_slow_function():
frappe.db.sql("select everything from everywhere")
```
* fix: use monotonic time for timing code
`time.time()` depends on system clock which can drift away and get corrected
over time. If you're unlucky it will get corrected in your timing code
and give absurd results.
* test: dont check for status
can refresh and give wrong output
[skip ci]
refactor: clean up code to py39+ supported syntax
- f-strings instead of format
- latest typing support instead of pre 3.9 TitleCase
- remove UTF-8 declarations.
- many more changes
Powered by https://github.com/asottile/pyupgrade/ + manual cleanups
Converted all possible usages of re.* that weren't compiling the regex
separately and re-using it. Separated out the compiled patterns as
global variables. Repetitive patterns could be made DRY-er.
Would be nicer to have all regexes in a single module so that we could
re-use better, keep track of outdated, and keep checks for possible
reDos' etc
The license.txt file has been replaced with LICENSE for quite a while
now. INAL but it didn't seem accurate to say "hey, checkout license.txt
although there's no such file". Apart from this, there were
inconsistencies in the headers altogether...this change brings
consistency.
* Remove six for PY2 compatability since our dependencies are not, PY2
is legacy.
* Removed usages of utils from future/past libraries since they are
deprecated. This includes 'from __future__ ...' and 'from past...'
statements.
* Removed compatibility imports for PY2, switched from six imports to
standard library imports.
* Removed utils code blocks that handle operations depending on PY2/3
versions.
* Removed 'from __future__ ...' lines from templates/code generators
* Used PY3 syntaxes in place of PY2 compatible blocks. eg: metaclass
Add breadcrumb for backward navigation
Add Table view for SQL Explain
Add __debug__ check for NOOP in production
Remove unnecessary v-bind
Use router.push instead of router-link
Route to request-detail page if route is set to /request/:id