> ## Documentation Index
> Fetch the complete documentation index at: https://microsanbox-staging-appcypher-sdk-runtime-bootstrap.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Metrics

> Monitor sandbox resource usage

<Tooltip tip="SDK and CLI resource metrics are not yet available on microsandbox cloud; instrument the workload with an external monitoring system."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

Query resource usage for a running sandbox: CPU, memory, and more. Get a single point-in-time snapshot, or open a streaming subscription that delivers updates at a fixed interval.

OCI sandboxes also expose optional upper filesystem fields for capacity dashboards. Guest-visible `upper_used_bytes` and `upper_free_bytes` are available when the protected bundled-kernel reporter is fresh. Host-observed `upper_host_allocated_bytes` is available when microsandbox can inspect the writable upper image from the host. SDKs surface those as nullable fields (`Option`, `null`, `None`, or `nil`) because custom kernels and non-OCI roots may not provide them.

<Note>
  Need continuous shipping to Grafana, Datadog, Prometheus, or any other OTel-compatible backend? See [`msb-metrics`](/observability/msb-metrics), a sidecar binary that reads the same data and ships it over OTLP.
</Note>

## Point-in-time

<CodeGroup>
  ```rust Rust theme={null}
  use microsandbox::Sandbox;

  let metrics = sb.metrics().await?;
  println!("CPU: {:.1}%, Mem: {} MB", metrics.cpu_percent, metrics.memory_bytes / 1024 / 1024);
  ```

  ```typescript TypeScript theme={null}
  const metrics = await sb.metrics();
  console.log(`CPU: ${metrics.cpuPercent.toFixed(1)}%, Mem: ${Math.floor(metrics.memoryBytes / 1024 / 1024)} MB`);
  ```

  ```python Python theme={null}
  m = await sb.metrics()
  print(f"CPU: {m.cpu_percent:.1f}%, Mem: {m.memory_bytes // 1024 // 1024} MB")
  ```

  ```go Go theme={null}
  metrics, err := sb.Metrics(ctx)
  fmt.Printf("CPU: %.1f%%, Mem: %d MB\n", metrics.CPUPercent, metrics.MemoryBytes/1024/1024)
  ```
</CodeGroup>

## Streaming

Subscribe to metric updates at a regular interval. Each update arrives as a separate event.

<CodeGroup>
  ```rust Rust theme={null}
  use std::time::Duration;
  use futures::StreamExt;

  let mut stream = sb.metrics_stream(Duration::from_secs(1));
  while let Some(m) = stream.next().await {
      let m = m?;
      println!("CPU: {:.1}%, Mem: {} MB", m.cpu_percent, m.memory_bytes / 1024 / 1024);
  }
  ```

  ```typescript TypeScript theme={null}
  for await (const m of await sb.metricsStream(1000)) {
      console.log(`[${m.timestamp.toISOString()}] CPU: ${m.cpuPercent.toFixed(1)}%`);
  }
  ```

  ```python Python theme={null}
  async for m in await sb.metrics_stream(interval=1.0):
      print(f"[{m.timestamp_ms}] CPU: {m.cpu_percent:.1f}%")
  ```

  ```go Go theme={null}
  stream, err := sb.MetricsStream(ctx, time.Second)
  defer stream.Close()
  for {
      metrics, err := stream.Recv(ctx)
      if err != nil {
          return err
      }
      if metrics == nil {
          break
      }
      fmt.Printf("CPU: %.1f%%\n", metrics.CPUPercent)
  }
  ```
</CodeGroup>

## Fleet-wide metrics

Get the latest metrics for every running sandbox at once. Useful for dashboards or capacity planning.

<CodeGroup>
  ```rust Rust theme={null}
  use microsandbox::all_sandbox_metrics;

  let all = all_sandbox_metrics().await?;
  ```

  ```typescript TypeScript theme={null}
  import { allSandboxMetrics } from "microsandbox";

  const all = await allSandboxMetrics();
  ```

  ```python Python theme={null}
  from microsandbox import all_sandbox_metrics

  all_metrics = await all_sandbox_metrics()
  ```

  ```go Go theme={null}
  all, err := m.AllSandboxMetrics(ctx)
  ```
</CodeGroup>

Fleet snapshots only include sandboxes whose runtime process is actually alive. A runtime that crashed without cleanup used to keep reporting its last sample as if the sandbox were running; readers now detect the dead owner and retire the entry on first read.

## Metrics reports (Rust)

The Rust SDK additionally exposes *reports*: metrics joined with catalog context for presentation. A report resolves the CPU and memory allocations from the sandbox's **active config**, so live resizes are reflected. It also carries a state field: `Running`, `Stalled` (runtime alive but no sample within three sampling intervals), or `Exited` (the preserved terminal sample of a stopped sandbox). This is what `msb metrics` renders.

```rust Rust theme={null}
use microsandbox::{all_sandbox_metrics_reports_local, sandbox_metrics_report_local};

// All sandboxes; pass true to include exited ones.
let reports = all_sandbox_metrics_reports_local(&local, false).await?;
for r in &reports {
    println!("{} [{:?}] {:.2} cores of {:?}", r.name, r.state, r.metrics.cpu_percent / 100.0, r.cpus);
}

// One sandbox by name, in any state (unlike `Sandbox::metrics`, which
// errors when the sandbox is not running).
let report = sandbox_metrics_report_local(&local, "my-app").await?;
```

Report APIs for TypeScript, Python, and Go will follow.
