Skip to content
Operations > Troubleshooting

f1 Console

The f1 console is a command line administration interface into a running AMI instance, reached over telnet.

Overview

Each AMI component registers a set of console objects when it starts, and the console exposes the methods on those objects as commands. Use the console to read runtime state that the Web interface does not surface, administration commands that exist only here, and to measure how deeply work is queued inside a component.

AMI opens two separate telnet interfaces:

  • f1.console.port, default 3285: the f1 console, described on this page.
  • ami.db.console.port, default 3290: the AMIDB SQL interface, described in the Center configuration guide.

Command history is recorded in the .console_history.txt file located in root directory of the installation.

Note

"Partition" carries two unrelated meanings in AMI. On this page a partition is a single lane execution queue inside a running container. The storage sense, which divides a historical table across files on disk, is covered in Historical Tables.

Connecting

Connect to the configured f1 console port with telnet:

telnet hostmachine 3285

When prompted, log in with an AMI admin account:

1
2
3
AmiOne>login demo demo123
#LOGGED IN AS: demo
#EXECUTED: 0.03 second(s). 717.40 MB in use. Thu Aug 20 12:00:00 GMT 2026

Console credentials come from the same admin user store as the Web admin interface, and permissions are resolved the same way. Login is disabled while the instance is still starting, so a connection made during startup cannot authenticate until startup completes.

f1 Console properties

There are 3 main configurable properties for the f1 console which can be set in local.properties:

1
2
3
4
5
6
7
8
# Connection port. Set to -1 to disable listener (accepts no network connection) but the console process still runs
f1.console.port=3285 

# Prompt string
f1.console.prompt=AmiOne>

# Command history file. Default location is in installation directory
f1.console.history.file=.console_history.txt 

Encrypting the connection

To access to the console port as an SSL socket rather than a plain socket, set the 2 following optional properties:

f1.console.keystore.file=/path/to/keystore/created/by/java/keytool
f1.console.keystore.password=<password>

Both must be supplied, the keystore encrypts the connection.

Note

It does not authenticate the user, so users still need to log in on connection.

Discovering Commands

Available console commands can be found within a live session.

Run SHOW OBJECTS to list every registered object with its type and a short description:

AmiOne>SHOW OBJECTS
 +----------------------------------------------------------------------------------------------------------------------+
 |                                               SHOW OBJECTS (7 objects)                                               |
 +-------------------+--------------+-----------------------------------------------------------------------------------+
 |Object             |Type          |Help                                                                               |
 +-------------------+--------------+-----------------------------------------------------------------------------------+
 |bs                 |Bootstrap     |Provides access to various tools and services used for bootstapping the application|
 |container_amiCenter|Container     |Provides runtime access to the f1 container                                        |
 |amiRelayServer     |AmiRelayServer|Used to diagnose/control relay connections, transforms and routings                |
 |log                |SpeedLogger   |Used to inspect and modify speed logger configuration at run time.                 |
 |container_amiRelay |Container     |Provides runtime access to the f1 container                                        |
 |container_amiWeb   |Container     |Provides runtime access to the f1 container                                        |
 |amiWebServer       |AmiWebServer  |Used to diagnose/control user sessions                                             |
 +-------------------+--------------+-----------------------------------------------------------------------------------+
 #EXECUTED: 0.02 second(s). 517.56 MB in use. Thu Aug 20 12:10:02 BST 2026 

To list the console's own commands, run help. These commands are available in every session:

Command Purpose
help List every available command. Add a command name for detail on one
show objects List every object that can be invoked from the console
show object <name> List every method associated to that object that can be called from the console
show env Environment overview: resolved properties, classpath, license, and JVM arguments
show cpu Recent CPU usage
show vm JVM options and boot classpath
show threads <pattern> Thread dump, grouped by thread state
show history List your command history
flame threads <pattern> Sample threads over a period and render them as a flame graph
call Call a method, storing the result in a variable when one is named
quit Close the connection

