Skip to content

in_podman_metrics: fix multiple cgroup v2 issues - #11719

Open
stondo wants to merge 3 commits into
fluent:masterfrom
stondo:fix/podman-metrics-cgroupv2
Open

in_podman_metrics: fix multiple cgroup v2 issues#11719
stondo wants to merge 3 commits into
fluent:masterfrom
stondo:fix/podman-metrics-cgroupv2

Conversation

@stondo

@stondo stondo commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix four cgroup v2 bugs in the in_podman_metrics input plugin that caused
most container metrics to be absent or incorrect on systems using cgroup v2
(unified hierarchy).

All four bugs are confirmed on an ARM64 embedded device running
Fluent Bit 4.2.0/5.0.2 with Podman and cgroup v2 unified hierarchy.

Bugs fixed

1. CPU counter division (incorrect unit conversion)

create_counter() divides raw CPU values by 1,000,000,000 (nanoseconds)
unconditionally. This is correct for cgroup v1 (cpuacct.usage reports
nanoseconds) but wrong for cgroup v2 (cpu.stat reports usage_usec
and user_usec in microseconds).

On v2, integer division truncates all values below 1e9 usec (~16.7 min of
CPU time) to zero. In practice, container_cpu_usage_seconds_total and
container_cpu_user_seconds_total always read 0.

Fix: Check ctx->cgroup_version and use the correct divisor:
1e9 for v1 (nanoseconds), 1e6 for v2 (microseconds).

2. RSS memory key name (wrong key for v2)

STAT_KEY_RSS is defined as "rss", which is correct for cgroup v1
memory.stat. However, cgroup v2 memory.stat does not have a rss
field; the equivalent is anon (anonymous memory pages).

Result: container_memory_rss gauge is never reported for any
container on v2, with a [warn] rss not found in .../memory.stat log
message emitted per container per scrape.

Fix: Add V2_STAT_KEY_RSS "anon" and use it in
fill_counters_with_sysfs_data_v2().

3. memory.max "max" keyword (parse failure)

cgroup v2 memory.max contains the literal string "max" when the
memory limit is unlimited (no limit set). read_from_file() uses
fscanf(fp, "%lu", &value) which fails to parse "max", returning
UINT64_MAX and logging a spurious warning per affected container per
scrape.

Result: container_spec_memory_limit_bytes is missing for
containers without an explicit memory limit. Warning spam in logs.

Fix: Add read_from_sysfs_or_max() helper that parses the "max"
keyword and returns 0 (unlimited), matching the convention used by
cAdvisor and other container metric exporters.

4. PID fallback path typo (singular vs. plural)

V2_SYSFS_FILE_PIDS_ALT is defined as "containers/cgroup.procs"
(plural), but the actual cgroup v2 subdirectory is
"container/cgroup.procs" (singular).

On v2, cgroup.procs at the scope level is empty for all containers.
Processes live only in the container/cgroup.procs subdirectory. The
plugin correctly tries the alt path, but the typo means it always fails.

Result: PID lookup fails for all containers, which prevents
get_net_data_from_proc() from being called. All four
container_network_* metrics are completely absent.

Fix: Change "containers/cgroup.procs" to "container/cgroup.procs".

Before/After (gw-cloud-connector container, ARM64 device)

Metric Before After
container_cpu_usage_seconds_total 0 449
container_cpu_user_seconds_total 0 145
container_memory_rss MISSING 12,472,320
container_spec_memory_limit_bytes MISSING 1,048,576,000
container_network_receive_bytes_total MISSING 3,229,233
container_network_transmit_bytes_total MISSING 4,721,901

After the fix, all 10 metric types are successfully emitted for all 9
containers, with zero warnings in the log.

Testing

Tested on:

  • ARM64 (Cortex-A7) embedded device, 4-core, 4 GB RAM
  • Yocto Scarthgap (kernel 6.6), cgroup v2 unified hierarchy
  • Podman 5.x with 9 containers (3 infra, 3 service, 3 app)
  • Fluent Bit 4.2.0 and verified patch applies cleanly to 5.0.2/5.0.3

Verified:

  • All 10 metric types present in Prometheus output
  • CPU values match raw cpu.stat divided by 1e6
  • RSS values match anon field in memory.stat
  • Memory limit correctly reports 0 for unlimited and real values for limited
  • Network metrics present for all containers with non-loopback interfaces
  • Zero warnings in journal log after fix (previously ~45 warnings per scrape)
  • No regression: cgroup v1 code path is unchanged

Fixes #7769

Summary by CodeRabbit

  • Bug Fixes
    • CPU metrics now convert correctly for both cgroup v1 and v2, improving reported CPU-time accuracy.
    • cgroup v2 memory limits now correctly recognize unlimited values and handle read or parsing failures safely.
    • RSS metrics for cgroup v2 now use the appropriate memory statistic.
    • Container image names default to “unknown” when metadata is incomplete.
    • Improved discovery of container process information on cgroup v2 systems.

@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e83718b-300d-4caf-a207-c783d857705f

📥 Commits

Reviewing files that changed from the base of the PR and between ae51533 and af0de5b.

📒 Files selected for processing (3)
  • plugins/in_podman_metrics/podman_metrics.c
  • plugins/in_podman_metrics/podman_metrics_config.h
  • plugins/in_podman_metrics/podman_metrics_data.c
🚧 Files skipped from review as they are similar to previous changes (3)
  • plugins/in_podman_metrics/podman_metrics_config.h
  • plugins/in_podman_metrics/podman_metrics_data.c
  • plugins/in_podman_metrics/podman_metrics.c

📝 Walkthrough

Walkthrough

Podman metrics now guard image-name parsing, convert CPU values by cgroup version, correct cgroup v2 keys and paths, and interpret "max" memory limits as unlimited.

Changes

Podman metrics updates

Layer / File(s) Summary
Container metadata and CPU conversion
plugins/in_podman_metrics/podman_metrics.c
Image-name extraction requires the metadata end delimiter and otherwise uses "unknown". CPU counters use cgroup-version-specific divisors before conversion to seconds.
cgroup v2 keys and paths
plugins/in_podman_metrics/podman_metrics_config.h
Adds V2_STAT_KEY_RSS with value "anon" and changes the alternate process path to "container/cgroup.procs".
cgroup v2 sysfs value handling
plugins/in_podman_metrics/podman_metrics_data.c
Adds read_from_sysfs_or_max(), which maps "max" to 0 and reports read or parse failures as UINT64_MAX. cgroup v2 memory limits use this reader, and RSS parsing uses V2_STAT_KEY_RSS.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Mergeability Score: ⚪ Minimal · up to af0de

This change corrects cgroup v2 CPU, memory, limit, and network metric collection without a supplied indication of new correctness or deployment risk; no actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: cosmo0920

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: fixing multiple cgroup v2 issues in the Podman metrics plugin.
Linked Issues check ✅ Passed The changes implement all four objectives from issue #7769 and preserve cgroup v1 handling.
Out of Scope Changes check ✅ Passed All changes directly support cgroup v2 metric collection and the requirements in issue #7769.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugins/in_podman_metrics/podman_metrics.c (1)

122-123: Avoid hard-coded terminator index for "unknown".

Using a literal index is brittle; derive it from the string length for safer maintenance.

♻️ Suggested refactor
-                        strncpy(image_name, "unknown", IMAGE_NAME_SIZE - 1);
-                        image_name[7] = '\0';
+                        strncpy(image_name, "unknown", IMAGE_NAME_SIZE - 1);
+                        image_name[sizeof("unknown") - 1] = '\0';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/in_podman_metrics/podman_metrics.c` around lines 122 - 123, The code
in podman_metrics.c sets image_name to "unknown" then hard-codes image_name[7] =
'\0'; which is brittle; in the block that assigns image_name (use the same spot
that calls strncpy(image_name, "unknown", IMAGE_NAME_SIZE - 1)), replace the
fixed index with a derived terminator using the actual string length (e.g.,
size_t n = strlen("unknown"); if (n >= IMAGE_NAME_SIZE) n = IMAGE_NAME_SIZE - 1;
image_name[n] = '\0') or use a bounded formatting function like snprintf to
write and terminate safely; update the logic around image_name, IMAGE_NAME_SIZE,
and the strncpy call accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/in_podman_metrics/podman_metrics_data.c`:
- Around line 372-387: The function read_from_sysfs_or_max currently ignores
fgets() failures/empty reads; update it to explicitly handle fgets returning
NULL by checking feof()/ferror(), calling fclose(fp), logging a warning via
flb_plg_warn (include path and reason e.g., strerror(errno) or mention empty
file), and returning UINT64_MAX; keep the existing cgroup v2 "max" handling and
successful-read path intact and reference buf, fp, path, flb_plg_warn, and
flb_plg_debug to locate the change.

---

Nitpick comments:
In `@plugins/in_podman_metrics/podman_metrics.c`:
- Around line 122-123: The code in podman_metrics.c sets image_name to "unknown"
then hard-codes image_name[7] = '\0'; which is brittle; in the block that
assigns image_name (use the same spot that calls strncpy(image_name, "unknown",
IMAGE_NAME_SIZE - 1)), replace the fixed index with a derived terminator using
the actual string length (e.g., size_t n = strlen("unknown"); if (n >=
IMAGE_NAME_SIZE) n = IMAGE_NAME_SIZE - 1; image_name[n] = '\0') or use a bounded
formatting function like snprintf to write and terminate safely; update the
logic around image_name, IMAGE_NAME_SIZE, and the strncpy call accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 11fd1877-05ab-4428-b4d0-5c5d7c213869

📥 Commits

Reviewing files that changed from the base of the PR and between 6c742a1 and 34b3477.

📒 Files selected for processing (3)
  • plugins/in_podman_metrics/podman_metrics.c
  • plugins/in_podman_metrics/podman_metrics_config.h
  • plugins/in_podman_metrics/podman_metrics_data.c

Comment thread plugins/in_podman_metrics/podman_metrics_data.c Outdated
@stondo

stondo commented May 12, 2026

Copy link
Copy Markdown
Contributor Author

Addressed both CodeRabbit review comments in commit a35a87d:

  • Actionable (podman_metrics_data.c): refactored read_from_sysfs_or_max() to guard-clause pattern — returns UINT64_MAX immediately when fgets() returns NULL, with a warning log including the path.
  • Nitpick (podman_metrics.c): replaced hard-coded image_name[7] = '\0' with image_name[sizeof("unknown") - 1] = '\0' so the index is derived from the string rather than being a magic literal.

@cosmo0920

Copy link
Copy Markdown
Contributor

The last comment does not have Signed-off line so we need to add it at first.

@stondo
stondo force-pushed the fix/podman-metrics-cgroupv2 branch from a35a87d to acaa540 Compare May 18, 2026 09:15
stondo added 2 commits August 13, 2026 00:09
Fix five bugs in the podman_metrics input plugin:

1. CPU counter division: cgroup v2 cpu.stat reports usage in
microseconds, not nanoseconds like cgroup v1 cpuacct.
Use the correct divisor (1e6) when converting to seconds.

2. RSS memory key: cgroup v2 memory.stat does not have a "rss"
field. The equivalent metric is "anon" (anonymous memory).
Add V2_STAT_KEY_RSS and use it in the v2 collection path.

3. memory.max "max" keyword: cgroup v2 uses the literal string
"max" in memory.max when the memory limit is unlimited.
read_from_file() fails to parse this with fscanf("%lu"),
causing spurious warnings. Add read_from_sysfs_or_max()
helper that returns 0 for "max" (unlimited).

4. PID alt path typo: V2_SYSFS_FILE_PIDS_ALT was set to
"containers/cgroup.procs" (plural) but the actual cgroup v2
subdirectory is "container/cgroup.procs" (singular). This
caused PID lookup to fail for all containers, which in turn
prevented all network metrics from being collected.

5. Image name NULL safety: when parsing container metadata JSON,
strstr() for the closing quote of the image name field can
return NULL if the metadata is malformed or truncated. The
result was used directly in pointer arithmetic and strncpy(),
causing undefined behaviour and potential crashes. Add a NULL
guard that falls back to image="unknown" when parsing fails.

GitHub issue fluent#7769.

Signed-off-by: stondo <stondo@gmail.com>
- read_from_sysfs_or_max: refactor to guard-clause pattern; return
  UINT64_MAX immediately when fgets() returns NULL instead of silently
  falling through and returning whatever value was last read.
- collect_container_data: use sizeof("unknown") - 1 instead of the
  magic literal 7 when NUL-terminating image_name after strncpy so the
  index stays correct if the fallback string ever changes.

Signed-off-by: Stefano Tondo <stondo@gmail.com>
@stondo
stondo force-pushed the fix/podman-metrics-cgroupv2 branch from acaa540 to af0de5b Compare August 12, 2026 22:11
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@stondo

stondo commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current master, conflicts resolved (V2_SYSFS_FILE_IO_STAT from #11986 now sits alongside the V2_SYSFS_FILE_PIDS_ALT typo fix). Both commits carry Signed-off-by.

Keep the new container/cgroup.procs fallback from the rebase, but also try the older containers/cgroup.procs layout still used by the runtime fixture and some Podman trees. This restores PID discovery for the cgroup-v2 test path without regressing the typo fix.

Signed-off-by: Stefano Tondo <stondo@gmail.com>
@stondo

stondo commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up after the latest push (601a3c40f):

The original regression from the rebase is fixed. The previously failing Ubuntu unit-test jobs are now green on the current head, including the in_podman_metrics runtime path that was failing in the cgroup-v2 fixture.

The fix keeps the corrected container/cgroup.procs lookup, but also restores compatibility with the older containers/cgroup.procs layout still used by the runtime fixture and some Podman trees, so PID discovery works in both cases.

The remaining red jobs do not look specific to this PR:

  • macOS TSan is failing in in_simple_systems.c:565 with Check records->num_records >= 20... failed
  • Windows 32-bit packaging is failing with CPack Error: Cannot find NSIS compiler makensis

So the Linux regression introduced by the rebase appears resolved on the current branch head.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Podman Metrics for cgroup v2

2 participants