Skip to content

Latest commit

 

History

History
282 lines (215 loc) · 13.7 KB

CONTRIBUTING.md

File metadata and controls

282 lines (215 loc) · 13.7 KB

Contributing

Welcome to OpenTelemetry Java repository!

Before you start - see OpenTelemetry general contributing requirements and recommendations.

If you want to add new features or change behavior, please make sure your changes follow the OpenTelemetry Specification. Otherwise, file an issue or submit a pull request (PR) to the specification repo first.

Make sure to review the projects license and sign the CNCF CLA. A signed CLA will be enforced by an automatic check once you submit a PR, but you can also sign it after opening your PR.

Requirements

Java 17 or higher is required to build the projects in this repository. The built artifacts can be used on Java 8 or higher.

Building opentelemetry-java

Continuous integration builds the project, runs the tests, and runs multiple types of static analysis.

  1. Note: Currently, to run the full suite of tests, you'll need to be running a docker daemon. The tests that require docker are disabled if docker is not present. If you wish to run them, you must run a local docker daemon.

  2. Clone the repository

    git clone https://github.com/open-telemetry/opentelemetry-java.git

  3. Run the following commands to build, run tests and most static analysis, and check formatting:

    ./gradlew build

  4. If you are a Windows user, use the alternate command mentioned below to run tests and check formatting:

    gradlew.bat

Checks

Before submitting a PR, you should make sure the style checks and unit tests pass. You can run these with the check task.

$ ./gradlew check

Note: this gradle task will potentially generate changes to files in the docs/apidiffs/current_vs_latest directory. Please make sure to include any changes to these files in your pull request (i.e. add those files to your commits in the PR).

PR Review

After you submit a PR, it will be reviewed by the project maintainers and approvers. Not all maintainers need to review a particular PR, but merging to the base branch is authorized to restricted members (administrators).

Draft PRs

Draft PRs are welcome, especially when exploring new ideas or experimenting with a hypothesis. However, draft PRs may not receive the same degree of attention, feedback, or scrutiny unless requested directly. In order to help keep the PR backlog maintainable, drafts older than 6 months will be closed by the project maintainers. This should not be interpreted as a rejection. Closed PRs may be reopened by the author when time or interest allows.

Project Scope

opentelemetry-java is one of several repositories which comprise the OpenTelemetry Java ecosystem, and contains the core components upon which instrumentation and extensions are built. In order to prevent sprawl and maintain a high level of quality, we limit this repository's scope to components which implement concepts defined in the opentelemetry-specification, with a few exceptions / comments:

  • The API incubator and SDK incubator contain prototypes which have been discussed in the specification or oteps and have a reasonable chance of becoming part of the specification, subject to maintainers' discretion.
  • Components like the Kotlin Extension are included which are required for the API / SDK to function in key areas of the Java ecosystem. Inclusion is subject to maintainers' discretion.
  • As a general rule, components which implement semantic conventions belong elsewhere.

Other repositories in the OpenTelemetry Java ecosystem include:

Style guideline

We follow the Google Java Style Guide. Our build will fail if source code is not formatted according to that style. To fix any style failures the above checks show, automatically apply the formatting with:

$ ./gradlew spotlessApply

To verify code style manually run the following command, which uses google-java-format library:

./gradlew spotlessCheck

Best practices that we follow

  • This project uses semantic versioning. Except for major versions, a user should be able to update their dependency version on this project and have nothing break. This means we do not make breaking changes to the API (e.g., remove a public method) or to the ABI ( e.g., change return type from void to non-void).
  • Avoid exposing publicly any class/method/variable that don't need to be public.
  • By default, all arguments/members are treated as non-null. Every argument/member that can be null must be annotated with @Nullable.
  • The project aims to provide a consistent experience across all the public APIs. It is important to ensure consistency (same look and feel) across different public packages.
  • Use final for public classes everywhere it is possible, this ensures that these classes cannot be extended when the API does not intend to offer that functionality.
  • In general, we use the following ordering of class members:
    • Static fields (final before non-final)
    • Instance fields (final before non-final)
    • Constructors
      • In static utility classes (where all members are static), the private constructor (used to prevent construction) should be ordered after methods instead of before methods.
    • Methods
      • If methods call each other, it's nice if the calling method is ordered (somewhere) above the method that it calls. So, for one example, a private method would be ordered (somewhere) below the non-private methods that use it.
    • Nested classes
  • Adding toString() overrides on classes is encouraged, but we only use toString() to provide debugging assistance. The implementations of all toString() methods should be considered to be unstable unless explicitly documented otherwise.
  • Avoid synchronizing using a class's intrinsic lock. Instead, synchronize on a dedicated lock object. E.g:
    private final Object lock = new Object();
    
    public void doSomething() {
      synchronized (lock) { ... }
    }
  • Don't use gradle test fixtures ( i.e. java-test-fixtures plugin) to reuse code for internal testing. The test fixtures plugin has side effects where test dependencies are added to the pom.xml and publishes an extra *-test-fixtures.jar artifact which is unnecessary for internal testing. Instead, create a new *:testing-internal module and omit the otel.java-conventions. For example, see /exporters/otlp/testing-internal.

If you notice any practice being applied in the project consistently that isn't listed here, please consider a pull request to add it.

Pre-commit hook

To completely delegate code style formatting to the machine, you can add git pre-commit hook. We provide an example script in buildscripts/pre-commit file. Just copy or symlink it into .git/hooks folder.

Editorconfig

As additional convenience for IntelliJ Idea users, we provide .editorconfig file. Idea will automatically use it to adjust its code formatting settings. It does not support all required rules, so you still have to run spotlessApply from time to time.

Javadoc

  • All public classes and their public and protected methods MUST have javadoc. It MUST be complete ( all params documented etc.) Everything else (package-protected classes, private) MAY have javadoc, at the code writer's whim. It does not have to be complete, and reviewers are not allowed to require or disallow it.
  • Each API element should have a @since tag specifying the minor version when it was released (or the next minor version).
  • There MUST be NO javadoc errors.

See section 7.3.1 in the guide for exceptions to the Javadoc requirement.

  • Reviewers may request documentation for any element that doesn't require Javadoc, though the style of documentation is up to the author.
  • Try to do the least amount of change when modifying existing documentation. Don't change the style unless you have a good reason.
  • We do not use @author tags in our javadoc.
  • Our javadoc is available via [ javadoc.io}(https://javadoc.io/doc/io.opentelemetry/opentelemetry-api)

SDK Configuration Documentation

All changes to the SDK configuration options or autoconfigure module should be documented on opentelemetry.io.

AutoValue

  • Use AutoValue, when possible, for any new value classes. Remember to add package-private constructors to all AutoValue classes to prevent classes in other packages from extending them.

Unit Tests

  • Unit tests target Java 8, so language features such as lambda and streams can be used in tests.

Specific tasks

Updating the Snapshot build number

The overall version number for opentelemetry-java is determined from git tags, and not fixed in any file.

This means it will not update, even if you git pull from the repo tip. It will still produce a set of libraries with the old version number.

To update it, you must fetch the tags, via git fetch --all --tags - which should work, even if you have forked the repo, as long as the trunk repo is set as an upstream remote.

Composing builds

Beware that this section is only meant for developers of opentelemetry-java, or closely related projects. The steps described here could change at any time and what you do for one version (commit) may break with the next one already.

Gradle provides a feature called "composite builds" that allows to replace some normally externally provided dependencies with a project that is built (included) in the same Gradle invocation. This can be useful to quickly test a new feature or bug fix you are developing in opentelemetry-java with the examples or the app or instrumentation library where you need the feature or run into the bug. Unfortunately, opentelemetry-java does not work out of the box with this feature because Gradle is unable to map the project names to the customized artifact coordinates (see e.g. gradle/gradle#18291 and related issues. However, gradle supports manually declaring the mapping between ("substitution of") artifact coordinates and project names. To ease this tedious task, opentelemetry-java provides a gradle task :generateBuildSubstitutions that generates a code snippet with these substitutions in kts (Kotlin Script) format.

Example usage could be as follows:

  1. Run ./gradlew generateBuildSubstitutions

  2. Two files named build/substitutions.gradle.kts are generated in the bom and bom-alpha project's directory, containing substitutions for the stable and alpha projects respectively.

  3. Copy & paste the content of these files to a new settings.gradle.kts or the one where you want to include the opentelemetry build into, so that it contains something like the following:

    includeBuild("PATH/TO/OPENTELEMETRY-JAVA/ROOT/DIRECTORY") {
      // Copy & paste following block from the generated substitutions.gradle.kts, *not* from here!
      dependencySubstitution {
        substitute(module("io.opentelemetry:opentelemetry-api")).using(project(":api:all"))
        substitute(module("io.opentelemetry:opentelemetry-sdk")).using(project(":sdk:all"))
        // ...
      }
    }

    Please confirm whether the local opentelemetry-java version is consistent with the opentelemetry-java version declared in the project that relies on opentelemetry-java. If it is inconsistent, dependencySubstitution may not take effect.

    See the Gradle documentation for more information.

  4. If you now build your project, it will use the included build to supply the opentelemetry-java artifacts, ignoring any version declarations. Use the prefix :DIRECTORY: to refer to tasks/projects within the included build, where DIRECTORY is the name of the directory in the included build (only the part after the last /).

  5. Here are some issues and solutions (discussions/6551) you may encounter that may be helpful to you.

Updating the OTLP protobufs

OTLP protobuf Java bindings are published via the opentelemetry-proto-java repository. This project does not use the java bindings, but does use the .proto files that are published in the binding jar by that project.

To update the OTLP protobuf version, first release a new version of the java bindings then simply update the dependency version that this project has on that jar.