feat: profile requests using recorder
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
This commit is contained in:
parent
c02f5d5876
commit
3c183344aa
3 changed files with 29 additions and 2 deletions
|
|
@ -20,7 +20,9 @@
|
|||
"section_break_sgro",
|
||||
"form_dict",
|
||||
"section_break_9jhm",
|
||||
"sql_queries"
|
||||
"sql_queries",
|
||||
"section_break_optn",
|
||||
"profile"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
|
|
@ -107,6 +109,16 @@
|
|||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Event Type"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_optn",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "profile",
|
||||
"fieldtype": "Code",
|
||||
"label": "cProfile Output",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
|
|
@ -114,7 +126,7 @@
|
|||
"index_web_pages_for_search": 1,
|
||||
"is_virtual": 1,
|
||||
"links": [],
|
||||
"modified": "2024-01-03 16:45:47.110048",
|
||||
"modified": "2024-02-01 22:13:26.505174",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Recorder",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class Recorder(Document):
|
|||
method: DF.Literal["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]
|
||||
number_of_queries: DF.Int
|
||||
path: DF.Data | None
|
||||
profile: DF.Code | None
|
||||
request_headers: DF.Code | None
|
||||
sql_queries: DF.Table[RecorderQuery]
|
||||
time: DF.Datetime | None
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: MIT. See LICENSE
|
||||
import cProfile
|
||||
import datetime
|
||||
import functools
|
||||
import inspect
|
||||
import io
|
||||
import json
|
||||
import pstats
|
||||
import re
|
||||
import time
|
||||
from collections import Counter
|
||||
|
|
@ -148,6 +151,8 @@ class Recorder:
|
|||
self.uuid = frappe.generate_hash(length=10)
|
||||
self.time = datetime.datetime.now()
|
||||
self.calls = []
|
||||
self.profiler = cProfile.Profile()
|
||||
self.profiler.enable()
|
||||
if frappe.request:
|
||||
self.path = frappe.request.path
|
||||
self.cmd = frappe.local.form_dict.cmd or ""
|
||||
|
|
@ -176,6 +181,13 @@ class Recorder:
|
|||
self.calls.append(data)
|
||||
|
||||
def dump(self):
|
||||
self.profiler.disable()
|
||||
|
||||
profiler_output = io.StringIO()
|
||||
pstats.Stats(self.profiler, stream=profiler_output).strip_dirs().sort_stats(
|
||||
"cumulative"
|
||||
).print_stats()
|
||||
|
||||
request_data = {
|
||||
"uuid": self.uuid,
|
||||
"path": self.path,
|
||||
|
|
@ -197,6 +209,8 @@ class Recorder:
|
|||
request_data["calls"] = self.calls
|
||||
request_data["headers"] = self.headers
|
||||
request_data["form_dict"] = self.form_dict
|
||||
request_data["profile"] = profiler_output.getvalue()
|
||||
profiler_output.close()
|
||||
frappe.cache.hset(RECORDER_REQUEST_HASH, self.uuid, request_data)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue