Query Commands
The screens are good for seeing what is happening now, but comparing a day of metrics against a baseline, or putting the applications of an anomalous window next to those of a normal one, is better done by query. This app adds nine query commands that read JENNIFER data.
- Seven console commands - read the same data as the console screens through a
JENNIFER Consoleconnect profile (a console account). They are built to be used in the order you narrow down the cause of a performance anomaly, and AI Agent Root Cause Analysis uses them too. They come with app 1.1.2610.0 or later - Two token commands - read transactions and running services through a
JENNIFER APMconnect profile (an Open API token)
Every command's options and output fields are listed in full on the store's Query Commands tab. This page is about the order in which to chain them.
Command overview
| Command | Profile | Step | What it does | Period |
|---|---|---|---|---|
jennifer-instances | Console | Targets | Domains and instances. With a period, the instances that sent data in it (including ones stopped since) | The currently registered instances when omitted |
jennifer-metrics | Console | Detect | Per-instance metric time series (5-minute or 1-hour buckets). One row per time × instance × metric | Last hour by default, at most 31 days |
jennifer-problems | Console | Verdict | Per-minute counts of the problems JENNIFER judged by itself, by type and instance | Last hour by default, at most one day |
jennifer-app-summary | Console | Scope | Calls, errors and response time per application per span | Last hour by default, at most one day |
jennifer-errors | Console | Scope | Error counts per instance and error type (totals of the period) | Last hour by default, at most 31 days |
jennifer-xview | Console | Evidence | Individual transactions (X-View points), one row per finished transaction | Last 10 minutes by default, at most one day |
jennifer-profile | Console | Cause | The call profile of one transaction (methods, SQL, external calls, errors, GAP) | Found by the transaction's collection time |
jennifer-apm-transaction-time | Token | - | Time spent per part and error type of the transactions that finished in the period | duration or from/to required |
jennifer-apm-active-service-list | Token | - | The services running right now | Now |
The token commands cannot read the statistics, problem verdicts, application summaries and transaction profiles the console commands read. Use the console commands for root cause analysis.
The root cause flow
The console commands chain in the order targets → detect → verdict → scope → evidence → cause. Each step's result sets the period, instances and applications of the next. Replace domain_id=1000, the times and the txids in the examples with values from your environment.
1. Targets - jennifer-instances
Every console command takes a domain_id. Start by finding the domain and instance IDs.
A restarted instance comes back with the same name and a new instance ID. When analyzing the past, give a period to find the old IDs that have gone away.
jennifer-instances domain_id=1000 duration=1d
| search registered == false
| fields instance_id, instance_name, status
2. Detect - jennifer-metrics
From a day of metrics, compute a baseline (mean and standard deviation) per metric and instance, and see with a z-score how far the last 30 minutes strayed from it. Treat |z| of 3 or more as anomalous.
jennifer-metrics domain_id=1000 duration=1d metrics=service_time,service_rate,service_err_count,sys_cpu,heap_usage,active_service
| eval recent = if(_time >= dateadd(now(), "min", -30), value, null)
| stats avg(value) as base_mean, stddev(value) as base_sd, avg(recent) as recent_avg by metric, instance_id, instance_name
| eval z = if(base_sd > 0, round((recent_avg - base_mean) / base_sd, 2), 0)
| search abs(z) >= 3
| eval abs_z = abs(z)
| sort limit=20 -abs_z
To see when the anomaly started, attach a z-score to every bucket.
jennifer-metrics domain_id=1000 duration=1d metrics=service_time
| join metric, instance_id [
jennifer-metrics domain_id=1000 duration=1d metrics=service_time
| stats avg(value) as base_mean, stddev(value) as base_sd by metric, instance_id
]
| eval z = if(base_sd > 0, round((value - base_mean) / base_sd, 2), 0)
| search z >= 3
| sort limit=50 -z
| fields _time, instance_name, metric, value, base_mean, z
3. Verdict - jennifer-problems
Check what JENNIFER judged to be a problem, and on which instance, at the time you found. An instance stopping, restarting or reconnecting explains a gap or a jump in that instance's metrics.
Zero rows is not a failure: it means JENNIFER found no problem in that period.
4. Scope - jennifer-app-summary, jennifer-errors
Compare the applications of the anomalous window with the window just before it, and find the ones whose calls, errors or response time changed.
jennifer-app-summary domain_id=1000 from=20261027020000 to=20261027040000 span=1h
| eval period = if(_time >= date("20261027030000", "yyyyMMddHHmmss"), "incident", "baseline")
| stats sum(calls) as calls, sum(errors) as errors, sum(total_response_time) as total by application, period
| eval avg_rt = round(total / calls, 1)
If errors went up, compare with the same hour the day before to find the error types that grew.
jennifer-errors domain_id=1000 from=20261027090000 to=20261027100000
| stats sum(count) as count by instance_name, error_type_name
| join type=left instance_name, error_type_name [
jennifer-errors domain_id=1000 from=20261026090000 to=20261026100000
| stats sum(count) as before_count by instance_name, error_type_name
]
| eval before_count = nvl(before_count, 0), increase = count - before_count
| sort limit=20 -increase
5. Evidence - jennifer-xview
List the slow or failed transactions of the narrowed window and see what share of the response time went to SQL, external calls and CPU. Keep the window to a few minutes around the problem.
jennifer-xview domain_id=1000 duration=10m min_response_time=3000
| sort limit=20 -response_time
| fields _time, instance_name, application, response_time, sql_time, external_call_time, cpu_time, error_name, txid
jennifer-xview domain_id=1000 from=20261027030000 to=20261027031000 min_response_time=1000
| stats count, avg(response_time) as rt, avg(sql_time) as sql, avg(fetch_time) as fetch, avg(external_call_time) as ext, avg(cpu_time) as cpu by application
| sort limit=10 -rt
6. Cause - jennifer-profile
Pick a representative transaction and take its row's domain_id, txid, collection_time and response_time.
jennifer-xview domain_id=1000 duration=10m
| sort limit=1 -response_time
| fields domain_id, txid, collection_time, response_time, application
Pass them to jennifer-profile and find the slowest SQL and external calls.
jennifer-profile domain_id=1000 txid=-2980609390376924461 collection_time=1792972233338 response_time=482
| search type == "SQL" or type == "TX_CALL"
| sort limit=10 -elapsed_ms
| fields no, type, name, start_ms, elapsed_ms, share, parameters
An N+1 pattern - the same SQL over and over - shows when you group by SQL.
jennifer-profile domain_id=1000 txid=-2980609390376924461 collection_time=1792972233338
| search type == "SQL"
| stats count, sum(elapsed_ms) as total_ms, max(elapsed_ms) as max_ms by name
| sort -total_ms
elapsed_ms includes nested calls, so an outer method covers the time of the calls inside it. Look for the cause in the deepest rows or in SQL and TX_CALL rows rather than in the outermost method. A large GAP is time spent in code that is not profiled, in locks or in waiting.
Token commands
The token commands read through the same Open API as the collector. Use them to see the same transactions the collector stores without collecting them, or to see the services running right now.
Common options
| Option | Commands | What it is |
|---|---|---|
profile | All | Connect profile name. Every usable profile of the command's type is used when omitted |
domain_id | All (optional for jennifer-instances) | Domain ID (sid). jennifer-instances lists them |
instance_ids | jennifer-metrics, jennifer-problems, jennifer-errors, jennifer-xview, jennifer-apm-transaction-time | Comma separated instance IDs. Every instance that sent data in the period when omitted |
instance_id | jennifer-apm-active-service-list | One instance ID. The whole domain when omitted |
duration | Commands that take a period | Recent period up to now, in s (second), m (minute), h (hour), d (day) units |
from, to | Commands that take a period | yyyyMMddHHmmss; omitted digits are padded with zero. from overrides duration, and to is now when omitted |
limit | jennifer-metrics, jennifer-errors, jennifer-xview, jennifer-profile | Maximum number of rows |
domain_id belongs to one console. The same number on another console is another domain, or none. So a console command given domain_id must use exactly one profile, and when several JENNIFER Console profiles are usable you have to name one with the profile option.
Error codes
| Range | For |
|---|---|
| 207900-207905 | Token commands: no profile, profile required, from, to or domain_id required, malformed instance ID |
| 207910-207919 | Shared by the console commands: no profile, profile required, missing or malformed domain_id, malformed instance_ids, malformed limit, several profiles with domain_id given |
| 207920-207929 | jennifer-instances |
| 207930-207939 | jennifer-metrics |
| 207940-207949 | jennifer-problems |
| 207950-207959 | jennifer-xview |
| 207960-207969 | jennifer-profile |
| 207970-207979 | jennifer-app-summary |
| 207980-207989 | jennifer-errors |
When a console call fails, a console command ends the query with an error, so zero rows really means no data. The token commands, by contrast, only write call errors to the server log; when their result is empty, check the connect profile and the network as well.
Things to know
| Command | Note |
|---|---|
| All console commands | They only read. No command changes the console's settings or state |
jennifer-metrics | Buckets an instance did not report also come as 0, so a run of zeros more likely means stopped or not collected than idle. Buckets that have not finished yet are not returned. There is no domain total row, only rows per instance |
jennifer-problems | One-minute resolution, and only the minutes that had a problem are returned |
jennifer-app-summary | Summarizes the whole domain per application, not split by instance. avg_sql_time and avg_external_call_time are averages per SQL call and per external call, not per transaction. The total of calls equals the call count of the daily system performance statistics |
jennifer-xview | Rows come oldest first, so when limit is reached the later part of the period is missing. Exactly limit rows means the result was cut short. A day's worth runs to hundreds of thousands of rows even on a small server |
jennifer-xview | Cancelling the query does not stop the console server, which still sends the whole period requested. Keep the window short and cut it down with min_response_time or errors_only=t |
jennifer-profile | The transaction is found by the collection_time of the jennifer-xview row. A few seconds off is fine, but a minute or more off fails to find it and raises an error. Do not pass _time or end_time |
jennifer-apm-transaction-time | The JENNIFER Open API returns one minute per call, so the period is split into one-minute calls. A longer period means that many more calls |