-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathsqlalchemy.py
More file actions
62 lines (55 loc) · 2.3 KB
/
sqlalchemy.py
File metadata and controls
62 lines (55 loc) · 2.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
"""SQL statement capture for SQLAlchemy."""
import time
from importlib.metadata import version
from sqlalchemy import event
from sqlalchemy.engine import Engine
from _appmap.event import ReturnEvent, SqlEvent
from _appmap.instrument import is_instrumentation_disabled
from _appmap.metadata import Metadata
from _appmap.recorder import Recorder
@event.listens_for(Engine, "before_cursor_execute")
# pylint: disable=too-many-arguments,unused-argument,too-many-positional-arguments
def capture_sql_call(conn, cursor, statement, parameters, context, executemany):
"""Capture SQL query call into appmap."""
if is_instrumentation_disabled():
# We must be in the middle of fetching object representation.
# Don't record this query in the appmap.
pass
elif Recorder.get_enabled():
Metadata.add_framework("SQLAlchemy", version("sqlalchemy"))
if executemany:
# Sometimes the same query is executed with different parameter sets.
# Instead of substituting them all, just say how many times it was run.
try:
times = len(parameters)
except TypeError:
times = "?"
sql = "-- %s times\n%s" % (times, statement)
else:
sql = statement
dialect = conn.dialect
call_event = SqlEvent(
sql, vendor=dialect.name, version=dialect.server_version_info
)
Recorder.add_event(call_event)
setattr(
context,
"appmap",
{"start_time": time.monotonic(), "call_event_id": call_event.id},
)
@event.listens_for(Engine, "after_cursor_execute")
# pylint: disable=too-many-arguments,unused-argument,too-many-positional-arguments
def capture_sql(conn, cursor, statement, parameters, context, executemany):
"""Capture SQL query return into appmap."""
if is_instrumentation_disabled():
# We must be in the middle of fetching object representation.
# Don't record this query in the appmap.
pass
elif Recorder.get_enabled():
stop = time.monotonic()
duration = stop - context.appmap["start_time"]
return_event = ReturnEvent(
parent_id=context.appmap["call_event_id"], elapsed=duration
)
del context.appmap
Recorder.add_event(return_event)