We welcome your contributions to this project!
Please read the OpenTelemetry Contributor Guide for general information on how to contribute including signing the Contributor License Agreement, the Code of Conduct, and Community Expectations.
As with other OpenTelemetry clients, opentelemetry-ruby follows the opentelemetry-specification and the library guidelines.
OpenTelemetry is an evolving specification, one where the desires and use cases are clear, but the method to satisfy those use cases are not.
As such, Contributions should provide functionality and behavior that conforms to the specification, but the interface and structure are flexible.
It is preferable to have contributions follow the idioms of the language rather than conform to specific API names or argument patterns in the spec.
For a deeper discussion, see: open-telemetry/opentelemetry-specification#165
Everyone is welcome to contribute code via GitHub Pull Requests (PRs).
Fork the project on GitHub by clicking the Fork
button at the top of the
repository and clone your fork locally:
git clone git@github.com:YOUR_GITHUB_NAME/opentelemetry-ruby-contrib.git
or
git clone https://github.com/YOUR_GITHUB_NAME/opentelemetry-ruby-contrib.git
It can be helpful to add the open-telemetry/opentelemetry-ruby-contrib
repo as a
remote so you can track changes (we're adding as upstream
here):
git remote add upstream git@github.com:open-telemetry/opentelemetry-ruby-contrib.git
or
git remote add upstream https://github.com/open-telemetry/opentelemetry-ruby-contrib.git
For more detailed information on this workflow read the GitHub Workflow.
Setting up a running Ruby environment is outside the scope of this document.
This repository contains multiple Ruby gems:
- Various instrumentation gems located in subdirectories of
instrumentation
- Various resource detector gems located in subdirectories of
resources
opentelemetry-propagator-xray
located in thepropagator/xray
directoryopentelemetry-propagator-ottrace
located in thepropagator/ottrace
directory
Each of these gems has its configuration and tests.
For example, to test opentelemetry-instrumentation-action_pack
you would:
- Change directory to
instrumentation/action_pack
- Install the bundle with
bundle install
- Run the tests with
bundle exec rake
Note: Some test suites make use of Appraisal, a library for testing against different versions of dependencies. To run tests in suites that use Appraisal:
- Change directory to the instrumentation you'd like to test, ex:
instrumentation/action_pack
- Install the bundle with
bundle exec appraisal install
- Run the tests with
bundle exec appraisal rake test
We use Docker Compose to configure and build services used in development and
testing. This makes it easier to test against libraries that have dependencies,
such as the MySQL instrumentation gem. See docker-compose.yml
for specific
configuration details.
The services provided include:
app
- main container environment scoped to the/app
directory. Used primarily to build and tag theopentelemetry/opentelemetry-ruby-contrib:latest
image.x-instrumentation-<library_name>
- container environment scoped to a specific instrumentation library. Seedocker-compose.yml
for available services.
To test using Docker:
- Install Docker and Docker Compose for your operating system
- Get the latest code for the project
- Build the
opentelemetry/opentelemetry-ruby-contrib
imagedocker-compose build
- This makes the image available locally
- Install dependencies for the service you want to interact with
docker-compose run <service-name> bundle install
- Run the tests
docker-compose run <service-name> bundle exec rake test
You may wish to test your changes against an OpenTelemetry collector. To facilitate this, we provide configuration in docker-compose.yml
that should be sufficient.
By default, docker-compose launches all services, including the collector - docker-compose up
from the repository root is sufficient.
However, if you only wish to launch the collector, run docker-compose up jaeger otelcol
instead.
The collector listens on the default HTTP and GRPC ports (4318
and 4317
, respectively). You can visualize the traces from your work via the Jaeger trace UI by visiting localhost:16686
in your browser.
Some important tips to keep in mind when making your modifications.
git checkout -b my-feature-branch
Do not open a pull request from your own main branch, because we squash when merging, and that will cause you problems when you update your fork after merging.
All commits to the main repository should follow the
conventional commit standard. In a nutshell,
this means commit messages should begin with a semantic tag such as feat:
,
fix:
, docs:
, test:
, refactor:
, etc... Our release tooling uses these tags
to determine the semantics of your commit, such as how it affects semantic
versioning of the libraries, and to generate changelogs from commit
descriptions. If you are not familiar with conventional commits, please review
the specification. It is pretty simple.
If you open a pull request without a conventional commit message, your reviewer may ask you to amend the commit message.
We use rubocop to check style rules for this repository. Please run rubocop:
bundle install
bundle exec rake rubocop
to ensure that your code complies before opening a pull request.
We also use Yard to generate class documentation automatically. Among other things, this means:
- Methods and arguments should include the appropriate type annotations
- You can use markdown formatting in your documentation comments
You can generate the docs locally to see the results, by running:
bundle install
bundle exec rake yard
Please make sure that you review the Instrumentation author's guide before submitting a new instrumentation.
You'll need to create a Pull Request once you've finished your work. The Kubernetes GitHub Workflow document has a significant section on PRs.
Open the PR against the open-telemetry/opentelemetry-ruby-contrib
repository.
Please put [WIP]
in the title, or create it as a Draft
PR
if the PR is not ready for review.
An important implication of conventional commits
is that each commit message can describe at most one change. For example, if you
add a feature and fix a bug, the commit message cannot include both the feat:
and fix:
semantic tags, so you should split your change into multiple commits.
The same goes for pull requests. When we merge pull requests, we generally do so by squashing, so your pull request will result in a single commit in the repository, and in turn will correspond to exactly one entry in the changelog. Therefore, please scope each pull request to include a single change.
All PRs are automatically checked for a signed CLA. Your first PR fails this check if you haven't signed the CNCF CLA.
The failed check displays a link to details
which walks you through the
process. Don't worry it's painless!
PRs require a review from one or more of the code owners before merge. You'll probably get some feedback from these fine folks which helps to make the project that much better. Respond to the feedback and work with your reviewer(s) to resolve any issues.
The some of the things the code owners are looking for include:
- a signed CNCF CLA
- a passing CI build
- adherence to the principles and features outlined in the instrumentation author's guide
Reviewers are responsible for ensuring that each merged PR's commit message conforms to conventional commits. This may mean editing the commit message or the pull request title when you merge the pull request. Alternately, the reviewer may ask the pull request submitter to amend the commit message of their initial commit.
In addition, when a change is complex or a reviewer is unfamiliar with the code, the reviewer may seek additional reviews from people more familiar with the change before merging a PR.
This repository includes a set of tools for releasing gems. Only maintainers can perform releases.
Releases are normally performed using GitHub Actions.
- Wait for the CI checks on the latest main branch commit to succeed. The release scripts will not run unless the build is green.
- In the GitHub UI, go to the
Actions
tab, select theOpen release request
workflow, and run the workflow manually using the dropdown in the upper right.- Releases must be run from the main branch.
- If you leave the
Gems to release
field, blank, and the script will find all the gems that have had conventional-commit-tagged changes since their last release. Alternately, you can specify which gems to release by including their names, space-delimited, in this this field. You can optionally append:<version>
to any gem in the list to specify the version to release, or omit the version to let the script decide based on conventional commits. You can also use the special nameall
to force release of all gems (and evenall:<version>
to release all gems with the same version.)
- The workflow will analyze the conventional commit messages for the gems to release, and will open a release pull request. This pull request will include the appropriate changes to each gem's version constants, and an initial changelog entry for each gem. Note that it is possible to release more than one gem using a single release pull request.
- You may optionally make further modifications to the pull request branch. For example, the workflow will suggest a version number based on semver analysis of the conventional commit types, but you can choose to release a different version. You might also want to edit the changelog wording.
- To trigger the release(s), merge the release pull request. Note that the
label
release: pending
will have been applied to the pull request when it was opened; make sure the label is still there when you merge it. - The automated release script will run automatically, and will release the
gem(s) once CI has completed. This includes:
- For each gem, it will create a release tag and a GitHub release.
- It will build and push the gems to rubygems.
- If the releases succeed, the script will update the release pull
request with the results and change its label to
release: complete
. If something went wrong, the script will, if possible, report the error on the release pull request and change its label torelease: error
. It will also attempt to open an issue to alert you to the failure.
- If you change your mind and do not want to follow through on a release pull
request, just close it without merging. (The release scripts will then
automatically change its label to
release: aborted
for you.)
If a release fails, the release scripts will attempt to alert you by opening an issue and/or updating the release pull request. However, you may also need to review the release logs for the GitHub Actions workflows.
There are four GitHub actions workflows related to releases.
Open release request
is the main release entrypoint, and is used to open a release pull request. If something goes wrong with this process, the logs will appear in the workflow run.Force release
is generally used only to restart a failed release.[release hook] Update open releases
is run on pushes to the main branch, and pushes warnings to open release pull requests if you make modifications before triggering the release (i.e. because you might need to update the changelogs.)[release hook] Process release
is the main release automation script and is run when a pull request is closed. If it determines that a release pull request was merged, it kicks off the release process for the affected gems. It also updates the label on a closed release pull request. Finally, it deletes release branches when they are no longer being used. If something goes wrong with any of these processes, the logs will appear here.
If you've already merged a release pull request and want to retry a failed
release, you can use the Force release
workflow.
- If the release tag has already been created, delete it manually using the GitHub UI.
- In the GitHub UI, go to the
Actions
tab, select theForce release
workflow, and run it manually.- You must provide the gem name and version explicitly in the fields.
- The
Extra flags
field is useful for advanced cases. For example, if the GitHub release tag is already created and the gem already pushed to Rubygems, but the docs still need to be built, you can pass--only=docs
to perform only that one step. You can also force a release even if the build is not green or the version/changelog checks are failing, by passing--skip-checks
. For more details, install thetoys
gem and runtoys release perform --help
locally.
It is possible to run the release scripts locally if GitHub Actions is having
problems. You will need to install the toys
gem first, and you will need the
Rubygems API key for opentelemetry-ruby-contrib. These commands will succeed only if
you have write access to the repository.
To open a release pull request:
toys release request
Pass the --gems=
flag to provide a list of gems, or omit it to release all
changed gems.
To force-release, assuming the version and changelog are already modified:
toys release perform --rubygems-api-key=$API_KEY $GEM_NAME $GEM_VERSION
Pass --help
to either command for details on the options.
The release configuration is defined in the .toys/.data/releases.yml
file.
Gems must be listed in this file to be supported by the release process.
To add a gem, add an appropriate entry under the gems:
section. The name:
and directory:
fields are generally required, as is version_constant:
.
Some gems will also need to provide version_rb_path:
if the file path does
not correspond exactly to the gem name.
For releases to succeed, new gems MUST include the following:
- The above configuration entry.
- The
*.gemspec
file, with the name matching the gem name. - A
version.rb
file in the standard location, or in a location listed in the configuration. - A
CHANGELOG.md
file. - A
yard
rake task.
This repository uses Dependabot to keep dependencies up to date, however there shared development dependencies are often scattered across multiple gems. Dependabot does not currently support the ability to group dependencies for gems in multiple subdirectories, so we use a custom script to bulk update dependencies across all gems.
Note: This script uses a version of sed that isn't available on MacOS bash. You'll need to use an ubuntu-linux machine to execute it. One way to accomplish this is to run docker-compose run app
and execute the script within the container.
E.g. if you want to update Rubocop to version 1.56.1, you would run:
$> bin/update-dependencies rubocop 1.56.1
Review your changes and commit
Press any key to continue
This will then run a bulk update on all of the gems in the repository, and then prompt you to review the changes and stage them for a commit:
diff --git a/propagator/ottrace/opentelemetry-propagator-ottrace.gemspec b/propagator/ottrace/opentelemetry-propagator-ottrace.gemspec
index 42c5ecba..74fcc743 100644
--- a/propagator/ottrace/opentelemetry-propagator-ottrace.gemspec
+++ b/propagator/ottrace/opentelemetry-propagator-ottrace.gemspec
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'bundler', '~> 2.4'
spec.add_development_dependency 'minitest', '~> 5.0'
spec.add_development_dependency 'rake', '~> 13.0'
- spec.add_development_dependency 'rubocop', '~> 1.50.0'
+ spec.add_development_dependency 'rubocop', '~> 1.56.1'
spec.add_development_dependency 'simplecov', '~> 0.22.0'
spec.add_development_dependency 'yard', '~> 0.9'
spec.add_development_dependency 'yard-doctest', '~> 0.1.6'
(1/1) Stage this hunk [y,n,q,a,d,e,?]? y
diff --git a/propagator/xray/opentelemetry-propagator-xray.gemspec b/propagator/xray/opentelemetry-propagator-xray.gemspec
index e29acbfc..85622d25 100644
--- a/propagator/xray/opentelemetry-propagator-xray.gemspec
+++ b/propagator/xray/opentelemetry-propagator-xray.gemspec
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'bundler', '~> 2.4'
spec.add_development_dependency 'minitest', '~> 5.0'
spec.add_development_dependency 'rake', '~> 13.0'
- spec.add_development_dependency 'rubocop', '~> 1.50.0'
+ spec.add_development_dependency 'rubocop', '~> 1.56.1'
spec.add_development_dependency 'simplecov', '~> 0.22.0'
spec.add_development_dependency 'yard', '~> 0.9'
spec.add_development_dependency 'yard-doctest', '~> 0.1.6'
(1/1) Stage this hunk [y,n,q,a,d,e,?]? y