AppMap for Ruby


appmap-ruby is a Ruby Gem for recording AppMaps of your code. “AppMap” is a data format which records code structure (modules, classes, and methods), code execution events (function calls and returns), and code metadata (repo name, repo URL, commit SHA, labels, 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.

There are several ways to record AppMaps of your Ruby program using the appmap gem:

  • Run your tests (RSpec, Minitest, Cucumber) with the environment variable APPMAP=true. An AppMap will be generated for each spec.
  • Run your application server with AppMap remote recording enabled, and use the AppMap browser extension to start, stop, and upload recordings.
  • Wrap some code in an AppMap.record block, which returns JSON containing the code execution trace.

Once you have made a recording, there are two ways to view automatically generated diagrams of the AppMaps.

The first option is to load the diagrams directly in your IDE, using the AppMap extension for VSCode or the AppMap plugin for RubyMine.

The second option is to upload them to the AppMap Cloud using the CLI for AppMap Cloud.

Supported versions

Supported Rails versions: 5.x, 6.x

Supported Ruby versions: 2.6, 2.7, 3.0

Support for new versions is added frequently, please check back regularly for updates.


Add gem ‘appmap’ to the beginning of your Gemfile. It needs to be the first gem in the list to record other gems. Also, we recommend you add the appmap gem to the :development, :test group. Your Gemfile should look something like this:

source ''
git_source(:github) { |repo| "{repo}.git" }

# Optional Ruby version
# ruby '2.7.2'

# The appmap gem is the first gem in the file
group :development, :test do
  gem 'appmap'

# The rest of the gems follows
gem 'rails',                      '6.1.0'

Install with bundle install, as usual.


When you run your program, the appmap gem reads configuration settings from appmap.yml. Here’s an extensive example file for a Rails project:

# 'name' should generally be the same as the code repo name.
name: my_project
- path: app/controllers
- path: app/models
  # Exclude sub-paths within the package path
  - concerns/accessor
- path: app/jobs
- path: app/helpers
# Include the gems that you want to see in the dependency maps.
# These are just examples.
- gem: activerecord
- gem: devise
- gem: aws-sdk
- gem: will_paginate
# Global exclusion of a class name
- MyClass
- MyClass#my_instance_method
- MyClass.my_class_method
- packages: myapp
  class: ControllerHelper
  function: logged_in_user
  labels: [ authentication ]
  • name Provides the project name (required)
  • packages A list of source code directories which should be recorded.
  • exclude A list of classes and/or methods to definitively exclude from recording.
  • functions A list of specific functions, scoped by package and class, to record.


Each entry in the packages list is a YAML object which has the following keys:

  • path The path to the source code directory. The path may be relative to the current working directory, or it may be an absolute path.
  • gem As an alternative to specifying the path, specify the name of a dependency gem. When using gem, don’t specify path. In your Gemfile, the appmap gem must be listed before any gem that you specify in your appmap.yml.
  • exclude A list of files and directories which will be ignored. By default, all modules, classes and public functions are inspected. See also: global exclude list.
  • shallow When set to true, only the first function call entry into a package will be recorded. Subsequent function calls within the same package are not recorded unless code execution leaves the package and re-enters it. Default: true when using gem, false when using path.


Optional list of fully qualified class and method names. Separate class and method names with period (.) for class methods and hash (#) for instance methods.


Optional list of class, function pairs. The package name is used to place the function within the class map, and does not have to match the folder or gem name. The primary use of functions is to apply specific labels to functions whose source code is not accessible (e.g., it’s in a Gem). For functions which are part of the application code, use @label or @labels in code comments to apply labels.


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 source code comments in your Ruby code. To apply a labels to a function, add a @label or @labels line to the comment which immediately precedes a function.

For example, if you add this comment to your source code:

class ApiKey
  # @labels provider.authentication security
  def authenticate(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" ]

Recording test cases


For non-Rails applications add the appmap/rspec helper:

Require appmap/rspec in your spec_helper.rb before any other classes are loaded.

require 'appmap/rspec'

Note that spec_helper.rb in a Rails project typically loads the application’s classes this way:

  require File.expand_path("../../config/environment", __FILE__)

and appmap/rspec must be required before this:

  require 'appmap/rspec'
  require File.expand_path("../../config/environment", __FILE__)


Record AppMaps from Rspec test cases

Run the tests with the environment variable APPMAP=true:

$ APPMAP=true bundle exec rspec

Each RSpec test will output an AppMap file into the directory tmp/appmap/rspec. For example:

$ find tmp/appmap/rspec


For non-Rails applications, add the appmap/minitest helper:

Require appmap/minitest in test_helper.rb

require 'appmap/minitest'

Note that test_helper.rb in a Rails project typically loads the application’s classes this way:

require_relative '../config/environment'

and appmap/minitest must be required before this:

require 'appmap/minitest'
require_relative '../config/environment'


Record AppMaps from Minitest test cases

Run your tests as you normally would with the environment variable APPMAP=true. For example:

$ APPMAP=true bundle exec rake test


$ APPMAP=true bundle exec ruby -Ilib -Itest test/*_test.rb

Each Minitest test will output an AppMap file into the directory tmp/appmap/minitest. For example:

$ find tmp/appmap/minitest


To record Cucumber tests, follow these additional steps:

1) Require appmap/cucumber in support/env.rb:

require 'appmap/cucumber'

Be sure to require it before config/environment is required.

2) Create an Around hook in support/hooks.rb to record the scenario:

if AppMap::Cucumber.enabled?
  Around('not @appmap-disable') do |scenario, block|
    appmap = AppMap.record do

    AppMap::Cucumber.write_scenario(scenario, appmap)

3) Run the tests with the environment variable APPMAP=true:

$ APPMAP=true bundle exec cucumber

Each Cucumber test will output an AppMap file into the directory tmp/appmap/cucumber. For example:

$ find tmp/appmap/cucumber

Remote recording

appmap-ruby supports the AppMap remote recording API. This functionality is provided by a Rack middleware which is injected automatically into the middlewark stack of your Rails app.

To view the middleware stack of your app, and confirm that the AppMap middleware is configured and available, run:

APPMAP=true rake middleware

Note Without APPMAP=true, the AppMap middleware will not be present, and remote recording is disabled. This is a safety feature to prevent remote recording from being accidentally enabled.

To run your Rails application which remote recording enabled, start the server with APPMAP=true. For example:

$ APPMAP=true bundle exec rails server

To make a remote recording, follow the Remote recording documentation.

Swagger (OpenAPI) generation

appmap-ruby provides a Rake task to generate Swagger files from AppMaps.


  • node.js
  • AppMaps recorded from integration tests in the tmp/appmap/ directory of your project


  1. Save this code snippet as lib/tasks/appmap.rake. It adds the appmap:swagger Rake task to your project:

     # frozen_string_literal: true
     lambda do
       namespace :appmap do
 if %w[test development].member?(Rails.env)
  2. (optional) Add swagger configuration to your appmap.yml:

     name: my_project
     - path: app/controllers
     # appmap:swagger configuration:
       project_name: My Project
       project_version: v1.1
       output_dir: swagger

swagger configuration parameters:

  • project_name: info/title in generated Swagger files. Default value: application Rails class name
  • project_version: info/version in generated Swagger files. Default value: 1.0
  • output_dir: directory where Swagger files are generated. Default value: swagger

Swagger generation

When you have the appmap:swagger task set up, run this Rake task to generate Swagger files from AppMaps located in the tmp/appmap directory of your project:

$ bundle exec rake appmap:swagger

The task will create two Swagger files in the output directory:

  • openapi.yml: high-fidelity API documentation, with parameter examples
  • openapi_stable.yml: a stable version with volatile parameter examples removed. It is intended for diffs and efficient reviews of API changes.

Advanced runtime options


appmap-ruby inspects and instruments code as it’s loaded by the Ruby virtual machine. Start your program with APPMAP_PROFILE_HOOK=true to see diagnostic information about how much time it’s taking appmap-ruby to instrument each Gem in your appmap.yml.


appmap-ruby tries to include a useful string representation of each parameter and return value in the AppMap. In some cases, there are pathological classes that take a long time to stringify. Start your program with APPMAP_PROFILE_DISPLAY_STRING=true to see diagnostic information about how much time it’s taking appmap-ruby to stringify different object classes.

GitHub repository

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