How to Monitor Container Resource Usage with Container Stats: Real-Time Statistics Guide

Use the container stats command to display live CPU, memory, network, and block I/O metrics for running containers, with support for both interactive streaming and static JSON output.

The apple/container repository provides a Swift-based container management toolset that includes built-in resource monitoring capabilities. Understanding how to monitor container resource usage with container stats enables operators to observe live performance metrics without external tooling. The implementation spans three architectural layers, from the CLI front-end through XPC communication to the underlying runtime statistics.

Architecture of the Container Stats Command

CLI Front-End

The ContainerStats command in Sources/ContainerCommands/Container/ContainerStats.swift handles user input parsing and output formatting. It supports two primary modes: streaming for real-time monitoring and static for single snapshots. The run() method evaluates flags such as --format and --no-stream to determine which execution path to invoke.

Client-Server API

Communication flows through ContainerClient, which issues XPC calls to the daemon. The stats(id:) method retrieves a ContainerResource.ContainerStats struct containing raw metrics. This data model, defined in Sources/ContainerResource/Container/ContainerStats.swift, encapsulates memory usage, CPU time, network I/O, block I/O, and process counts.

Runtime Service

On the daemon side, RuntimeService (located in Sources/Services/RuntimeLinux/Server/RuntimeService.swift) queries the container runtime via container.statistics(). It returns a ContainerStatistics structure that the client decodes into the Swift model used for display.

How to Use Container Stats

Real-Time Streaming Mode

By default, the command enters an alternate screen buffer and continuously refreshes metrics similar to the top utility.

container stats

The runStreaming() method handles this live display, clearing the screen and printing updated tables until you press Ctrl-C.

Static Snapshot with JSON Output

For scripting and automation, use the --no-stream flag combined with --format json:

container stats --format json --no-stream

This invokes runStatic(), which enumerates containers via client.list(...), collects statistics, and outputs a JSON array. The collectStats() method gathers two samples two seconds apart to calculate CPU percentages via calculateCPUPercent().

Targeting Specific Containers

Monitor individual containers by specifying their ID or name:

container stats my-web-app

Without --no-stream, this streams updates for only that container.

Understanding the Metrics Output

The container stats command displays these key metrics derived from the ContainerStats struct:

  • CPU %: Percentage of a full core used, computed from the delta between two cpuUsageUsec readings
  • Memory Usage / Limit: Current consumption versus the container-configured limit
  • Network Rx/Tx: Bytes received and transmitted across all interfaces
  • Block I/O: Bytes read and written to block devices
  • PIDs: Number of processes running inside the container

The formatBytes(_:) function converts raw byte values into human-readable KiB/MiB/GiB units, while statsTable(_:) builds the formatted table output.

Example JSON Payload

When using --format json, the output matches the Swift model structure:

[
  {
    "id": "e5f9a7c3b2d1",
    "memoryUsageBytes": 104857600,
    "memoryLimitBytes": 2147483648,
    "cpuUsageUsec": 12345678,
    "networkRxBytes": 5242880,
    "networkTxBytes": 1048576,
    "blockReadBytes": 262144,
    "blockWriteBytes": 131072,
    "numProcesses": 12
  }
]

These fields correspond directly to the properties in Sources/ContainerResource/Container/ContainerStats.swift.

Key Implementation Files

File Role
Sources/ContainerCommands/Container/ContainerStats.swift CLI command implementation with streaming and static logic
Sources/ContainerResource/Container/ContainerStats.swift Data model for per-container metrics
Sources/Services/RuntimeLinux/Server/RuntimeService.swift Daemon-side statistics collection from the runtime
Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift XPC service exposing the stats(id:) RPC

Summary

  • The container stats command provides real-time visibility into container resource consumption across CPU, memory, network, and I/O metrics.
  • Streaming mode (runStreaming()) offers an interactive, continuously updating display ideal for live debugging.
  • Static mode (runStatic()) with --no-stream and --format json enables scriptable access to resource data.
  • CPU percentages are calculated from two samples taken two seconds apart using calculateCPUPercent().
  • All metrics flow through the XPC-based ContainerClient API, with data models defined in the ContainerResource module.

Frequently Asked Questions

How does container stats calculate CPU percentage?

The calculateCPUPercent() function in ContainerStats.swift collects two samples of cpuUsageUsec approximately two seconds apart via collectStats(). It derives the percentage by comparing the delta in CPU microseconds against the elapsed time, giving you the percentage of a full CPU core being utilized.

Can I monitor container resource usage without streaming updates?

Yes. Append the --no-stream flag to container stats to fetch a single snapshot. Combine this with --format json to receive machine-readable output suitable for logging or monitoring systems, as implemented in the runStatic() method.

What is the difference between memory usage and memory limit in the output?

memoryUsageBytes shows the current resident set size of the container's processes, while memoryLimitBytes reflects the maximum memory configured for that container. The ContainerStats struct in Sources/ContainerResource/Container/ContainerStats.swift encapsulates both values, allowing you to calculate utilization percentages.

Does the container stats command work with specific container names?

Yes. You can pass a container ID or name as an argument to container stats to filter output to that specific container. If you omit the --no-stream flag, the command will stream real-time updates for only that container rather than all running containers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →