Recording methods

Overview

Recording automated tests is an excellent way to make AppMaps, but there are situations where other methods are needed:

  • when test coverage is thin.
  • when the server runs in a separate process from the test cases.
  • when recording distributed applications that consist of multiple components (such as microservices) deployed to multiple VMs.

AppMap agents can record all running application code - not just tests - provided there is control logic that determines when the recording is started, when it stopped, and how it should be named. Automated tests offer a convenient automated control layer as they trigger recording when they start, the recording stops when they finish, and the AppMaps files are naturally named after the tests - which are typically understandable names. In the absence of a test layer, the recording control has to be performed manually by code or by a human operator.

Direct code block recording

All AppMap agents provide an API that enables rapid recording of execution of a block of code. This is a useful method for a quick spin of application logic without tests such as when prototyping new code or troubleshooting stubborn bugs. The method can be performed with a few lines of code, it allows for programmatic control of the recording context, and it does not require an upfront setup of functional or integration tests. You can read more details about Appmap.record() in the agent documentation.

Examples:

Remote recording

Remote recording allows starting, stopping, retrieving and storing the AppMaps from a remote host. When AppMap agents are set up and running, they expose the recording API via REST endpoints that can be invoked by control logic run on the same or remote hosts. This control logic can be implemented programmatically or performed by human operators and the Browser Extension with its Start/Stop button.

Simple remote recording

Let us consider this recording scenario where a test framework executes functional/integration tests that in turn interact with the tested application deployed to a remote host. These tests may perform both API- and UI-driven testing:

Simple remote recording diagram

Fig. 1 Simple remote recording diagram

Setup

  • Functional1 tests are run by a test framework on Host A
  • Functional tests interact with the application running on Host B
  • AppMap agent records the application on Host B

Execution flow

In this setup, an AppMap is recorded and saved to disk when this flow is completed:

  1. Prior to each individual test’s execution, the test framework calls the AppMap agent’s endpoint that starts recording the application on Host B
  2. The test framework starts a test on Host A
  3. The test interacts with the tested application on Host B. AppMap agent records the execution of the tested application on Host B
  4. When the test finishes on Host A, the test framework calls the AppMap agent’s endpoint to finish recording on Host B
  5. In the response payload, the AppMap agent returns the recorded AppMap back to the test framework. The test framework names the returned AppMap and saves it to disk on Host A.

These steps are repeated by the test framework for all tests in a suite. When finished, the AppMap files will have been stored on Host A and ready for downstream processing, either in an AppMap code editor plugin or in an AppMap Server.

Instructions for remote recording

Additional detailed instructions are provided in the documentation of AppMap agents.

Install and configure the agent

Install and configure the AppMap agent on Host B. Follow the agent installation instructions for Java, Python, or Ruby agents and configure the agent in appmap.yml.

Start remote recording

Having the AppMap agent installed and running with the tested application on Host B, configure the test framework2 on Host A to call the AppMap agent endpoints when the tests are started and finished, and to save the recorded AppMaps to disk.

Use this HTTP call to start recording the app on Host B:

POST /_appmap/record

No payload in the request is expected.

This endpoint returns 200 if a new recording session was started successfully or 409 if an existing recording session was already in progress. It returns an empty body in the response.

Stop remote recording and save AppMaps to disk

To stop recording and to receive the recorded AppMap, call this endpoint:

DELETE /_appmap/record

No payload in the request is expected.

This method returns 200 If an active recording session was stopped successfully, and the body contains AppMap JSON, or 404 If there was no active recording session to be stopped.

If successful, the recorded AppMap is returned in the response body.

Content-type: application/json
{
  "version": "1.x",
  "metadata": {},
  "classMap": [],
  "events": [],
}

Save the returned payload to disk as a .appmap.json file. We recommend that the AppMap file be named after the recorded test and that additional metadata is added to the recorded AppMap prior to saving, such as the AppMap’s name or labels indicating the test outcome and framework. See the AppMap specification for details about AppMap metadata.

