4.1. APM dashboard
Near real-time application performance, based on L7 requests collected with eBPF.

Overview
The APM dashboard shows application performance in near real time (a lag of roughly one to five seconds), based on the L7 requests (spans) observed with eBPF. It monitors, on one screen and by category and namespace, the request volume your applications are taking right now, along with response times, errors, concurrency and resource use.
Operators, SREs and developers use it to read the state of things now. It suits watching how traffic responds just after a deployment, spotting an instance whose response time has jumped, or catching the moment errors spike. Unlike the Applications screen, which is built around querying past periods, the APM dashboard uses a real-time data path with the lag kept to a minimum.
Open it from the APM dashboard menu (the speedometer icon) in the left sidebar. This screen is always anchored to "now", so unlike other screens it has no start and end time picker at the top.
Note: L7 means layer 7 of the network stack, the application layer. eBPF observes application requests such as HTTP, gRPC and database calls at the kernel level, so performance data is collected without changing application code or adding a separate library.
Screen layout
The filter bar at the top sets the scope by category and namespace, and the widgets below refresh against that scope.
| Widget | Description |
|---|---|
| Request viewer | An in-flight request gauge, the active user count, and a three-band elapsed-time legend |
| Live request monitor | A column per instance with falling-request animation, namespace bands, and stopped-state markers |
| Transaction heatmap (T-Map) | A response time × time heatmap. Click or drag cells to query traces and transactions |
| Info card | Six cells summarising Apdex, TPS, active users, error rate and response time (P50/P95) |
| TPS | The trend in transactions per second (last 10 minutes) |
| Apdex | The satisfaction trend, with satisfied, tolerating and frustrated bands |
| Response time | The P50 and P95 response time trend |
| Error rate | The error rate (%) and error count trend |
| CPU usage / memory usage | The top resource consumers per application, over time |
| Active users | The active user trend over the last 10 minutes |
| Transaction query dialog (drill-down) | Not a permanent widget — the transaction list that opens when you drag a selection on the T-Map |
Note: a real-time connection badge (LIVE) is shown at the top of the screen. It stays active while the connection to the server carries data, and reconnects automatically if the connection drops.
Main features
Category and namespace filters
Two combos in the filter bar at the top set the scope.
- Category filter: exactly one category is always selected; it cannot be emptied. Change it and only data for the applications in that category is shown.
- Namespace filter: only the namespaces belonging to the selected category appear in the list, and you can choose ALL.
Changing a selection re-subscribes to the server so only that scope's data arrives, which lets you concentrate on the group of services you care about. Your selection is saved and restored next time you connect.
If no application matches the filters, a message reading "no apps to show in the selected category/namespace" appears with a button to reset the filters.
Tip: the namespace selection is shared with other screens such as custom dashboards and user estimation. Choose a namespace on one screen and the same selection follows you to the others, which makes tracking one target across screens easier.
The right of the filter bar carries these secondary controls.
| Control | Description |
|---|---|
| Full-screen toggle | Switches to full screen. Useful for leaving on a shared team monitor |
| Preferences (gear) | Adjusts display options such as the strength of the traffic visual effects |
| LIVE badge | Shows the real-time connection state |
| Aggregation lag badge | Appears when server aggregation falls behind. The data may be briefly out of date |
| Top-N notice | When there are too many items to show them all, a "showing top N" notice |
Info summary card

The info card at the top of the screen summarises the current state in six figures.
| Cell | Contents |
|---|---|
| Apdex | Response time satisfaction (%). Colour-coded by value |
| TPS | Transactions (requests) per second |
| Active users | The active user count (over the last 5 minutes) |
| Error rate | Errors as a proportion of all requests (%). Colour-coded by value |
| Response time | P50 / P95 response time (ms) |
| 30-minute active users | The active user count over the last 30 minutes |
The values are the most recent, taken from the last completed 10-second bucket. Apdex and error rate change colour with state (good = green, fair = orange, poor = red), so problems are visible at a glance. Where there is no data, "—" is shown.
Note: the active users label carries the basis of the estimate. Where session coverage is sufficient it reads (Session); otherwise the estimate is (IP+UA). For the difference between the two, see user estimation.
Live trend charts