show threads and flame threads both require a search pattern and report Please provide a pattern to search for without one. Use * to match everything:

AmiOne>show threads *
AmiOne>flame threads *

flame threads accepts an optional sampling window written as total and period in milliseconds, as in flame 1000/5 threads *, which is also the default.

Some administration methods exist only in the console. The per component showPorts and showFiles methods are examples, reporting the server ports and configured file paths owned by one component and its plugins.

Available console objects

Every registered container is wrapped in a console object with the following naming convention:

container_ami<Component>

Each component's container is therefore:

  • Center: container_amiCenter
  • Web: container_amiWeb
  • Relay: container_amiRelay

The wrapper class is the same for every component, so each container has the same methods. To call an object's method, use dot notation, e.g:

container_amiCenter.showPartitions()

Each container runs different partitions.

Other objects are registered alongside the containers. For a 3 component instance, the following objects are registered:

  • Bootstrap services: bs
  • Logger configuration: log
  • User Web session management: amiWebServer
  • Relay connections, transforms, and routing: amiRelayServer

Monitoring Queue Depth

A partition processes its work in a single lane, so a partition that cannot keep up accumulates a backlog rather than consuming more threads. Reading that backlog is the fastest way to tell whether a component is saturated and which part of it is responsible.

Run showPartitions() on the container you want to inspect:

AmiOne>container_amiCenter.showPartitions()
 +----------------+-----------------+------------+-------+-------+------+-----------+----------+-----------+------------+
 |id              |startTime        |threadpoolId|states |actions|queued|timeSpentMs|exceptions|writeLocked|inThreadPool|
 |String          |String           |String      |Integer|Integer|Long  |Long       |Integer   |Boolean    |Boolean     |
 +----------------+-----------------+------------+-------+-------+------+-----------+----------+-----------+------------+
 |AMI_CENTERRQ    |20260820-12:05:26|F1POOL      |1      |1      |0     |9          |0         |false      |false       |
 |AMI_CENTER_RR   |20260820-12:04:39|F1POOL      |1      |1      |0     |4          |0         |false      |false       |
 |AMI_PREPROCESSOR|20260820-12:05:07|F1POOL      |1      |3      |0     |2          |0         |false      |false       |
 |AMI_CENTER_CR   |20260820-12:04:39|F1POOL      |1      |5      |0     |8          |0         |false      |false       |
 |AMI_CENTER_AR   |20260820-12:04:39|F1POOL      |1      |12     |0     |0          |0         |false      |false       |
 |MSG_AGENTS      |20260820-12:04:39|F1POOL      |1      |16     |0     |20         |0         |false      |false       |
 |MSG_CLIENTS     |20260820-12:04:39|F1POOL      |1      |62     |0     |22         |0         |false      |false       |
 |AMI_CENTER      |20260820-12:04:39|F1POOL      |1      |1085   |0     |269        |0         |false      |false       |
 +----------------+-----------------+------------+-------+-------+------+-----------+----------+-----------+------------+

 #EXECUTED: 0.02 second(s). 512.44 MB in use. Thu Aug 20 12:11:02 BST 2026 

Reading the output

The method returns one row per partition, with ten columns:

Column Type Meaning
id String The partition identifier
startTime String When the partition's runner started. Shows !null when the partition has no runner
threadpoolId String The thread pool the partition runs on
states Integer Number of state types the partition holds
actions Integer Actions processed since the partition started
queued Long Actions currently waiting to be processed
timeSpentMs Long Total time spent processing actions. -1 when the partition has no runner
exceptions Integer Errors recorded across the partition's states
writeLocked Boolean Whether a write lock is currently held
inThreadPool Boolean Whether the partition has actions to process. false means it is idle

Important values

queued
  • Always check this column first
  • A value that is consistently above zero, or that climbs between two samples taken a few seconds apart, means the partition is receiving work faster than it can process it
writeLocked
  • This column reads true while a write lock is held
  • A partition showing true alongside a rising queued value is being held up by a table mutation
  • A trigger, procedure, or timer locks the database while it runs, so a write lock is expected during execution and is worth investigating only when it persists

Rows are sorted by actions, so the busiest partitions appear at the bottom of the table.

Partitions to watch

Partition names identify the mechanism that owns the queue. Each component has its own specific partitions.

  • AMI_CENTERRQ: Translation of an incoming request into an itinerary.
  • AMI_CENTER_AR: Agent routing. Messages arriving from the agent suite (the Relay connection carried on MSG_AGENTS) are routed on this partition.

    • A deep queue means either that inbound data is arriving faster than the Center can process it, or that the Center has just connected and is taking a large initial snapshot.
  • AMI_CENTER_RR: Result routing. Responses are routed back to their caller on this partition.

  • AMI_PREPROCESSOR: Query parsing.

    • A deep queue means queries are arriving faster than they can be parsed, or that the incoming queries are complex and slow to parse.
  • AMI_CENTER_CR: Client routing.

  • MSG_AGENTS: The message transport between the Relay and the Center, carrying traffic in both directions.
  • MSG_CLIENTS: The message transport between the Web and the Center, carrying traffic in both directions.
  • AMI_CENTER: The database itself. Actions here cover a wide range of activity, from Relay messages, replication, and write queries through triggers, procedures, and timers, down to routine status and connection checks.
  • USERLOGIN: Carries and authenticates all user login requests to the Web interface. Not the same as the console login.

    • A deep queue here delays logging in for all users.
  • <session_ID_string>: One partition per active Session named with the session ID. To map a session ID back to a user, run amiWebServer.showSessions(), described in Users and Sessions.

  • PORTLET_BACKEND: A single fixed partition in AMI Web that routes backend responses into per Session processing. The name carries no number, and one instance exists per Web process.
  • SNAPSHOT_PARTITION: Pushes snapshots and deltas from the Center's database out to the realtime visualizations.

    • A deep queue means either over-subscription, or logic in the tables or datamodels, such as a column formula, heavy enough that the interface cannot keep up with the push rate.
  • AMI_CENTER_CLIENT_<n>: One partition per Center connection opened by a client process such as AMI Web, numbered in the order the connections are made.AMI_CENTER_CLIENT_1 is the first Center connection that process opened.

  • RELAY_TRANSFORM: Applies the message transforms defined in the file named by ami.relay.transforms.file.

    • Shows !null and -1 when no transforms are in use, because the processor has never run.
  • MSG_CENTER_<n>: One partition per Center that a Relay connects to, numbered from zero in the order the connections are added.

  • AMI_RELAY: The Relay's main partition, equivalent to AMI_CENTER on the Center. Carries application routing, result routing, itinerary translation, and traffic bound for the Center.

  • RELAY_FILE_MONITOR: Watches the Relay's configuration files for changes and reloads them, polling on the interval set by ami.relay.check.config.file.changes.period.ms, default 2000.

    • A steadily climbing actions count is normal here, since each poll counts as an action.

What an action means

An action is one unit of queued work and is processed as a single transaction. An action is not one message. The Center batches messages arriving from the Relay, up to the limit set by ami.center.relay.batch.messages.max, which defaults to 1000.

This means a partition can show a low actions count while carrying a high message volume. Read actions as a count of transactions, and size the batch limit against it when tuning.

Warning

Do not confuse ami.center.relay.batch.messages.max with ami.center.snapshot.batchsize or idfountain.batchsize. They control unrelated batching and have very different defaults.

Investigating a deep queue

Once showPartitions() identifies a partition with a backlog, inspect the queue itself:

AmiOne>container_amiCenter.showQueue("AMI_CENTER")

The method takes the partition ID and returns the queued actions, with columns Type, Position, Action, Source, and Target. Source and Target name the components at each end, which turns a queue depth number into an identifiable path through the system.

A partition with nothing waiting returns the column headers and no rows. That is the normal result for an idle partition, not a failure. Because a single lane drains quickly, run this while showPartitions() still reports a non-zero queued value for that partition.

The same container object carries further inspection methods:

Method Returns
diagnose() A diagnostic summary of the container
showStates() The states held by each partition
showThreads() The container's threads
showServices() The services registered in the container
showContainerScopes() The container's scopes and their start status

For the same diagnosis through the interface rather than the console, the log viewer's "Messages Queued" tab charts queue depth over time. See Interpreting the Log Viewer.

Investigating CPU and Thread Use

Queue depth shows how much work is waiting. These three commands show what the JVM's threads are doing, and they are most useful run in sequence.

Confirming CPU is the problem

Start with show cpu, which reports recent process CPU use as a percentage:

AmiOne>show cpu
 CPU Usage: %6.97

A low figure means a slow instance is not CPU bound, and queue depth or lock contention is the more likely cause. Check that before reading any stacks.

Listing threads by state

show threads <pattern> returns a thread dump grouped into WAITING, TIMED_WAITING, and RUNNABLE sections. Threads sharing an identical stack are collapsed into a single entry with a count and a list of their names.

Name a state before threads to filter to it:

AmiOne>show runnable threads *

Runnable threads are the only ones able to consume CPU, so that filter is usually the fastest way to narrow a CPU investigation.

Aggregating stacks with flame threads

flame threads <pattern> samples every matching thread repeatedly over a window, then merges the stacks into a tree. Each frame carries the number of samples in which it appeared.

Set the window by placing a total and a period in milliseconds before threads:

AmiOne>flame 5000/10 threads *

That samples for 5 seconds at 10 millisecond intervals, giving 500 runs. The default is 1000/5.

Counts aggregate across every matching thread, so a frame's count can exceed the number of runs. 6 threads parked on the same stack across 500 runs produce a count of 3000.

Warning

flame threads is not a CPU profile. It counts how often each frame was seen, including on threads that were blocked or idle. show threads filters by state; flame threads does not. On a healthy instance the largest frames are usually threads parked in a socket read, consuming no CPU at all. Read the tree for what is doing work, not for what is biggest.

The following output, abbreviated, was taken from an idle instance:

AmiOne>flame 5000/10 threads *
 Evaluated 500 Runs. All Matching Stack Traces [7013]
 +-java.lang.Thread.run(Thread.java:748) [7001]
 | +-com.f1.msgdirect.MsgDirectClientSocket.run(Unknown Source) [3000]
 | |   java.io.DataInputStream.readInt(DataInputStream.java:387) [3000]
 | |     ...
 | |       java.net.SocketInputStream.socketRead0(Native Method) [3000]
 | +-com.f1.msgdirect.MsgDirectServerSocket$ServerConnection.run(Unknown Source) [3000]
 | |     ...
 | |       java.net.SocketInputStream.socketRead0(Native Method) [3000]
 | +-com.f1.utils.concurrent.FastThreadPool.run(Unknown Source) [500]
 | |   com.f1.http.impl.BasicHttpRequestResponse.run(Unknown Source) [500]
 | |     ...
 +-com.f1.ami.one.AmiOneMain$3.run(Unknown Source) [11]
 |   javax.swing.JLabel.setText(JLabel.java:330) [11]
 |     ...
 |       javax.swing.plaf.basic.BasicHTML.updateRenderer(BasicHTML.java:207) [11]

Roughly 6000 of the 7013 samples sit in two sets of message socket readers, all of them stopped in socketRead0 waiting for data to arrive. That is an idle instance, not a busy one. The only frames performing computation are the 11 samples beneath JLabel.setText, where the interface is rendering a status label. A genuinely CPU bound instance looks different: the deep, high count branches sit in AMI or application code rather than in a socket read.