Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

Conversation

@bitoku
Copy link
Contributor

@bitoku bitoku commented Dec 18, 2025

What type of PR is this?

/kind cleanup

What this PR does / why we need it:

It consists of 4 commits. It may be better to look per commit.
In the last commit, I addressed #9608 (comment)

Which issue(s) this PR fixes:

Special notes for your reviewer:

Does this PR introduce a user-facing change?

None

Summary by CodeRabbit

  • Bug Fixes

    • Fixed potential nil pointer in network metrics generation.
  • New Features

    • Richer cgroup/process metrics (per-process FDs, sockets, threads) and unified cgroup/disk/memory metric types.
    • Exported OOM event metrics on Linux.
    • VM runtime now reports cgroup and disk stats with platform-specific fallbacks.
  • Refactor

    • Harmonized statistics collection and public APIs across components for consistent reporting.

✏️ Tip: You can customize this high-level summary in your review settings.

Signed-off-by: Ayato Tokubi <[email protected]>
…s for consistency with other structs and cadvisor

Signed-off-by: Ayato Tokubi <[email protected]>
@openshift-ci openshift-ci bot added release-note-none Denotes a PR that doesn't merit a release note. kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. dco-signoff: yes Indicates the PR's author has DCO signed all their commits. labels Dec 18, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 18, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Replaces in-repo cgmgr-specific stat types with centralized internal/lib/stats types, updates function signatures and call sites across cgroup managers, statsserver, and OCI runtime to use stats.CgroupStats/stats.DiskStats, removes legacy stat definitions/stubs, and adjusts metric generators to consume opencontainers cgroups types.

Changes

Cohort / File(s) Summary
Cgroup manager interfaces
internal/config/cgmgr/cgmgr_linux.go, internal/config/cgmgr/cgmgr_unsupported.go, internal/config/cgmgr/cgroupfs_linux.go, internal/config/cgmgr/systemd_linux.go
Updated CgroupManager methods (ContainerCgroupStats, SandboxCgroupStats) to return *stats.CgroupStats; added internal/lib/stats imports and adjusted Null/manager implementations.
Cgroup stats refactor
internal/config/cgmgr/stats_linux.go, (removed) internal/config/cgmgr/stats_unsupported.go
Removed internal CgroupStats/related structs and helpers; statsFromLibctrMgr now returns *stats.CgroupStats; introduced cgroupProcessStats to populate stats.ProcessStats.
Centralized stats types
internal/lib/stats/cgroup_stats_linux.go, internal/lib/stats/cgroup_stats_unsupported.go
Added stats.CgroupStats (embeds cgroups.Stats, adds ProcessStats and SystemNano) and stats.ProcessStats; added non-Linux stub.
Disk stats rename & platform stubs
internal/lib/stats/disk_stats_linux.go, internal/lib/stats/disk_stats_freebsd.go, internal/lib/stats/disk_stats_unsupported.go, (removed) internal/oci/disk_metrics_unsupported.go
Renamed/moved DiskMetricsDiskStats, FilesystemMetricsFilesystemStats into internal/lib/stats; added unsupported-platform stubs and removed legacy unsupported OCI file.
Statsserver metric generators
internal/lib/statsserver/cpu_metrics_linux.go, internal/lib/statsserver/disk_metrics_linux.go, internal/lib/statsserver/hugetlb_metrics_linux.go, internal/lib/statsserver/memory_metrics_linux.go, internal/lib/statsserver/pressure_metrics_linux.go, internal/lib/statsserver/process_metrics_linux.go, internal/lib/statsserver/network_metrics_linux.go
Updated generator signatures to consume github.com/opencontainers/cgroups and internal/lib/stats types (e.g., cgroups.CpuStats, cgroups.MemoryStats, cgroups.BlkioStats, cgroups.PidsStats, stats.ProcessStats); added nil checks; added Linux memory/OOM metric implementations.
StatsServer core refactor
internal/lib/statsserver/stats_server_linux.go
Core now accepts *stats.CgroupStats and *stats.DiskStats; updated CRI stat builders and field paths, added helpers computeMemoryStats, computeSwapUsage, isMemoryUnlimited, and adapted memory/swap/process conversions.
OCI runtime API & implementations
internal/oci/oci.go, internal/oci/runtime_oci.go, internal/oci/runtime_pod.go, internal/oci/runtime_vm.go, internal/oci/runtime_vm_linux.go, internal/oci/runtime_vm_unsupported.go
Renamed/changed runtime API: ContainerStatsCgroupStats returning *stats.CgroupStats; DiskStats now returns *stats.DiskStats; added Linux VM converters and non-Linux stubs; removed old VM-stats conversions where applicable.
Mocks, tests, imports
internal/lib/container_server.go, test/mocks/oci/oci.go, server/container_stats_test.go
Updated imports/aliases, mock methods and recorders to new CgroupStats/DiskStats signatures; adjusted test Describe strings to "CgroupStats".
Removed legacy metric files
(removed) internal/lib/stats/memory_metrics.go, (removed) internal/lib/stats/disk_metrics_unsupported.go, (removed) internal/lib/stats/pressure_metrics_unsupported.go, (removed) internal/oci/disk_metrics_unsupported.go
Deleted legacy metric generator stubs and unsupported-platform placeholders replaced by new stats types and implementations.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Spot-checks:

  • All interface and call-site updates for *stats.CgroupStats and *stats.DiskStats.
  • Field/path changes in internal/lib/statsserver/stats_server_linux.go (pointer usage, .CpuStats/.MemoryStats/.PidsStats).
  • Correct population and unit handling in cgroupProcessStats and VM V1/V2 converters.
  • Memory/swap computations and v1/v2 distinctions in new helpers.
  • Mock updates and non-Linux stubs consistency.

Possibly related PRs

Suggested reviewers

  • mrunalp
  • fidencio
  • littlejawa

"I hopped through types and fields all day,
Moved stats to one neat burrowed way,
Pids counted, sockets tallied with care,
Cgroup and disk now live over there —
A carrot cake celebration, stats everywhere! 🥕🐇"

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly reflects the main objective of the PR: migrating from internal CgroupStats types to using cgroups.CgroupStats for stats collection across multiple files and components.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci openshift-ci bot requested a review from littlejawa December 18, 2025 12:32
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Dec 18, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: bitoku
Once this PR has been reviewed and has the lgtm label, please assign kolyshkin for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot requested a review from QiWang19 December 18, 2025 12:32
coderabbitai[bot]

This comment was marked as outdated.

@bitoku bitoku force-pushed the cri-stats-refactor branch from 9eb7359 to 8ef621b Compare December 18, 2025 12:38
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
internal/lib/statsserver/disk_metrics_linux.go (2)

53-73: Loop variable capture in closures may cause incorrect metric values.

The stat variable is captured by the closures in valueFunc, but since stat changes on each iteration, all closures will reference the final value of stat when executed. This can result in incorrect metric values being reported.