TPS, response time, error rate and Apdex are each aggregated over the last 10 minutes in 10-second buckets and drawn as trends. "Last 10 minutes" appears under each chart title.
The response time chart
Response time is drawn as two lines, P50 and P95. Where live L7 values are unavailable, a single average response time line replaces them.
- P50 (median): half of all requests complete within this time. It represents the ordinary user experience.
- P95: the boundary of the slowest 5% of requests. Use it to understand tail latency. A low P50 with a high P95 means only some requests are slow.
Why P50 and P95 rather than an average: response time distributions are usually right-skewed — most requests are fast and a few are very slow. An average is dragged upwards by that slow minority into a figure nobody actually experiences, or else dilutes the slow requests among the many and hides the problem. If 990 of 1,000 requests take 100 ms and 10 take 5,000 ms, the average is 149 ms and looks healthy — but ten users waited five seconds.
| Metric | Value in the example above | What it tells you |
|---|---|---|
| Average | 149 ms | Dragged up by the slow minority — neither the typical experience nor the worst one |
| P50 (median) | 100 ms | The middle value when requests are ordered by response time = what a representative user actually experiences (unmoved by the slow minority) |
| P95 | 5,000 ms | The boundary of the slowest 5% = tail latency. The part the average conceals |
Users abandon, and SLOs and SLAs are breached, in the tail (P95, P99) rather than at the average. Looking at P50 ("how fast is it usually?") alongside P95 ("how slow is it at its worst?") separates the fast majority from the slow minority, which a single average misses, and tells you immediately whether the problem is universal or confined to some requests.
The error rate chart
An error rate (%) line with a secondary error count line. Hover over the line and a tooltip gives the request count for that bucket, so you can judge whether a rate came from a small sample.
The Apdex chart
A satisfaction line over satisfied, tolerating and frustrated bands. The threshold is fixed at three seconds (satisfied below 3 s, tolerating 3–12 s, frustrated 12 s and above).
Comparison mode
Each trend chart has a comparison mode dropdown behind a lightning icon.
- Live: shows only the current trend (the default).
- Compare with yesterday: overlays the values from the same period yesterday.
- Compare with last week: overlays the values from the same period last week.
Use it to compare before and after a deployment, or to see day-of-week patterns. When values change sharply, a status dot (green → orange → red) appears beside the chart title to flag the anomaly.
Tip: click the chart header, or the jump (↗) button at its top right, to drill down into the application details (the SLO tab and so on). Where the filter scope holds more than one application, a dialog asks you to choose the target application first.
Transaction heatmap (T-Map)

The transaction heatmap divides response time (vertical) and time (horizontal) into a grid and shows how many transactions fell into each cell, as colour intensity.
How to read the heatmap
- Each cell represents the number of transactions in one time × response time bucket. The darker the colour, the more requests in that bucket.
- A cell with a red border contains errors.
- Points clustered towards the top (higher response times) mean many slow requests.
Interacting with cells
- Hover and a tooltip gives the time range, the response time bucket, the response count and the 5xx error count.
- Click a cell to jump to a representative trace for that bucket and analyse it span by span.
- You can also move between cells with the arrow keys and open one with Enter.
- Drag to select a time range and the transaction query dialog opens. That list is fixed to the data at the moment you selected it and does not follow the live stream. The Drill-down screens section below covers what the dialog shows in detail.
Direction toggle
Where data exists for all three directions (all, inbound, outbound), a direction toggle appears in the header, letting you separate the requests the app received (inbound) from the requests it sent (outbound). The jump (↗) button at the top right goes to the distributed tracing tab.
Note: in environments where the distributed trace store (ClickHouse) is not configured, the T-Map is disabled and a notice is shown instead.
Live request monitor
A wide area at the bottom of the screen, where each column is one application instance.
Columns and their order
- Namespace bands run across the top. The application (deployment) name is on the instance label at the foot of each column.
- Click an instance name to open that application's detail screen. The same applies when the widget is placed on a custom dashboard.
- The order is fixed as namespace → deployment → name, so instances do not move around when the screen refreshes.
- Each column stacks its pending requests in three colours (satisfied, tolerating, frustrated); the falling-request animation can be toggled on and off.
Column detail tooltip
Hover over an instance column and the tooltip gives the following.
- A status dot and the instance name (with the original name too, where a display name is set)
- TPS, P50 and P95 response times
- The number of pending requests, broken into the three satisfied / tolerating / frustrated bands
- For stopped instances, the time it stopped and the reason (no metrics received, node down, and so on)
Setting a display name (alias): you can give namespaces and applications a recognisable custom name. Register an alias on the Settings > Application categories screen and the APM dashboard's labels show the alias instead of the original identifier (the tooltip shows both). Filtering, sorting and routing continue to work against the original name.
Stopped-state markers
An instance judged stopped — because metrics are no longer arriving, for instance — carries a vertical STOPPED label together with the reason (no metrics received, node down, pod pending, and so on).
Where clicks take you
| What you click | Where it goes |
|---|---|
| A namespace name | The topology map dialog |
| A column (an instance) | The application detail dialog |
| A column with slow requests (3 seconds or more) | Slow request details |
Note: at most 200 columns are shown. Beyond that, a
+Nbadge appears in the header, and where space runs short, stopped columns are hidden first so that live instances take priority.
Request viewer

The request viewer at the top of the screen shows the current processing situation at a glance.
- The in-flight request count is shown large in the centre. It is the absolute number of requests in progress that have not yet received a response.
- The active user count is on the left.
- A three-band elapsed-time legend breaks the in-progress requests down.
| Band | Meaning |
|---|---|
| Under 3 seconds | Satisfied — the normal range |
| 3 to 12 seconds | Tolerating — somewhat slow |
| 12 seconds and over | Frustrated — a slow request |
The launch (particle) animation can be toggled on and off. Where there are slow requests (three seconds or more), a slow request details button appears, giving you the protocol, the URL or query being run, the destination and the elapsed time.
Note: the in-flight count is based on pending outbound requests and does not include HTTP/2 (this is stated in the widget tooltip). Even where the number appears to keep climbing, the requests may simply be long-lived by design, as with streaming or long polling.
Resource and active user widgets
- CPU usage (cores) / memory usage (RSS): the top consumers per application, as lines. Unlike the other widgets, these two use the metric path, so they lag by about a minute (they are not strictly real time). The category filter applies.
- Active users: the active user trend over the last 10 minutes. Whether the basis is session or IP+UA is noted alongside, and the jump (↗) button goes to the user estimation screen.
Drill-down screens
Clicking or dragging on a particular point of a widget opens a more detailed screen (a dialog). Here is what each shows.
The transaction query dialog
Opens when you drag to select a time range on the transaction heatmap (T-Map). It shows the transactions (requests) within that range at the top, and the spans (the call path) of the selected request below.

The toolbar
| Control | Description |
|---|---|
| Title and selected range | "Transaction query" and the selected time and response time range (for example 10:20:05 → 10:20:25 · 0.2s ~ 1.0s). Where there is no upper bound on response time, ∞ |
| Count | How many transactions were found. Where the server limit truncated the result, it reads "(top only)" |
| Search | Filters the list against the text of every column |
| Span source toggle | Switches between eBPF (observed automatically by the agent) and OTEL (instrumented in the app) |
| Direction toggle | Inbound / outbound (press again for both). Inherits the T-Map's direction selection |
| Errors only | Shows only failed transactions |
Transaction list columns
Click a header to sort (again for reverse order, a third time to return to the default order).
| Column | Contents |
|---|---|
| Namespace | The namespace the transaction belongs to |
| Trace | A coloured dot for the trace identifier and its first 8 characters. Requests in the same trace share a colour (the full value is in the tooltip) |
| Target app | The application that handled the request |
| Direction | ↓ inbound / ↑ outbound (colour-coded) |
| Peer | The caller for inbound requests, the destination server for outbound ones |
| URL | The request URL or name (the full value is in the tooltip) |
| Operation | A type badge (HTTP, PostgreSQL, Redis, Kafka and so on) and the operation name |
| Status | The HTTP status code, or OK/ERR (errors in red) |
| Response time | How long it took. Three seconds or more is shown in bold red |
| Response bytes | The response size. Where a payload cap may have made this an undercount, it is prefixed with ≥ |
| Start time | When the request started (to the millisecond) |
Request details (the span tree)
Click a row in the list (the first row is selected automatically) and the span tree for that transaction appears below, showing the call path and how long each step took. Where the list is empty it reads "healthy · no traffic"; before you pick a row it reads "select a row to see the transaction details".
Note: this dialog is navigated by scrolling rather than paging, and the server returns at most 1,000 transactions at a time. The list is fixed to the data at the moment you selected it and does not follow the live stream.
Slow request details
A list of the requests running for three seconds or more among those still in progress (not yet answered). It opens from two places.
- The slow request details button in the request viewer → the oldest requests across the whole scope (the top N).
- Clicking a column with slow requests in the live request monitor → only that instance's slow requests.
Each request is shown with the following.
| Column | Contents |
|---|---|
| Protocol | A coloured badge: HTTP, HTTP/2, PostgreSQL, MySQL, Oracle, ClickHouse, MongoDB, Redis, Memcached, ZooKeeper and so on |
| URL / query being run | The URL or SQL currently executing (with bind values where present). A copy button is provided |
| Destination | The namespace and app name (where resolved), or IP:port |
| Elapsed | How long since the request started. Colour-coded by band (green under 3 s, orange 3–12 s, red 12 s and over) |
Where there are too many slow requests to list, it reads "showing the oldest M of N slow requests"; where there are none, "no requests are running slow".
Note: slow request details are based on pending outbound requests, and the requests in this list are not necessarily errors. Use it to catch long-running queries and external calls as they happen.
The application detail dialog
Opens when you click a column (an instance) in the live request monitor, or press the jump (↗) button on a widget. It is the Applications detail page moved into a dialog, and contains the following.
- Title area: the application name with its namespace and kind, and a button to open it as a full page.
- Time range bar: shows the query period. Beyond three days a "3-day limit" badge appears, and the dependency map can be collapsed and expanded.
- Dependency map (AppMap): how this application relates to the services connected to it.
- Report tabs: SLO, tracing, logs, profiling, security and other tabs appear in the order the server supplies them, each with a status light. Each tab shows the charts and tables for its perspective.
- Opening from a column selects the default tab; opening from the transaction map widget's ↗ selects the tracing tab; opening from a trend chart's ↗ selects the SLO tab.
- The security tab lists attacking IP addresses (address, country, city, count) and lets you configure exceptions, and dragging on the heatmaps in the SLO and tracing tabs drills back down into the transaction query.
Tip: what each tab of the application detail dialog shows is covered in detail in the "Report tabs" section of Applications.
How the live data behaves
Each widget on the APM dashboard looks at a different window of time.
| Widget | Window |
|---|---|
| Request viewer and request monitor (particles/gauges) | A live window of about 90 seconds |
| Trend charts (TPS, response time, error rate, Apdex) | The last 10 minutes (10-second buckets) |
| Transaction heatmap (T-Map) | A window of the last 10 minutes |
| CPU and memory | The metric path (about a minute of lag) |
The essential point is that this screen is based on live L7 requests. A second, an application or a namespace with no traffic therefore does not appear on screen. Each widget reads "healthy · no traffic" when there is none. In environments where node-agent is not deployed, a notice explains that there is no live data.
Worked examples
Checking the response just after a deployment
- Narrow the filters to the category and namespace the deployed application belongs to.
- On the info card, check that the error rate and response times (P50/P95) are holding at their pre-deployment levels.
- Set the error rate chart to compare with yesterday and see whether errors have risen against the same period.
- In the live request monitor, check that the new instances are taking requests normally, without a STOPPED marker.
Finding the cause of slow requests
- Find the moment P95 jumped on the response time chart.
- On the transaction heatmap (T-Map), drag across the upper (high response time) region at that moment to open the transaction query dialog.
- Pick out a slow transaction and click its cell to move to distributed tracing, then find the longest step in the span waterfall.
- If the request viewer has caught slow requests, check the URL being run and its destination under slow request details.
Responding to a spike in errors
- Notice that the error rate cell on the info card has turned red.
- Establish the time of the spike and the error count on the error rate chart.
- Click a red-bordered cell (a bucket containing errors) on the T-Map to jump to a representative trace and check the exception and status code.
- Where only one instance is producing errors, click its column in the live request monitor to go into the application details.
Checking one instance's resource use
- Find the application whose usage jumped on the CPU usage / memory usage widgets (with about a minute of lag).
- Look at the colour distribution of pending requests in that application's column in the live request monitor.
- Click the column to go to the application details and analyse resources and requests together.
Frequently asked questions
A namespace or application is missing from the screen
The APM dashboard is based on live L7 requests, so it shows only what has had traffic. Something missing from the list because it has had no traffic is not an error. To see the application list regardless of traffic, use the Applications screen: it is based on the existence of workloads and pods, so applications appear even with no traffic.
The values look briefly out of date
Check whether the aggregation lag badge is showing at the top. It appears when server aggregation falls behind repeatedly, and the data may be briefly out of date. The last few seconds of the live request window may also not be on screen yet, while aggregation completes.
Only the CPU and memory widgets respond slowly
Unlike the others, the CPU and memory widgets use the metric path, so they lag by about a minute. This is normal, and their refresh interval differs from the live widgets such as request volume and response time.
I want to look at a time in the past
The APM dashboard is a live-only screen and has no start and end time picker. For analysing past periods, use a screen where you can set a time range: the Applications details, the distributed tracing heatmap, or incidents.
The in-flight count keeps rising
The in-flight count is based on pending outbound requests and does not include HTTP/2. Requests that are long-lived by design — streaming, long polling, subscriptions — can register as in-flight without being slow. Confirm whether they are genuinely slow using the elapsed-time bands in the request viewer and slow request details.
No live data appears at all
Check that node-agent is deployed. eBPF-based L7 observation is collected by node-agent, so without the agent a notice explains that there is no live data. For installation, see the installation guide.
Terms
| Term | Description |
|---|---|
| APM | Application performance monitoring |
| L7 request (span) | A record of one application-layer request (HTTP, gRPC, database and so on) as observed by eBPF |
| Transaction | One unit of request handling. The unit of aggregation for the heatmap and the transaction query |
| TPS | Transactions per second |
| P50 / P95 | Response time percentiles. P50 is the median; P95 is the boundary of the slowest 5% |
| Error rate | Failed requests as a proportion of all requests (%) |
| In-flight | The number of requests in progress that have not yet been answered (based on pending outbound requests) |
| Apdex | A response time satisfaction metric, on a 3-second threshold (satisfied, tolerating, frustrated) |
| Active users | The user count estimated from recent traffic (on a session or IP+UA basis) |
| Direction (inbound/outbound) | Traffic the app received versus traffic the app sent |
| STOPPED | The marker for an instance judged stopped, for example because metrics stopped arriving |
Related documents
- Applications — the application list that appears even without traffic, and detailed analysis of past periods
- Distributed tracing — the span waterfall and trace details a T-Map cell leads to
- User estimation — how active users are estimated (session / IP+UA) and their geographic distribution
- Topology map — the service dependency map that opens when you click a namespace
- Custom dashboards — the shared namespace selection and user-defined metric screens
- Settings — setting response time SLO targets and check conditions