The AppMap CLI @appland/appmap
provides utility commands for working with AppMaps.
The AppMap Client CLI is written in Node.JS, so you install and manage this CLI using yarn
or npm
:
$ yarn add --dev @appland/appmap
Run @appland/appmap
with npx
or yarn run
:
$ npx @appland/appmap --help
or
$ yarn run appmap --help
Search AppMaps for references to a code object (package, function, class, query, route, etc) and print available event info.
$ npx @appland/appmap inspect --help
appmap inspect <code-object>
Positionals:
code-object identifies the code-object to inspect [required]
Options:
--version Show version number [boolean]
-v, --verbose Run with verbose logging [boolean]
--help Show help [boolean]
--appmap-dir directory to recursively inspect for AppMaps
[default: "tmp/appmap"]
-i, --interactive interact with the output via CLI [boolean]
You can use this command to search and display events and associated data from across all the AppMaps in a directory (recursively explored).
The code-object
argument is a required argument, composed of a type and identifier. The inspect command will find all events that match this code object across all the AppMaps. Whether an event matches the code-object
argument is defined as follows:
code-object type | match criteria |
---|---|
function | The event is a call to the specified function |
class | The event is a call to any function on the specified class |
package | The event is a call to any function on any class in the specified package |
database | The event is a SQL query |
table | The event is a SQL query which includes the specified table |
query | The event is a SQL query which, when normalized, matches the specified query |
route | The event is an HTTP server request which matches the specified route method and normalized path. |
Examples of supported search syntax:
function:my/package/My::Class#instance_method
function:my/package/My::Class.static_method
class:my/package/My::Class
package:my/package
table:table_name
database:
route:REQUEST_METHOD /route/:id
(HTTP request method followed by normalized path)query:SELECT * FROM tables WHERE some_column = ?
(normalized SQL)With the --interactive
option, the results are presented in table form, and you can refine and drill into the data using the command line.
$ npx @appland/appmap inspect --interactive
Without the --interactive
option, all matching results are printed as JSON. This mode is suitable for searching AppMaps and printing results that can be piped into other scripts (e.g. using jq) for further processing.
Interactive mode arguments
The home screen is displayed at the beginning of interactive mode. The (h)ome
command will generally return you to the home screen, when you are in other parts of the app.
The home screen presents the following data:
Field index | Field name | Description |
---|---|---|
1 | Events | A list of AppMaps and event indices that match the initial search term and filters. |
2 | Return values | Enumeration of all the different values returned by the matching object (most applicable when searching for a function). |
3 | HTTP server requests | Distinct routes in which the code object is found. Each listed result is a unique request method, normalized path, and status code. |
4 | SQL queries | Unique normalized SQL which is a descendant (or self) of the matching code object. |
5 | SQL tables | Unique tables which are found in the SQL queries, as defined in field 4. |
6 | Callers | Unique functions which are the parent of each matching code object. |
7 | Ancestors | Unique HTTP server requests and labeled functions which appear as an ancestor of a matching code object. |
8 | Descendants | Unique labeled functions which appear as a descendant of a matching code object. |
9 | Package trigrams | Unique combinations of caller → code-object → calee, converted to package names. |
10 | Class trigrams | Unique combinations of caller → code-object → calee, converted to class names. |
11 | Function trigrams | Unique combinations of caller → code-object → calee, as functions, SQL, or HTTP client requests. |
On the home screen, a field is displayed if there are only a small number of distinct values. Otherwise, the number of distinct values is shown, and you can use the (p)rint
command to see the full details.
Prints the full details of a numbered field. Unlike the (h)ome
view, which will summarize fields with many values, the (p)rint
command will always print out all the distinct values of a field (even if there are thousands of them…).
Applies a filter to the result set. You can use this command to reduce the number of search matches that are displayed, both on the (h)ome
screen and in the (p)rint
views.
When you choose the (f)ilter
command, you’re first prompted to select which field you want to choose the filter value from. For example, you may see a table that includes (2) Return values (3) HTTP server requests (6) Callers
. On choosing one of these fields, you are then prompted to select a value. The values will be the same as if you chose to (p)rint
the selected field. Each field value is numbered; enter the number of the field value to activate it as a filter.
The result set is then recomputed, matching only events that match BOTH the main code-object argument that you initially provided to the search command, AND the filter.
For example, if you searched for table:users
and then filtered by request:GET /user 200
, the search would match every query that accesses the users table within an HTTP GET
request to /user
that returns status code 200
.
If you apply another filter, then BOTH filter conditions must match each result.
Un-apply the most recently applied filter.
Remove all filters.
Quit the interactive program.
$ npx @appland/appmap openapi --help
appmap openapi
Generate OpenAPI from AppMaps in a directory
Options:
--version Show version number [boolean]
-v, --verbose Run with verbose logging [boolean]
--help Show help [boolean]
--appmap-dir directory to recursively inspect for AppMaps
[default: "tmp/appmap"]
-o, --output-file output file name
--openapi-template template YAML; generated content will be placed in the
paths and components sections
--openapi-title info/title field of the OpenAPI document
--openapi-version info/version field of the OpenAPI document
Use this command to generate OpenAPI documentation from all AppMaps in a directory (recursively explored).
openapi
ships with a default yml
template but you can use a custom template if
you specify its file with the optional --openapi-template
parameter.
The --openapi-title
and --openapi-version
parameters override the values of the
info/title
and info/version
properties in the generated document.
$ npx @appland/appmap prune --help
appmap prune <file> <size>
Prune an appmap file down to the given size
Positionals:
file AppMap to prune [required]
size Prune input file to this size [required]
Options:
--version Show version number [boolean]
-v, --verbose Run with verbose logging [boolean]
--help Show help [boolean]
-o, --output-dir Specifies the output directory. Pruned files will be written
here. [string] [default: "."]
Use this command to remove events from an AppMap, to make it easier to understand.
Pruning works by finding the most repetitive calls within a given “chunk” and removing events associated with those calls. A chunk is defined as a group of logic, consisting of one or more full call stacks. Boundaries of these chunks are created around application entrypoints such as inbound HTTP request.
An example list of chunks is provided below:
HTTP request - GET /user
Background thread processing
HTTP request - PUT /user
Background thread processing
HTTP request - GET /
For each chunk, aggregate the total number of unique events. Starting from the most repetitive event type, remove instances of that event until the size of the chunk (in byte) is less than:
requested size / total event array size * starting chunk size
In essence, we’re calculating a unique exclusion list for each chunk. This prevents an excessively noisy or repetitive call stack in one area of execution from affecting the results of unrelated areas of execution.
Non-application events such as HTTP requests and SQL queries will always be retained. This means that the end result can never be smaller than the total size of these events combined.
https://github.com/getappmap/appmap-js/tree/main/packages/cli