appmap
is a Python package for recording AppMaps of your code.
The AppMap data format includes code structure (packages, modules, classes, and methods), trace events (function calls, web services, RPC calls, SQL, parameters, return values, exceptions, etc), and code metadata (repo URL, commit SHA, etc). It’s more granular than a performance profile, but it’s less granular than a full debug trace. It’s designed to be optimal for understanding the design intent and structure of code and key data flows.
AppMap for Python is currently in early access.
Requirements:
Supported Frameworks:
Using a framework we don't support yet? Let us know in Slack!
Support for new versions is added frequently, please check back regularly for updates.
If your project uses pip
for dependency management, add the appmap
package to the requirements
file or install it directly with
pip install appmap
For projects that use poetry
, add the appmap
package to pyproject.toml
.
poetry add --group=dev appmap
pipenv
is also supported:
pipenv install --dev appmap
To use AppMaps in your code editor, you’ll also want to install the corresponding AppMap extension:
Add your modules as path
entries in appmap.yml
, and external packages
(distributions) as dist
:
name: my_python_app
packages:
- path: app.mod1
shallow: true
- path: app.mod2
exclude:
- MyClass
- MyOtherClass.my_instance_method
- MyOtherClass.my_class_method
# You can record dependency packages, such as Django.
# We don't recommend recording Django by default though, your AppMaps will be quite large
# and mostly about Django itself, not your own code.
#- dist: Django
# exclude:
# - django.db
Note that an exclude
is resolved relative to the associated path. So, for example, this
configuration excludes app.mod2.MyClass
.
For external distribution packages
use the dist
specifier; the names are looked up in the
database of installed Python distributions.
This is generally the same package name as you’d give to pip install
or put
in pyproject.toml
. You can additionally use path
and exclude
on dist
entries to limit the capture to specific patterns.
By default, shallow capture is enabled on dist
packages, supressing tracking
of most internal execution flow. This allows you to capture the interaction without
getting bogged down with detail. To see these details, set shallow: false
.
You can also use shallow: true
on path
entries.
The AppMap data format provides for class and
function labels
, which can be used to enhance the AppMap visualizations, and to
programatically analyze the data.
You can apply function labels using the appmap.labels
decorator in your Python code. To
apply a labels to a function, decorate the function with @appmap.labels
.
For example
import appmap
class ApiKey
@appmap.labels('provider.authentication', 'security')
def authenticate(self, key):
# logic to verify the key here...
Then the AppMap metadata section for this function will include:
{
"name": "authenticate",
"type": "function",
"labels": [ "provider.authentication", "security" ]
}
appmap
supports recording pytest and
unittest test cases.
appmap
is a pytest
plugin. When it’s installed in a project that uses
pytest
, it will be available to generate AppMaps.
root@e9987eaa93c8:/src/appmap/test/data/pytest# pip show appmap
Name: appmap
Version: 0.0.0
Summary: Create AppMap files by recording a Python application.
Home-page: None
Author: Alan Potter
Author-email: alan@app.land
License: None
Location: /usr/local/lib/python3.9/site-packages
Requires: orjson, PyYAML, inflection
Required-by:
root@e9987eaa93c8:/src/appmap/test/data/pytest# APPMAP_LOG_LEVEL=info pytest -svv
[2021-02-10 11:37:59,345] INFO root: appmap enabled: True
[2021-02-10 11:37:59,350] INFO appmap._implementation.configuration: ConfigFilter, includes {'simple'}
[2021-02-10 11:37:59,350] INFO appmap._implementation.configuration: ConfigFilter, excludes set()
===================================================================== test session starts =====================================================================
platform linux -- Python 3.9.1, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 -- /usr/local/bin/python
cachedir: .pytest_cache
rootdir: /src, configfile: pytest.ini
plugins: appmap-0.0.0
collected 1 item
test_simple.py::test_hello_world [2021-02-10 11:37:59,482] INFO appmap.pytest: starting recording /tmp/pytest/test_hello_world.appmap.json
[2021-02-10 11:37:59,484] INFO appmap._implementation.configuration: included class simple.Simple
[2021-02-10 11:37:59,484] INFO appmap._implementation.configuration: included function simple.Simple.hello
[2021-02-10 11:37:59,489] INFO appmap._implementation.configuration: included function simple.Simple.hello_world
[2021-02-10 11:37:59,490] INFO appmap._implementation.configuration: included function simple.Simple.world
[2021-02-10 11:37:59,828] INFO appmap.pytest: wrote recording /tmp/pytest/test_hello_world.appmap.json
PASSED
====================================================================== 1 passed in 0.45s ======================================================================
A subclass of unittest.TestCase
is instrumented automatically, and an AppMap is recorded for each
test_*
function in the subclass.
appmap-python
can automatically record and save an AppMap for each HTTP server request. To do this, the AppMap agent hooks into the web server request processing framework. It starts a recording when each new request is received,
records the execution thread into an AppMap, and saves in when the request is completed.
Note Your application must be running in a supported web framework (Django, Flask) for requests recording to work.
The AppMap agent supports remote recording of Django and Flask web applications during development. When your application is run with debugging support, remote recording will be enabled automatically.
To enable debugging support, ensure:
DEBUG = True
in settings.py--debug
optionNote Your application must be running in a supported web framework (Django, Flask) for remote recording to work.
You can use appmap.record
as a context manager to record a specific span of code. With this method, you can control exactly
what code is recorded, and where the recording is saved.
Given a source file record_sample.py
:
import os
import sys
import appmap
r = appmap.Recording()
with r:
import sample
print(sample.C().hello_world(), file=sys.stderr)
with os.fdopen(sys.stdout.fileno(), "w", closefd=False) as stdout:
stdout.write(appmap.generation.dump(r))
stdout.flush()
and a source file sample.py
:
class C:
def make_str(self, s):
return s;
def hello_world(self):
return f'{self.make_str("Hello")} {self.make_str("world!")}'
as well as appmap.yml
:
name: sample
packages:
- path: sample
language: python
appmap_dir: tmp/appmap
you can generate a recording of the code
% python record_sample.py > record_sample.appmap.json
% jq '.events | length' record_sample.appmap.json
6
% jq < record_sample.appmap.json | head -10
{
"version": "1.4",
"metadata": {
"language": {
"name": "python",
"engine": "CPython",
"version": "3.9.1"
},
"client": {
"name": "appmap",
appmap-python
integrates with both the Django and Flask web frameworks. When an application is started in a development environment, it inserts itself into the application’s request processing stack. This enables recording of requests, as well as support for the AppMap remote recording API.
To start a Django app with AppMap integration enabled, add
DEBUG = True
to your application’s settings.py
.
When flask
is invoked with the --debug
switch, debugging is enabled, as well as AppMap integration.
These environment variables can be used to control various aspects of the AppMap agent.
APPMAP_CONFIG
specifies the configuration file to use. Defaults to appmap.yml
in the
current directory.
APPMAP_LOG_LEVEL
specifies log level to use, from the set CRITICAL
, ERROR
,
WARNING
, INFO
, DEBUG
. Not case-sensitive, defaults to INFO
.
APPMAP_DISPLAY_PARAMS
enables rendering of parameters as strings. If true
(the
default, not case-sensitive), parameters are rendered using repr
. If
false
, a generic string is used instead.
APPMAP_RECORD_<PYTEST|UNITTEST>
disables recording for individual test frameworks when set to false
. For example, to disable recording when using pytest
, use the variable APPMAP_RECORD_PYTEST
.
APPMAP_RECORD_REQUESTS
disables recording of HTTP requests when set to false
.
APPMAP_RECORD_REMOTE
disables remote recording when set to false
.
APPMAP
controls all instrumentation and recording. When set to false
, application code will run as if the AppMap agent was not installed.
https://github.com/getappmap/appmap-python