Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FreeBSD support #53

Merged
merged 4 commits into from
Oct 10, 2024
Merged

Add FreeBSD support #53

merged 4 commits into from
Oct 10, 2024

Conversation

AMDmi3
Copy link
Contributor

@AMDmi3 AMDmi3 commented Oct 9, 2024

Though FreeBSD does support procfs/linprocfs, these are not required to be mounted (and are commontly not), so use standard always available interfaces instead:

  • Take CPU time from getrusage(2)
  • Take max open files and max virtual memory size from getrlimit(2)
  • Take number of open files from /dev/fd (which is the same as /proc/self/fd on Linux)
  • Take remaining fields from kernel process structure retrieved from sysctl(3)

Note that this code may likely be reused for other BSD systems (OpenBSD, NetBSD) with minimal changes.

Example cargo test -- --nocapture output on my system:

rs-metrics-process% cargo test -- --nocapture
   Compiling metrics-process v2.1.0 (/home/amdmi3/projects/rs-metrics-process)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.21s
     Running unittests src/lib.rs (target/debug/deps/metrics_process-8fe640db94da7b0a)

running 1 test
[src/collector.rs:71:9] &m = Metrics {
    cpu_seconds_total: Some(
        0.632475,
    ),
    open_fds: Some(
        3,
    ),
    max_fds: Some(
        352665,
    ),
    virtual_memory_bytes: Some(
        19263488,
    ),
    virtual_memory_max_bytes: Some(
        0,
    ),
    resident_memory_bytes: Some(
        3719168,
    ),
    start_time_seconds: Some(
        1728493026,
    ),
    threads: Some(
        2,
    ),
}
test collector::tests::test_collect_internal_ok ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.63s

   Doc-tests metrics_process

running 7 tests
test src/lib.rs - Collector::describe (line 96) - compile ... ok
test src/../README.md - (line 69) - compile ... ok
test src/lib.rs - Collector::collect (line 168) - compile ... ok
test src/../README.md - (line 98) - compile ... ok
test src/lib.rs - Collector::prefix (line 67) ... ok
test src/lib.rs - Collector::new (line 82) ... ok
warning: use of deprecated method `metrics_process::Collector::prefix`: Use `Collector::new(prefix)`.
 --> src/lib.rs:61:38
  |
6 | let collector = Collector::default().prefix("my_prefix_");
  |                                      ^^^^^^
  |
  = note: `#[warn(deprecated)]` on by default

warning: 1 warning emitted

test src/lib.rs - Collector::prefix (line 58) ... ok

test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.11s

Notably, after ulimit -n 100 -v $((1024*1024)):

[src/collector.rs:71:9] &m = Metrics {
    cpu_seconds_total: Some(
        0.631953,
    ),
    open_fds: Some(
        3,
    ),
    max_fds: Some(
        100,
    ),
    virtual_memory_bytes: Some(
        19263488,
    ),
    virtual_memory_max_bytes: Some(
        1073741824,
    ),
    resident_memory_bytes: Some(
        3719168,
    ),
    start_time_seconds: Some(
        1728493170,
    ),
    threads: Some(
        2,
    ),
}

Summary by CodeRabbit

  • New Features

    • Introduced support for FreeBSD operating systems, enabling the collection of system metrics specific to FreeBSD.
    • Added functionality for collecting resource usage and process information on FreeBSD systems.
    • Updated documentation to reflect FreeBSD support, including a metrics availability table.
    • Added a new cross-platform testing job for FreeBSD in the GitHub Actions workflow.
  • Bug Fixes

    • Updated conditional checks to ensure proper error messaging for unsupported platforms.

Though FreeBSD does support procfs/linprocfs, these are not required
to be mounted (and are commontly not), so use standard always available
interfaces instead:

- Take CPU time from getrusage(2)
- Take max open files and max virtual memory size from getrlimit(2)
- Take number of open files from /dev/fd (which is the same as
  /proc/self/fd on Linux)
- Take remaining fields from kernel process structure retrieved from
  sysctl(3)

Note that this code may likely be reused for other BSD systems
(OpenBSD, NetBSD) with minimal changes.
Copy link

coderabbitai bot commented Oct 9, 2024

Walkthrough

The changes introduce support for the FreeBSD operating system in the metrics-process package. The Cargo.toml file is updated to include the libc crate as a dependency for FreeBSD. Conditional compilation is implemented in src/collector.rs to include FreeBSD-specific code and modify error handling for unsupported platforms. A new file, src/collector/freebsd.rs, is created, which defines functions for collecting system metrics using the FreeBSD libc library. The README.md is also updated to reflect this new support. Additionally, a new GitHub Actions job is added for cross-platform testing.

Changes

File Path Change Summary
Cargo.toml Added libc = "0.2.159" under [target.'cfg(target_os = "freebsd")'.dependencies].
src/collector.rs Updated conditional compilation to include FreeBSD; modified error handling for unsupported platforms; adjusted test configuration for FreeBSD.
src/collector/freebsd.rs Created new file with fn collect() -> Metrics and functions for collecting metrics on FreeBSD.
README.md Updated to reflect FreeBSD support; added metrics availability for FreeBSD in the metrics table.
.github/workflows/test.yml Added new job test-cross-platform-freebsd for testing on FreeBSD in GitHub Actions.

Poem

In fields of code, a rabbit hops,
With FreeBSD, the fun never stops!
Metrics gathered, oh what a sight,
In every byte, we find delight.
With libc's help, we leap and bound,
In the world of tech, joy is found! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🧹 Outside diff range and nitpick comments (5)
Cargo.toml (1)

45-47: LGTM! Consider using a caret requirement for the libc dependency.

The addition of the libc dependency for FreeBSD is correct and aligns well with the PR objectives. It's properly placed in the FreeBSD-specific target section and uses a recent version of the crate.

Consider using a caret requirement (^) for the libc dependency to allow for compatible updates:

[target.'cfg(target_os = "freebsd")'.dependencies]
-libc = "0.2.159"
+libc = "^0.2.159"

This change would allow for minor and patch updates within the 0.2.x series, which can include bug fixes and performance improvements while maintaining compatibility.

src/collector.rs (2)

11-16: LGTM: FreeBSD added to supported platforms list.

The update correctly includes FreeBSD in the list of supported platforms, ensuring that the compile error for unsupported platforms is not triggered for FreeBSD.

Consider alphabetizing the list of operating systems for better readability:

 not(any(
-    target_os = "macos",
-    target_os = "linux",
-    target_os = "windows",
-    target_os = "freebsd"
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "macos",
+    target_os = "windows"
 ))

61-66: LGTM: FreeBSD added to test configuration.

The update correctly includes FreeBSD in the list of operating systems for which the test_collect_internal_ok test should run, ensuring that the test will be compiled and executed on FreeBSD.

Consider alphabetizing the list of operating systems for consistency with the previous suggestion:

 #[cfg(any(
-    target_os = "macos",
-    target_os = "linux",
-    target_os = "windows",
-    target_os = "freebsd"
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "macos",
+    target_os = "windows"
 ))]
src/collector/freebsd.rs (2)

78-80: Nitpick: Rename variable limit_as to limit_nofile for clarity

In lines 78 to 80, the variable limit_as is used to store the result of getrlimit(libc::RLIMIT_NOFILE). To enhance readability and accurately reflect the resource, consider renaming limit_as to limit_nofile.

Apply this diff to rename the variable:

-if let Some(limit_as) = getrlimit(libc::RLIMIT_NOFILE) {
-    metrics.max_fds = Some(translate_rlim(limit_as.rlim_cur));
+if let Some(limit_nofile) = getrlimit(libc::RLIMIT_NOFILE) {
+    metrics.max_fds = Some(translate_rlim(limit_nofile.rlim_cur));
 }

94-94: Nitpick: Move use statement to the top-level scope

At line 94, the use std::convert::TryInto as _; statement is inside the collect function. For consistency and to adhere to Rust conventions, consider moving this use statement to the top of the file.

Apply this diff to relocate the use statement:

+use std::convert::TryInto as _;

 use super::Metrics;

 fn getrusage(who: libc::c_int) -> Option<libc::rusage> {
     // existing code
 }
 
-    use std::convert::TryInto as _;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between b8f5df2 and f423752.

📒 Files selected for processing (3)
  • Cargo.toml (1 hunks)
  • src/collector.rs (3 hunks)
  • src/collector/freebsd.rs (1 hunks)
🧰 Additional context used
🔇 Additional comments (9)
src/collector.rs (3)

4-4: LGTM: FreeBSD-specific conditional compilation attribute added correctly.

The addition of the FreeBSD-specific conditional compilation attribute is consistent with the existing structure for other operating systems and correctly specifies the path to the FreeBSD implementation file.


87-87: LGTM: FreeBSD excluded from dummy test configuration.

The addition of the FreeBSD-specific conditional compilation check correctly excludes FreeBSD from running the dummy test when the "dummy" feature is enabled. This is consistent with the existing structure for other operating systems.


Line range hint 1-103: Overall: FreeBSD support successfully implemented.

The changes to src/collector.rs consistently and correctly implement FreeBSD support across the file. The conditional compilation attributes, unsupported platform checks, and test configurations have been updated appropriately.

To ensure the FreeBSD-specific implementation is complete, please run the following verification script:

This script will help confirm that the FreeBSD-specific implementation file exists and contains the necessary collect() function.

✅ Verification successful

Line range hint 1-103: Overall: FreeBSD support successfully implemented.

The verification confirms that src/collector/freebsd.rs exists and contains the necessary collect() function. FreeBSD support in src/collector.rs has been correctly integrated and is functioning as intended.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify FreeBSD-specific implementation file exists and contains necessary functions.

# Test 1: Check if FreeBSD-specific implementation file exists
fd -t f "freebsd.rs" src/collector

# Test 2: Verify that the FreeBSD implementation file contains necessary functions
rg -t rust "fn collect\(\)" src/collector/freebsd.rs

Length of output: 144

src/collector/freebsd.rs (6)

25-31: Approved: translate_rlim function logic is correct

The translate_rlim function correctly translates rlim_t values, handling RLIM_INFINITY appropriately.


3-12: Approved: getrusage function implementation is safe and correct

The use of MaybeUninit and unsafe blocks in getrusage is appropriate and handles the initialization safely.


14-23: Approved: getrlimit function implementation is safe and correct

The getrlimit function correctly retrieves resource limits using safe patterns for unsafe code.


33-62: Approved: kinfo_getproc function correctly retrieves process information

The implementation of kinfo_getproc is sound, and references to external resources are helpful for future maintenance.


64-112: Approved: collect function accurately gathers system metrics

The collect function aggregates system metrics effectively, utilizing the helper functions defined. The use of unsafe blocks is justified and handled correctly.


107-109: Verify the accuracy of open file descriptors count

When counting open file descriptors using /dev/fd, ensure that the count accurately reflects the number of open files, excluding any special entries that may not represent actual file descriptors.

You can run the following script to list and count the actual file descriptors:

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

🧹 Outside diff range and nitpick comments (1)
README.md (1)

Line range hint 1-54: Consider additional documentation updates for FreeBSD support

While the changes accurately reflect the addition of FreeBSD support in the project description and metrics table, consider the following suggestions to further improve the documentation:

  1. Update the usage examples to mention FreeBSD compatibility, if applicable.
  2. Add a note in the Features section about FreeBSD support, possibly mentioning any specific considerations or requirements for FreeBSD users.

These additions would provide a more comprehensive overview of the new FreeBSD support for users.

🧰 Tools
🪛 LanguageTool

[style] ~41-~41: ‘Prior to’ might be wordy. Consider a shorter alternative.
Context: ...lient_golang]) provides. > [!NOTE] > > Prior to version 2.0.0, the `process_cpu_seconds...

(EN_WORDINESS_PREMIUM_PRIOR_TO)


[style] ~56-~56: Using many exclamation marks might seem excessive (in this case: 7 exclamation marks for a text that’s 4678 characters long)
Context: ...x | x | | x | > [!NOTE] > > If you only need to compile th...

(EN_EXCESSIVE_EXCLAMATION)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between f423752 and 3b11032.

📒 Files selected for processing (1)
  • README.md (2 hunks)
🧰 Additional context used
🔇 Additional comments (2)
README.md (2)

11-12: LGTM: FreeBSD support added to project description

The addition of FreeBSD to the list of supported platforms accurately reflects the new feature implemented in this PR.


44-54: Verify process_heap_bytes metric support

The addition of the FreeBSD column in the metrics table is great and accurately reflects the new support. However, could you please verify if the process_heap_bytes metric is indeed only supported on FreeBSD and not on other platforms? This seems unusual and might be worth double-checking.

README.md Outdated
[metrics] crate, supporting Linux, macOS, and Windows. The collector code is
manually rewritten in Rust from the official Prometheus client for Go
[metrics] crate, supporting Linux, macOS, Windows, and FreeBSD. The collector
code is manually rewritten in Rust from the official Prometheus client for Go
Copy link

Choose a reason for hiding this comment

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

Is this also the case for your FreeBSD addition? If not, maybe "Some collector code..."?

Copy link

codecov bot commented Oct 9, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 52.74%. Comparing base (b8f5df2) to head (5024f5e).
Report is 7 commits behind head on main.

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

HEAD has 1 upload less than BASE
Flag BASE (b8f5df2) HEAD (5024f5e)
3 2
Additional details and impacted files
@@             Coverage Diff             @@
##             main      #53       +/-   ##
===========================================
- Coverage   68.69%   52.74%   -15.95%     
===========================================
  Files           5        4        -1     
  Lines         214      237       +23     
===========================================
- Hits          147      125       -22     
- Misses         67      112       +45     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@lambdalisue
Copy link
Owner

@AMDmi3 Thanks a lot! I was wondering if we could use https://github.com/cross-platform-actions/action to ensure that metrics-process can at least build on FreeBSD. However, I don’t have any experience with FreeBSD, so I’m not sure which commands are needed to set up the test (build) environment. Could you add a GitHub Action for this? If it’s time-consuming, please let me know—I can merge this PR and wait for a separate one for the CI setup.

@lambdalisue lambdalisue mentioned this pull request Oct 9, 2024
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

🧹 Outside diff range and nitpick comments (1)
.github/workflows/test.yml (1)

107-127: LGTM! Good addition of FreeBSD testing.

The new test-cross-platform-freebsd job is well-structured and appropriately integrated into the existing workflow. It correctly uses cross-platform-actions to test on FreeBSD 14.1, which enhances the project's cross-platform compatibility testing.

Consider the following improvements:

  1. Make the job conditional to run only on specific branches or events to optimize CI resources:
test-cross-platform-freebsd:
  if: github.event_name == 'pull_request' || github.ref == 'refs/heads/main'
  runs-on: ubuntu-latest
  # ... rest of the job configuration
  1. Use a more specific cache key for FreeBSD testing:
- uses: actions/cache@v4
  with:
    path: |
      ~/.cargo/bin/
      ~/.cargo/registry/index/
      ~/.cargo/registry/cache/
      ~/.cargo/git/db/
      target/
    key: freebsd-14.1-cargo-${{ hashFiles('**/Cargo.lock') }}
  1. Pin package versions for better reproducibility:
run: |
  sudo pkg update && sudo pkg install -y rust-1.70.0 cmake-3.25.2 rust-bindgen-cli-0.65.1
  cargo test

These suggestions can improve the job's efficiency, caching, and reproducibility.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 526e99d and 5024f5e.

📒 Files selected for processing (1)
  • .github/workflows/test.yml (1 hunks)
🧰 Additional context used

@AMDmi3
Copy link
Contributor Author

AMDmi3 commented Oct 10, 2024

Done. See https://github.com/lambdalisue/rs-metrics-process/actions/runs/11264911567/job/31325788843?pr=53 for example run. The only preparation steps inside the VM would be to install rust and couple of transitive depends (cmake and rust-cbindgen-cli for aws-lc-sys).

@lambdalisue lambdalisue merged commit 0bd9266 into lambdalisue:main Oct 10, 2024
11 of 12 checks passed
@lambdalisue
Copy link
Owner

Thanks!

@AMDmi3
Copy link
Contributor Author

AMDmi3 commented Oct 10, 2024

  1. Use a more specific cache key for FreeBSD testing:

This makes sense

  1. Pin package versions for better reproducibility:

And this does not as FreeBSD is rolling release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants