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, default3285: the f1 console, described on this page.ami.db.console.port, default3290: 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:
When prompted, log in with an AMI admin account:
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:
Encrypting the connection¶
To access to the console port as an SSL socket rather than a plain socket, set the 2 following optional properties:
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:
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:
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:
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:
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:
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
truewhile a write lock is held - A partition showing
truealongside a risingqueuedvalue 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
- This column reads
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 onMSG_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, runamiWebServer.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_1is the first Center connection that process opened.
-
RELAY_TRANSFORM: Applies the message transforms defined in the file named byami.relay.transforms.file.- Shows
!nulland-1when no transforms are in use, because the processor has never run.
- Shows
-
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 toAMI_CENTERon 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 byami.relay.check.config.file.changes.period.ms, default2000.- A steadily climbing
actionscount is normal here, since each poll counts as an action.
- A steadily climbing
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:
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:
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:
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:
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:
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.