🔎 Apply this diff to capture the loop variable correctly:
 	for _, stat := range ioStats.IoServicedRecursive {
+		stat := stat // capture loop variable
 		// TODO (@haircommander): cadvisor translates to device name, but finding the device is tricky
 		// update to populate device name
 		device := fmt.Sprintf("%d:%d", stat.Major, stat.Minor)

75-104: Same loop variable capture issue in the second loop.

The stat variable captured in closures will have incorrect values when valueFunc is executed.

🔎 Apply this diff:
 	for _, stat := range ioStats.IoServiceBytesRecursive {
+		stat := stat // capture loop variable
 		// TODO (@haircommander): cadvisor translates to device name, but finding the device is tricky
 		// update to populate device name
 		device := fmt.Sprintf("%d:%d", stat.Major, stat.Minor)
♻️ Duplicate comments (6)
internal/lib/statsserver/disk_metrics_linux.go (2)

17-18: Fix function comment to match function name.

The comment says "generateSandboxDiskMetrics" but the function is named generateContainerDiskMetrics.


49-50: Fix function comment to match function name.

The comment says "generateSandboxDiskIOMetrics" but the function is named generateContainerDiskIOMetrics.

internal/lib/statsserver/memory_metrics_linux.go (2)

11-15: Add nil check for mem parameter.

The function accesses mem fields directly without verifying it's non-nil. If mem is nil, this will cause a panic at lines 13-15 when dereferencing fields like mem.Cache, mem.KernelUsage.Usage, etc.

🔎 Suggested fix:
 func generateContainerMemoryMetrics(ctr *oci.Container, mem *cgroups.MemoryStats) []*types.Metric {
+	if mem == nil {
+		return nil
+	}
 	// Compute derived memory values
 	workingSetBytes, rssBytes, pageFaults, majorPageFaults, _ := computeMemoryMetricValues(mem)

145-151: Potential integer underflow in swap calculation.

For cgroup v2, if SwapUsage.Usage < Usage.Usage (which could happen due to timing or accounting edge cases), the subtraction at line 148 will underflow to a very large uint64 value.

🔎 Suggested fix:
 func computeSwapUsageForMetrics(memStats *cgroups.MemoryStats) uint64 {
 	if node.CgroupIsV2() {
-		return memStats.SwapUsage.Usage - memStats.Usage.Usage
+		if memStats.SwapUsage.Usage > memStats.Usage.Usage {
+			return memStats.SwapUsage.Usage - memStats.Usage.Usage
+		}
+		return 0
 	}
 	return memStats.SwapUsage.Usage
 }
internal/oci/runtime_vm_linux.go (1)

31-36: Using stored context instead of passed context parameter.

The method uses r.ctx for the Stats call instead of the ctx parameter passed to the function. This prevents proper cancellation and deadline propagation.

As per coding guidelines: "Propagate context.Context through function calls in Go code."

🔎 Suggested fix:
-	resp, err := r.task.Stats(r.ctx, &task.StatsRequest{
+	resp, err := r.task.Stats(ctx, &task.StatsRequest{
 		ID: c.ID(),
 	})
internal/lib/statsserver/stats_server_linux.go (1)

454-463: Potential integer underflow in swap calculation.

Same issue as in memory_metrics_linux.go: for cgroup v2, if SwapUsage.Usage < Usage.Usage, the subtraction at line 460 will underflow to a very large uint64 value.

🔎 Suggested fix:
 func computeSwapUsage(memStats *cgroups.MemoryStats) uint64 {
 	if node.CgroupIsV2() {
-		return memStats.SwapUsage.Usage - memStats.Usage.Usage
+		if memStats.SwapUsage.Usage > memStats.Usage.Usage {
+			return memStats.SwapUsage.Usage - memStats.Usage.Usage
+		}
+		return 0
 	}
 	return memStats.SwapUsage.Usage
 }
🧹 Nitpick comments (2)
internal/lib/stats/cgroup_stats_linux.go (1)

1-9: Consider adding an explicit build tag for consistency.

While the _linux.go suffix implicitly restricts this to Linux builds, other files in this PR (like cgroupfs_linux.go and cgmgr_linux.go) use explicit //go:build linux tags. Adding one here would improve consistency and make the build constraint immediately visible.

🔎 Suggested diff:
+//go:build linux
+
 package stats

 import "github.com/opencontainers/cgroups"
internal/lib/statsserver/memory_metrics_linux.go (1)

117-143: Consider consolidating duplicate memory computation logic.

The logic in computeMemoryMetricValues (lines 117-143) is nearly identical to computeMemoryStats in stats_server_linux.go (lines 419-452). Both compute working set bytes, RSS, and page faults using the same cgroup v1/v2 branching logic.

Consider extracting this shared logic into a single helper function in a common location to reduce duplication and ensure consistency.

Also applies to: 419-452

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9eb7359 and 8ef621b.

📒 Files selected for processing (24)
  • internal/config/cgmgr/cgmgr_linux.go (3 hunks)
  • internal/config/cgmgr/cgmgr_unsupported.go (3 hunks)
  • internal/config/cgmgr/cgroupfs_linux.go (3 hunks)
  • internal/config/cgmgr/stats_linux.go (3 hunks)
  • internal/config/cgmgr/stats_unsupported.go (0 hunks)
  • internal/config/cgmgr/systemd_linux.go (3 hunks)
  • internal/lib/stats/cgroup_stats_linux.go (1 hunks)
  • internal/lib/stats/cgroup_stats_unsupported.go (1 hunks)
  • internal/lib/stats/disk_stats_unsupported.go (1 hunks)
  • internal/lib/statsserver/cpu_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/disk_metrics_linux.go (3 hunks)
  • internal/lib/statsserver/hugetlb_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/memory_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/pressure_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/process_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/stats_server_linux.go (8 hunks)
  • internal/oci/oci.go (4 hunks)
  • internal/oci/runtime_oci.go (4 hunks)
  • internal/oci/runtime_pod.go (2 hunks)
  • internal/oci/runtime_vm.go (0 hunks)
  • internal/oci/runtime_vm_linux.go (1 hunks)
  • internal/oci/runtime_vm_unsupported.go (1 hunks)
  • server/container_stats_test.go (2 hunks)
  • test/mocks/oci/oci.go (3 hunks)
💤 Files with no reviewable changes (2)
  • internal/config/cgmgr/stats_unsupported.go
  • internal/oci/runtime_vm.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/oci/runtime_pod.go
  • server/container_stats_test.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use interface-based design and dependency injection patterns in Go code
Propagate context.Context through function calls in Go code
Use fmt.Errorf with %w for error wrapping in Go code
Use logrus with structured fields for logging in Go code
Add comments explaining 'why' not 'what' in Go code
Use platform-specific file naming: *_{linux,freebsd}.go for platform-dependent code

Files:

  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/lib/stats/cgroup_stats_linux.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • test/mocks/oci/oci.go
  • internal/oci/runtime_oci.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/oci/oci.go
  • internal/oci/runtime_vm_unsupported.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
🧠 Learnings (4)
📚 Learning: 2025-12-17T13:38:34.646Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9667
File: server/container_create.go:1233-1236
Timestamp: 2025-12-17T13:38:34.646Z
Learning: In the cri-o/cri-o repository, protobuf-generated Get* methods for k8s.io/cri-api types are nil-safe: if the receiver is nil, GetX() returns the zero value instead of panicking. Do not add explicit nil checks before chaining calls on such getters. Apply this guidance to all Go code that uses these generated getters across the codebase.

Applied to files:

  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/lib/stats/cgroup_stats_linux.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • test/mocks/oci/oci.go
  • internal/oci/runtime_oci.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/oci/oci.go
  • internal/oci/runtime_vm_unsupported.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Add comments explaining 'why' not 'what' in Go code

Applied to files:

  • internal/lib/statsserver/disk_metrics_linux.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Use platform-specific file naming: `*_{linux,freebsd}.go` for platform-dependent code

Applied to files:

  • internal/lib/stats/disk_stats_unsupported.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Propagate context.Context through function calls in Go code

Applied to files:

  • internal/oci/runtime_vm_linux.go
🧬 Code graph analysis (14)
internal/config/cgmgr/cgroupfs_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/statsserver/disk_metrics_linux.go (4)
internal/lib/stats/disk_stats_unsupported.go (1)
  • FilesystemStats (13-18)
internal/lib/stats/disk_stats_linux.go (1)
  • FilesystemStats (16-21)
internal/lib/stats/disk_stats_freebsd.go (1)
  • FilesystemStats (16-21)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • BlkioStats (151-166)
internal/config/cgmgr/cgmgr_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/config/cgmgr/cgmgr_unsupported.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
test/mocks/oci/oci.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/lib/stats/disk_stats_unsupported.go (2)
internal/lib/stats/disk_stats_linux.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (24-47)
  • DiskStats (11-13)
internal/lib/stats/disk_stats_freebsd.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (23-46)
  • DiskStats (12-14)
internal/config/cgmgr/systemd_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/oci/oci.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/oci/runtime_vm_unsupported.go (6)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/config/cgmgr/cgmgr_linux.go (1)
  • New (91-98)
internal/config/cgmgr/cgmgr_unsupported.go (1)
  • New (38-40)
internal/oci/oci.go (1)
  • New (89-99)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/config/cgmgr/stats_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/oci/runtime_vm_linux.go (1)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/statsserver/memory_metrics_linux.go (1)
vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go (2)
  • MetricType_GAUGE (680-680)
  • MetricType_COUNTER (679-679)
internal/lib/statsserver/stats_server_linux.go (3)
vendor/github.com/opencontainers/cgroups/stats.go (3)
  • CpuStats (55-60)
  • MemoryStats (96-117)
  • PidsStats (137-142)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-9)
internal/lib/stats/disk_stats_linux.go (2)
  • DiskStats (11-13)
  • FilesystemStats (16-21)
internal/lib/statsserver/process_metrics_linux.go (1)
vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go (1)
  • MetricType_GAUGE (680-680)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: build static / amd64
  • GitHub Check: build static / ppc64le
  • GitHub Check: build static / s390x
  • GitHub Check: security-checks
  • GitHub Check: unit / arm64 / root
  • GitHub Check: build-freebsd
  • GitHub Check: build static / arm64
  • GitHub Check: codeql-build
  • GitHub Check: unit / amd64 / rootless
  • GitHub Check: unit / amd64 / root
  • GitHub Check: build
  • GitHub Check: rpm-build:fedora-43-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-aarch64:fedora-rawhide
  • GitHub Check: docs
  • GitHub Check: lint
🔇 Additional comments (22)
internal/lib/stats/disk_stats_unsupported.go (1)

1-23: LGTM!

The unsupported platform stub correctly mirrors the Linux/FreeBSD implementations with matching type definitions and provides a clear not-supported error. The build constraint and file naming follow the platform-specific conventions per the coding guidelines.

internal/config/cgmgr/cgroupfs_linux.go (1)

18-19: LGTM!

The signature updates to *stats.CgroupStats are consistent with the interface changes, and both methods properly delegate to statsFromLibctrMgr while handling errors from the underlying cgroup manager retrieval.

Also applies to: 99-106, 166-173

internal/oci/runtime_vm_unsupported.go (1)

1-20: LGTM!

The unsupported platform stubs correctly provide explicit "not supported" errors and follow the expected method signatures with proper context propagation per the coding guidelines.

internal/config/cgmgr/cgmgr_linux.go (1)

19-19: LGTM!

The interface signature updates to use *stats.CgroupStats are well-aligned with the PR objective to consolidate stats types into the new internal/lib/stats package. The interface documentation is appropriately preserved.

Also applies to: 60-63, 84-87

internal/config/cgmgr/cgmgr_unsupported.go (1)

72-74: Referenced file runtime_vm_unsupported.go not found in codebase; cannot verify inconsistency claim.

The inconsistency claim cannot be verified because the comparison file (runtime_vm_unsupported.go) does not appear to exist. Within cgmgr_unsupported.go itself, the (nil, nil) return pattern is actually consistent across all NullCgroupManager methods. While other unsupported stubs in the codebase do vary—some using no-op nil returns and others returning explicit errors—without the specific reference point, the claimed inconsistency is unverifiable. If consistency across unsupported platform stubs is desired, clarify which error pattern should apply and provide the correct file reference.

internal/lib/statsserver/process_metrics_linux.go (1)

10-42: No nil-safety issue — pidsStats is always valid.

The parameter receives a pointer to an embedded struct field (&containerStats.PidsStats), which is guaranteed to be non-nil. Even if cgroup stats report zero values for Current or Limit, the pointer itself is always valid.

Likely an incorrect or invalid review comment.

internal/config/cgmgr/systemd_linux.go (3)

13-13: LGTM!

The import of the new internal/lib/stats package is correctly added to support the updated return types for cgroup stats methods.


131-138: LGTM!

The ContainerCgroupStats method signature is correctly updated to return *stats.CgroupStats, maintaining the same control flow and error handling while aligning with the centralized stats type.


277-284: LGTM!

The SandboxCgroupStats method signature is correctly updated to return *stats.CgroupStats, consistent with ContainerCgroupStats and the broader refactor.

internal/lib/statsserver/cpu_metrics_linux.go (5)

7-7: LGTM!

The import correctly references the github.com/opencontainers/cgroups package to use the CpuStats type directly.


13-13: LGTM!

The function signature correctly uses *cgroups.CpuStats from the opencontainers cgroups library, aligning with the broader stats type consolidation.


19-19: LGTM!

The nested field access cpu.CpuUsage.UsageInUsermode and cpu.CpuUsage.UsageInKernelmode correctly matches the cgroups.CpuStats structure.

Also applies to: 27-27


34-43: LGTM!

The per-CPU usage handling is correctly updated to use cpu.CpuUsage.PercpuUsage and cpu.CpuUsage.TotalUsage, maintaining the fallback logic when per-CPU data is unavailable.


59-59: LGTM!

The throttling data fields are correctly accessed via the nested cpu.ThrottlingData struct (Periods, ThrottledPeriods, ThrottledTime), matching the cgroups.CpuStats structure.

Also applies to: 67-67, 75-75

internal/config/cgmgr/stats_linux.go (2)

10-10: LGTM!

Import correctly added to use the centralized stats.CgroupStats type from internal/lib/stats.


41-56: Clean refactor that simplifies stats collection.

The function now delegates directly to cgMgr.GetStats() and cgMgr.GetPids(), eliminating the previous in-file stat computation logic. The stats.CgroupStats struct is correctly constructed by:

  • Dereferencing and embedding the cgroups.Stats value (Line 53)
  • Populating SystemNano with the current timestamp
  • Including the process IDs from GetPids()

Error handling is properly preserved for both operations.

internal/oci/runtime_oci.go (3)

22-22: LGTM!

Import correctly added for the centralized internal/lib/stats package.


1279-1287: LGTM!

The method is appropriately renamed from ContainerStats to CgroupStats with return type updated to *stats.CgroupStats. The implementation correctly delegates to the cgroup manager.


1290-1305: LGTM!

The DiskStats method correctly returns *stats.DiskStats and delegates to stats.GetDiskUsageForPath(), maintaining proper error handling for missing mount points.

test/mocks/oci/oci.go (1)

1-2: Generated code correctly updated.

This mock file is auto-generated by MockGen and correctly reflects the interface changes to RuntimeImpl. The updates include:

  • New CgroupStats method (replacing ContainerStats)
  • Updated DiskStats return type to *stats.DiskStats
  • Proper import of the internal/lib/stats package
internal/oci/oci.go (1)

14-14: LGTM! Clean refactoring to use the new stats types.

The changes consistently update the API surface to use *stats.CgroupStats and *stats.DiskStats instead of the legacy cgmgr-based types. The interface definition and method implementations are aligned properly.

Also applies to: 72-73, 460-470, 473-483

internal/lib/statsserver/stats_server_linux.go (1)

54-60: Well-structured refactoring to use new stats types.

The migration from legacy cgmgr types to the new stats.CgroupStats structure is implemented consistently throughout. The addition of helper functions like computeMemoryStats, computeSwapUsage, and isMemoryUnlimited improves code organization and handles cgroup v1/v2 differences appropriately.

Also applies to: 256-329, 352-417, 419-468

@bitoku bitoku force-pushed the cri-stats-refactor branch from 8ef621b to bd29980 Compare December 18, 2025 12:49
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (5)
internal/lib/statsserver/disk_metrics_linux.go (2)

17-18: Fix function comment to match function name.

The comment says "generateSandboxDiskMetrics" but the function is named generateContainerDiskMetrics.

🔎 Apply this diff:
-// generateSandboxDiskMetrics computes filesystem disk metrics from DiskStats for a container sandbox.
+// generateContainerDiskMetrics computes filesystem disk metrics from DiskStats for a container.

49-50: Fix function comment to match function name.

The comment says "generateSandboxDiskIOMetrics" but the function is named generateContainerDiskIOMetrics. The past review indicates this was addressed in commit 8ef621b, but the mismatch still appears in the current code.

🔎 Apply this diff:
-// generateSandboxDiskIOMetrics computes filesystem disk metrics from DiskStats for a container sandbox.
+// generateContainerDiskIOMetrics computes disk IO metrics from BlkioStats for a container.
internal/lib/statsserver/memory_metrics_linux.go (2)

11-15: Add nil check for mem parameter.

The function accesses mem fields directly without verifying it's non-nil. If mem is nil, this will cause a panic.

🔎 Apply this diff to add the nil check:
 func generateContainerMemoryMetrics(ctr *oci.Container, mem *cgroups.MemoryStats) []*types.Metric {
+	if mem == nil {
+		return nil
+	}
 	// Compute derived memory values
 	workingSetBytes, rssBytes, pageFaults, majorPageFaults, _ := computeMemoryMetricValues(mem)

145-152: Potential integer underflow in swap calculation.

For cgroup v2, if SwapUsage.Usage < Usage.Usage (which could happen due to timing or accounting edge cases), the subtraction will underflow to a very large uint64 value.

🔎 Apply this diff to guard against underflow:
 func computeSwapUsageForMetrics(memStats *cgroups.MemoryStats) uint64 {
 	if node.CgroupIsV2() {
-		return memStats.SwapUsage.Usage - memStats.Usage.Usage
+		if memStats.SwapUsage.Usage > memStats.Usage.Usage {
+			return memStats.SwapUsage.Usage - memStats.Usage.Usage
+		}
+		return 0
 	}
 	return memStats.SwapUsage.Usage
 }
internal/lib/statsserver/stats_server_linux.go (1)

455-465: Potential integer underflow in swap calculation.

For cgroup v2, if SwapUsage.Usage < Usage.Usage (which could happen due to timing or accounting edge cases), the subtraction will underflow to a very large uint64 value.

🔎 Apply this diff to guard against underflow:
 func computeSwapUsage(memStats *cgroups.MemoryStats) uint64 {
 	if node.CgroupIsV2() {
-		return memStats.SwapUsage.Usage - memStats.Usage.Usage
+		if memStats.SwapUsage.Usage > memStats.Usage.Usage {
+			return memStats.SwapUsage.Usage - memStats.Usage.Usage
+		}
+		return 0
 	}
 	return memStats.SwapUsage.Usage
 }
🧹 Nitpick comments (5)
server/container_stats_test.go (1)

14-14: Redundant nested Describe label.

Both the outer Describe (line 14) and the inner Describe (line 23) now have the same label "CgroupStats". This creates redundancy in test output. Consider either:

  1. Removing the nested Describe wrapper, or
  2. Using a more specific label for the inner block (e.g., "ContainerStats API" since the test calls sut.ContainerStats).
🔎 Suggested fix
 var _ = t.Describe("CgroupStats", func() {
 	// Prepare the sut
 	BeforeEach(func() {
 		beforeEach()
 		setupSUT()
 	})

 	AfterEach(afterEach)

-	t.Describe("CgroupStats", func() {
+	t.Describe("ContainerStats API", func() {
 		It("should fail on invalid container", func() {

Also applies to: 23-23

internal/oci/runtime_oci.go (1)

1278-1279: Update method comment to match renamed method.

The comment still says "ContainerStats provides statistics" but the method has been renamed to CgroupStats.

🔎 Apply this diff:
-// ContainerStats provides statistics of a container.
+// CgroupStats provides cgroup statistics of a container.
internal/lib/statsserver/memory_metrics_linux.go (2)

118-143: Add nil check for memStats parameter.

For consistency and robustness, add a nil check at the beginning of this helper function.

🔎 Suggested fix:
 func computeMemoryMetricValues(memStats *cgroups.MemoryStats) (workingSetBytes, rssBytes, pageFaults, majorPageFaults, availableBytes uint64) {
+	if memStats == nil {
+		return 0, 0, 0, 0, 0
+	}
 	var inactiveFileName string

154-165: Consider adding a nil check for memStats parameter.

For consistency with other helper functions, add a defensive nil check.

internal/lib/statsserver/stats_server_linux.go (1)

420-453: Consider adding a nil check for robustness.

While callers likely ensure non-nil memStats, adding a defensive nil check would make this helper more robust.

🔎 Suggested fix:
 func computeMemoryStats(memStats *cgroups.MemoryStats) (workingSetBytes, rssBytes, pageFaults, majorPageFaults, availableBytes uint64) {
+	if memStats == nil {
+		return 0, 0, 0, 0, 0
+	}
 	var inactiveFileName string
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ef621b and bd29980.

📒 Files selected for processing (24)
  • internal/config/cgmgr/cgmgr_linux.go (3 hunks)
  • internal/config/cgmgr/cgmgr_unsupported.go (3 hunks)
  • internal/config/cgmgr/cgroupfs_linux.go (3 hunks)
  • internal/config/cgmgr/stats_linux.go (3 hunks)
  • internal/config/cgmgr/stats_unsupported.go (0 hunks)
  • internal/config/cgmgr/systemd_linux.go (3 hunks)
  • internal/lib/stats/cgroup_stats_linux.go (1 hunks)
  • internal/lib/stats/cgroup_stats_unsupported.go (1 hunks)
  • internal/lib/stats/disk_stats_unsupported.go (1 hunks)
  • internal/lib/statsserver/cpu_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/disk_metrics_linux.go (3 hunks)
  • internal/lib/statsserver/hugetlb_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/memory_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/pressure_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/process_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/stats_server_linux.go (11 hunks)
  • internal/oci/oci.go (4 hunks)
  • internal/oci/runtime_oci.go (4 hunks)
  • internal/oci/runtime_pod.go (2 hunks)
  • internal/oci/runtime_vm.go (0 hunks)
  • internal/oci/runtime_vm_linux.go (1 hunks)
  • internal/oci/runtime_vm_unsupported.go (1 hunks)
  • server/container_stats_test.go (2 hunks)
  • test/mocks/oci/oci.go (3 hunks)
💤 Files with no reviewable changes (2)
  • internal/config/cgmgr/stats_unsupported.go
  • internal/oci/runtime_vm.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/stats/cgroup_stats_linux.go
  • internal/oci/runtime_vm_unsupported.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/oci/runtime_vm_linux.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use interface-based design and dependency injection patterns in Go code
Propagate context.Context through function calls in Go code
Use fmt.Errorf with %w for error wrapping in Go code
Use logrus with structured fields for logging in Go code
Add comments explaining 'why' not 'what' in Go code
Use platform-specific file naming: *_{linux,freebsd}.go for platform-dependent code

Files:

  • internal/config/cgmgr/cgmgr_unsupported.go
  • server/container_stats_test.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/oci/oci.go
  • internal/oci/runtime_pod.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • test/mocks/oci/oci.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/oci/runtime_oci.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

Use *_test.go naming convention for unit test files

Files:

  • server/container_stats_test.go
🧠 Learnings (3)
📚 Learning: 2025-12-17T13:38:34.646Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9667
File: server/container_create.go:1233-1236
Timestamp: 2025-12-17T13:38:34.646Z
Learning: In the cri-o/cri-o repository, protobuf-generated Get* methods for k8s.io/cri-api types are nil-safe: if the receiver is nil, GetX() returns the zero value instead of panicking. Do not add explicit nil checks before chaining calls on such getters. Apply this guidance to all Go code that uses these generated getters across the codebase.

Applied to files:

  • internal/config/cgmgr/cgmgr_unsupported.go
  • server/container_stats_test.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/oci/oci.go
  • internal/oci/runtime_pod.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • test/mocks/oci/oci.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/oci/runtime_oci.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Add comments explaining 'why' not 'what' in Go code

Applied to files:

  • internal/lib/statsserver/disk_metrics_linux.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Use platform-specific file naming: `*_{linux,freebsd}.go` for platform-dependent code

Applied to files:

  • internal/lib/stats/disk_stats_unsupported.go
🧬 Code graph analysis (10)
internal/config/cgmgr/cgmgr_unsupported.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
server/container_stats_test.go (1)
vendor/github.com/onsi/ginkgo/v2/core_dsl.go (1)
  • Describe (546-548)
internal/lib/statsserver/pressure_metrics_linux.go (1)
vendor/github.com/opencontainers/cgroups/stats.go (3)
  • CpuStats (55-60)
  • MemoryStats (96-117)
  • BlkioStats (151-166)
internal/lib/statsserver/cpu_metrics_linux.go (2)
vendor/github.com/opencontainers/cgroups/stats.go (2)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go (1)
  • MetricType_COUNTER (679-679)
internal/oci/oci.go (3)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/oci/runtime_pod.go (4)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/statsserver/disk_metrics_linux.go (2)
internal/lib/stats/disk_stats_linux.go (1)
  • FilesystemStats (16-21)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • BlkioStats (151-166)
internal/lib/stats/disk_stats_unsupported.go (2)
internal/lib/stats/disk_stats_freebsd.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (23-46)
  • DiskStats (12-14)
internal/lib/stats/disk_stats_linux.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (24-47)
  • DiskStats (11-13)
internal/lib/statsserver/stats_server_linux.go (3)
vendor/github.com/opencontainers/cgroups/stats.go (3)
  • CpuStats (55-60)
  • MemoryStats (96-117)
  • PidsStats (137-142)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/disk_stats_linux.go (2)
  • DiskStats (11-13)
  • FilesystemStats (16-21)
internal/lib/statsserver/hugetlb_metrics_linux.go (1)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • HugetlbStats (168-175)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: rpm-build:fedora-43-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-aarch64:fedora-rawhide
  • GitHub Check: build static / arm64
  • GitHub Check: build-freebsd
  • GitHub Check: build static / amd64
  • GitHub Check: security-checks
  • GitHub Check: unit / amd64 / root
  • GitHub Check: build
  • GitHub Check: unit / arm64 / root
  • GitHub Check: build static / s390x
  • GitHub Check: build static / ppc64le
  • GitHub Check: unit / amd64 / rootless
  • GitHub Check: codeql-build
  • GitHub Check: lint
  • GitHub Check: docs
🔇 Additional comments (33)
internal/config/cgmgr/cgmgr_unsupported.go (2)

5-9: LGTM!

The import addition and type changes correctly align the unsupported platform stub with the new stats.CgroupStats type used across the codebase.


28-28: Interface and stub implementation are consistent.

The signature change and the nil, nil return are appropriate for the non-Linux stub, matching the pattern of other no-op methods in this file.

Also applies to: 72-74

internal/config/cgmgr/stats_linux.go (2)

41-56: Clean refactor to use the new stats.CgroupStats type.

The function correctly handles errors from GetStats() and GetPids(), and constructs the new type properly by embedding *cgStats via value copy. The implementation is concise and maintainable.


10-10: Import correctly added for the new stats package.

The import aligns with the type changes in statsFromLibctrMgr.

internal/lib/statsserver/pressure_metrics_linux.go (2)

19-19: Function signature correctly updated to use external cgroups types.

The signature now uses *cgroups.CpuStats, *cgroups.MemoryStats, and *cgroups.BlkioStats directly from the opencontainers/cgroups package, aligning with the PR's goal of consolidating on external types.


22-43: Appropriate nil safety for PSI metrics.

The nil checks for both the stat structs and their PSI fields before accessing PSI.Full.Total and PSI.Some.Total correctly prevent potential nil pointer dereferences.

Also applies to: 45-66, 68-89

internal/lib/statsserver/process_metrics_linux.go (1)

12-28: Verify: containerProcesses and containerThreads report the same value.

Both metrics use pidsStats.Current. This appears intentional since the cgroups pids controller counts all tasks (processes + threads), but worth confirming this matches the expected semantics for these distinct metric descriptors.

internal/oci/runtime_pod.go (2)

19-19: LGTM!

Import updated correctly to use the new internal/lib/stats package, aligning with the PR's migration from cgmgr types.


300-306: LGTM!

Method renames (ContainerStatsCgroupStats) and return type updates (*stats.CgroupStats, *stats.DiskStats) are consistent with the interface changes in internal/oci/oci.go. The delegation to r.oci is preserved correctly.

internal/lib/statsserver/hugetlb_metrics_linux.go (2)

4-4: LGTM!

Import and parameter type correctly updated to use cgroups.HugetlbStats from the github.com/opencontainers/cgroups package.

Also applies to: 10-10


32-32: LGTM!

Field access correctly updated from stat.Max to stat.MaxUsage to match the cgroups.HugetlbStats structure which uses MaxUsage for "maximum usage ever recorded."

internal/lib/statsserver/disk_metrics_linux.go (2)

10-14: LGTM!

Imports correctly updated to use github.com/opencontainers/cgroups and internal/lib/stats packages.


53-53: LGTM!

Field accesses correctly updated to use IoServicedRecursive and IoServiceBytesRecursive from cgroups.BlkioStats, matching the vendor type definition.

Also applies to: 75-75

internal/lib/statsserver/cpu_metrics_linux.go (3)

7-7: LGTM!

Import and parameter type correctly updated to use *cgroups.CpuStats from the github.com/opencontainers/cgroups package.

Also applies to: 13-13


19-19: LGTM!

CPU usage field accesses correctly updated to use the nested CpuUsage structure (cpu.CpuUsage.UsageInUsermode, cpu.CpuUsage.UsageInKernelmode, cpu.CpuUsage.PercpuUsage, cpu.CpuUsage.TotalUsage), matching the cgroups.CpuStats type definition.

Also applies to: 27-27, 34-36, 42-43


59-59: LGTM!

Throttling data field accesses correctly updated to use the nested ThrottlingData structure (cpu.ThrottlingData.Periods, cpu.ThrottlingData.ThrottledPeriods, cpu.ThrottlingData.ThrottledTime), matching the cgroups.CpuStats type definition.

Also applies to: 67-67, 75-75

internal/lib/stats/disk_stats_unsupported.go (3)

1-1: LGTM!

Build constraint //go:build !linux && !freebsd correctly targets unsupported platforms. As per coding guidelines, platform-specific file naming convention is followed.


7-18: LGTM!

Type definitions (DiskStats, FilesystemStats) are consistent with the Linux and FreeBSD implementations, ensuring type compatibility across platforms while the function returns an appropriate error.


20-23: LGTM!

GetDiskUsageForPath correctly returns nil and an error indicating the platform is unsupported. This provides a clear error message for callers on unsupported platforms.

internal/oci/runtime_oci.go (2)

36-36: LGTM!

Import for internal/lib/stats correctly added to support the new stats types.


1289-1305: LGTM!

DiskStats method correctly updated to return *stats.DiskStats and delegates to stats.GetDiskUsageForPath(mountPoint). The error handling for missing mount points is preserved.

test/mocks/oci/oci.go (3)

17-17: LGTM!

Import correctly updated to use internal/lib/stats package in the generated mock.


63-76: LGTM!

Generated CgroupStats mock method correctly reflects the renamed interface method with *stats.CgroupStats return type, replacing the previous ContainerStats method.


121-124: LGTM!

DiskStats mock method correctly updated to return *stats.DiskStats, matching the interface changes.

internal/lib/statsserver/memory_metrics_linux.go (1)

167-178: LGTM!

The OOM metrics generation is clean and straightforward.

internal/oci/oci.go (3)

20-20: LGTM! Clean refactoring to new stats types.

The import and interface changes correctly adopt the new stats.CgroupStats and stats.DiskStats types, maintaining consistency with the broader refactoring effort.

Also applies to: 72-73


459-470: LGTM! Correct delegation to new interface method.

The function properly delegates to impl.CgroupStats and returns the updated type *stats.CgroupStats.


472-483: LGTM! DiskStats properly updated.

The function signature and delegation are correctly updated to use the new *stats.DiskStats type.

internal/lib/statsserver/stats_server_linux.go (5)

6-6: LGTM! New imports support the stats refactoring.

The added imports are appropriate for the new stats types and helper functions introduced in this refactoring.

Also applies to: 11-11, 15-15, 17-17


54-60: LGTM! Correct usage of new stats structure.

The code properly accesses nested fields from stats.CgroupStats and passes pointers to the CRI stat conversion functions.


256-329: LGTM! Consistent refactoring to new stats types.

The function signature and internal field accesses are correctly updated to use stats.CgroupStats and the new nested field structure.


352-418: LGTM! CRI stats conversion functions properly refactored.

All CRI conversion functions correctly use the new types from the cgroups package and delegate to appropriate helper functions for derived metrics.


467-470: LGTM! Proper unlimited memory check.

The function correctly uses math.MaxUint64 to detect unlimited memory limits.

@bitoku bitoku force-pushed the cri-stats-refactor branch from bd29980 to ced8c34 Compare December 18, 2025 13:30
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/config/cgmgr/cgroupfs_linux.go (1)

22-22: Fix incomplete documentation comment.

The comment contains a typo and incomplete text: "whrn **** TODO: Update this". This appears to be a placeholder that was not completed.

🔎 Suggested fix:
-// CgroupfsManager defines functionality whrn **** TODO: Update this.
+// CgroupfsManager defines functionality when using cgroupfs as the cgroup manager.
♻️ Duplicate comments (1)
internal/oci/runtime_vm_linux.go (1)

30-32: Use passed context parameter instead of stored context.

Line 30 uses r.ctx instead of the ctx parameter passed to the function, preventing proper cancellation and deadline propagation. As per coding guidelines, context.Context should be propagated through function calls.

Based on coding guidelines, context propagation is required.

🔎 Apply this diff to fix the context propagation:
-	resp, err := r.task.Stats(r.ctx, &task.StatsRequest{
+	resp, err := r.task.Stats(ctx, &task.StatsRequest{
 		ID: c.ID(),
 	})
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd29980 and ced8c34.

📒 Files selected for processing (24)
  • internal/config/cgmgr/cgmgr_linux.go (3 hunks)
  • internal/config/cgmgr/cgmgr_unsupported.go (3 hunks)
  • internal/config/cgmgr/cgroupfs_linux.go (3 hunks)
  • internal/config/cgmgr/stats_linux.go (3 hunks)
  • internal/config/cgmgr/stats_unsupported.go (0 hunks)
  • internal/config/cgmgr/systemd_linux.go (3 hunks)
  • internal/lib/stats/cgroup_stats_linux.go (1 hunks)
  • internal/lib/stats/cgroup_stats_unsupported.go (1 hunks)
  • internal/lib/stats/disk_stats_unsupported.go (1 hunks)
  • internal/lib/statsserver/cpu_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/disk_metrics_linux.go (3 hunks)
  • internal/lib/statsserver/hugetlb_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/memory_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/pressure_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/process_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/stats_server_linux.go (11 hunks)
  • internal/oci/oci.go (4 hunks)
  • internal/oci/runtime_oci.go (4 hunks)
  • internal/oci/runtime_pod.go (2 hunks)
  • internal/oci/runtime_vm.go (0 hunks)
  • internal/oci/runtime_vm_linux.go (1 hunks)
  • internal/oci/runtime_vm_unsupported.go (1 hunks)
  • server/container_stats_test.go (2 hunks)
  • test/mocks/oci/oci.go (3 hunks)
💤 Files with no reviewable changes (2)
  • internal/oci/runtime_vm.go
  • internal/config/cgmgr/stats_unsupported.go
🚧 Files skipped from review as they are similar to previous changes (11)
  • server/container_stats_test.go
  • internal/oci/runtime_vm_unsupported.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
  • test/mocks/oci/oci.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/lib/stats/cgroup_stats_linux.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use interface-based design and dependency injection patterns in Go code
Propagate context.Context through function calls in Go code
Use fmt.Errorf with %w for error wrapping in Go code
Use logrus with structured fields for logging in Go code
Add comments explaining 'why' not 'what' in Go code
Use platform-specific file naming: *_{linux,freebsd}.go for platform-dependent code

Files:

  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/oci/runtime_oci.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/oci.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/oci/runtime_pod.go
🧠 Learnings (4)
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Propagate context.Context through function calls in Go code

Applied to files:

  • internal/oci/runtime_vm_linux.go
📚 Learning: 2025-12-17T13:38:34.646Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9667
File: server/container_create.go:1233-1236
Timestamp: 2025-12-17T13:38:34.646Z
Learning: In the cri-o/cri-o repository, protobuf-generated Get* methods for k8s.io/cri-api types are nil-safe: if the receiver is nil, GetX() returns the zero value instead of panicking. Do not add explicit nil checks before chaining calls on such getters. Apply this guidance to all Go code that uses these generated getters across the codebase.

Applied to files:

  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/oci/runtime_oci.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/oci.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/oci/runtime_pod.go
📚 Learning: 2025-12-18T13:28:24.244Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9676
File: internal/lib/stats/cgroup_stats_unsupported.go:1-7
Timestamp: 2025-12-18T13:28:24.244Z
Learning: In the cri-o/cri-o repository, for platform-specific types guarded by Go build tags (for example //go:build !linux), implement empty structs for unsupported platforms to permit compilation and clearly indicate the feature is not available rather than mirroring the Linux struct with unpopulated fields. Apply this pattern to all relevant platform-specific files across the codebase (i.e., any file under build-taged sections that should compile on all targets but lacks full implementation for some platforms).

Applied to files:

  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/oci/runtime_oci.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/oci.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/oci/runtime_pod.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Use platform-specific file naming: `*_{linux,freebsd}.go` for platform-dependent code

Applied to files:

  • internal/lib/stats/disk_stats_unsupported.go
🧬 Code graph analysis (9)
internal/oci/runtime_vm_linux.go (3)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
vendor/github.com/opencontainers/cgroups/stats.go (6)
  • HugetlbStats (168-175)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
  • MemoryStats (96-117)
  • MemoryData (89-94)
  • PidsStats (137-142)
internal/lib/statsserver/memory_metrics_linux.go (1)
vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go (1)
  • MetricType_GAUGE (680-680)
internal/lib/statsserver/cpu_metrics_linux.go (1)
vendor/github.com/opencontainers/cgroups/stats.go (2)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
internal/lib/stats/disk_stats_unsupported.go (2)
internal/lib/stats/disk_stats_freebsd.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (23-46)
  • DiskStats (12-14)
internal/lib/stats/disk_stats_linux.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (24-47)
  • DiskStats (11-13)
internal/oci/runtime_oci.go (4)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/disk_stats_unsupported.go (2)
  • DiskStats (8-10)
  • GetDiskUsageForPath (21-23)
internal/lib/stats/disk_stats_freebsd.go (2)
  • DiskStats (12-14)
  • GetDiskUsageForPath (23-46)
internal/lib/stats/disk_stats_linux.go (2)
  • DiskStats (11-13)
  • GetDiskUsageForPath (24-47)
internal/config/cgmgr/stats_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/oci/oci.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/config/cgmgr/cgmgr_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/config/cgmgr/cgroupfs_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: rpm-build:fedora-43-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-x86_64:fedora-rawhide
  • GitHub Check: binaries / arm64
  • GitHub Check: rpm-build:centos-stream-9-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-aarch64:fedora-rawhide
  • GitHub Check: docs
  • GitHub Check: lint
  • GitHub Check: unit / amd64 / root
  • GitHub Check: build static / amd64
  • GitHub Check: build static / ppc64le
  • GitHub Check: build static / s390x
  • GitHub Check: unit / arm64 / root
  • GitHub Check: unit / amd64 / rootless
  • GitHub Check: build-freebsd
  • GitHub Check: codeql-build
  • GitHub Check: build static / arm64
  • GitHub Check: security-checks
  • GitHub Check: build
🔇 Additional comments (30)
internal/config/cgmgr/cgmgr_linux.go (1)

19-19: LGTM! Interface changes are consistent.

The import addition and method signature updates to return *stats.CgroupStats are correctly aligned with the PR's objective to consolidate stat types into the internal/lib/stats package. The interface contract remains clear and well-documented.

Also applies to: 63-63, 87-87

internal/config/cgmgr/cgroupfs_linux.go (1)

99-106: LGTM! Method implementations are clean and consistent.

Both ContainerCgroupStats and SandboxCgroupStats correctly delegate to statsFromLibctrMgr after obtaining the cgroup manager, with proper error propagation.

Also applies to: 166-173

internal/lib/stats/disk_stats_unsupported.go (1)

1-23: LGTM! Platform stub correctly implements the unsupported path.

The build tag properly excludes Linux and FreeBSD. The struct definitions match the supported platforms for API compatibility, and GetDiskUsageForPath correctly returns an error indicating the feature is unavailable. This approach differs slightly from cgroup_stats_unsupported.go (which uses an empty struct), but is appropriate here since callers may need to work with the DiskStats type even when compilation occurs on unsupported platforms.

internal/oci/runtime_oci.go (2)

36-36: LGTM! CgroupStats method correctly updated.

The import addition and method implementation are correct. The method properly delegates to the cgroup manager and returns the new *stats.CgroupStats type.

Also applies to: 1279-1287


1290-1305: LGTM! DiskStats method implementation is clean.

The method correctly validates the mount point and delegates to stats.GetDiskUsageForPath. Error handling is appropriate, and the delegation pattern aligns with the codebase's approach.

internal/config/cgmgr/stats_linux.go (1)

41-56: No nil dereference risk from GetStats().

The cgMgr.GetStats() method follows the standard libcontainer pattern where a nil error guarantee indicates a non-nil Stats pointer. The code's error checking on lines 43-45 is sufficient; no additional nil check is needed before dereferencing cgStats.

internal/lib/statsserver/cpu_metrics_linux.go (3)

7-7: LGTM!

The addition of the github.com/opencontainers/cgroups import aligns with the PR's objective to standardize on external cgroups statistics types.


14-80: LGTM!

The metric field accesses have been correctly updated to use the nested CpuUsage and ThrottlingData structures from cgroups.CpuStats. The guard condition at line 34 properly handles the edge case when PercpuUsage is empty.


13-13: Add nil check for cpu parameter before accessing its fields.

The function directly accesses cpu.CpuUsage and cpu.ThrottlingData fields without checking if cpu is nil. This is inconsistent with generateContainerMemoryMetrics, which explicitly checks for nil at the start. Add a defensive nil check to match the pattern:

if cpu == nil {
    return nil
}
internal/lib/statsserver/memory_metrics_linux.go (5)

11-118: LGTM!

The nil check at lines 12-14 properly addresses the earlier review concern about panic on nil mem parameter. All memory metric field accesses correctly use the cgroups.MemoryStats structure.


120-146: LGTM!

The cgroup v2/v1 conditional logic is correct, and the working set calculation includes proper underflow protection at lines 138-142.


148-158: LGTM!

The underflow protection at lines 151-154 properly addresses the earlier review concern. The guard ensures SwapUsage.Usage > Usage.Usage before subtraction to prevent uint64 underflow.


160-171: LGTM!

The cgroup version-specific logic correctly handles file_mapped for v2 and mapped_file/total_mapped_file for v1 based on the hierarchy flag.


173-184: LGTM!

The exported GenerateContainerOOMMetrics function correctly constructs OOM event metrics using the COUNTER metric type.

internal/oci/runtime_vm_linux.go (3)

63-65: LGTM!

The stub implementation for DiskStats is appropriate for VM runtimes where disk statistics may not be available or applicable.


176-178: Kernel stack field mapping may be incomplete for KernelUsage representation.

In cgroup v2 memory.stat, kernel_stack is a specific breakdown field, whereas KernelUsage in cgroup v1 represents total kernel memory from the memory.kmem file. Mapping only kernel_stack misses other kernel memory components. Consider whether the total kernel memory should be derived from multiple cgroup v2 fields (e.g., kernel_stack, slab, and other kernel allocations) or document why kernel_stack alone is the appropriate mapping.


67-130: No issues found. Neither cgroupsV1.Metrics nor cgroupsV2.Metrics contain timestamp fields. Using time.Now().UnixNano() to set SystemNano is the correct approach—it records when the stats were collected, and both V1 and V2 converters consistently follow this pattern.

internal/oci/runtime_pod.go (2)

19-19: LGTM!

The import update to internal/lib/stats aligns with the PR's objective to consolidate stats types.


300-306: LGTM!

The method signatures have been correctly updated to return *stats.CgroupStats and *stats.DiskStats, and both properly delegate to the underlying OCI runtime implementation while propagating the context parameter.

internal/oci/oci.go (4)

20-20: LGTM!

The import addition for internal/lib/stats is necessary to support the new stats types returned by the interface methods.


72-73: LGTM!

The RuntimeImpl interface methods have been correctly updated to return the consolidated stats types: *stats.CgroupStats and *stats.DiskStats.


460-470: LGTM!

The ContainerStats method correctly delegates to impl.CgroupStats and returns the updated *stats.CgroupStats type while properly propagating the context parameter.


473-483: LGTM!

The DiskStats method properly delegates to the implementation and returns the updated *stats.DiskStats type while propagating the context parameter.

internal/lib/statsserver/stats_server_linux.go (7)

6-6: LGTM!

The import additions are all justified: math for unlimited memory checks, github.com/opencontainers/cgroups for stats types, internal/config/node for cgroup version detection, and internal/lib/stats for the consolidated stats package.

Also applies to: 11-11, 15-15, 17-17


57-59: LGTM!

The field accesses correctly reference the embedded cgroups.Stats fields from the *stats.CgroupStats type.


256-329: LGTM!

The containerMetricsFromContainerStats function correctly passes nested stat fields to the various metric generation functions, properly accessing the embedded cgroups.Stats fields.


352-418: LGTM!

The CRI stats conversion functions correctly use the nested cgroups stat structures and properly delegate to helper functions for derived metrics.


420-453: LGTM!

The computeMemoryStats function correctly handles cgroup v2/v1 differences, includes proper underflow protection for working set calculation, and checks for unlimited memory limits.


455-468: LGTM!

The underflow protection at lines 461-464 correctly guards against uint64 underflow by checking SwapUsage.Usage > Usage.Usage before subtraction, addressing the concern from the earlier review.


470-473: LGTM!

The isMemoryUnlimited function correctly checks for the maximum uint64 value to identify unlimited memory limits.

@bitoku bitoku force-pushed the cri-stats-refactor branch from ced8c34 to e458f5c Compare December 18, 2025 13:46
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
internal/config/cgmgr/cgroupfs_linux.go (1)

22-22: Fix the incomplete TODO comment.

The comment "CgroupfsManager defines functionality whrn **** TODO: Update this." appears to be a leftover placeholder with typos. Please complete or remove it.

🔎 Suggested fix:
-// CgroupfsManager defines functionality whrn **** TODO: Update this.
+// CgroupfsManager defines functionality for managing cgroups using the cgroupfs driver.
 type CgroupfsManager struct {
internal/lib/statsserver/pressure_metrics_linux.go (1)

91-91: Change metric category from "cpu" to "pressure".

The generateContainerPressureMetrics function collects pressure stalling metrics for CPU, memory, and IO subsystems (lines 22-88), but labels them all with category "cpu" at line 91. This is inconsistent with the pattern used elsewhere: other metric functions use category names matching their specific subsystem (e.g., "memory" in memory_metrics_linux.go, "disk" in disk_metrics_linux.go). Since this function spans multiple subsystems, use "pressure" instead to accurately reflect the metric category.

♻️ Duplicate comments (1)
internal/oci/runtime_vm_linux.go (1)

30-35: Using stored context instead of passed context parameter.

The method uses r.ctx for the Stats call instead of the ctx parameter passed to the function. This could cause issues with cancellation propagation and context deadlines. As per coding guidelines, context.Context should be propagated through function calls.

🔎 Suggested fix:
-	resp, err := r.task.Stats(r.ctx, &task.StatsRequest{
+	resp, err := r.task.Stats(ctx, &task.StatsRequest{
 		ID: c.ID(),
 	})
🧹 Nitpick comments (2)
internal/oci/runtime_vm_linux.go (1)

50-60: Consider using a type switch for cleaner type assertion.

The nested if-else pattern for type assertions works but can be simplified using a type switch for better readability.

🔎 Suggested refactor:
-	m, ok := statsData.(*cgroupsV1.Metrics)
-	if ok {
-		return metricsV1ToCgroupStats(ctx, m), nil
-	} else {
-		m, ok := statsData.(*cgroupsV2.Metrics)
-		if ok {
-			return metricsV2ToCgroupStats(ctx, m), nil
-		} else {
-			return nil, errors.New("unknown stats type")
-		}
-	}
+	switch m := statsData.(type) {
+	case *cgroupsV1.Metrics:
+		return metricsV1ToCgroupStats(ctx, m), nil
+	case *cgroupsV2.Metrics:
+		return metricsV2ToCgroupStats(ctx, m), nil
+	default:
+		return nil, errors.New("unknown stats type")
+	}
internal/lib/statsserver/disk_metrics_linux.go (1)

53-54: Function comment does not accurately describe the parameter type.

The comment states "computes filesystem disk metrics from DiskStats" but the function now takes *cgroups.BlkioStats. Consider updating the comment to accurately reflect the parameter type.

🔎 Suggested fix:
-// generateContainerDiskIOMetrics computes filesystem disk metrics from DiskStats for a container sandbox.
+// generateContainerDiskIOMetrics computes disk I/O metrics from BlkioStats for a container.
 func generateContainerDiskIOMetrics(ctr *oci.Container, ioStats *cgroups.BlkioStats) []*types.Metric {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ced8c34 and e458f5c.

📒 Files selected for processing (25)
  • internal/config/cgmgr/cgmgr_linux.go (3 hunks)
  • internal/config/cgmgr/cgmgr_unsupported.go (3 hunks)
  • internal/config/cgmgr/cgroupfs_linux.go (3 hunks)
  • internal/config/cgmgr/stats_linux.go (3 hunks)
  • internal/config/cgmgr/stats_unsupported.go (0 hunks)
  • internal/config/cgmgr/systemd_linux.go (3 hunks)
  • internal/lib/stats/cgroup_stats_linux.go (1 hunks)
  • internal/lib/stats/cgroup_stats_unsupported.go (1 hunks)
  • internal/lib/stats/disk_stats_unsupported.go (1 hunks)
  • internal/lib/statsserver/cpu_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/disk_metrics_linux.go (3 hunks)
  • internal/lib/statsserver/hugetlb_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/memory_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/network_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/pressure_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/process_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/stats_server_linux.go (11 hunks)
  • internal/oci/oci.go (4 hunks)
  • internal/oci/runtime_oci.go (4 hunks)
  • internal/oci/runtime_pod.go (2 hunks)
  • internal/oci/runtime_vm.go (0 hunks)
  • internal/oci/runtime_vm_linux.go (1 hunks)
  • internal/oci/runtime_vm_unsupported.go (1 hunks)
  • server/container_stats_test.go (2 hunks)
  • test/mocks/oci/oci.go (3 hunks)
💤 Files with no reviewable changes (2)
  • internal/oci/runtime_vm.go
  • internal/config/cgmgr/stats_unsupported.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • internal/lib/statsserver/process_metrics_linux.go
  • server/container_stats_test.go
  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/oci/runtime_vm_unsupported.go
  • internal/lib/stats/cgroup_stats_linux.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use interface-based design and dependency injection patterns in Go code
Propagate context.Context through function calls in Go code
Use fmt.Errorf with %w for error wrapping in Go code
Use logrus with structured fields for logging in Go code
Add comments explaining 'why' not 'what' in Go code
Use platform-specific file naming: *_{linux,freebsd}.go for platform-dependent code

Files:

  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/network_metrics_linux.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • test/mocks/oci/oci.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/oci/runtime_pod.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/oci/oci.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/runtime_oci.go
🧠 Learnings (5)
📚 Learning: 2025-12-17T13:38:34.646Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9667
File: server/container_create.go:1233-1236
Timestamp: 2025-12-17T13:38:34.646Z
Learning: In the cri-o/cri-o repository, protobuf-generated Get* methods for k8s.io/cri-api types are nil-safe: if the receiver is nil, GetX() returns the zero value instead of panicking. Do not add explicit nil checks before chaining calls on such getters. Apply this guidance to all Go code that uses these generated getters across the codebase.

Applied to files:

  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/network_metrics_linux.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • test/mocks/oci/oci.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/oci/runtime_pod.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/oci/oci.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/runtime_oci.go
📚 Learning: 2025-12-18T13:28:24.244Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9676
File: internal/lib/stats/cgroup_stats_unsupported.go:1-7
Timestamp: 2025-12-18T13:28:24.244Z
Learning: In the cri-o/cri-o repository, for platform-specific types guarded by Go build tags (for example //go:build !linux), implement empty structs for unsupported platforms to permit compilation and clearly indicate the feature is not available rather than mirroring the Linux struct with unpopulated fields. Apply this pattern to all relevant platform-specific files across the codebase (i.e., any file under build-taged sections that should compile on all targets but lacks full implementation for some platforms).

Applied to files:

  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/network_metrics_linux.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • test/mocks/oci/oci.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/oci/runtime_pod.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/oci/oci.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/runtime_oci.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Propagate context.Context through function calls in Go code

Applied to files:

  • internal/oci/runtime_vm_linux.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Use platform-specific file naming: `*_{linux,freebsd}.go` for platform-dependent code

Applied to files:

  • internal/lib/stats/disk_stats_unsupported.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Add comments explaining 'why' not 'what' in Go code

Applied to files:

  • internal/lib/statsserver/disk_metrics_linux.go
🧬 Code graph analysis (11)
internal/config/cgmgr/systemd_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/statsserver/pressure_metrics_linux.go (1)
vendor/github.com/opencontainers/cgroups/stats.go (3)
  • CpuStats (55-60)
  • MemoryStats (96-117)
  • BlkioStats (151-166)
internal/oci/runtime_vm_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
vendor/github.com/opencontainers/cgroups/stats.go (5)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
  • MemoryStats (96-117)
  • MemoryData (89-94)
  • PidsStats (137-142)
internal/config/cgmgr/cgroupfs_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
test/mocks/oci/oci.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/oci/runtime_pod.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/statsserver/disk_metrics_linux.go (2)
internal/lib/stats/disk_stats_linux.go (1)
  • FilesystemStats (16-21)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • BlkioStats (151-166)
internal/lib/statsserver/stats_server_linux.go (1)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/oci/oci.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/statsserver/cpu_metrics_linux.go (1)
vendor/github.com/opencontainers/cgroups/stats.go (2)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
internal/config/cgmgr/stats_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: rpm-build:fedora-43-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-x86_64:fedora-rawhide
  • GitHub Check: binaries / arm64
  • GitHub Check: binaries / amd64
  • GitHub Check: rpm-build:centos-stream-9-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-aarch64:fedora-rawhide
  • GitHub Check: build
  • GitHub Check: build static / amd64
  • GitHub Check: unit / amd64 / root
  • GitHub Check: build static / ppc64le
  • GitHub Check: build static / s390x
  • GitHub Check: security-checks
  • GitHub Check: unit / amd64 / rootless
  • GitHub Check: codeql-build
  • GitHub Check: build static / arm64
  • GitHub Check: unit / arm64 / root
  • GitHub Check: docs
  • GitHub Check: lint
🔇 Additional comments (25)
internal/lib/statsserver/pressure_metrics_linux.go (1)

4-4: LGTM!

The import and function signature updates correctly align with the PR's refactor to use github.com/opencontainers/cgroups types. The nil checks on lines 22, 45, and 68 properly guard both the parent stat struct and the nested PSI field before access.

Also applies to: 19-19

internal/config/cgmgr/systemd_linux.go (2)

23-23: LGTM!

The import addition and return type change for ContainerCgroupStats correctly align with the PR's refactor to use the consolidated *stats.CgroupStats type. The implementation delegates to statsFromLibctrMgr which handles the conversion.

Also applies to: 131-131


277-284: LGTM!

The SandboxCgroupStats method signature update to return *stats.CgroupStats is consistent with ContainerCgroupStats and the broader refactor across cgroup managers.

internal/lib/statsserver/cpu_metrics_linux.go (2)

7-7: LGTM!

The import change and function signature update correctly align with the PR's refactor. The nil guard on lines 14-16 properly protects against nil cpu input, and since CpuUsage and ThrottlingData are value types (not pointers) in cgroups.CpuStats, no additional nil checks are needed for those nested accesses.

Also applies to: 13-16


23-23: LGTM!

The field access paths are correctly updated to use the new cgroups.CpuStats structure:

  • cpu.CpuUsage.UsageInUsermode, cpu.CpuUsage.UsageInKernelmode, cpu.CpuUsage.TotalUsage, cpu.CpuUsage.PercpuUsage
  • cpu.ThrottlingData.Periods, cpu.ThrottlingData.ThrottledPeriods, cpu.ThrottlingData.ThrottledTime

These match the vendored struct definitions from github.com/opencontainers/cgroups.

Also applies to: 31-31, 38-40, 46-47, 63-63, 71-71, 79-79

internal/config/cgmgr/cgroupfs_linux.go (2)

18-18: LGTM!

The import addition and return type change for ContainerCgroupStats correctly align with the PR's refactor to use the consolidated *stats.CgroupStats type, matching the changes in systemd_linux.go.

Also applies to: 99-99


166-173: LGTM!

The SandboxCgroupStats method signature update to return *stats.CgroupStats is consistent with ContainerCgroupStats and the systemd manager implementation.

internal/lib/stats/disk_stats_unsupported.go (1)

1-23: LGTM! Platform stub correctly indicates unsupported feature.

The implementation follows the platform-specific file naming convention (*_unsupported.go) and correctly returns an error indicating the feature is not available. The struct definitions maintain API compatibility across platforms, which is appropriate for this use case.

internal/oci/runtime_oci.go (3)

36-36: LGTM! Import added for new stats package.

The import of github.com/cri-o/cri-o/internal/lib/stats is correctly added to support the migration to the new stats types.


1279-1287: LGTM! CgroupStats method updated correctly.

The method signature is updated to return *stats.CgroupStats, context is properly propagated, and the delegation to ContainerCgroupStats is appropriate.


1290-1305: LGTM! DiskStats method correctly migrated to use stats package.

The method properly delegates to stats.GetDiskUsageForPath(mountPoint) and maintains appropriate error handling for containers without a mount point.

internal/oci/runtime_vm_linux.go (2)

63-65: DiskStats returns empty struct without error.

This stub returns an empty DiskStats without an error, unlike the unsupported platform implementation. If disk statistics are not available for VM runtime, consider returning an error to be consistent with the unsupported platform behavior, or add a comment explaining why an empty struct is the intended behavior.


156-163: LGTM! Correct unit conversion from microseconds to nanoseconds.

The multiplication by 1000 correctly converts cgroups v2 CPU usage values from microseconds to nanoseconds, maintaining consistency with the v1 format.

internal/lib/statsserver/disk_metrics_linux.go (1)

17-21: LGTM! Nil check added for defensive programming.

The nil check for diskStats prevents potential panics when disk statistics are unavailable, returning an empty metrics slice gracefully.

internal/lib/statsserver/memory_metrics_linux.go (3)

11-14: LGTM! Nil check properly implemented.

The nil check for mem prevents panics when memory statistics are unavailable, returning an empty metrics slice gracefully.


148-159: LGTM! Underflow protection correctly implemented.

The function properly checks that SwapUsage.Usage > Usage.Usage before performing the subtraction for cgroups v2, preventing uint64 underflow.


174-185: LGTM! OOM metrics generation is straightforward and correct.

The function properly creates an OOM event counter metric using the provided count value.

internal/oci/runtime_pod.go (1)

19-19: LGTM! Clean refactoring to use consolidated stats types.

The changes correctly update the import and method signatures to use the new internal/lib/stats package types. The delegation pattern is maintained appropriately.

Also applies to: 300-306

test/mocks/oci/oci.go (1)

1-23: LGTM! Mock correctly reflects the updated RuntimeImpl interface.

The generated mock has been properly updated to reflect the interface changes:

  • ContainerStats renamed to CgroupStats returning *stats.CgroupStats
  • DiskStats now returns *stats.DiskStats

The mock generation appears correct and consistent with the interface definition.

Also applies to: 63-76, 121-127

internal/config/cgmgr/stats_linux.go (1)

10-11: LGTM! Correct integration with the new stats package.

The function properly constructs stats.CgroupStats by:

  1. Retrieving raw cgroup stats from the manager
  2. Getting process IDs
  3. Wrapping them with a timestamp

This aligns well with the stats.CgroupStats structure that embeds cgroups.Stats and adds SystemNano and Pids fields.

Also applies to: 41-56

internal/oci/oci.go (1)

20-20: LGTM! Interface and implementation correctly updated.

The changes properly update:

  • The RuntimeImpl interface to use *stats.CgroupStats and *stats.DiskStats
  • The Runtime methods to delegate to the new interface methods
  • Context propagation is maintained throughout

The refactoring maintains the existing API behavior while using the consolidated stats types.

Also applies to: 72-73, 460-483

internal/lib/statsserver/stats_server_linux.go (4)

6-6: LGTM! Proper integration with new stats types.

The changes correctly:

  • Add necessary imports (math, cgroups, updated stats package)
  • Update field access to use the new embedded cgroups.Stats structure
  • Pass pointers to stats fields for the helper functions

Also applies to: 11-11, 15-21, 54-60


256-329: LGTM! Metrics generation properly updated for new stats structure.

The function correctly:

  • Updates signature to accept *stats.CgroupStats and stats.DiskStats
  • Accesses nested stats fields with appropriate pointer passing
  • Maintains consistent handling across all metric types (CPU, Hugetlb, Disk, DiskIO, Memory, Process, Pressure)

352-418: LGTM! CRI stats conversion properly refactored.

The changes correctly:

  • Update function signatures to use types from the cgroups package
  • Change field access from TotalUsageNano to CpuUsage.TotalUsage (aligns with cgroups.CpuStats structure)
  • Delegate complex memory/swap calculations to dedicated helper functions
  • Maintain proper pointer passing throughout

420-474: LGTM! Helper functions correctly implement memory/swap calculations.

The new helper functions are well-designed:

  1. computeMemoryStats (lines 420-453):

    • Properly handles both cgroup v1 and v2 differences
    • Guards against underflow when computing workingSetBytes (lines 441-445)
    • Correctly uses "anon" for v2 RSS and "total_rss" for v1
  2. computeSwapUsage (lines 455-469):

    • Correctly addresses the past review comment by guarding subtraction (line 461)
    • Returns 0 instead of underflowing when SwapUsage.Usage <= Usage.Usage
    • Properly handles the v2 combined reporting behavior
  3. isMemoryUnlimited (lines 471-474):

    • Simple and correct check using math.MaxUint64

These implementations align with standard cgroup statistics collection patterns used in tools like cAdvisor.

Comment on lines +1 to +9
package statsserver

import (
"github.com/opencontainers/cgroups"
types "k8s.io/cri-api/pkg/apis/runtime/v1"

"github.com/cri-o/cri-o/internal/config/node"
"github.com/cri-o/cri-o/internal/oci"
)
Copy link

@coderabbitai coderabbitai bot Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing Linux build tag for platform-specific file.

This file uses node.CgroupIsV2() and contains Linux-specific cgroup logic, but lacks a //go:build linux build tag. Based on the file naming convention in the codebase (e.g., disk_metrics_linux.go has the build tag), this file should also have the Linux build constraint.

🔎 Suggested fix:
+//go:build linux
+
 package statsserver
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
package statsserver
import (
"github.com/opencontainers/cgroups"
types "k8s.io/cri-api/pkg/apis/runtime/v1"
"github.com/cri-o/cri-o/internal/config/node"
"github.com/cri-o/cri-o/internal/oci"
)
//go:build linux
package statsserver
import (
"github.com/opencontainers/cgroups"
types "k8s.io/cri-api/pkg/apis/runtime/v1"
"github.com/cri-o/cri-o/internal/config/node"
"github.com/cri-o/cri-o/internal/oci"
)
🤖 Prompt for AI Agents
In internal/lib/statsserver/memory_metrics_linux.go around lines 1 to 9, the
file contains Linux-specific cgroup logic (uses node.CgroupIsV2 and cgroups) but
is missing the required Linux build constraint; add the standard Go build tags
to the top of the file — include the modern "//go:build linux" line followed by
the legacy "// +build linux" line and a blank line after them — so the file only
builds on Linux like other *_linux.go files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file name has suffix, it's enough.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bitoku, you're absolutely right! The _linux.go file suffix is indeed sufficient for platform-specific builds in Go. The compiler automatically restricts these files to the Linux platform without needing explicit build tags. Thank you for the clarification!

🐰


✏️ Learnings added
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9676
File: internal/lib/statsserver/memory_metrics_linux.go:1-9
Timestamp: 2025-12-18T16:05:32.646Z
Learning: In the cri-o/cri-o repository, platform-specific file naming (e.g., `*_linux.go`) is preferred and sufficient for platform-dependent code without requiring explicit build tags like `//go:build linux`. The file naming convention alone controls platform-specific compilation.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9676
File: internal/lib/stats/cgroup_stats_unsupported.go:1-7
Timestamp: 2025-12-18T13:28:24.244Z
Learning: In the cri-o/cri-o repository, when implementing platform-specific types under build tags (e.g., `//go:build !linux`), use empty structs for unsupported platforms where the functionality doesn't exist (like cgroups on FreeBSD). This allows compilation while clearly indicating the feature is not supported, rather than attempting to mirror the Linux struct definition with fields that cannot be populated.

Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Use platform-specific file naming: `*_{linux,freebsd}.go` for platform-dependent code

Comment on lines +67 to +130
func metricsV1ToCgroupStats(ctx context.Context, m *cgroupsV1.Metrics) *stats.CgroupStats {
_ = ctx // unused but kept for consistency with V2 function

hugetlbStats := map[string]cgroups.HugetlbStats{}
for _, hugetlb := range m.Hugetlb {
hugetlbStats[hugetlb.Pagesize] = cgroups.HugetlbStats{
Usage: hugetlb.Usage,
MaxUsage: hugetlb.Max,
}
}

memStats := map[string]uint64{
"total_inactive_file": m.Memory.TotalInactiveFile,
"total_rss": m.Memory.RSS,
"mapped_file": m.Memory.MappedFile,
"total_mapped_file": m.Memory.TotalMappedFile,
}

return &stats.CgroupStats{
Stats: cgroups.Stats{
CpuStats: cgroups.CpuStats{
CpuUsage: cgroups.CpuUsage{
TotalUsage: m.CPU.Usage.Total,
PercpuUsage: m.CPU.Usage.PerCPU,
UsageInKernelmode: m.CPU.Usage.Kernel,
UsageInUsermode: m.CPU.Usage.User,
},
ThrottlingData: cgroups.ThrottlingData{
Periods: m.CPU.Throttling.Periods,
ThrottledPeriods: m.CPU.Throttling.ThrottledPeriods,
ThrottledTime: m.CPU.Throttling.ThrottledTime,
},
},
MemoryStats: cgroups.MemoryStats{
Cache: m.Memory.Cache,
Usage: cgroups.MemoryData{
Usage: m.Memory.Usage.Usage,
MaxUsage: m.Memory.Usage.Max,
Failcnt: m.Memory.Usage.Failcnt,
Limit: m.Memory.Usage.Limit,
},
SwapUsage: cgroups.MemoryData{
Usage: m.Memory.Swap.Usage,
MaxUsage: m.Memory.Swap.Max,
Failcnt: m.Memory.Swap.Failcnt,
Limit: m.Memory.Swap.Limit,
},
KernelUsage: cgroups.MemoryData{
Usage: m.Memory.Kernel.Usage,
},
KernelTCPUsage: cgroups.MemoryData{
Usage: m.Memory.KernelTCP.Usage,
},
Stats: memStats,
},
PidsStats: cgroups.PidsStats{
Current: m.Pids.Current,
Limit: m.Pids.Limit,
},
HugetlbStats: hugetlbStats,
},
SystemNano: time.Now().UnixNano(),
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add nil checks for V1 metrics sub-structures.

The function accesses nested fields like m.CPU.Usage.Total, m.Memory.Cache, etc., without checking if the intermediate pointers are nil. Since these fields are optional protobuf-generated pointers, they can be nil at runtime, causing a panic on direct field access.

🤖 Prompt for AI Agents
In internal/oci/runtime_vm_linux.go around lines 67 to 130, the function
metricsV1ToCgroupStats dereferences nested protobuf pointer fields (e.g.
m.CPU.Usage.Total, m.CPU.Throttling.*, m.Memory.*, m.Pids.*, entries in
m.Hugetlb) without nil checks and can panic if any intermediate pointer is nil;
add defensive nil checks: return an empty stats.CgroupStats (or a
zero-initialized struct) immediately if m is nil, and for each nested field
(m.CPU, m.CPU.Usage, m.CPU.Throttling, m.Memory, m.Memory.Usage, m.Memory.Swap,
m.Memory.Kernel, m.Memory.KernelTCP, m.Pids) check for nil before reading
subfields and use zero/default values when absent; when iterating m.Hugetlb
handle nil slice safely; preserve SystemNano population. Ensure you only read
fields after confirming their parents are non-nil to avoid panics.

@codecov
Copy link

codecov bot commented Dec 18, 2025

Codecov Report

❌ Patch coverage is 0% with 173 lines in your changes missing coverage. Please review.
✅ Project coverage is 46.94%. Comparing base (d41f131) to head (f9aa3e6).
⚠️ Report is 12 commits behind head on main.

❗ There is a different number of reports uploaded between BASE (d41f131) and HEAD (f9aa3e6). Click for more details.

HEAD has 11 uploads less than BASE
Flag BASE (d41f131) HEAD (f9aa3e6)
14 3
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #9676       +/-   ##
===========================================
- Coverage   66.97%   46.94%   -20.04%     
===========================================
  Files         208      166       -42     
  Lines       28865    25218     -3647     
===========================================
- Hits        19333    11838     -7495     
- Misses       7870    12196     +4326     
+ Partials     1662     1184      -478     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bitoku bitoku force-pushed the cri-stats-refactor branch 2 times, most recently from d9931fe to d5334df Compare December 18, 2025 15:54
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/lib/statsserver/process_metrics_linux.go (1)

11-26: Missing nil checks for pids and process parameters.

The function accesses fields from both pids (line 26: pids.Current) and process (lines 17, 35, 44, 53, 62) without nil guards. If either parameter is nil, the closures will panic when evaluated.

🔎 Apply this diff:
 func generateContainerProcessMetrics(ctr *oci.Container, pids *cgroups.PidsStats, process *stats.ProcessStats) []*types.Metric {
+	if pids == nil {
+		pids = &cgroups.PidsStats{}
+	}
+	if process == nil {
+		process = &stats.ProcessStats{}
+	}
+
 	processMetrics := []*containerMetric{
♻️ Duplicate comments (2)
internal/lib/statsserver/disk_metrics_linux.go (1)

53-57: Add nil check for ioStats parameter.

The function accesses ioStats.IoServicedRecursive without nil-guarding. Unlike generateContainerDiskMetrics which properly checks for nil, this function will panic if ioStats is nil.

🔎 Apply this diff:
 // generateContainerDiskIOMetrics computes filesystem disk metrics from DiskStats for a container sandbox.
 func generateContainerDiskIOMetrics(ctr *oci.Container, ioStats *cgroups.BlkioStats) []*types.Metric {
+	if ioStats == nil {
+		return []*types.Metric{}
+	}
 	diskMetrics := []*containerMetric{}
internal/lib/statsserver/memory_metrics_linux.go (1)

1-9: Missing Linux build tag for platform-specific file.

This file uses node.CgroupIsV2() and contains Linux-specific cgroup logic, but lacks a //go:build linux build tag. Based on the file naming convention (e.g., disk_metrics_linux.go has the build tag), this file should also have the Linux build constraint.

🔎 Apply this diff:
+//go:build linux
+
 package statsserver
🧹 Nitpick comments (1)
internal/config/cgmgr/cgroupfs_linux.go (1)

22-23: Incomplete TODO comment with typo.

The comment "CgroupfsManager defines functionality whrn **** TODO: Update this." contains a typo ("whrn" → "when") and appears to be an unfinished documentation note. Consider completing or removing this TODO.

🔎 Apply this diff:
-// CgroupfsManager defines functionality whrn **** TODO: Update this.
+// CgroupfsManager defines functionality for cgroupfs-based cgroup management.
 type CgroupfsManager struct {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e458f5c and d9931fe.

📒 Files selected for processing (25)
  • internal/config/cgmgr/cgmgr_linux.go (3 hunks)
  • internal/config/cgmgr/cgmgr_unsupported.go (3 hunks)
  • internal/config/cgmgr/cgroupfs_linux.go (3 hunks)
  • internal/config/cgmgr/stats_linux.go (4 hunks)
  • internal/config/cgmgr/stats_unsupported.go (0 hunks)
  • internal/config/cgmgr/systemd_linux.go (3 hunks)
  • internal/lib/stats/cgroup_stats_linux.go (1 hunks)
  • internal/lib/stats/cgroup_stats_unsupported.go (1 hunks)
  • internal/lib/stats/disk_stats_unsupported.go (1 hunks)
  • internal/lib/statsserver/cpu_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/disk_metrics_linux.go (3 hunks)
  • internal/lib/statsserver/hugetlb_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/memory_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/network_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/pressure_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/process_metrics_linux.go (5 hunks)
  • internal/lib/statsserver/stats_server_linux.go (11 hunks)
  • internal/oci/oci.go (4 hunks)
  • internal/oci/runtime_oci.go (4 hunks)
  • internal/oci/runtime_pod.go (2 hunks)
  • internal/oci/runtime_vm.go (0 hunks)
  • internal/oci/runtime_vm_linux.go (1 hunks)
  • internal/oci/runtime_vm_unsupported.go (1 hunks)
  • server/container_stats_test.go (2 hunks)
  • test/mocks/oci/oci.go (3 hunks)
💤 Files with no reviewable changes (2)
  • internal/oci/runtime_vm.go
  • internal/config/cgmgr/stats_unsupported.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • internal/oci/runtime_vm_unsupported.go
  • internal/oci/runtime_vm_linux.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/lib/statsserver/network_metrics_linux.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use interface-based design and dependency injection patterns in Go code
Propagate context.Context through function calls in Go code
Use fmt.Errorf with %w for error wrapping in Go code
Use logrus with structured fields for logging in Go code
Add comments explaining 'why' not 'what' in Go code
Use platform-specific file naming: *_{linux,freebsd}.go for platform-dependent code

Files:

  • internal/lib/stats/cgroup_stats_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • server/container_stats_test.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • test/mocks/oci/oci.go
  • internal/oci/oci.go
  • internal/oci/runtime_oci.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/runtime_pod.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/lib/statsserver/stats_server_linux.go
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

Use *_test.go naming convention for unit test files

Files:

  • server/container_stats_test.go
🧠 Learnings (4)
📚 Learning: 2025-12-17T13:38:34.646Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9667
File: server/container_create.go:1233-1236
Timestamp: 2025-12-17T13:38:34.646Z
Learning: In the cri-o/cri-o repository, protobuf-generated Get* methods for k8s.io/cri-api types are nil-safe: if the receiver is nil, GetX() returns the zero value instead of panicking. Do not add explicit nil checks before chaining calls on such getters. Apply this guidance to all Go code that uses these generated getters across the codebase.

Applied to files:

  • internal/lib/stats/cgroup_stats_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • server/container_stats_test.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • test/mocks/oci/oci.go
  • internal/oci/oci.go
  • internal/oci/runtime_oci.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/runtime_pod.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/lib/statsserver/stats_server_linux.go
📚 Learning: 2025-12-18T13:28:24.244Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9676
File: internal/lib/stats/cgroup_stats_unsupported.go:1-7
Timestamp: 2025-12-18T13:28:24.244Z
Learning: In the cri-o/cri-o repository, for platform-specific types guarded by Go build tags (for example //go:build !linux), implement empty structs for unsupported platforms to permit compilation and clearly indicate the feature is not available rather than mirroring the Linux struct with unpopulated fields. Apply this pattern to all relevant platform-specific files across the codebase (i.e., any file under build-taged sections that should compile on all targets but lacks full implementation for some platforms).

Applied to files:

  • internal/lib/stats/cgroup_stats_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • server/container_stats_test.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • test/mocks/oci/oci.go
  • internal/oci/oci.go
  • internal/oci/runtime_oci.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/runtime_pod.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/lib/statsserver/stats_server_linux.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Use platform-specific file naming: `*_{linux,freebsd}.go` for platform-dependent code

Applied to files:

  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/stats/cgroup_stats_unsupported.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Add comments explaining 'why' not 'what' in Go code

Applied to files:

  • internal/lib/statsserver/disk_metrics_linux.go
🧬 Code graph analysis (14)
internal/lib/stats/cgroup_stats_linux.go (1)
vendor/github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types/sandbox.go (1)
  • Sockets (244-244)
internal/lib/statsserver/cpu_metrics_linux.go (2)
vendor/github.com/opencontainers/cgroups/stats.go (2)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go (1)
  • MetricType_COUNTER (679-679)
server/container_stats_test.go (1)
vendor/github.com/onsi/ginkgo/v2/core_dsl.go (1)
  • Describe (546-548)
internal/lib/statsserver/pressure_metrics_linux.go (1)
vendor/github.com/opencontainers/cgroups/stats.go (3)
  • CpuStats (55-60)
  • MemoryStats (96-117)
  • BlkioStats (151-166)
internal/config/cgmgr/systemd_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/statsserver/disk_metrics_linux.go (2)
internal/lib/stats/disk_stats_linux.go (1)
  • FilesystemStats (16-21)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • BlkioStats (151-166)
internal/config/cgmgr/cgmgr_unsupported.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
test/mocks/oci/oci.go (4)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/oci/oci.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/statsserver/hugetlb_metrics_linux.go (1)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • HugetlbStats (168-175)
internal/lib/statsserver/process_metrics_linux.go (2)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • PidsStats (137-142)
internal/lib/stats/cgroup_stats_linux.go (1)
  • ProcessStats (12-19)
internal/oci/runtime_pod.go (3)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/config/cgmgr/cgroupfs_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/statsserver/stats_server_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (2)
  • CgroupStats (5-10)
  • ProcessStats (12-19)
internal/lib/stats/disk_stats_linux.go (2)
  • DiskStats (11-13)
  • FilesystemStats (16-21)
🪛 GitHub Actions: integration
internal/config/cgmgr/stats_linux.go

[error] 61-61: cannot use cgroupProcessStats(cgStats, pids) as "github.com/cri-o/cri-o/internal/lib/stats".ProcessStats value in struct literal

🪛 GitHub Check: binaries / amd64
internal/config/cgmgr/stats_linux.go

[failure] 61-61:
cannot use cgroupProcessStats(cgStats, pids) (value of type *"github.com/cri-o/cri-o/internal/lib/stats".ProcessStats) as "github.com/cri-o/cri-o/internal/lib/stats".ProcessStats value in struct literal

🪛 GitHub Check: binaries / arm64
internal/config/cgmgr/stats_linux.go

[failure] 61-61:
cannot use cgroupProcessStats(cgStats, pids) (value of type *"github.com/cri-o/cri-o/internal/lib/stats".ProcessStats) as "github.com/cri-o/cri-o/internal/lib/stats".ProcessStats value in struct literal

🪛 GitHub Check: security-checks
internal/config/cgmgr/stats_linux.go

[failure] 61-61:
cannot use cgroupProcessStats(cgStats, pids) (value of type *"github.com/cri-o/cri-o/internal/lib/stats".ProcessStats) as "github.com/cri-o/cri-o/internal/lib/stats".ProcessStats value in struct literal

internal/lib/statsserver/stats_server_linux.go

[failure] 309-309:
undefined: cgroupStats


[failure] 309-309:
undefined: cgroupStats

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: rpm-build:centos-stream-9-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-x86_64:fedora-rawhide
  • GitHub Check: build static / s390x
  • GitHub Check: unit / arm64 / root
  • GitHub Check: build static / amd64
  • GitHub Check: build-freebsd
  • GitHub Check: build static / arm64
  • GitHub Check: build static / ppc64le
  • GitHub Check: codeql-build
  • GitHub Check: unit / amd64 / rootless
  • GitHub Check: build
  • GitHub Check: docs
  • GitHub Check: lint
  • GitHub Check: shfmt
🔇 Additional comments (27)
internal/lib/statsserver/hugetlb_metrics_linux.go (1)

1-44: LGTM! Type migration correctly implemented.

The refactoring successfully migrates from internal cgmgr types to the external OpenContainers cgroups types. The field name change from stat.Max to stat.MaxUsage correctly aligns with the vendor struct definition.

internal/lib/statsserver/cpu_metrics_linux.go (1)

1-87: LGTM! CPU metrics migration correctly implemented.

The refactoring properly migrates to the external cgroups types with appropriate nil-safety check and correct field path updates (e.g., cpu.CpuUsage.UsageInUsermode, cpu.ThrottlingData.Periods). All metric calculations are preserved correctly.

server/container_stats_test.go (1)

14-34: LGTM! Test descriptors updated appropriately.

The test description updates from "ContainerStats" to "CgroupStats" correctly reflect the type naming changes in the codebase refactoring. No functional test changes were made.

internal/lib/stats/cgroup_stats_unsupported.go (1)

1-7: LGTM! Correct pattern for unsupported platforms.

The empty struct implementation for non-Linux platforms is appropriate, as confirmed by the retrieved learnings. This allows compilation on platforms where cgroups functionality is not available (e.g., FreeBSD) while clearly indicating the feature is unsupported.

Based on learnings, empty structs for unsupported platforms is the standard pattern in this repository.

internal/lib/statsserver/pressure_metrics_linux.go (1)

1-92: LGTM! Pressure metrics migration correctly implemented.

The function signature correctly migrates to external cgroups types (*cgroups.CpuStats, *cgroups.MemoryStats, *cgroups.BlkioStats). The type name change from DiskIOStats to BlkioStats aligns with OpenContainers terminology. All PSI field accesses and nil checks are preserved correctly.

internal/config/cgmgr/systemd_linux.go (1)

23-23: LGTM! Public API correctly migrated to new stats types.

The return type updates from *CgroupStats to *stats.CgroupStats for both ContainerCgroupStats and SandboxCgroupStats methods consistently migrate the public API surface to the new external stats package. The implementation logic remains unchanged.

Also applies to: 131-138, 277-284

internal/lib/stats/cgroup_stats_linux.go (1)

1-19: LGTM! Well-structured stats type definitions.

The new CgroupStats and ProcessStats types are well-designed:

  • Proper composition via embedded cgroups.Stats
  • Logical grouping of process metrics in ProcessStats
  • Appropriate field types and naming conventions

The struct organization cleanly separates cgroup statistics from process-level metrics, providing a clear API surface for the refactoring.

internal/config/cgmgr/cgmgr_unsupported.go (1)

1-78: LGTM! Unsupported platform interface correctly updated.

The interface and implementation updates properly migrate to *stats.CgroupStats for non-Linux platforms. The NullCgroupManager returning (nil, nil) is appropriate for a no-op implementation on platforms where cgroups are not supported.

internal/lib/statsserver/disk_metrics_linux.go (3)

17-21: LGTM!

The nil check for diskStats is properly implemented, and the function correctly handles the new stats.FilesystemStats type.


57-77: LGTM!

The iteration over IoServicedRecursive and the switch-case handling for "Write" and "Read" operations are correctly implemented to work with the new cgroups types.


79-108: LGTM!

The iteration over IoServiceBytesRecursive correctly handles device labels and both bytes-based metrics (containerFsWritesBytesTotal, containerFsReadsBytesTotal) and the aggregate device usage metric.

internal/config/cgmgr/cgroupfs_linux.go (2)

99-106: LGTM!

The return type update to *stats.CgroupStats is consistent with the PR's consolidation of cgroup stats types.


166-173: LGTM!

The SandboxCgroupStats signature and delegation are correctly updated to use the new stats types.

internal/lib/statsserver/memory_metrics_linux.go (4)

11-18: LGTM!

The nil check for mem is properly implemented, preventing panics when the parameter is nil.


148-159: LGTM!

The swap usage calculation correctly guards against uint64 underflow by checking if SwapUsage.Usage > Usage.Usage before performing the subtraction.


120-146: LGTM!

The computeMemoryMetricValues function correctly handles cgroup v1/v2 differences for RSS, page faults, and working set calculations with proper underflow protection.


174-185: LGTM!

The exported GenerateContainerOOMMetrics function is correctly implemented to generate OOM event metrics.

internal/oci/runtime_oci.go (2)

1279-1287: LGTM!

The CgroupStats method correctly delegates to the cgroup manager and returns the new *stats.CgroupStats type.


1290-1305: LGTM!

The DiskStats method correctly delegates to stats.GetDiskUsageForPath and returns the new *stats.DiskStats type. The mount point validation is appropriately placed.

internal/oci/runtime_pod.go (1)

300-306: LGTM!

The CgroupStats and DiskStats methods correctly delegate to the underlying OCI runtime implementation with consistent type signatures.

test/mocks/oci/oci.go (2)

63-76: LGTM!

The auto-generated mock correctly implements the new CgroupStats method signature, returning *stats.CgroupStats.


121-127: LGTM!

The DiskStats mock is correctly updated to return *stats.DiskStats.

internal/oci/oci.go (3)

72-73: LGTM!

The RuntimeImpl interface is correctly updated with the new CgroupStats and DiskStats method signatures using the stats package types.


459-470: Verify the intentional naming asymmetry between ContainerStats and CgroupStats.

The public Runtime.ContainerStats method (line 460) delegates to impl.CgroupStats (line 469). This naming difference is fine if intentional for backward compatibility, but worth confirming this is the desired API design.


472-483: LGTM!

The DiskStats method correctly delegates to the runtime implementation and returns the new *stats.DiskStats type.

internal/config/cgmgr/stats_linux.go (1)

65-82: LGTM!

The process stats aggregation logic is well-structured, correctly gathering per-process metrics (file descriptors, sockets, ulimits) and combining them with cgroup-level PID stats.

internal/lib/statsserver/stats_server_linux.go (1)

420-474: LGTM!

The new helper functions correctly handle cgroup v1/v2 differences and include proper underflow protection for uint64 calculations. The memory and swap computations follow established cAdvisor patterns.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/lib/statsserver/process_metrics_linux.go (1)

11-69: Add nil checks for both parameters.

The function accesses fields from both pids (line 26) and process (lines 17, 35, 44, 53, 62) inside closures without nil guards. If either parameter is nil, this will panic.

🔎 Apply this diff to add nil checks:
 func generateContainerProcessMetrics(ctr *oci.Container, pids *cgroups.PidsStats, process *stats.ProcessStats) []*types.Metric {
+	if pids == nil || process == nil {
+		return nil
+	}
+
 	processMetrics := []*containerMetric{
♻️ Duplicate comments (4)
internal/lib/statsserver/stats_server_linux.go (1)

309-309: Fix undefined variable causing compilation failure.

The variable name is containerStats (defined at line 256), not cgroupStats.

🔎 Apply this diff to fix the compilation error:
-		if processMetrics := generateContainerProcessMetrics(c, &cgroupStats.PidsStats, &cgroupStats.ProcessStats); processMetrics != nil {
+		if processMetrics := generateContainerProcessMetrics(c, &containerStats.PidsStats, &containerStats.ProcessStats); processMetrics != nil {
internal/lib/statsserver/disk_metrics_linux.go (1)

54-57: Add nil check for ioStats parameter.

Unlike generateContainerDiskMetrics which guards against nil input, this function will panic if ioStats is nil when accessing ioStats.IoServicedRecursive at line 57.

🔎 Apply this diff to add the nil check:
 func generateContainerDiskIOMetrics(ctr *oci.Container, ioStats *cgroups.BlkioStats) []*types.Metric {
+	if ioStats == nil {
+		return []*types.Metric{}
+	}
+
 	diskMetrics := []*containerMetric{}
internal/oci/runtime_vm_linux.go (2)

30-35: Use passed context parameter instead of stored context.

The Stats call uses r.ctx instead of the ctx parameter passed to the function, preventing proper cancellation and deadline propagation.

🔎 Apply this diff to fix context propagation:
-	resp, err := r.task.Stats(r.ctx, &task.StatsRequest{
+	resp, err := r.task.Stats(ctx, &task.StatsRequest{
 		ID: c.ID(),
 	})

Based on coding guidelines, context.Context should be propagated through function calls.


67-130: Add nil checks for nested protobuf fields to prevent panics.

The function directly accesses nested fields like m.CPU.Usage.Total, m.CPU.Throttling.*, m.Memory.*, m.Pids.*, and entries in m.Hugetlb without checking if intermediate pointers are nil. Since these are optional protobuf pointers, they can be nil at runtime and cause panics.

🔎 Add defensive nil checks:

Check each parent pointer before accessing nested fields:

 func metricsV1ToCgroupStats(ctx context.Context, m *cgroupsV1.Metrics) *stats.CgroupStats {
 	_ = ctx // unused but kept for consistency with V2 function
+
+	if m == nil {
+		return &stats.CgroupStats{SystemNano: time.Now().UnixNano()}
+	}
 
 	hugetlbStats := map[string]cgroups.HugetlbStats{}
 	for _, hugetlb := range m.Hugetlb {
+		if hugetlb == nil {
+			continue
+		}
 		hugetlbStats[hugetlb.Pagesize] = cgroups.HugetlbStats{
 			Usage:    hugetlb.Usage,
 			MaxUsage: hugetlb.Max,
 		}
 	}
 
 	memStats := map[string]uint64{
-		"total_inactive_file": m.Memory.TotalInactiveFile,
-		"total_rss":           m.Memory.RSS,
-		"mapped_file":         m.Memory.MappedFile,
-		"total_mapped_file":   m.Memory.TotalMappedFile,
 	}
+	if m.Memory != nil {
+		memStats["total_inactive_file"] = m.Memory.TotalInactiveFile
+		memStats["total_rss"] = m.Memory.RSS
+		memStats["mapped_file"] = m.Memory.MappedFile
+		memStats["total_mapped_file"] = m.Memory.TotalMappedFile
+	}
+
+	cpuUsage := cgroups.CpuUsage{}
+	if m.CPU != nil && m.CPU.Usage != nil {
+		cpuUsage = cgroups.CpuUsage{
+			TotalUsage:        m.CPU.Usage.Total,
+			PercpuUsage:       m.CPU.Usage.PerCPU,
+			UsageInKernelmode: m.CPU.Usage.Kernel,
+			UsageInUsermode:   m.CPU.Usage.User,
+		}
+	}
+
+	throttlingData := cgroups.ThrottlingData{}
+	if m.CPU != nil && m.CPU.Throttling != nil {
+		throttlingData = cgroups.ThrottlingData{
+			Periods:          m.CPU.Throttling.Periods,
+			ThrottledPeriods: m.CPU.Throttling.ThrottledPeriods,
+			ThrottledTime:    m.CPU.Throttling.ThrottledTime,
+		}
+	}
 
 	return &stats.CgroupStats{
 		Stats: cgroups.Stats{
 			CpuStats: cgroups.CpuStats{
-				CpuUsage: cgroups.CpuUsage{
-					TotalUsage:        m.CPU.Usage.Total,
-					PercpuUsage:       m.CPU.Usage.PerCPU,
-					UsageInKernelmode: m.CPU.Usage.Kernel,
-					UsageInUsermode:   m.CPU.Usage.User,
-				},
-				ThrottlingData: cgroups.ThrottlingData{
-					Periods:          m.CPU.Throttling.Periods,
-					ThrottledPeriods: m.CPU.Throttling.ThrottledPeriods,
-					ThrottledTime:    m.CPU.Throttling.ThrottledTime,
-				},
+				CpuUsage:       cpuUsage,
+				ThrottlingData: throttlingData,
 			},
-			MemoryStats: cgroups.MemoryStats{
-				Cache: m.Memory.Cache,
-				Usage: cgroups.MemoryData{
-					Usage:    m.Memory.Usage.Usage,
-					MaxUsage: m.Memory.Usage.Max,
-					Failcnt:  m.Memory.Usage.Failcnt,
-					Limit:    m.Memory.Usage.Limit,
-				},
-				SwapUsage: cgroups.MemoryData{
-					Usage:    m.Memory.Swap.Usage,
-					MaxUsage: m.Memory.Swap.Max,
-					Failcnt:  m.Memory.Swap.Failcnt,
-					Limit:    m.Memory.Swap.Limit,
-				},
-				KernelUsage: cgroups.MemoryData{
-					Usage: m.Memory.Kernel.Usage,
-				},
-				KernelTCPUsage: cgroups.MemoryData{
-					Usage: m.Memory.KernelTCP.Usage,
-				},
-				Stats: memStats,
-			},
-			PidsStats: cgroups.PidsStats{
-				Current: m.Pids.Current,
-				Limit:   m.Pids.Limit,
-			},
+			MemoryStats:  buildMemoryStats(m.Memory, memStats),
+			PidsStats:    buildPidsStats(m.Pids),
 			HugetlbStats: hugetlbStats,
 		},
 		SystemNano: time.Now().UnixNano(),
 	}
 }
+
+func buildMemoryStats(mem *cgroupsV1.MemoryStat, stats map[string]uint64) cgroups.MemoryStats {
+	if mem == nil {
+		return cgroups.MemoryStats{Stats: stats}
+	}
+	result := cgroups.MemoryStats{
+		Cache: mem.Cache,
+		Stats: stats,
+	}
+	if mem.Usage != nil {
+		result.Usage = cgroups.MemoryData{
+			Usage:    mem.Usage.Usage,
+			MaxUsage: mem.Usage.Max,
+			Failcnt:  mem.Usage.Failcnt,
+			Limit:    mem.Usage.Limit,
+		}
+	}
+	if mem.Swap != nil {
+		result.SwapUsage = cgroups.MemoryData{
+			Usage:    mem.Swap.Usage,
+			MaxUsage: mem.Swap.Max,
+			Failcnt:  mem.Swap.Failcnt,
+			Limit:    mem.Swap.Limit,
+		}
+	}
+	if mem.Kernel != nil {
+		result.KernelUsage = cgroups.MemoryData{Usage: mem.Kernel.Usage}
+	}
+	if mem.KernelTCP != nil {
+		result.KernelTCPUsage = cgroups.MemoryData{Usage: mem.KernelTCP.Usage}
+	}
+	return result
+}
+
+func buildPidsStats(pids *cgroupsV1.PidsStat) cgroups.PidsStats {
+	if pids == nil {
+		return cgroups.PidsStats{}
+	}
+	return cgroups.PidsStats{
+		Current: pids.Current,
+		Limit:   pids.Limit,
+	}
+}

Apply similar nil-safe patterns to metricsV2ToCgroupStats at lines 132-189.

🧹 Nitpick comments (2)
internal/lib/stats/disk_stats_unsupported.go (1)

7-18: Consider using empty structs per established pattern.

Based on learnings, platform-specific types guarded by build tags should implement empty structs for unsupported platforms rather than mirroring the Linux struct with unpopulated fields. This approach more clearly indicates the feature is unavailable.

Additionally, the JSON tags on FilesystemStats serve no purpose here since GetDiskUsageForPath always returns an error on these platforms.

🔎 Apply this diff to use empty structs:
-// DiskStats represents comprehensive disk statistics for a container.
+// DiskStats is not supported on this platform.
 type DiskStats struct {
-	Filesystem FilesystemStats
 }
 
-// FilesystemStats represents filesystem usage statistics.
+// FilesystemStats is not supported on this platform.
 type FilesystemStats struct {
-	UsageBytes  uint64 `json:"usage_bytes"`
-	LimitBytes  uint64 `json:"limit_bytes"`
-	InodesFree  uint64 `json:"inodes_free"`
-	InodesTotal uint64 `json:"inodes_total"`
 }

Based on learnings, this pattern clearly indicates feature unavailability and permits compilation across all platforms.

internal/config/cgmgr/stats_linux.go (1)

84-147: Consider propagating context through the call chain.

The functions addFdsForProcess and addUlimitsForProcess use context.Background() for logging (lines 93, 104, 124). Per coding guidelines, context should be propagated through function calls. Since these functions perform I/O operations on the /proc filesystem, accepting a context parameter would enable proper cancellation and timeout handling.

As per coding guidelines, propagate context.Context through function calls in Go code.

🔎 Suggested refactor to add context parameters:

Update the function signatures:

-func statsFromLibctrMgr(cgMgr cgroups.Manager) (*stats.CgroupStats, error) {
+func statsFromLibctrMgr(ctx context.Context, cgMgr cgroups.Manager) (*stats.CgroupStats, error) {
 	cgStats, err := cgMgr.GetStats()
 	if err != nil {
 		return nil, err
 	}
 
 	pids, err := cgMgr.GetPids()
 	if err != nil {
 		return nil, err
 	}
 
 	return &stats.CgroupStats{
 		Stats:        *cgStats,
 		SystemNano:   time.Now().UnixNano(),
-		ProcessStats: *cgroupProcessStats(cgStats, pids),
+		ProcessStats: *cgroupProcessStats(ctx, cgStats, pids),
 	}, nil
 }

-func cgroupProcessStats(cgroupStats *cgroups.Stats, pids []int) *stats.ProcessStats {
+func cgroupProcessStats(ctx context.Context, cgroupStats *cgroups.Stats, pids []int) *stats.ProcessStats {
 	var fdCount, socketCount, ulimitsSoft uint64
 
 	for _, pid := range pids {
-		addFdsForProcess(pid, &fdCount, &socketCount)
-		addUlimitsForProcess(pid, &ulimitsSoft)
+		addFdsForProcess(ctx, pid, &fdCount, &socketCount)
+		addUlimitsForProcess(ctx, pid, &ulimitsSoft)
 	}
 	// ... rest of function
 }

-func addFdsForProcess(pid int, fdCount, socketCount *uint64) {
+func addFdsForProcess(ctx context.Context, pid int, fdCount, socketCount *uint64) {
 	// ... panic checks ...
 	fds, err := os.ReadDir(dirPath)
 	if err != nil {
-		log.Infof(context.Background(), "error while listing directory %q to measure fd count: %v", dirPath, err)
+		log.Infof(ctx, "error while listing directory %q to measure fd count: %v", dirPath, err)
 		return
 	}
 	// ... rest of function with ctx in log calls ...
 }

-func addUlimitsForProcess(pid int, limits *uint64) {
+func addUlimitsForProcess(ctx context.Context, pid int, limits *uint64) {
 	// ... panic checks ...
 	limitsData, err := os.ReadFile(limitsPath)
 	if err != nil {
-		log.Infof(context.Background(), "error while reading %q to get thread limits: %v", limitsPath, err)
+		log.Infof(ctx, "error while reading %q to get thread limits: %v", limitsPath, err)
 		return
 	}
 	// ... rest of function ...
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d9931fe and d5334df.

📒 Files selected for processing (25)
  • internal/config/cgmgr/cgmgr_linux.go (3 hunks)
  • internal/config/cgmgr/cgmgr_unsupported.go (3 hunks)
  • internal/config/cgmgr/cgroupfs_linux.go (3 hunks)
  • internal/config/cgmgr/stats_linux.go (4 hunks)
  • internal/config/cgmgr/stats_unsupported.go (0 hunks)
  • internal/config/cgmgr/systemd_linux.go (3 hunks)
  • internal/lib/stats/cgroup_stats_linux.go (1 hunks)
  • internal/lib/stats/cgroup_stats_unsupported.go (1 hunks)
  • internal/lib/stats/disk_stats_unsupported.go (1 hunks)
  • internal/lib/statsserver/cpu_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/disk_metrics_linux.go (3 hunks)
  • internal/lib/statsserver/hugetlb_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/memory_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/network_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/pressure_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/process_metrics_linux.go (5 hunks)
  • internal/lib/statsserver/stats_server_linux.go (11 hunks)
  • internal/oci/oci.go (4 hunks)
  • internal/oci/runtime_oci.go (4 hunks)
  • internal/oci/runtime_pod.go (2 hunks)
  • internal/oci/runtime_vm.go (0 hunks)
  • internal/oci/runtime_vm_linux.go (1 hunks)
  • internal/oci/runtime_vm_unsupported.go (1 hunks)
  • server/container_stats_test.go (2 hunks)
  • test/mocks/oci/oci.go (3 hunks)
💤 Files with no reviewable changes (2)
  • internal/oci/runtime_vm.go
  • internal/config/cgmgr/stats_unsupported.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • internal/oci/runtime_vm_unsupported.go
  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/lib/statsserver/network_metrics_linux.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use interface-based design and dependency injection patterns in Go code
Propagate context.Context through function calls in Go code
Use fmt.Errorf with %w for error wrapping in Go code
Use logrus with structured fields for logging in Go code
Add comments explaining 'why' not 'what' in Go code
Use platform-specific file naming: *_{linux,freebsd}.go for platform-dependent code

Files:

  • internal/lib/statsserver/process_metrics_linux.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/cgroup_stats_linux.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/oci/runtime_oci.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/oci/runtime_pod.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/oci/runtime_vm_linux.go
  • server/container_stats_test.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/oci.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • test/mocks/oci/oci.go
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

Use *_test.go naming convention for unit test files

Files:

  • server/container_stats_test.go
🧠 Learnings (5)
📚 Learning: 2025-12-17T13:38:34.646Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9667
File: server/container_create.go:1233-1236
Timestamp: 2025-12-17T13:38:34.646Z
Learning: In the cri-o/cri-o repository, protobuf-generated Get* methods for k8s.io/cri-api types are nil-safe: if the receiver is nil, GetX() returns the zero value instead of panicking. Do not add explicit nil checks before chaining calls on such getters. Apply this guidance to all Go code that uses these generated getters across the codebase.

Applied to files:

  • internal/lib/statsserver/process_metrics_linux.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/cgroup_stats_linux.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/oci/runtime_oci.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/oci/runtime_pod.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/oci/runtime_vm_linux.go
  • server/container_stats_test.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/oci.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • test/mocks/oci/oci.go
📚 Learning: 2025-12-18T13:28:24.244Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9676
File: internal/lib/stats/cgroup_stats_unsupported.go:1-7
Timestamp: 2025-12-18T13:28:24.244Z
Learning: In the cri-o/cri-o repository, for platform-specific types guarded by Go build tags (for example //go:build !linux), implement empty structs for unsupported platforms to permit compilation and clearly indicate the feature is not available rather than mirroring the Linux struct with unpopulated fields. Apply this pattern to all relevant platform-specific files across the codebase (i.e., any file under build-taged sections that should compile on all targets but lacks full implementation for some platforms).

Applied to files:

  • internal/lib/statsserver/process_metrics_linux.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/cgroup_stats_linux.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/oci/runtime_oci.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/oci/runtime_pod.go
  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/oci/runtime_vm_linux.go
  • server/container_stats_test.go
  • internal/config/cgmgr/stats_linux.go
  • internal/oci/oci.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • test/mocks/oci/oci.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Add comments explaining 'why' not 'what' in Go code

Applied to files:

  • internal/lib/statsserver/disk_metrics_linux.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Use platform-specific file naming: `*_{linux,freebsd}.go` for platform-dependent code

Applied to files:

  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Propagate context.Context through function calls in Go code

Applied to files:

  • internal/oci/runtime_vm_linux.go
🧬 Code graph analysis (15)
internal/lib/statsserver/process_metrics_linux.go (3)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • PidsStats (137-142)
internal/lib/stats/cgroup_stats_linux.go (1)
  • ProcessStats (12-19)
vendor/github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types/sandbox.go (1)
  • Sockets (244-244)
internal/lib/statsserver/disk_metrics_linux.go (2)
internal/lib/stats/disk_stats_linux.go (1)
  • FilesystemStats (16-21)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • BlkioStats (151-166)
internal/config/cgmgr/cgmgr_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/oci/runtime_oci.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (2)
  • DiskStats (8-10)
  • GetDiskUsageForPath (21-23)
internal/lib/stats/disk_stats_linux.go (2)
  • DiskStats (11-13)
  • GetDiskUsageForPath (24-47)
internal/lib/stats/disk_stats_freebsd.go (2)
  • DiskStats (12-14)
  • GetDiskUsageForPath (23-46)
internal/config/cgmgr/cgmgr_unsupported.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/config/cgmgr/cgroupfs_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/config/cgmgr/systemd_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/statsserver/memory_metrics_linux.go (2)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • MemoryStats (96-117)
vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go (2)
  • MetricType_GAUGE (680-680)
  • MetricType_COUNTER (679-679)
internal/lib/stats/disk_stats_unsupported.go (2)
internal/lib/stats/disk_stats_linux.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (24-47)
  • DiskStats (11-13)
internal/lib/stats/disk_stats_freebsd.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (23-46)
  • DiskStats (12-14)
internal/oci/runtime_vm_linux.go (3)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/log/log.go (1)
  • Debugf (21-23)
vendor/github.com/opencontainers/cgroups/stats.go (5)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
  • MemoryStats (96-117)
  • MemoryData (89-94)
  • PidsStats (137-142)
server/container_stats_test.go (1)
vendor/github.com/onsi/ginkgo/v2/core_dsl.go (1)
  • Describe (546-548)
internal/config/cgmgr/stats_linux.go (3)
internal/lib/stats/cgroup_stats_linux.go (2)
  • CgroupStats (5-10)
  • ProcessStats (12-19)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • PidsStats (137-142)
internal/oci/oci.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/lib/statsserver/stats_server_linux.go (1)
internal/lib/stats/cgroup_stats_linux.go (2)
  • CgroupStats (5-10)
  • ProcessStats (12-19)
internal/lib/statsserver/cpu_metrics_linux.go (1)
vendor/github.com/opencontainers/cgroups/stats.go (2)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
🪛 GitHub Actions: integration
internal/lib/statsserver/stats_server_linux.go

[error] 309-309: go build failed: undefined: cgroupStats

🪛 GitHub Check: binaries / amd64
internal/lib/statsserver/stats_server_linux.go

[failure] 309-309:
undefined: cgroupStats

🪛 GitHub Check: binaries / arm64
internal/lib/statsserver/stats_server_linux.go

[failure] 309-309:
undefined: cgroupStats

🪛 GitHub Check: build
internal/lib/statsserver/stats_server_linux.go

[failure] 309-309:
undefined: cgroupStats

🪛 GitHub Check: security-checks
internal/lib/statsserver/stats_server_linux.go

[failure] 309-309:
undefined: cgroupStats


[failure] 309-309:
undefined: cgroupStats

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: rpm-build:fedora-43-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-aarch64:fedora-rawhide
  • GitHub Check: build-freebsd
  • GitHub Check: codeql-build
  • GitHub Check: rpm-build:fedora-rawhide-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-aarch64:fedora-rawhide
  • GitHub Check: lint
🔇 Additional comments (29)
internal/lib/stats/disk_stats_unsupported.go (1)

20-23: LGTM!

The function correctly implements the unsupported platform stub by returning an explicit error message. The approach is appropriate for platform-specific functionality.

internal/lib/statsserver/stats_server_linux.go (3)

420-453: LGTM!

The computeMemoryStats function correctly handles both cgroup v1 and v2 with appropriate field mappings and includes a guard against underflow when computing workingSetBytes.


455-469: LGTM!

The computeSwapUsage function correctly handles the difference between cgroup v1 and v2 swap reporting. The guard at lines 461-463 prevents integer underflow when computing v2 swap usage.


471-474: LGTM!

The isMemoryUnlimited helper provides a clear abstraction for checking unlimited memory limits.

server/container_stats_test.go (1)

14-23: LGTM!

The test suite names have been updated to reflect the new CgroupStats terminology, aligning with the broader refactoring.

internal/config/cgmgr/cgmgr_linux.go (2)

19-19: LGTM!

The import of internal/lib/stats correctly supports the updated interface signatures.


63-87: LGTM!

The interface signatures have been updated to return *stats.CgroupStats, aligning with the externalization of stats types.

internal/config/cgmgr/systemd_linux.go (2)

23-23: LGTM!

The import addition supports the updated return types.


131-138: LGTM!

The method signatures are correctly updated to return *stats.CgroupStats, maintaining consistency with the CgroupManager interface.

Also applies to: 277-284

internal/lib/stats/cgroup_stats_linux.go (1)

1-19: LGTM!

The new CgroupStats and ProcessStats types provide a clean abstraction for cgroup and process-level metrics. Embedding cgroups.Stats allows extending the external type with additional fields (ProcessStats, SystemNano) while maintaining compatibility.

internal/config/cgmgr/cgmgr_unsupported.go (2)

8-8: LGTM!

The import addition supports the updated interface signatures on unsupported platforms.


28-28: LGTM!

The interface and stub implementation correctly return *stats.CgroupStats for non-Linux platforms, maintaining cross-platform compilation.

Based on learnings, this aligns with the pattern of using empty structs for unsupported platforms.

Also applies to: 72-74

internal/lib/statsserver/disk_metrics_linux.go (1)

17-21: LGTM!

The nil check for diskStats properly prevents panics when disk statistics are unavailable.

internal/lib/statsserver/cpu_metrics_linux.go (1)

13-87: LGTM! Type migration and nil safety look good.

The function signature update to use *cgroups.CpuStats is correct, the nil check prevents panics, and the field access updates (e.g., cpu.CpuUsage.UsageInUsermode, cpu.ThrottlingData.Periods) properly reflect the nested structure of the vendored cgroups types.

internal/config/cgmgr/cgroupfs_linux.go (2)

99-106: LGTM! Return type migration is correct.

The updated signature returning *stats.CgroupStats aligns with the consolidated stats types, and delegation to statsFromLibctrMgr is appropriate.


166-173: LGTM! Consistent with ContainerCgroupStats update.

The return type change to *stats.CgroupStats is consistent with the broader migration to centralized stats types.

internal/oci/runtime_oci.go (2)

1279-1287: LGTM! Method rename and type update are correct.

The rename from ContainerStats to CgroupStats and the return type change to *stats.CgroupStats align with the PR's consolidation of stats types into internal/lib/stats.


1290-1305: LGTM! DiskStats updated correctly.

The return type change to *stats.DiskStats and delegation to stats.GetDiskUsageForPath are consistent with the refactor.

internal/lib/statsserver/memory_metrics_linux.go (2)

11-118: LGTM! Nil safety and metric generation look correct.

The nil check at the start prevents panics, and the metric computation properly handles cgroup v1/v2 differences. The derived values (working set, RSS, page faults) are calculated correctly.


148-159: LGTM! Underflow protection is correct.

The comparison check before subtraction prevents uint64 underflow when SwapUsage < Usage in cgroup v2.

test/mocks/oci/oci.go (2)

63-76: LGTM! Generated mock matches updated interface.

The CgroupStats method correctly returns *stats.CgroupStats, aligning with the interface changes.


120-133: LGTM! DiskStats mock updated correctly.

The return type change to *stats.DiskStats is consistent with the interface update.

internal/oci/runtime_pod.go (1)

300-306: LGTM! Delegation to OCI runtime is correct.

The updated signatures returning *stats.CgroupStats and *stats.DiskStats properly delegate to the underlying OCI runtime implementation.

internal/oci/oci.go (3)

72-73: LGTM! Interface updated to use consolidated stats types.

The interface methods now correctly use *stats.CgroupStats and *stats.DiskStats, aligning with the PR's migration to centralized stats types.


459-470: LGTM! ContainerStats delegates to CgroupStats correctly.

The implementation maintains the ContainerStats public API while delegating to impl.CgroupStats, ensuring backward compatibility during the transition.


473-483: LGTM! DiskStats implementation updated correctly.

The return type change to *stats.DiskStats and delegation to impl.DiskStats are consistent with the refactor.

internal/config/cgmgr/stats_linux.go (3)

12-12: LGTM: Imports align with refactoring objectives.

The new imports support the consolidation of stats collection into internal/lib/stats and enable structured logging via internal/log.

Also applies to: 16-16


47-63: Compilation error resolved; verify runtime safety of ProcessStats population.

The type mismatch from the previous review has been addressed by dereferencing the result of cgroupProcessStats on line 61. However, ensure that cgroupProcessStats handles nil fields gracefully (see separate comment on lines 78-79).


78-79: This concern about nil dereference is incorrect. The PidsStats field in the cgroups.Stats struct is embedded directly as a value type, not as a pointer, so direct access to its fields (Current and Limit) on lines 78-79 is safe. No nil guard is needed.

Likely an incorrect or invalid review comment.

@bitoku bitoku force-pushed the cri-stats-refactor branch from d5334df to f9aa3e6 Compare December 18, 2025 16:07
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
internal/oci/runtime_vm_linux.go (2)

30-35: Using stored context instead of passed context parameter.

The method uses r.ctx for the Stats call instead of the ctx parameter passed to the function. This breaks cancellation propagation and context deadlines. As per coding guidelines, context.Context should be propagated through function calls.

🔎 Suggested fix:
-	resp, err := r.task.Stats(r.ctx, &task.StatsRequest{
+	resp, err := r.task.Stats(ctx, &task.StatsRequest{
 		ID: c.ID(),
 	})

67-130: Add nil checks for V1 metrics sub-structures.

The function accesses nested fields like m.CPU.Usage.Total, m.Memory.Cache, etc., without checking if the intermediate pointers are nil. Since these fields are optional protobuf-generated pointers, they can be nil at runtime, causing a panic on direct field access.

🔎 Suggested approach:

Add defensive nil checks before accessing nested fields:

func metricsV1ToCgroupStats(ctx context.Context, m *cgroupsV1.Metrics) *stats.CgroupStats {
	if m == nil {
		return &stats.CgroupStats{SystemNano: time.Now().UnixNano()}
	}
	
	result := &stats.CgroupStats{
		SystemNano: time.Now().UnixNano(),
	}
	
	if m.CPU != nil {
		if m.CPU.Usage != nil {
			result.CpuStats.CpuUsage = cgroups.CpuUsage{
				TotalUsage:        m.CPU.Usage.Total,
				PercpuUsage:       m.CPU.Usage.PerCPU,
				UsageInKernelmode: m.CPU.Usage.Kernel,
				UsageInUsermode:   m.CPU.Usage.User,
			}
		}
		// ... similar for Throttling
	}
	// ... similar for Memory, Pids, Hugetlb
	
	return result
}
🧹 Nitpick comments (4)
internal/config/cgmgr/cgroupfs_linux.go (1)

22-22: Address the TODO comment.

The comment contains an incomplete TODO: "TODO: Update this." — this documentation should be updated to accurately describe the CgroupfsManager functionality.

Would you like me to suggest updated documentation for this struct?

internal/lib/statsserver/disk_metrics_linux.go (1)

53-57: Minor: Comment doesn't match parameter type.

The comment says "from DiskStats" but the function accepts *cgroups.BlkioStats. Consider updating for clarity:

🔎 Suggested fix
-// generateContainerDiskIOMetrics computes filesystem disk metrics from DiskStats for a container sandbox.
+// generateContainerDiskIOMetrics computes disk I/O metrics from BlkioStats for a container.
internal/oci/runtime_vm_linux.go (2)

50-60: Consider using a type switch for cleaner code.

The nested if-else with type assertions can be simplified using a type switch pattern, which is more idiomatic Go.

🔎 Suggested refactor:
-	m, ok := statsData.(*cgroupsV1.Metrics)
-	if ok {
-		return metricsV1ToCgroupStats(ctx, m), nil
-	} else {
-		m, ok := statsData.(*cgroupsV2.Metrics)
-		if ok {
-			return metricsV2ToCgroupStats(ctx, m), nil
-		} else {
-			return nil, errors.New("unknown stats type")
-		}
-	}
+	switch m := statsData.(type) {
+	case *cgroupsV1.Metrics:
+		return metricsV1ToCgroupStats(ctx, m), nil
+	case *cgroupsV2.Metrics:
+		return metricsV2ToCgroupStats(ctx, m), nil
+	default:
+		return nil, errors.New("unknown stats type")
+	}

63-65: DiskStats returns empty struct - verify this is intentional.

For VM-based runtimes, returning an empty DiskStats may be appropriate if disk statistics are not available from the VM. Consider adding a comment explaining why this returns empty stats rather than an error.

🔎 Suggested documentation:
 func (r *runtimeVM) DiskStats(ctx context.Context, c *Container, _ string) (*stats.DiskStats, error) {
+	// VM runtimes don't expose disk statistics through the containerd shim API.
+	// Return empty stats rather than an error to allow callers to proceed.
 	return &stats.DiskStats{}, nil
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d5334df and f9aa3e6.

📒 Files selected for processing (25)
  • internal/config/cgmgr/cgmgr_linux.go (3 hunks)
  • internal/config/cgmgr/cgmgr_unsupported.go (3 hunks)
  • internal/config/cgmgr/cgroupfs_linux.go (3 hunks)
  • internal/config/cgmgr/stats_linux.go (4 hunks)
  • internal/config/cgmgr/stats_unsupported.go (0 hunks)
  • internal/config/cgmgr/systemd_linux.go (3 hunks)
  • internal/lib/stats/cgroup_stats_linux.go (1 hunks)
  • internal/lib/stats/cgroup_stats_unsupported.go (1 hunks)
  • internal/lib/stats/disk_stats_unsupported.go (1 hunks)
  • internal/lib/statsserver/cpu_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/disk_metrics_linux.go (3 hunks)
  • internal/lib/statsserver/hugetlb_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/memory_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/network_metrics_linux.go (1 hunks)
  • internal/lib/statsserver/pressure_metrics_linux.go (2 hunks)
  • internal/lib/statsserver/process_metrics_linux.go (5 hunks)
  • internal/lib/statsserver/stats_server_linux.go (12 hunks)
  • internal/oci/oci.go (4 hunks)
  • internal/oci/runtime_oci.go (4 hunks)
  • internal/oci/runtime_pod.go (2 hunks)
  • internal/oci/runtime_vm.go (0 hunks)
  • internal/oci/runtime_vm_linux.go (1 hunks)
  • internal/oci/runtime_vm_unsupported.go (1 hunks)
  • server/container_stats_test.go (2 hunks)
  • test/mocks/oci/oci.go (3 hunks)
💤 Files with no reviewable changes (2)
  • internal/oci/runtime_vm.go
  • internal/config/cgmgr/stats_unsupported.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • internal/config/cgmgr/systemd_linux.go
  • internal/lib/stats/cgroup_stats_linux.go
  • internal/oci/runtime_vm_unsupported.go
  • internal/config/cgmgr/cgmgr_linux.go
  • internal/lib/statsserver/hugetlb_metrics_linux.go
  • server/container_stats_test.go
  • internal/lib/statsserver/network_metrics_linux.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use interface-based design and dependency injection patterns in Go code
Propagate context.Context through function calls in Go code
Use fmt.Errorf with %w for error wrapping in Go code
Use logrus with structured fields for logging in Go code
Add comments explaining 'why' not 'what' in Go code
Use platform-specific file naming: *_{linux,freebsd}.go for platform-dependent code

Files:

  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/oci/runtime_oci.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/oci/runtime_pod.go
  • test/mocks/oci/oci.go
  • internal/oci/oci.go
🧠 Learnings (8)
📚 Learning: 2025-12-18T13:28:24.244Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9676
File: internal/lib/stats/cgroup_stats_unsupported.go:1-7
Timestamp: 2025-12-18T13:28:24.244Z
Learning: In the cri-o/cri-o repository, for platform-specific types guarded by Go build tags (for example //go:build !linux), implement empty structs for unsupported platforms to permit compilation and clearly indicate the feature is not available rather than mirroring the Linux struct with unpopulated fields. Apply this pattern to all relevant platform-specific files across the codebase (i.e., any file under build-taged sections that should compile on all targets but lacks full implementation for some platforms).

Applied to files:

  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/oci/runtime_oci.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/oci/runtime_pod.go
  • test/mocks/oci/oci.go
  • internal/oci/oci.go
📚 Learning: 2025-12-18T16:05:32.646Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9676
File: internal/lib/statsserver/memory_metrics_linux.go:1-9
Timestamp: 2025-12-18T16:05:32.646Z
Learning: In the cri-o/cri-o repository, platform-specific file naming (e.g., `*_linux.go`) is preferred and sufficient for platform-dependent code without requiring explicit build tags like `//go:build linux`. The file naming convention alone controls platform-specific compilation.

Applied to files:

  • internal/lib/stats/cgroup_stats_unsupported.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Use platform-specific file naming: `*_{linux,freebsd}.go` for platform-dependent code

Applied to files:

  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/lib/statsserver/memory_metrics_linux.go
📚 Learning: 2025-12-17T13:38:34.646Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9667
File: server/container_create.go:1233-1236
Timestamp: 2025-12-17T13:38:34.646Z
Learning: In the cri-o/cri-o repository, protobuf-generated Get* methods for k8s.io/cri-api types are nil-safe: if the receiver is nil, GetX() returns the zero value instead of panicking. Do not add explicit nil checks before chaining calls on such getters. Apply this guidance to all Go code that uses these generated getters across the codebase.

Applied to files:

  • internal/lib/stats/cgroup_stats_unsupported.go
  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/oci/runtime_oci.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/lib/stats/disk_stats_unsupported.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/config/cgmgr/cgmgr_unsupported.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
  • internal/oci/runtime_pod.go
  • test/mocks/oci/oci.go
  • internal/oci/oci.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Propagate context.Context through function calls in Go code

Applied to files:

  • internal/oci/runtime_vm_linux.go
📚 Learning: 2025-12-18T16:05:32.646Z
Learnt from: bitoku
Repo: cri-o/cri-o PR: 9676
File: internal/lib/statsserver/memory_metrics_linux.go:1-9
Timestamp: 2025-12-18T16:05:32.646Z
Learning: In Go, platform-specific files can be compiled based on filename suffixes like *_linux.go without needing explicit build tags (e.g., //go:build linux). This pattern is used across the repository to control platform-specific implementations. For memory_metrics_linux.go and similar files, ensure the linux-specific variant uses the *_linux.go suffix and avoid adding redundant build tags. If introducing new platform-specific files, follow the same naming convention (e.g., *_windows.go, *_darwin.go) and rely on Go's build constraints via filename patterns.

Applied to files:

  • internal/oci/runtime_vm_linux.go
  • internal/lib/statsserver/process_metrics_linux.go
  • internal/lib/statsserver/disk_metrics_linux.go
  • internal/config/cgmgr/cgroupfs_linux.go
  • internal/lib/statsserver/cpu_metrics_linux.go
  • internal/config/cgmgr/stats_linux.go
  • internal/lib/statsserver/pressure_metrics_linux.go
  • internal/lib/statsserver/memory_metrics_linux.go
  • internal/lib/statsserver/stats_server_linux.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*.go : Add comments explaining 'why' not 'what' in Go code

Applied to files:

  • internal/lib/statsserver/disk_metrics_linux.go
📚 Learning: 2025-12-03T18:27:19.593Z
Learnt from: CR
Repo: cri-o/cri-o PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T18:27:19.593Z
Learning: Applies to **/*_test.go : Use `*_test.go` naming convention for unit test files

Applied to files:

  • internal/lib/statsserver/memory_metrics_linux.go
🧬 Code graph analysis (13)
internal/oci/runtime_vm_linux.go (3)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/log/log.go (1)
  • Debugf (21-23)
vendor/github.com/opencontainers/cgroups/stats.go (6)
  • HugetlbStats (168-175)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
  • MemoryStats (96-117)
  • MemoryData (89-94)
  • PidsStats (137-142)
internal/lib/statsserver/process_metrics_linux.go (2)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • PidsStats (137-142)
internal/lib/stats/cgroup_stats_linux.go (1)
  • ProcessStats (12-19)
internal/lib/statsserver/disk_metrics_linux.go (2)
internal/lib/stats/disk_stats_linux.go (1)
  • FilesystemStats (16-21)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • BlkioStats (151-166)
internal/lib/stats/disk_stats_unsupported.go (2)
internal/lib/stats/disk_stats_linux.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (24-47)
  • DiskStats (11-13)
internal/lib/stats/disk_stats_freebsd.go (3)
  • FilesystemStats (16-21)
  • GetDiskUsageForPath (23-46)
  • DiskStats (12-14)
internal/config/cgmgr/cgroupfs_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/config/cgmgr/cgmgr_unsupported.go (2)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/statsserver/cpu_metrics_linux.go (2)
vendor/github.com/opencontainers/cgroups/stats.go (2)
  • CpuStats (55-60)
  • ThrottlingData (3-10)
vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go (1)
  • MetricType_COUNTER (679-679)
internal/config/cgmgr/stats_linux.go (2)
internal/lib/stats/cgroup_stats_linux.go (2)
  • CgroupStats (5-10)
  • ProcessStats (12-19)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • PidsStats (137-142)
internal/lib/statsserver/pressure_metrics_linux.go (1)
vendor/github.com/opencontainers/cgroups/stats.go (3)
  • CpuStats (55-60)
  • MemoryStats (96-117)
  • BlkioStats (151-166)
internal/lib/statsserver/memory_metrics_linux.go (2)
vendor/github.com/opencontainers/cgroups/stats.go (1)
  • MemoryStats (96-117)
vendor/k8s.io/cri-api/pkg/apis/runtime/v1/api.pb.go (2)
  • MetricType_GAUGE (680-680)
  • MetricType_COUNTER (679-679)
internal/oci/runtime_pod.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
test/mocks/oci/oci.go (5)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
internal/oci/oci.go (6)
internal/lib/stats/cgroup_stats_linux.go (1)
  • CgroupStats (5-10)
internal/lib/stats/cgroup_stats_unsupported.go (1)
  • CgroupStats (7-7)
internal/oci/container.go (1)
  • Container (44-92)
internal/lib/stats/disk_stats_unsupported.go (1)
  • DiskStats (8-10)
internal/lib/stats/disk_stats_linux.go (1)
  • DiskStats (11-13)
internal/lib/stats/disk_stats_freebsd.go (1)
  • DiskStats (12-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (27)
  • GitHub Check: rpm-build:fedora-43-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:centos-stream-9-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-aarch64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-rawhide-x86_64:fedora-rawhide
  • GitHub Check: rpm-build:fedora-43-aarch64:fedora-rawhide
  • GitHub Check: lint
  • GitHub Check: docs
  • GitHub Check: binaries / amd64
  • GitHub Check: binaries / arm64
  • GitHub Check: unit / amd64 / rootless
  • GitHub Check: unit / amd64 / root
  • GitHub Check: codeql-build
  • GitHub Check: build static / amd64
  • GitHub Check: unit / arm64 / root
  • GitHub Check: build
  • GitHub Check: build static / arm64
  • GitHub Check: security-checks
  • GitHub Check: build static / s390x
  • GitHub Check: build static / ppc64le
  • GitHub Check: build-freebsd
🔇 Additional comments (42)
internal/lib/stats/cgroup_stats_unsupported.go (1)

1-7: LGTM!

The empty struct stub for non-Linux platforms is the correct approach. It satisfies type requirements for compilation while clearly indicating that cgroup functionality isn't available on unsupported platforms like FreeBSD. The comment on line 6 appropriately documents this intentional design. Based on learnings, this follows the established pattern in the repository.

internal/lib/statsserver/pressure_metrics_linux.go (2)

4-4: LGTM!

Import updated correctly to use the opencontainers/cgroups package.


19-43: LGTM!

The function signature is correctly updated to accept *cgroups.CpuStats, *cgroups.MemoryStats, and *cgroups.BlkioStats. The nil checks at lines 22, 45, and 68 properly guard against nil parameters and nil PSI fields before accessing nested fields like PSI.Full.Total and PSI.Some.Total.

internal/config/cgmgr/cgroupfs_linux.go (3)

18-18: LGTM!

Import for internal/lib/stats correctly added to support the new return type.


99-106: LGTM!

Return type correctly updated to *stats.CgroupStats. The delegation to statsFromLibctrMgr maintains the existing logic while adapting to the new type surface.


166-173: LGTM!

SandboxCgroupStats return type correctly updated to *stats.CgroupStats, consistent with ContainerCgroupStats.

internal/config/cgmgr/cgmgr_unsupported.go (3)

7-8: LGTM!

Import for internal/lib/stats correctly added to support the updated interface return type.


28-28: LGTM!

Interface method ContainerCgroupStats correctly updated to return *stats.CgroupStats, aligning with the Linux implementation.


72-74: LGTM!

The NullCgroupManager.ContainerCgroupStats implementation correctly returns (nil, nil) for unsupported platforms. This is appropriate since cgroup stats functionality is not available on non-Linux systems.

internal/lib/statsserver/process_metrics_linux.go (3)

3-9: LGTM!

Imports correctly updated to include both github.com/opencontainers/cgroups for PidsStats and internal/lib/stats for ProcessStats.


11-14: LGTM!

The nil check for both pids and process parameters addresses the previously identified issue and ensures safe access to their fields throughout the function.


16-71: LGTM!

Metric value sources correctly updated:

  • pids.Current for process count (from cgroups)
  • process.FileDescriptors, process.Sockets, process.Threads, process.ThreadsMax, process.UlimitsSoft (from internal stats)

This separation appropriately uses cgroups for pids data and the internal ProcessStats for process-level metrics.

internal/lib/statsserver/disk_metrics_linux.go (4)

10-14: LGTM!

Imports correctly updated to use github.com/opencontainers/cgroups for BlkioStats and internal/lib/stats for FilesystemStats.


17-21: LGTM!

Function signature updated to accept *stats.FilesystemStats with proper nil-safety check returning an empty slice.


61-81: LGTM!

Correctly iterates over ioStats.IoServicedRecursive (updated field name from cgroups.BlkioStats) to generate read/write operation count metrics.


83-112: LGTM!

Correctly iterates over ioStats.IoServiceBytesRecursive to generate byte-level I/O metrics. The device label construction and operation-based metric selection are well implemented.

internal/lib/statsserver/cpu_metrics_linux.go (4)

7-7: LGTM!

Import for github.com/opencontainers/cgroups correctly added.


13-16: LGTM!

Function signature correctly updated to accept *cgroups.CpuStats with proper nil-safety check.


18-58: LGTM!

CPU usage metrics correctly updated to use nested field paths:

  • cpu.CpuUsage.UsageInUsermode and cpu.CpuUsage.UsageInKernelmode for user/system time
  • cpu.CpuUsage.TotalUsage as fallback when PercpuUsage is empty
  • cpu.CpuUsage.PercpuUsage for per-CPU breakdown

The nanosecond-to-second conversion using / uint64(time.Second) is preserved correctly.


59-84: LGTM!

Throttling metrics correctly updated to use cpu.ThrottlingData.* fields:

  • Periods for total CFS periods
  • ThrottledPeriods for throttled period count
  • ThrottledTime for aggregate throttled time
internal/lib/stats/disk_stats_unsupported.go (1)

1-23: LGTM! Platform stub implementation follows established patterns.

The unsupported platform stub correctly mirrors the type definitions from disk_stats_linux.go and disk_stats_freebsd.go, ensuring API compatibility across platforms. The error message clearly indicates the feature unavailability. Based on learnings, this approach is appropriate since DiskStats requires populated fields for callers to handle gracefully, unlike CgroupStats which can use an empty struct.

internal/oci/runtime_oci.go (3)

36-36: LGTM! Import added for the new stats package.

The import aligns with the refactor to use centralized stats types from internal/lib/stats.


1279-1287: LGTM! CgroupStats method correctly delegates to the cgroup manager.

The method properly:

  • Uses context for tracing with log.StartSpan
  • Acquires the container operation lock
  • Delegates to the cgroup manager's ContainerCgroupStats method
  • Returns the new *stats.CgroupStats type

1290-1305: LGTM! DiskStats method correctly uses the new stats package.

The implementation properly validates the mount point exists before calling stats.GetDiskUsageForPath, and follows the established pattern with context tracing and lock acquisition.

internal/oci/runtime_pod.go (2)

19-19: LGTM! Import updated to use the new stats package.


300-306: LGTM! Stats methods correctly delegate to the underlying OCI runtime.

Both CgroupStats and DiskStats properly propagate the context and delegate to r.oci, maintaining the established delegation pattern used throughout runtimePod.

internal/lib/statsserver/memory_metrics_linux.go (5)

1-9: LGTM! Platform-specific file follows naming conventions.

The _linux.go suffix correctly restricts this file to Linux builds without requiring explicit build tags. Based on learnings, this is the preferred pattern in this repository.


11-18: LGTM! Nil check added for mem parameter.

The nil check at line 12-14 properly guards against nil mem parameter, returning an empty slice instead of panicking. This addresses the previously flagged issue.


120-146: LGTM! Memory metric computation handles V1/V2 differences correctly.

The function properly:

  • Uses different stat keys for V1 (total_inactive_file, total_rss) vs V2 (inactive_file, anon)
  • Guards against underflow when computing workingSetBytes
  • Returns pageFaults/majorPageFaults only for V2 (V1 doesn't populate them here)

148-159: LGTM! Swap underflow protection implemented.

The check at lines 151-155 properly guards against integer underflow when computing swap usage for cgroup V2, returning 0 if SwapUsage.Usage <= Usage.Usage. This addresses the previously flagged issue.


174-185: LGTM! OOM metrics generation is properly exported.

The GenerateContainerOOMMetrics function follows the same pattern as generateContainerMemoryMetrics and correctly uses the shared computeContainerMetrics helper.

test/mocks/oci/oci.go (1)

1-8: LGTM! Mock file correctly reflects interface changes.

The generated mock properly reflects the refactoring from cgmgr.CgroupStats to stats.CgroupStats types. The new CgroupStats method replaces the old ContainerStats method, and DiskStats now returns the correct *stats.DiskStats type.

Also applies to: 17-23, 63-76, 120-133

internal/oci/oci.go (4)

20-20: LGTM! Proper import addition for stats types.

The import of internal/lib/stats is correctly added to support the new centralized stats types used throughout this refactor.


72-73: LGTM! Interface updated to use centralized stats types.

The RuntimeImpl interface methods correctly updated to return the new *stats.CgroupStats and *stats.DiskStats types, aligning with the PR's objective of using centralized stats collection.


460-470: LGTM! Public method delegates to updated interface method.

The ContainerStats method correctly returns *stats.CgroupStats and delegates to impl.CgroupStats, properly updating the delegation from the old ContainerStats interface method to the new CgroupStats method.


473-483: LGTM! DiskStats properly updated.

The method signature and delegation correctly updated to use *stats.DiskStats.

internal/config/cgmgr/stats_linux.go (2)

15-15: LGTM! Successful refactor to centralized stats types.

The refactor correctly migrates from custom CgroupStats types to the centralized stats.CgroupStats structure, simplifying the codebase by leveraging the opencontainers cgroups library directly. The dereference on line 61 is safe since cgroupProcessStats always returns a non-nil pointer.

Also applies to: 47-63


65-82: The review comment is incorrect. PidsStats is not a pointer field and cannot be nil. No changes are needed.

Likely an incorrect or invalid review comment.

internal/lib/statsserver/stats_server_linux.go (4)

6-6: LGTM! Proper imports for new stats types.

The imports are correctly updated to include math, cgroups, node, and stats packages needed for the refactored stats collection implementation.

Also applies to: 11-11, 15-17


256-329: LGTM! Container metrics generation properly refactored.

The function signature correctly updated to accept *stats.CgroupStats and *stats.DiskStats, and all metric generators properly access the new nested cgroups types (e.g., &cgroupStats.CpuStats, &cgroupStats.MemoryStats).


352-418: LGTM! CRI stats conversion functions properly updated.

All CRI stats conversion functions (containerCRIStats, criCPUStats, criMemStats, criSwapStats, criProcessStats, criFilesystemStats) correctly updated to consume the new cgroups and stats types.


420-474: LGTM! Memory calculation helpers with proper underflow protection.

The new helper functions properly implement underflow guards:

  • Line 441: Checks workingSetBytes < v before subtraction
  • Line 461: Checks SwapUsage.Usage > Usage.Usage before subtraction

This addresses the past review concern about integer underflow in swap calculation.

Comment on lines +132 to +189
func metricsV2ToCgroupStats(ctx context.Context, m *cgroupsV2.Metrics) *stats.CgroupStats {
_ = ctx // unused but kept for interface consistency

hugetlbStats := map[string]cgroups.HugetlbStats{}
for _, hugetlb := range m.Hugetlb {
hugetlbStats[hugetlb.Pagesize] = cgroups.HugetlbStats{
Usage: hugetlb.Current,
MaxUsage: hugetlb.Max,
}
}

// For cgroup v2, create the Stats map with the appropriate keys
memStats := map[string]uint64{
"inactive_file": m.Memory.InactiveFile,
"anon": m.Memory.Anon,
"file_mapped": m.Memory.FileMapped,
"pgfault": m.Memory.Pgfault,
"pgmajfault": m.Memory.Pgmajfault,
}

return &stats.CgroupStats{
Stats: cgroups.Stats{
CpuStats: cgroups.CpuStats{
CpuUsage: cgroups.CpuUsage{
TotalUsage: m.CPU.UsageUsec * 1000,
UsageInKernelmode: m.CPU.SystemUsec * 1000,
UsageInUsermode: m.CPU.UserUsec * 1000,
},
ThrottlingData: cgroups.ThrottlingData{
Periods: m.CPU.NrPeriods,
ThrottledPeriods: m.CPU.NrThrottled,
ThrottledTime: m.CPU.ThrottledUsec * 1000,
},
},
MemoryStats: cgroups.MemoryStats{
Cache: m.Memory.File,
Usage: cgroups.MemoryData{
Usage: m.Memory.Usage,
Limit: m.Memory.UsageLimit,
},
SwapUsage: cgroups.MemoryData{
Usage: m.Memory.SwapUsage,
Limit: m.Memory.SwapLimit,
},
KernelUsage: cgroups.MemoryData{
Usage: m.Memory.KernelStack,
},
Stats: memStats,
},
PidsStats: cgroups.PidsStats{
Current: m.Pids.Current,
Limit: m.Pids.Limit,
},
HugetlbStats: hugetlbStats,
},
SystemNano: time.Now().UnixNano(),
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add nil checks for V2 metrics sub-structures.

Similar to V1, the V2 conversion function accesses nested protobuf fields without nil checks. Fields like m.CPU, m.Memory, m.Pids, and m.Hugetlb can be nil.

🔎 Suggested approach:

Add defensive nil checks:

func metricsV2ToCgroupStats(ctx context.Context, m *cgroupsV2.Metrics) *stats.CgroupStats {
	if m == nil {
		return &stats.CgroupStats{SystemNano: time.Now().UnixNano()}
	}
	
	result := &stats.CgroupStats{
		SystemNano: time.Now().UnixNano(),
	}
	
	if m.CPU != nil {
		result.CpuStats.CpuUsage = cgroups.CpuUsage{
			TotalUsage:        m.CPU.UsageUsec * 1000,
			UsageInKernelmode: m.CPU.SystemUsec * 1000,
			UsageInUsermode:   m.CPU.UserUsec * 1000,
		}
		result.CpuStats.ThrottlingData = cgroups.ThrottlingData{
			Periods:          m.CPU.NrPeriods,
			ThrottledPeriods: m.CPU.NrThrottled,
			ThrottledTime:    m.CPU.ThrottledUsec * 1000,
		}
	}
	// ... similar for Memory, Pids, Hugetlb
	
	return result
}
🤖 Prompt for AI Agents
In internal/oci/runtime_vm_linux.go around lines 132 to 189, the
metricsV2ToCgroupStats function dereferences nested fields (m, m.CPU, m.Memory,
m.Pids, m.Hugetlb) without nil checks; update it to first return an empty
&stats.CgroupStats{SystemNano: time.Now().UnixNano()} if m is nil, then guard
each nested assignment with if m.CPU != nil / if m.Memory != nil / if m.Pids !=
nil and only populate CpuStats, MemoryStats and PidsStats when present, and
iterate m.Hugetlb only if non-nil (or treat empty slice safely) to build
HugetlbStats; ensure all numeric conversions remain the same and leave
unpopulated fields zero-valued when absent.

@haircommander
Copy link
Member

personally, it feels important to reduce the number of struct translations. I think one of the bottlenecks of metrics collection is the cpu time allocated to lots of tiny structs allocated and deallocated. I want to get as few hops between structs as possible. Can we extend opencontainer/cgroups library to have a freebsd variant that is largely empty, but allows us to use those objects natively?

@bitoku
Copy link
Contributor Author

bitoku commented Dec 19, 2025

@haircommander

personally, it feels important to reduce the number of struct translations. I think one of the bottlenecks of metrics collection is the cpu time allocated to lots of tiny structs allocated and deallocated. I want to get as few hops between structs as possible.

As long as we don't use make, the new allocation won't happen but it'll use stack, I guess.
There may be some consequential make calls like append, but otherwise I think there are not many (de)allocations around this.
Is there any specific code that you are concerned about this?
Aside from that, this PR is primarily for addressing #9608 (comment)

Can we extend opencontainer/cgroups library to have a freebsd variant that is largely empty, but allows us to use those objects natively?

I would rather create a new package for freebsd, since the cgroup is only for linux.
Also it doesn't look they're interested in the idea.
opencontainers/cgroups@b014568

@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 20, 2025
@openshift-merge-robot
Copy link
Contributor

PR needs rebase.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has DCO signed all their commits. kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. release-note-none Denotes a PR that doesn't merit a release note.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants