Contribution guidelines

Thank you for investing your time and considering contributing to Retis! :tada:

This guide documents the process to get changes merged into this project, what one should expect, as well as prerequisites for pull-requests and patches to be considered acceptable.

Reporting bugs

Following the guidelines will help the community understand bug reports, which in turn will help in reproducing, triaging and fixing those bugs.

Before submitting the report

  1. Check for similar opened or closed issues. If a similar issue is still open, please add a comment there.
  2. Check the version used when the bug was triggered. If it was not the latest, please reproduce with it.

Submitting a good bug report

  1. Use a clear, concise and descriptive title.
  2. Include the output of retis --version in the description.
  3. Describe how to reproduce the bug, in clear exact steps, with examples. The community should not have to guess extra steps, configuration, prerequisites and spend a lot of time gathering this information to work on fixing a bug.
  4. How reliable are those steps to reproduce the issue?
  5. Describe the outcome of those steps.
  6. Then describe what would have been expected and why.
  7. If it is performance-related, include numbers.

Following-up on the report

  • It's OK to ping once or twice.
  • But give time to the community to reproduce and come up with a solution.
  • Also note we all have limited time and prioritize things.

Suggesting new features

Features requirements vary depending on users, use cases, priorities, etc. But expressing an interest is valuable as it can help prioritize things and shape the actual behavior.

Before suggesting a new feature

  1. Check if the feature isn't already available. See the tool help.
  2. Check it is not already being planned by looking at the different milestones and issues. If a matching issue is found, please comment on it to express an interest and make suggestions.

Adding an issue to request a new feature

  1. Use a clear, concise and descriptive title.
  2. Describe the environment on which the feature would be used and provide value.
  3. Provide a detailed explanation of what you'd like to be implemented, the expected output and behavior.
  4. If applicable, explain what the current behavior is lacking and how different you'd like it to be.
  5. Understand we have limited time and do prioritize things. In this regard, external contributions for new features are highly recommended and can have a great impact on choosing the direction of the project.

Code contribution

Guidelines

  1. Follow the coding style.
  2. Document functions, structures (including members), enums, ..., and the code itself. You can look at the existing code to understand what level of documentation we expect.
  3. Add unit tests.
  4. Base new work on top of the main branch.
  5. Use conscious language. Sometimes the information to collect (eg. in the kernel) is not converted yet or is part of a stable API; we can still use a better word in Retis. A good example is the Linux nf_conn->master object in the ct collector: we expose it as the "parent".

Coding style

We strictly follow the Rust coding style as enforced by rustfmt and have a strong preference for the Linux kernel and particularly its networking flavor coding style for the BPF parts.

Events and Rust bindings

If you are introducing new events or modifying the content of existing ones, bindings must be refreshed. If you are introducing a new event type, you have to follow all the steps below, conversely, in the case you are adding one or more members to an existing, and already annotated data-structure, you can skip the first:

  1. Annotate the target type with __binding.
  2. Run make gen-bindings.
  3. Commit the generated files and include them in your pull-request.

While not strictly required, it is advisable to submit binding introductions or modifications in a separate patch to facilitate the review process.

Rust code is generated by the means of bindgen, and this means you need to install it in order to complete the process. For minor modifications, it is strongly recommended to use the current version. The current version can be found in the top comment of one of the headers under the directory bindings.

When updating the version of bindgen, instead, the current stable has to be used. It is also preferable that this kind of pull-request does not contain any other logical change other than the version bump. Installing a specific version of bindgen can be done with cargo install bindgen-cli@<VERSION>.

Lastly, gen-bindings target also requires python bindings for Clang and its dependencies installed (i.e. libclang). You may install the Python bindings for Clang using your system's package manager or any other preferred installation method. For example, on Fedora, you can simply use dnf -y install python3-clang.

Backward compatibility

Retis offers some compatibility guarantees as described in the compatibility page. Make sure those guarantees are met.

As part of this, backward compatibility of generated events at collection time should work. This is done in retis-events/src/compat/compat.rs. Make sure to do the relevant changes in there.

Opening a pull-request

  1. Before opening the pull-request, test the changes. Yes, even for those simple one-liner last minute changes.
  2. Check the following commands do not return an error:
  3. cargo fmt --check
  4. cargo clippy -- -D warnings
  5. make test V=1, or to include runtime tests, CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER=sudo CARGO_CMD_OPTS="--features=test_cap_bpf" make test V=1
  6. make pytest V=1
  7. Make sure commits are signed off.
  8. Use a clear, concise and descriptive title.
  9. If the pull-request is linked to an issue, or based on top of another pull-request; reference those.
  10. Describe the environment on which the feature is used and provide value.
  11. Provide a detailed explanation of why the feature was added, how it was done and what is the expected output and behavior.
  12. If applicable, provide a step-by-step guide on how to test the feature.
  13. For pull-requests demonstrating a change to start a discussion, please add "[RFC]" in the pull-request title. Once in a state ready to be formally reviewed for inclusion, remove it.

Following-up on the pull-request

  1. As new versions of the pull-request are pushed, make sure to mark applicable conversations as resolved.
  2. If the pull-request has a conflict and cannot be merged, please rebase on the latest main. This can happen at any time, e.g. when other pull-requests are being merged.

Code coverage

Considering the importance of tests, it is highly recommended to introduce new tests aimed at covering as much code as possible. To locally assess the amount of code covered by the tests, you need first to install the following:

$ cargo install cargo-llvm-cov
$ rustup component add llvm-tools-preview

After installation, you can execute make test COV=1 to obtain coverage statistics following the execution of all tests.

Note that if your default toolchain is not installed via rustup, you can set $CARGO_OPTS to specify your rustup-installed toolchain (i.e., use CARGO_OPTS=+nightly for the nightly version).

To report previously generated coverage statistics, you can issue the command make report-cov. The target behavior can be adjusted using the available options. For instance, to enhance readability, you can set CARGO_CMD_OPTS=--html and generate an HTML report instead. For further details on how the target behavior can be customized, run CARGO_CMD_OPTS=--help make report-cov.

Python bindings development

When changing python bindings, it can be useful to quickly build and install the current code into a virtual environment for testing. An easy way to do it is by using maturin:

$ python -m venv venv && source venv/bin/activate # jump into a virtual env (required)
$ pip install maturin
$ maturin develop -m retis-events/Cargo.toml -F python-lib
$ python
>>> import retis

Documentation preview

HTTP documentation is automatically generated for releases and the main branch. However, if you want to generate a local preview of the documentation, you can use MkDocs directly:

$ pip install -r docs/requirements.txt
$ mkdocs serve

Then point your browser to localhost:8000.