Hardware Telemetry Collectors#
Important
This page documents the legacy Python-reader images and their configuration,
retained for users of older images and charts. For the native Docker image
in 2026.3.0, use Native Docker Collectors
and the metric migration guide.
The legacy ENABLE_* switches below are not the native image’s interface.
Besides the default CPU, memory, temperature, GPU, and NPU metrics, Metrics Manager can collect a set of additional Intel hardware metrics: package and platform power, DRAM bandwidth, per-core frequency and C-state residency, interrupts, disk and network I/O, GPU throttle state, and (opt-in) turbostat diagnostics.
These collectors cover what TCMI (Thermal, Compute, Memory, I/O) measures. TCMI describes the four areas of hardware behavior that matter for robotics and physical-AI workloads on Intel platforms. Each collector is a separate, opt-in switch, so you incur only the cost of the collectors you enable.
Note
Everything on this page is off by default. With no ENABLE_* variable set, the
container produces the same metrics as before these collectors existed. This also holds
when you mount your own telegraf.conf.
Collectors at a Glance#
Variable |
Default |
Telegraf drop-in |
Source |
Main series (Prometheus names) |
|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The NPU power_state field (npu_power_state) is not behind a toggle; it is part of the
existing NPU reader. Accepted “on” values are true, 1, yes, on, and auto
(case-insensitive). The table above lists the legacy collector variables;
the current variable reference describes native images.
Quick Start: The TCMI Preset#
To turn on the set of collectors TCMI users typically need on an Intel host, add this to
your .env (copy it from .env.example):
# .env
ENABLE_RAPL_POWER=true
ENABLE_PSYS_POWER=true
ENABLE_DRAM_BW=auto # also needs an image built with INSTALL_PERF=true (see below)
ENABLE_DISK_IO=true
ENABLE_NET_IO=true # sees host NICs only with the host-nic-telemetry profile
ENABLE_INTERRUPTS=true
ENABLE_GPU_THROTTLE=true # Intel xe driver only
ENABLE_TEMP_STATS and ENABLE_TURBOSTAT are left out on purpose: they are for
specific tuning work and add sampling load. Enable them separately.
Then recreate the container:
docker compose up -d
Warning
Changing any ENABLE_* variable takes effect only after the container is recreated.
There is no hot reload.
Check what was loaded:
docker compose logs metrics-manager | grep -E "^\[(INFO|WARN)\] "
[INFO] 10-power: ENABLED
[INFO] 20-dram-bw: ENABLED
[INFO] 30-disk: ENABLED
...
[INFO] 60-turbostat: disabled
A collector that was requested but cannot work is skipped with a [WARN] line (for
example turbostat without a usable binary, or ENABLE_DRAM_BW=auto without perf in
the image). The rest of Telegraf keeps running.
Supported Hardware and Expected Series Count#
Collectors never disrupt core metrics: on hardware that lacks a data source they emit nothing and log why (see Troubleshooting). Plan for the following:
Collector |
Where it gives no or partial data |
|---|---|
|
No data on CPUs without the IMC free-running PMU, for example Skylake-SP (Intel® Xeon® 8176), which exposes only |
|
Intel |
|
Intel® Core™ Ultra Series 2 and Intel® Core™ Ultra Series 3 (formerly codenamed as Panther Lake) client parts: no |
|
In the default bridge deployment it reports only the container’s own interface. See Network metrics. |
Some collectors scale with the number of CPU cores or devices. Measured per Prometheus scrape on a 112-thread Intel® Xeon® Platinum 8176:
Collector |
Lines per scrape (112 threads) |
Notes |
|---|---|---|
|
about 650 |
Per-core frequency, temperature, and C-state series scale with core count. |
|
about 150 (21 KB) |
One |
|
about 2,050 per sample |
Per-core diagnostics. Use it for engineering work, not continuous monitoring. |
On smaller client systems the same collectors produce far fewer lines. Measured per
scrape on a 6-CPU Intel® Core™ Ultra Series 3 and a 16-CPU Intel® Core™ Ultra Series 2 system:
ENABLE_INTERRUPTS 40 and 57 lines, ENABLE_TURBOSTAT 266 and 612 lines, and the full TCMI
preset about 167 and 202 lines in total (3.5 KB without any collector).
Note
Every Telegraf sample is also forwarded to each /metrics/stream Server-Sent Events
(SSE) client every 500 ms, so large collectors increase the size of every stream frame.
Enable only what you use.
Requirements and Behavior per Collector#
Power: ENABLE_RAPL_POWER and ENABLE_PSYS_POWER#
Need the privileged container (the compose default),
/sysmounted read-only, andpid: host. Running Average Power Limit (RAPL)energy_ujis readable by root only; without privilege the readers find nothing readable and idle.Kernel modules:
intel_rapl_common,msr,cpufreq,intel-uncore-frequency.ENABLE_PSYS_POWERadds the RAPL platform (psys) domain, the best Linux proxy for whole-board power (CPU, iGPU, NPU, and memory).intel_powerstatdoes not expose it.Package and psys power are gauges in watts. DRAM RAPL power is not collected by default because client SoCs have no DRAM subzone.
DRAM Bandwidth: ENABLE_DRAM_BW#
The reader runs perf stat on the integrated memory controller (IMC) free-running counters
and reports ready-to-use GB/s. Telegraf’s native inputs.intel_pmu plugin is not used for
three reasons:
It needs per-model perfmon event JSON files (from the
intel/perfmonproject) that the image does not ship, and the files must match the CPU model.On an Intel® Core™ Ultra Series 1 CPU (Intel® Core™ Ultra 5 125H, Telegraf 1.39.3) the
UNC_M_CAS_COUNT_RD/WRevents did work under memory load: about 11.0 GB/s read and 5.5 GB/s write, against 10.6 and 5.6 GB/s fromperf statover the same period (single samples). The plugin returns raw per-IMC cache-line counts, so you must multiply by 64 bytes and take a rate yourself. The counters are also multiplexed, so the values are scaled estimates.The
*_CAS_COUNT_FREERUNevents read zero under the same load. On CPUs whose model is not in the perfmon event tables the plugin cannot be used at all.
inputs.intel_pmu is a reasonable alternative if you already maintain the event files.
perfcomes from thelinux-perfDebian package (GPL-2.0), which is not in the published image. Build your own image with it:INSTALL_PERF=true make build # or: docker compose build --build-arg INSTALL_PERF=true metrics-manager
It adds about 150 MB to the image.
Set
ENABLE_DRAM_BW=auto. Ifperfis missing, the entrypoint logsENABLE_DRAM_BW=auto but perf not installedand skips the drop-in.Needs
perf_event_paranoidat0or lower (cat /proc/sys/kernel/perf_event_paranoid) and the performance monitoring unit (PMU) to be exposed (ls /sys/bus/event_source/devices/uncore_imc_free_running*).Sampling window:
DRAM_BW_INTERVAL(seconds, default1).
Interrupts: ENABLE_INTERRUPTS#
Emits one interrupts_total series per numbered (device) IRQ, with irq, type, and
device tags. Kernel housekeeping counters (LOC, NMI, IPI, …) and the per-CPU
breakdown are dropped. Keeping per-CPU fields would produce about 16,000 lines per
scrape on a 112-thread host. If you need per-CPU affinity, remove
fieldinclude = ["total"] in telegraf.d/50-interrupts.conf and accept the cardinality.
It is a counter, so query it with rate().
Disk I/O: ENABLE_DISK_IO#
Collects whole physical disks only. The default device filter is
nvme[0-9]*n[0-9], sd[a-z], vd[a-z], and mmcblk[0-9]. It skips loop, RAM, and
device-mapper devices and partitions. It also misses the 27th SCSI disk onward
(sdaa, …) and NVMe namespaces 10 and above. The series are counters.
Network Metrics and the Host-NIC Profile#
ENABLE_NET_IO loads inputs.net and inputs.ethtool. In the default bridge
deployment they see only the container’s own interface (usually eth0), not the host’s
NICs. To report the host’s physical NICs, opt in to the host-nic-telemetry Compose
profile. It runs the same image with network_mode: host and enables ENABLE_NET_IO by
default:
docker compose stop metrics-manager
docker compose --profile host-nic-telemetry up -d metrics-manager-host-nic
Warning
This changes the networking model for clients that connect through the
metrics-manager service name, and the API and metrics ports bind directly on the
host. Always name metrics-manager-host-nic explicitly: starting the profile without
a service name also starts the default service. Switch back with:
docker compose --profile host-nic-telemetry stop metrics-manager-host-nic
docker compose up -d metrics-manager
GPU Throttle: ENABLE_GPU_THROTTLE#
Reads the Intel xe DRM sysfs tree for the achieved GPU frequency and throttle reasons
(thermal, PL1, PL2, PROCHOT). It complements the existing GPU metrics, which report the
requested frequency but not the achieved one. A requested frequency above the achieved
frequency together with a non-zero throttle flag means the hardware held the GPU back.
Hosts using the i915 driver produce no data.
Turbostat: ENABLE_TURBOSTAT#
Turbostat is an engineering diagnostic. It adds instructions per cycle (IPC), which
distinguishes busy from stalled; system management interrupt (SMI) counts, a common hidden
cause of latency spikes; per-core temperature; and per-core interrupts. The summary row
carries core="-", so filter per-core queries with core!="-".
The image ships no turbostat binary because it is coupled to the kernel version. Compose bind-mounts the host’s kernel-matched binary from
TURBOSTAT_BIN. When you usemake upwithENABLE_TURBOSTAT=true(in the environment or.env), the Makefile resolves it for you. When you rundocker composedirectly, set it yourself:export TURBOSTAT_BIN=$( [ -x /usr/lib/linux-tools/$(uname -r)/turbostat ] \ && echo /usr/lib/linux-tools/$(uname -r)/turbostat || command -v turbostat ) docker compose up -d
Do not write a kernel-specific path into
.env; it breaks on the next kernel update.Needs model-specific register (MSR) access (
msrmodule, privileged container). Before loading the drop-in the entrypoint checks that the binary is a runnable file and that/dev/cpu/0/msrcan be opened. If either check fails, it logs[WARN] 60-turbostat: ...and skips the collector instead of letting turbostat restart in a loop.TURBOSTAT_INTERVALsets the sampling cadence in seconds (default5).The Helm chart has no turbostat bind-mount. Turbostat is a Docker Compose feature in this release.
High-Frequency Temperature: ENABLE_TEMP_STATS#
Adds temp_highres_* series sampled every 100 ms and aggregated to per-second
minimum, maximum, and mean for the CPU package sensors. The default temp input keeps its
1-second cadence.
Using Your Own telegraf.conf#
You can still mount your own telegraf.conf with TELEGRAF_CONFIG. The container
always starts Telegraf with --config-directory /etc/telegraf/active.d, which holds only
the collectors you enabled. With every toggle off that directory is empty, so your
configuration runs unchanged. Native images use the separate
native collector selection interface instead.
Querying the Metrics#
Metrics Manager exposes everything on :9273 in Prometheus format; it does not ship
dashboards. A scrape-job snippet is in dashboards/prometheus-scrape-job.yml. The Helm
chart can create a ServiceMonitor (see Helm Deployment).
Prometheus appends the field name to the measurement name, so rapl_power with field
power_w becomes rapl_power_power_w. Counters need rate(); gauges are queried directly:
# Gauges
rapl_power_power_w{domain="psys"} # platform power (W)
powerstat_package_current_power_consumption_watts # CPU package power (W)
dram_bw_read_gbps # DRAM read bandwidth (GB/s)
gpu_throttle_act_freq_mhz # achieved GPU frequency
temp_highres_temp_max{sensor=~"coretemp_package_id_.*"} # needs ENABLE_TEMP_STATS
turbostat_ipc{core!="-"} # needs ENABLE_TURBOSTAT
# Counters
rate(diskio_io_time[1m]) / 10 # disk utilization %
rate(net_bytes_recv[1m]) # network receive (bytes/s)
rate(interrupts_total[1m]) # interrupts per second
# NPU PCI power state: -1 unknown, D0=0, D1=1, D2=2, D3hot=3, D3cold=4
npu_power_state
Note
Telegraf’s Prometheus output serves only the last collected value. Scrape at an interval no longer than Telegraf’s 1 s collection interval, or intermediate samples are lost.
Troubleshooting#
A metric is missing. Check the startup log first, then the reader’s trace log. The readers park themselves instead of exiting when their data source is absent, so a missing metric is usually a logged reason, not an error:
docker compose logs metrics-manager | grep -E "WARN|disabled"
docker exec metrics-manager tail -n 20 /app/rapl_reader_trace.log
docker exec metrics-manager tail -n 20 /app/dram_bw_reader_trace.log
docker exec metrics-manager tail -n 20 /app/gpu_throttle_reader_trace.log
A line such as entering idle mode: perf could not count IMC free-running events names the
cause. To confirm the readers are running:
docker exec metrics-manager ps -ef | grep -E 'rapl_reader|dram_bw_reader|gpu_throttle_reader|npu_reader'
Turbostat is skipped. Read the [WARN] 60-turbostat line: it distinguishes a missing
binary, a wrapper script or kernel mismatch, and missing MSR access.
ENABLE_DRAM_BW=auto does nothing. The image has no perf. Rebuild with
INSTALL_PERF=true.
Too many series. Disable the collector, or for interrupts keep the default per-IRQ total. See Expected Series Count.
Supporting Resources#
License#
Copyright (C) 2025-2026 Intel Corporation
SPDX-License-Identifier: Apache-2.0