Skip to content

Commit 81e5226

Browse files
committed
feat: add process recording
1 parent b180f90 commit 81e5226

File tree

5 files changed

+69
-4
lines changed

5 files changed

+69
-4
lines changed

_appmap/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from . import configuration
22
from . import env as appmapenv
3-
from . import event, importer, metadata, recorder, web_framework
3+
from . import event, importer, metadata, recorder, recording, web_framework
44
from .py_version_check import check_py_version
55

66

@@ -13,6 +13,7 @@ def initialize(**kwargs):
1313
configuration.initialize() # needs to be initialized after recorder
1414
metadata.initialize()
1515
web_framework.initialize()
16+
recording.initialize()
1617

1718

1819
initialize()

_appmap/recording.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
import atexit
2+
import datetime
3+
import os
4+
from tempfile import NamedTemporaryFile
5+
6+
from _appmap import generation
7+
from _appmap.web_framework import APPMAP_SUFFIX, HASH_LEN, NAME_MAX, name_hash
8+
19
from .env import Env
210
from .recorder import Recorder
311

@@ -68,3 +76,25 @@ def write_appmap(
6876
appmap_file = basedir / filename
6977
logger.info("info, writing %s", appmap_file)
7078
os.replace(tmp.name, appmap_file)
79+
80+
81+
def initialize():
82+
if Env.current.enables("process", "false"):
83+
r = Recording()
84+
r.start()
85+
86+
def save_at_exit():
87+
nonlocal r
88+
r.stop()
89+
appmap_name = datetime.utcnow().isoformat(timespec='seconds') + "Z"
90+
recorder_type = "process"
91+
metadata = {
92+
"name": appmap_name,
93+
"recorder": {
94+
"name": "process",
95+
"type": recorder_type,
96+
}
97+
}
98+
write_appmap(r, appmap_name, recorder_type, metadata)
99+
100+
atexit.register(save_at_exit)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import sys
2+
3+
from .mod1 import Mod1Class
4+
5+
def main():
6+
print(Mod1Class().func())
7+
return 0
8+
9+
sys.exit(main())

_appmap/test/test_recording.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import json
55
import os
6+
from distutils.dir_util import copy_tree
7+
from distutils.file_util import copy_file
68
from threading import Thread
79

810
import pytest
@@ -168,9 +170,7 @@ def add_event(name):
168170
r.add_event(Event({"name": name}))
169171
recorders[name] = r
170172

171-
threads = [
172-
Thread(target=add_event, args=(f"thread{i}",)) for i in range(thread_count)
173-
]
173+
threads = [Thread(target=add_event, args=(f"thread{i}",)) for i in range(thread_count)]
174174
for _, t in enumerate(threads):
175175
t.start()
176176
for _, t in enumerate(threads):
@@ -188,3 +188,27 @@ def add_event(name):
188188
events = recorders[f"thread{n}"].events
189189
assert len(events) == 1
190190
assert events[0].event["name"] == f"thread{n}"
191+
192+
193+
def test_process_recording(data_dir, shell, tmp_path):
194+
fixture = data_dir / "package1"
195+
tmp = tmp_path / "process"
196+
copy_tree(fixture, str(tmp / "package1"))
197+
copy_file(data_dir / "appmap.yml", str(tmp))
198+
copy_tree(data_dir / "flask" / "init", str(tmp / "init"))
199+
200+
ret = shell.run(
201+
"python",
202+
"-m",
203+
"package1.package2",
204+
env={"PYTHONPATH": "init", "APPMAP_RECORD_PROCESS": "true"},
205+
cwd=tmp,
206+
)
207+
assert ret.returncode == 0
208+
209+
appmap_dir = tmp / "tmp" / "appmap" / "process"
210+
appmap_files = list(appmap_dir.glob("*.appmap.json"))
211+
assert len(appmap_files) == 1
212+
actual = json.loads(appmap_files[0].read_text())
213+
assert len(actual["events"]) > 0
214+
assert len(actual["classMap"]) > 0

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ python-decouple = "^3.5"
8080
black = "^22.8.0"
8181
isort = "^5.10.1"
8282
pylint = "^2.16.2"
83+
pytest-shell-utilities = "^1.8.0"
8384

8485
[build-system]
8586
requires = ["poetry-core>=1.1.0"]

0 commit comments

Comments
 (0)