Ruby example

For inspiration, see this sample Ruby code 3 that starts and stops the recorder, retrieves the AppMap, updates its metadata and saves it to disk. This code snippet is used to record Cucumber tests.

Remote recording of distributed applications

A similar strategy can be adopted when recording mapsets of distributed applications that have services deployed to remote hosts. The topology and flow of such setups looks like this:

Remote recording distributed apps

Fig. 2 Remote recording distributed apps

Setup

  • Functional4 tests are run by a test framework on Host A.
  • Functional tests interact with the application running on Host B.
  • Application running on Host B invokes services running on Host C.
  • AppMap client records the application on Host B and the services are recorded on Host C.

Execution flow

Just like in the simple case, AppMaps are recorded remotely by the Test framework logic, then fetched and saved to disk on Host A. The major differences between the simple and distributed scenarios are:

  • The test framework on Host A starts and stops remote recording on multiple hosts, on Host B and on Host C in this example.
  • The test framework fetches and stores AppMaps from each host when a test ends. The control logic is responsible for giving the AppMaps names representing the hosts/applications/services that they were recorded for.

Processing data from distributed tests

In your code editor

AppMap for Visual Studio Code only opens a single AppMap at a time and so the multiple AppMaps recorded per each test need to be viewed sequentially, or in multiple open code editors.

In AppMap Server

When uploading mapsets recorded on multiple hosts to an AppMap Server, there are two options for aggregating the data:

  1. The Recommended: Application’s distributed components’5 AppMaps are uploaded as separate mapsets for a dedicated application. This is the recommended route.
  2. Not recommended: Recorded AppMaps of multiple distributed components are merged into one large mapset during upload. We do not recommend this route without consulting with our team first.

Associating distributed components with dedicated applications in AppMap Server comes with these important benefits:

  • Git metadata can only be properly tracked in mapsets and their histories if all recorded code objects in a mapset were managed in the same git repository, coming from the same branch, commits, etc. al
  • A set of smaller mapsets is faster and easier to process, interact with and analyze than a single large mapset
  • It is common for individual components to have different owners. Component owners may perceive data recorded from other components as extraneous or as noise

Application
Components
AppMap Server Data
Application - Mapset - AppMap
Tests
Main
Application
Main
Application
Mapset
For M.A.
v1.0.0
AppMap Test 1 Test Session
for
v1.0.0
Test 1
AppMap Test 2 Test 2
AppMap Test 3 Test 3
Mapset
For M.A.
v1.1.0
AppMap Test 1 Test Session
for
v1.1.0
Test 1
AppMap Test 2 Test 2
AppMap Test 3 Test 3
Service A Service A Mapset
For S.A
v1.0.0
AppMap Test 1 Test Session
for
v1.0.0
Test 1
AppMap Test 2 Test 2
AppMap Test 3 Test 3
Mapset
For S.A
v1.1.0
AppMap Test 1 Test Session
for
v1.1.0
Test 1
AppMap Test 2 Test 2
AppMap Test 3 Test 3
Service B Service B Mapset
For S.B
v1.0.0
AppMap Test 1 Test Session
for
v1.0.0
Test 1
AppMap Test 2 Test 2
AppMap Test 3 Test 3
Mapset
For S.B
v1.1.0
AppMap Test 1 Test Session
for
v1.1.0
Test 1
AppMap Test 2 Test 2
AppMap Test 3 Test 3
  1. Functional / integration / end-to-end tests, as opposed to elementary unit tests 

  2. Example: Cucumber hooks 

  3. Some of the metadata attributes such as ‘feature’ and ‘feature group’ can be ignored 

  4. Functional / integration / end-to-end tests, as opposed to elementary unit tests 

  5. In this context, the components are the application itself or any of its (micro)services 


Was this page helpful? thumb_up Yes thumb_down No
Thank you for your feedback!