From ee36ce4b51967a6caa4aa24f55e3fb02c80a1bc5 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sat, 23 Aug 2025 15:22:01 -0700 Subject: [PATCH 01/12] Add copilot review instructions --- .github/copilot-instructions.md | 30 ++++++ CONTRIBUTING.md | 89 +++++++--------- README.md | 23 +---- docs/style-guide.md | 173 ++++++++++++++++++++++++++++++++ 4 files changed, 240 insertions(+), 75 deletions(-) create mode 100644 .github/copilot-instructions.md create mode 100644 docs/style-guide.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..f5c985dd5 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,30 @@ +# Copilot Instructions for OpenTelemetry Java Contrib + +This repository provides observability instrumentation for Java applications. + +## Code Review Priorities + +### Style Guide Compliance + +**PRIORITY**: Verify that all code changes follow the [Style Guide](../docs/style-guide.md). Check: + +- Code formatting (auto-formatting, static imports, class organization) +- Java language conventions (`final` usage, `@Nullable` annotations, `Optional` usage) +- Performance constraints (hot path allocations) +- Implementation patterns (SPI registration, configuration conventions) +- Gradle conventions (Kotlin DSL, plugin usage, module naming) +- Documentation standards (README files, deprecation processes) + +### Critical Areas + +- **Public APIs**: Changes affect downstream users and require careful review +- **Performance**: Instrumentation must have minimal overhead +- **Thread Safety**: Ensure safe concurrent access patterns +- **Memory Management**: Prevent leaks and excessive allocations + +### Quality Standards + +- Proper error handling with appropriate logging levels +- OpenTelemetry specification and semantic convention compliance +- Resource cleanup and lifecycle management +- Comprehensive unit tests for new functionality diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6d8a6a806..04a50c300 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,82 +1,65 @@ # Contributing -Welcome to the OpenTelemetry Java Contrib Repository! +Welcome to the OpenTelemetry Java Contrib repository! ## Introduction -This repository focuses on providing tools and utilities for Java-based observability, such as remote JMX metric gathering and reporting. We’re excited to have you here! Whether you’re fixing a bug, adding a feature, or suggesting an idea, your contributions are invaluable. +This repository provides observability libraries and utilities for Java applications that complement +the [OpenTelemetry Java SDK](https://github.com/open-telemetry/opentelemetry-java) and +[OpenTelemetry Java Instrumentation](https://github.com/open-telemetry/opentelemetry-java-instrumentation) +projects. -Before submitting new features or changes to current functionality, it is recommended to first -[open an issue](https://github.com/open-telemetry/opentelemetry-java-contrib/issues/new) -and discuss your ideas or propose the changes you wish to make. - -Questions? Ask in the OpenTelemetry [java channel](https://cloud-native.slack.com/archives/C014L2KCTE3) +Before submitting new features or changes, please consider +[opening an issue](https://github.com/open-telemetry/opentelemetry-java-contrib/issues/new) first to +discuss your ideas. Pull requests for bug fixes are always welcome! -## Pre-requisites - -To work with this repository, ensure you have: - -### Tools: - -Java 17 or higher - -### Platform Notes: +## Building and Testing -macOS/Linux: Ensure JAVA_HOME is set correctly. +While most modules target Java 8, building this project requires Java 17 or higher. -## Workflow - -1. Fork the repository -2. Clone locally -3. Create a branch before working on an issue - -## Local Run/Build - -In order to build and test this whole repository you need JDK 11+. - -#### Snapshot builds - -For developers testing code changes before a release is complete, there are -snapshot builds of the `main` branch. They are available from -the Sonatype snapshot repository at `https://central.sonatype.com/repository/maven-snapshots/` -([browse](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/io/opentelemetry/contrib/)). - -#### Building from source - -Building using Java 11+: +To build the project: ```bash -$ java -version +./gradlew assemble ``` +To run the tests: + ```bash -$ ./gradlew assemble +./gradlew test ``` -## Testing +Some modules include integration tests that can be run with: ```bash -$ ./gradlew test +./gradlew integrationTest ``` -### Some modules have integration tests +## Snapshot Builds -``` -$ ./gradlew integrationTest -``` +Snapshot builds of the `main` branch are available from the Sonatype snapshot repository at: +`https://central.sonatype.com/repository/maven-snapshots/` +([browse](https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/io/opentelemetry/contrib/)). + +## Style Guide + +See [Style Guide](docs/style-guide.md). -Follow the Java Instrumentation [Style Guide](https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/contributing/style-guideline.md) from the opentelemetry-java-instrumentation repository. +## Pull Request Guidelines -Failure? Check logs for errors or mismatched dependencies. +When submitting a pull request, please ensure that you: -## Gradle conventions +- Clearly describe the change and its motivation +- Mention any breaking changes +- Include tests for new functionality +- Follow the [Style Guide](docs/style-guide.md) -- Use kotlin instead of groovy -- Plugin versions should be specified in `settings.gradle.kts`, not in individual modules -- All modules use `plugins { id("otel.java-conventions") }` +## Getting Help -## Further Help +If you need assistance or have questions: -Join [#otel-java](https://cloud-native.slack.com/archives/C014L2KCTE3) on OpenTelemetry Slack +- Post on the [#otel-java](https://cloud-native.slack.com/archives/C014L2KCTE3) Slack channel +- [Open an issue](https://github.com/open-telemetry/opentelemetry-java-contrib/issues/new/choose) in + this repository diff --git a/README.md b/README.md index c42ea7e27..29b2e01f2 100644 --- a/README.md +++ b/README.md @@ -48,30 +48,9 @@ On reaching stable status, the `otel.stable` value in `gradle.properties` should Note that currently all the libraries are released together with the version of this repo, so breaking changes (after stable status is reached) would bump the major version of all libraries together. This could get complicated so `stable` has a high bar. -## Getting Started - -```bash -# Apply formatting -$ ./gradlew spotlessApply - -# Build the complete project -$ ./gradlew build - -# Run integration tests -$ ./gradlew integrationTest - -# Clean artifacts -$ ./gradlew clean -``` - ## Contributing -The Java Contrib project was initially formed to provide methods of easy remote JMX metric gathering and reporting, -which is actively in development. If you have an idea for a similar use case in the metrics, traces, or logging -domain we would be very interested in supporting it. Please -[open an issue](https://github.com/open-telemetry/opentelemetry-java-contrib/issues/new/choose) to share your idea or -suggestion. PRs are always welcome and greatly appreciated, but for larger functional changes a pre-coding introduction -can be helpful to ensure this is the correct place and that active or conflicting efforts don't exist. +See [CONTRIBUTING.md](CONTRIBUTING.md). ### Maintainers diff --git a/docs/style-guide.md b/docs/style-guide.md new file mode 100644 index 000000000..8bf101218 --- /dev/null +++ b/docs/style-guide.md @@ -0,0 +1,173 @@ +# Style Guide + +This project follows the +[Google Java Style Guide](https://google.github.io/styleguide/javaguide.html). + +## Code Formatting + +### Auto-formatting + +The build will fail if source code is not formatted according to Google Java Style. + +Run the following command to reformat all files: + +```bash +./gradlew spotlessApply +``` + +For IntelliJ users, an `.editorconfig` file is provided that IntelliJ will automatically use to +adjust code formatting settings. However, it does not support all required rules, so you may still +need to run `./gradlew spotlessApply` periodically. + +### Static imports + +Consider statically importing the following commonly used methods and constants: + +- **Test methods** + - `io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions` (assertThat, satisfies, etc.) + - `org.assertj.core.api.Assertions.*` (assertThat, assertThatThrownBy, entry, etc.) + - `org.mockito.Mockito.*` (when, mock, verify, times, etc.) + - `org.mockito.ArgumentMatchers.*` (any, eq, anyLong, etc.) +- **Utility methods** + - `io.opentelemetry.api.common.AttributeKey.*` (stringKey, longKey, etc.) + - `java.util.Arrays.*` (asList, etc.) + - `java.util.Collections.*` (singletonList, emptyList, emptyMap, emptySet, etc.) + - `java.util.stream.Collectors.*` (toList, toMap, toSet, etc.) + - `java.util.Objects` (requireNonNull, etc.) + - `java.util.logging.Level.*` (FINE, INFO, WARNING, etc.) + - `java.nio.charset.StandardCharsets.*` (UTF_8, etc.) +- **Time unit constants** + - `java.util.concurrent.TimeUnit.*` (SECONDS, etc.) +- **OpenTelemetry semantic convention constants** + - All constants under `io.opentelemetry.semconv.**` + +### Class organization + +Prefer this order: + +- Static fields (final before non-final) +- Instance fields (final before non-final) +- Constructors +- Methods +- Nested classes + +**Method ordering**: Place calling methods above the methods they call. For example, place private +methods below the non-private methods that use them. + +**Static utility classes**: Place the private constructor (used to prevent instantiation) after all +methods. + +## Java Language Conventions + +### Package conventions + +Classes in `.internal` packages are not considered public API and may change without notice. These +packages contain implementation details that should not be used by external consumers. + +- Use `.internal` packages for implementation classes that need to be public within the module but + should not be used externally +- Try to avoid referencing `.internal` classes from other modules + +### `final` keyword usage + +Public API classes should be declared `final` where possible. + +Methods should only be declared `final` if they are in non-final public API classes. + +Fields should be declared `final` where possible. + +Method parameters and local variables should never be declared `final`. + +### `@Nullable` annotation usage + +**Note: This section is aspirational and may not reflect the current codebase.** + +Annotate all parameters and fields that can be `null` with `@Nullable` (specifically +`javax.annotation.Nullable`, which is included by the `otel.java-conventions` Gradle plugin as a +`compileOnly` dependency). + +`@NonNull` is unnecessary as it is the default. + +**Defensive programming**: Public APIs should still check for `null` parameters even if not +annotated with `@Nullable`. Internal APIs do not need these checks. + +**Enforcement**: Use the `otel.errorprone-conventions` Gradle plugin in all modules: + +```kotlin +plugins { + id("otel.errorprone-conventions") +} +``` + +### `Optional` usage + +Following the reasoning from +[Writing a Java library with better experience (slide 12)](https://speakerdeck.com/trustin/writing-a-java-library-with-better-experience?slide=12), +`java.util.Optional` usage is kept to a minimum. + +**Guidelines**: + +- `Optional` shouldn't appear in public API signatures +- Avoid `Optional` on the hot path (instrumentation code), unless the instrumented library uses it + +## Tooling conventions + +### AssertJ + +Prefer AssertJ assertions over JUnit assertions (assertEquals, assertTrue, etc.) for better error +messages. + +### AutoService + +Use the `@AutoService` annotation when implementing SPI interfaces. This automatically generates the +necessary `META-INF/services/` files at compile time, eliminating the need to manually create and +maintain service registration files. + +```java +@AutoService(AutoConfigurationCustomizerProvider.class) +public class MyCustomizerProvider implements AutoConfigurationCustomizerProvider { + // implementation +} +``` + +### Gradle + +- Use Kotlin instead of Groovy for build scripts +- Plugin versions should be specified in `settings.gradle.kts`, not in individual modules +- All modules should use `plugins { id("otel.java-conventions") }` +- Set module names with `otelJava.moduleName.set("io.opentelemetry.contrib.mymodule")` + +## Configuration + +- Use `otel.` prefix for all configuration property keys +- Read config via the `ConfigProperties` interface +- Provide sensible defaults and document all options +- Validate configuration early with clear error messages + +## Performance + +Avoid allocations on the hot path (instrumentation code) whenever possible. This includes `Iterator` +allocations from collections; note that `for (SomeType t : plainJavaArray)` does not allocate an +iterator object. + +Non-allocating Stream API usage on the hot path is acceptable but may not fit the surrounding code +style; this is a judgment call. Some Stream APIs make efficient allocation difficult (e.g., +`collect` with pre-sized sink data structures involves convoluted `Supplier` code, or lambdas passed +to `forEach` may be capturing/allocating lambdas). + +## Documentation + +### Component README files + +- Include a component owners section in each module's README +- Document configuration options with examples + +### Deprecation and breaking changes + +Breaking changes are allowed in unstable modules (published with `-alpha` version suffix). + +1. Mark APIs with `@Deprecated` and a removal timeline (there must be at least one release with the + API marked as deprecated before removing it) +2. Document the replacement in Javadoc with `@deprecated` tag +3. Note the migration path for breaking changes under a "Migration notes" section of CHANGELOG.md + (create this section at the top of the Unreleased section if not already present) From 2d183c384671a47d223b584b81fc03b8fb2a3000 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 24 Aug 2025 08:40:16 -0700 Subject: [PATCH 02/12] Add copilot coding agent setup steps --- .github/workflows/copilot-setup-steps.yml | 34 +++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/copilot-setup-steps.yml diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 000000000..bb9b2badb --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,34 @@ +# Custom setup steps for GitHub Copilot coding agent to speed up Copilot's work on coding tasks +name: "Copilot Setup Steps" + +on: + pull_request: + paths: + - .github/workflows/copilot-setup-steps.yml + push: + paths: + - .github/workflows/copilot-setup-steps.yml + workflow_dispatch: + +permissions: + contents: read + +jobs: + copilot-setup-steps: # Job name required by GitHub Copilot coding agent + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Set up JDK for running Gradle + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + with: + distribution: temurin + java-version: 17 + + - name: Set up gradle + uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + + - name: Build project and download dependencies + run: ./gradlew build -x test From b5f02e3c530c1aebfa31ecef57f14806b0cff9d0 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 24 Aug 2025 08:48:39 -0700 Subject: [PATCH 03/12] Convert JUnit assertions to AssertJ assertions --- .../storage/files/utils/FileStreamTest.java | 2 +- .../gcp/resource/GCPResourceProviderTest.java | 2 +- ...corderDiagnosticCommandConnectionTest.java | 36 ++--- .../jfr/connection/OpenDataUtilsTest.java | 4 +- .../RecordingConfigurationTest.java | 23 +-- .../jfr/connection/RecordingOptionsTest.java | 55 ++++---- .../contrib/jfr/connection/RecordingTest.java | 40 +++--- .../kafka/KafkaSpanExporterBuilderTest.java | 133 +++++++++--------- .../kafka/SpanDataDeserializerTest.java | 10 +- .../contrib/kafka/SpanDataSerializerTest.java | 19 +-- .../FilteringLogRecordProcessorTest.java | 8 +- .../InterceptableLogRecordExporterTest.java | 20 +-- .../InterceptableMetricExporterTest.java | 7 +- .../InterceptableSpanExporterTest.java | 18 +-- .../JettyServiceNameDetectorTest.java | 21 ++- 15 files changed, 194 insertions(+), 204 deletions(-) diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/utils/FileStreamTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/utils/FileStreamTest.java index 1d801db7b..c2ad06f28 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/utils/FileStreamTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/utils/FileStreamTest.java @@ -61,7 +61,7 @@ void truncateTop() throws IOException { // Truncate all available data stream.truncateTop(3); - assertThat(stream.size()).isEqualTo(0); + assertThat(stream).isEmpty(); assertThat(readString(temporaryFile)).isEqualTo(""); stream.close(); diff --git a/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java b/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java index 9b17b22d2..b0683994e 100644 --- a/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java +++ b/gcp-resources/src/test/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProviderTest.java @@ -52,7 +52,7 @@ import static io.opentelemetry.semconv.incubating.HostIncubatingAttributes.HOST_NAME; import static io.opentelemetry.semconv.incubating.HostIncubatingAttributes.HOST_TYPE; import static io.opentelemetry.semconv.incubating.K8sIncubatingAttributes.K8S_CLUSTER_NAME; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.Mockito.verify; import com.google.cloud.opentelemetry.detection.DetectedPlatform; diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/FlightRecorderDiagnosticCommandConnectionTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/FlightRecorderDiagnosticCommandConnectionTest.java index 8cf7f06e1..280c06909 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/FlightRecorderDiagnosticCommandConnectionTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/FlightRecorderDiagnosticCommandConnectionTest.java @@ -5,9 +5,9 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; @@ -33,32 +33,32 @@ void assertCommercialFeaturesUnlocked() throws Exception { @Test void assertCommercialFeaturesLockedThrows() throws Exception { - assertThrows( - JfrConnectionException.class, - () -> { - ObjectName objectName = mock(ObjectName.class); - MBeanServerConnection mBeanServerConnection = mockMbeanServer(objectName, "locked"); - FlightRecorderDiagnosticCommandConnection.assertCommercialFeaturesUnlocked( - mBeanServerConnection, objectName); - }); + assertThatThrownBy( + () -> { + ObjectName objectName = mock(ObjectName.class); + MBeanServerConnection mBeanServerConnection = mockMbeanServer(objectName, "locked"); + FlightRecorderDiagnosticCommandConnection.assertCommercialFeaturesUnlocked( + mBeanServerConnection, objectName); + }) + .isInstanceOf(JfrConnectionException.class); } @Test void closeRecording() throws Exception { - assertThrows(UnsupportedOperationException.class, () -> createconnection().closeRecording(1)); + assertThatThrownBy(() -> createconnection().closeRecording(1)) + .isInstanceOf(UnsupportedOperationException.class); } @Test void testGetStream() throws Exception { - assertThrows( - UnsupportedOperationException.class, - () -> createconnection().getStream(1L, null, null, 0L)); + assertThatThrownBy(() -> createconnection().getStream(1L, null, null, 0L)) + .isInstanceOf(UnsupportedOperationException.class); } @Test void testCloneRecording() throws Exception { - assertThrows( - UnsupportedOperationException.class, () -> createconnection().cloneRecording(1, false)); + assertThatThrownBy(() -> createconnection().cloneRecording(1, false)) + .isInstanceOf(UnsupportedOperationException.class); } @Test @@ -73,7 +73,7 @@ void startRecordingParsesIdCorrectly() throws Exception { long id = connection.startRecording( new RecordingOptions.Builder().build(), RecordingConfiguration.PROFILE_CONFIGURATION); - assertEquals(id, 99); + assertThat(id).isEqualTo(99); } @Test diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/OpenDataUtilsTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/OpenDataUtilsTest.java index 9059980c3..041232b54 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/OpenDataUtilsTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/OpenDataUtilsTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import java.lang.management.ManagementFactory; import java.util.HashMap; @@ -49,6 +49,6 @@ void makeOpenData() throws Exception { mBeanServerConnection.invoke( objectInstance.getObjectName(), "getRecordingSettings", args, argTypes); - assertEquals(expected, actual); + assertThat(actual).isEqualTo(expected); } } diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingConfigurationTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingConfigurationTest.java index d34bb3f45..091a6ca5f 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingConfigurationTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingConfigurationTest.java @@ -5,10 +5,9 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.fail; import java.io.IOException; import java.nio.file.Files; @@ -44,18 +43,20 @@ void tearDown() { @Test void nullConfigThrows() { - assertThrows(IllegalArgumentException.class, () -> new JfcFileConfiguration(null)); + assertThatThrownBy(() -> new JfcFileConfiguration(null)) + .isInstanceOf(IllegalArgumentException.class); } @Test void brokenJfcConfigFileThrowsError() { - assertThrows(RuntimeMBeanException.class, () -> executeRecording("brokenJfcFile.jfc")); + assertThatThrownBy(() -> executeRecording("brokenJfcFile.jfc")) + .isInstanceOf(RuntimeMBeanException.class); } @Test void jfcFileFromInputStreamCanBeRead() { IItemCollection recordingContent = executeRecording("sampleJfcFile.jfc"); - assertTrue(containsEvent(recordingContent, "jdk.ThreadAllocationStatistics")); + assertThat(containsEvent(recordingContent, "jdk.ThreadAllocationStatistics")).isTrue(); } @Test @@ -68,9 +69,9 @@ void mapConfiguration() { RecordingConfiguration recordingConfiguration = new MapConfiguration(recordingConfigAsMap); IItemCollection recordingContent = excecuteRecordingWithConfig(recordingConfiguration); - assertNotNull(recordingContent, "excecuteRecordingWithConfig returned null"); - assertTrue(containsEvent(recordingContent, "jdk.ObjectAllocationInNewTLAB")); - assertTrue(containsEvent(recordingContent, "jdk.ObjectAllocationOutsideTLAB")); + assertThat(recordingContent).isNotNull(); + assertThat(containsEvent(recordingContent, "jdk.ObjectAllocationInNewTLAB")).isTrue(); + assertThat(containsEvent(recordingContent, "jdk.ObjectAllocationOutsideTLAB")).isTrue(); } private static boolean containsEvent(IItemCollection recordingContent, String eventName) { @@ -110,7 +111,7 @@ private IItemCollection excecuteRecordingWithConfig(RecordingConfiguration confi } recording.stop(); recording.dump(dumpFile.toString()); - assertTrue(Files.exists(dumpFile)); + assertThat(dumpFile).exists(); try { return JfrLoaderToolkit.loadEvents(dumpFile.toFile()); diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingOptionsTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingOptionsTest.java index 9291fb7f2..2ca0135ba 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingOptionsTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingOptionsTest.java @@ -5,8 +5,8 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.errorprone.annotations.Keep; import java.util.HashMap; @@ -33,14 +33,14 @@ private static Stream testGetName() { @MethodSource void testGetName(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().name(testValue).build(); - assertEquals(expected, opts.getName()); + assertThat(opts.getName()).isEqualTo(expected); } @Test void testGetNameDefault() { String expected = ""; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getName()); + assertThat(opts.getName()).isEqualTo(expected); } @Keep @@ -64,14 +64,14 @@ static Stream testGetMaxAge() { @MethodSource void testGetMaxAge(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().maxAge(testValue).build(); - assertEquals(expected, opts.getMaxAge()); + assertThat(opts.getMaxAge()).isEqualTo(expected); } @Test void testGetMaxAgeDefault() { String expected = "0"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getMaxAge()); + assertThat(opts.getMaxAge()).isEqualTo(expected); } @Keep @@ -91,9 +91,8 @@ private static Stream testGetMaxAgeNegative() { @ParameterizedTest @MethodSource void testGetMaxAgeNegative(String badValue) { - assertThrows( - IllegalArgumentException.class, - () -> new RecordingOptions.Builder().maxAge(badValue).build()); + assertThatThrownBy(() -> new RecordingOptions.Builder().maxAge(badValue).build()) + .isInstanceOf(IllegalArgumentException.class); } @Keep @@ -113,14 +112,14 @@ private static Stream testGetMaxSize() { @MethodSource void testGetMaxSize(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().maxSize(testValue).build(); - assertEquals(expected, opts.getMaxSize()); + assertThat(opts.getMaxSize()).isEqualTo(expected); } @Test void testGetMaxSizeDefault() { String expected = "0"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getMaxSize()); + assertThat(opts.getMaxSize()).isEqualTo(expected); } @Keep @@ -135,30 +134,29 @@ private static Stream testGetMaxSizeNegative() { @ParameterizedTest @MethodSource void testGetMaxSizeNegative(String badValue) { - assertThrows( - IllegalArgumentException.class, - () -> new RecordingOptions.Builder().maxSize(badValue).build()); + assertThatThrownBy(() -> new RecordingOptions.Builder().maxSize(badValue).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test void testGetDumpOnExit() { String expected = "true"; RecordingOptions opts = new RecordingOptions.Builder().dumpOnExit(expected).build(); - assertEquals(expected, opts.getDumpOnExit()); + assertThat(opts.getDumpOnExit()).isEqualTo(expected); } @Test void testGetDumpOnExitDefault() { String expected = "false"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getDumpOnExit()); + assertThat(opts.getDumpOnExit()).isEqualTo(expected); } @Test void testGetDumpOnExitBadValue() { String expected = "false"; RecordingOptions opts = new RecordingOptions.Builder().dumpOnExit("BAD_VALUE").build(); - assertEquals(expected, opts.getDumpOnExit()); + assertThat(opts.getDumpOnExit()).isEqualTo(expected); } @Keep @@ -175,35 +173,35 @@ private static Stream testGetDestination() { @MethodSource void testGetDestination(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().destination(testValue).build(); - assertEquals(expected, opts.getDestination()); + assertThat(opts.getDestination()).isEqualTo(expected); } @Test void testGetDestinationDefault() { String expected = ""; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getDestination()); + assertThat(opts.getDestination()).isEqualTo(expected); } @Test void testGetDisk() { String expected = "true"; RecordingOptions opts = new RecordingOptions.Builder().disk(expected).build(); - assertEquals(expected, opts.getDisk()); + assertThat(opts.getDisk()).isEqualTo(expected); } @Test void testGetDiskDefault() { String expected = "false"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getDisk()); + assertThat(opts.getDisk()).isEqualTo(expected); } @Test void testGetDiskBadValue() { String expected = "false"; RecordingOptions opts = new RecordingOptions.Builder().disk("BAD_VALUE").build(); - assertEquals(expected, opts.getDisk()); + assertThat(opts.getDisk()).isEqualTo(expected); } @Keep @@ -227,14 +225,14 @@ private static Stream testGetDuration() { @MethodSource void testGetDuration(String testValue, String expected) { RecordingOptions opts = new RecordingOptions.Builder().duration(testValue).build(); - assertEquals(expected, opts.getDuration()); + assertThat(opts.getDuration()).isEqualTo(expected); } @Test void testGetDurationDefault() { String expected = "0"; RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getDuration()); + assertThat(opts.getDuration()).isEqualTo(expected); } @Keep @@ -254,9 +252,8 @@ private static Stream testGetDurationNegative() { @ParameterizedTest @MethodSource void testGetDurationNegative(String badValue) { - assertThrows( - IllegalArgumentException.class, - () -> new RecordingOptions.Builder().duration(badValue).build()); + assertThatThrownBy(() -> new RecordingOptions.Builder().duration(badValue).build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -279,7 +276,7 @@ void testGetRecordingOptions() { .disk("true") .duration("120 s") .build(); - assertEquals(expected, opts.getRecordingOptions()); + assertThat(opts.getRecordingOptions()).isEqualTo(expected); } @Test @@ -289,6 +286,6 @@ void testGetRecordingOptionsDefaults() { // to insure consistent behaviour. expected.put("disk", "false"); RecordingOptions opts = new RecordingOptions.Builder().build(); - assertEquals(expected, opts.getRecordingOptions()); + assertThat(opts.getRecordingOptions()).isEqualTo(expected); } } diff --git a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingTest.java b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingTest.java index ac5c781ee..715d25bcb 100644 --- a/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingTest.java +++ b/jfr-connection/src/test/java/io/opentelemetry/contrib/jfr/connection/RecordingTest.java @@ -5,12 +5,8 @@ package io.opentelemetry.contrib.jfr.connection; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; import com.google.errorprone.annotations.Keep; import java.io.FileInputStream; @@ -109,8 +105,8 @@ void tearDown() { @Test void assertNewRecordingInitialValues() { try (Recording recording = flightRecorderConnection.newRecording(null, null)) { - assertEquals(Recording.State.NEW, recording.getState()); - assertEquals(-1, recording.getId()); + assertThat(recording.getState()).isEqualTo(Recording.State.NEW); + assertThat(recording.getId()).isEqualTo(-1); } catch (IOException | IllegalStateException | JfrConnectionException exception) { fail("assertNewRecordingInitialValues caught exception", exception); } @@ -120,8 +116,8 @@ void assertNewRecordingInitialValues() { void assertRecordingStartIdAndState() { try (Recording recording = flightRecorderConnection.newRecording(null, null)) { long id = recording.start(); - assertEquals(id, recording.getId()); - assertEquals(Recording.State.RECORDING, recording.getState()); + assertThat(recording.getId()).isEqualTo(id); + assertThat(recording.getState()).isEqualTo(Recording.State.RECORDING); } catch (IOException | IllegalStateException | JfrConnectionException e) { fail("assertRecordingStartIdAndState caught exception", e); } @@ -131,9 +127,9 @@ void assertRecordingStartIdAndState() { void assertRecordingStopState() { try (Recording recording = flightRecorderConnection.newRecording(null, null)) { long id = recording.start(); - assertEquals(id, recording.getId()); + assertThat(recording.getId()).isEqualTo(id); recording.stop(); - assertEquals(Recording.State.STOPPED, recording.getState()); + assertThat(recording.getState()).isEqualTo(Recording.State.STOPPED); } catch (IOException | IllegalStateException | JfrConnectionException e) { fail("assertRecordingStopState caught exception", e); } @@ -143,9 +139,9 @@ void assertRecordingStopState() { void assertRecordingCloseState() { try (Recording recording = flightRecorderConnection.newRecording(null, null)) { long id = recording.start(); - assertEquals(id, recording.getId()); + assertThat(recording.getId()).isEqualTo(id); recording.close(); - assertEquals(Recording.State.CLOSED, recording.getState()); + assertThat(recording.getState()).isEqualTo(Recording.State.CLOSED); } catch (IOException | IllegalStateException | JfrConnectionException e) { fail("assertRecordingCloseState caught exception", e); } @@ -255,7 +251,7 @@ void assertInvalidStateChangeThrowsIllegalStateException( try (Recording recording = flightRecorderConnection.newRecording(null, null)) { reflectivelyInvokeMethods(recording, args); } catch (InvocationTargetException invocationTargetException) { - assertTrue(invocationTargetException.getCause() instanceof IllegalStateException); + assertThat(invocationTargetException.getCause()).isInstanceOf(IllegalStateException.class); } catch (Exception e) { fail("Bad test code", e); } @@ -322,7 +318,7 @@ void assertRecordingOptionsAreSetInFlightRecorderMXBean( "getRecordingOptions", new Object[] {id}, new String[] {long.class.getName()}); - assertFalse(flightRecorderMXBeanOptions.isEmpty()); + assertThat(flightRecorderMXBeanOptions.isEmpty()).isFalse(); ((Collection) flightRecorderMXBeanOptions.values()) .forEach( compositeData -> { @@ -344,7 +340,7 @@ void assertRecordingOptionsAreSetInFlightRecorderMXBean( // and for destination since FlightRecorderMXBean returns null as default if (!("name".equals(key) && "".equals(actual)) && !("destination".equals(key) && "".equals(actual))) { - assertEquals(expected, actual, getter); + assertThat(actual).as(getter).isEqualTo(expected); } } catch (NoSuchMethodException | IllegalArgumentException @@ -393,7 +389,7 @@ void assertFileExistsAfterRecordingDump() { recording.stop(); Path dumpFile = Paths.get(System.getProperty("user.dir"), "testRecordingDump_dumped.jfr"); recording.dump(dumpFile.toString()); - assertTrue(Files.exists(dumpFile)); + assertThat(dumpFile).exists(); } catch (IllegalArgumentException badData) { fail("Issue in test data: " + badData.getMessage()); } catch (IOException ioe) { @@ -428,7 +424,7 @@ void assertFileExistsAfterRecordingStream() { fail(e.getMessage(), e); } - assertTrue(Files.exists(streamedFile)); + assertThat(streamedFile).exists(); } catch (IllegalArgumentException badData) { fail("Issue in test data: " + badData.getMessage()); @@ -502,9 +498,9 @@ void assertRecordingCloneState() { try (Recording recording = flightRecorderConnection.newRecording(recordingOptions, null)) { recording.start(); Recording clone = recording.clone(true); - assertSame(recording.getState(), Recording.State.RECORDING); - assertSame(clone.getState(), Recording.State.STOPPED); - assertNotEquals(recording.getId(), clone.getId()); + assertThat(recording.getState()).isEqualTo(Recording.State.RECORDING); + assertThat(clone.getState()).isEqualTo(Recording.State.STOPPED); + assertThat(recording.getId()).isNotEqualTo(clone.getId()); recording.stop(); } catch (IOException ioe) { // possible that this can be thrown, but should not happen in this context diff --git a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilderTest.java b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilderTest.java index a7a5239ee..8c520514e 100644 --- a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilderTest.java +++ b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilderTest.java @@ -9,8 +9,8 @@ import static org.apache.kafka.clients.CommonClientConfigs.CLIENT_ID_CONFIG; import static org.apache.kafka.clients.producer.ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG; import static org.apache.kafka.clients.producer.ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.common.collect.ImmutableMap; import io.opentelemetry.sdk.trace.data.SpanData; @@ -49,7 +49,7 @@ void buildWithSerializersInSetters() { .build()) .build(); - assertNotNull(actual); + assertThat(actual).isNotNull(); actual.close(); } @@ -74,7 +74,7 @@ void buildWithSerializersInConfig() { .build()) .build(); - assertNotNull(actual); + assertThat(actual).isNotNull(); actual.close(); } @@ -91,33 +91,32 @@ void buildWithMissingTopic() { VALUE_SERIALIZER_CLASS_CONFIG, valueSerializerMock.getClass().getName()); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test void buildWithMissingProducer() { - assertThrows( - IllegalArgumentException.class, - () -> new KafkaSpanExporterBuilder().setTopicName("a-topic").build()); + assertThatThrownBy(() -> new KafkaSpanExporterBuilder().setTopicName("a-topic").build()) + .isInstanceOf(IllegalArgumentException.class); } @Test void buildWithMissingProducerConfig() { - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer(KafkaSpanExporterBuilder.ProducerBuilder.newInstance().build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer(KafkaSpanExporterBuilder.ProducerBuilder.newInstance().build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -129,16 +128,16 @@ void buildWithMissingSerializers() { ProducerConfig.CLIENT_ID_CONFIG, "some clientId"); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -152,17 +151,17 @@ void buildWithKeySerializerInConfigAndValueSerializerInSetter() { KEY_SERIALIZER_CLASS_CONFIG, keySerializerMock.getClass().getName()); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .setValueSerializer(valueSerializerMock) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .setValueSerializer(valueSerializerMock) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -176,17 +175,17 @@ void buildWithValueSerializerInConfigAndKeySerializerInSetter() { VALUE_SERIALIZER_CLASS_CONFIG, valueSerializerMock.getClass().getName()); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .setKeySerializer(keySerializerMock) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .setKeySerializer(keySerializerMock) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -202,17 +201,17 @@ void buildWithSerializersInConfigAndSetters() { VALUE_SERIALIZER_CLASS_CONFIG, valueSerializerMock.getClass().getName()); - assertThrows( - IllegalArgumentException.class, - () -> - new KafkaSpanExporterBuilder() - .setTopicName("a-topic") - .setProducer( - KafkaSpanExporterBuilder.ProducerBuilder.newInstance() - .setConfig(producerConfig) - .setKeySerializer(keySerializerMock) - .setValueSerializer(valueSerializerMock) - .build()) - .build()); + assertThatThrownBy( + () -> + new KafkaSpanExporterBuilder() + .setTopicName("a-topic") + .setProducer( + KafkaSpanExporterBuilder.ProducerBuilder.newInstance() + .setConfig(producerConfig) + .setKeySerializer(keySerializerMock) + .setValueSerializer(valueSerializerMock) + .build()) + .build()) + .isInstanceOf(IllegalArgumentException.class); } } diff --git a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataDeserializerTest.java b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataDeserializerTest.java index 395fd357d..46636a247 100644 --- a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataDeserializerTest.java +++ b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataDeserializerTest.java @@ -5,9 +5,7 @@ package io.opentelemetry.contrib.kafka; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest; import io.opentelemetry.proto.resource.v1.Resource; @@ -38,16 +36,16 @@ void deserialize() { ExportTraceServiceRequest actual = testSubject.deserialize("test-topic", data); - assertEquals(request, actual); + assertThat(actual).isEqualTo(request); } @Test void deserializeNullData() { - assertNull(testSubject.deserialize("test-topic", null)); + assertThat(testSubject.deserialize("test-topic", null)).isNull(); } @Test void deserializeEmptyData() { - assertNotNull(testSubject.deserialize("test-topic", new byte[0])); + assertThat(testSubject.deserialize("test-topic", new byte[0])).isNotNull(); } } diff --git a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataSerializerTest.java b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataSerializerTest.java index 517610724..06c3df63e 100644 --- a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataSerializerTest.java +++ b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/SpanDataSerializerTest.java @@ -6,8 +6,7 @@ package io.opentelemetry.contrib.kafka; import static io.opentelemetry.contrib.kafka.TestUtil.makeBasicSpan; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.assertj.core.api.Assertions.assertThat; import com.google.common.collect.ImmutableList; import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest; @@ -28,14 +27,14 @@ void serialize() { byte[] actual = testSubject.serialize("test-topic", spans); - assertNotNull(actual); + assertThat(actual).isNotNull(); } @Test void serializeEmptyData() { byte[] actual = testSubject.serialize("test-topic", Collections.emptySet()); - assertEquals(0, actual.length); + assertThat(actual).isEmpty(); } @Test @@ -46,16 +45,18 @@ void convertSpansToRequest() { ExportTraceServiceRequest actual = testSubject.convertSpansToRequest(spans); - assertNotNull(actual); - assertEquals("span-1", actual.getResourceSpans(0).getScopeSpans(0).getSpans(0).getName()); - assertEquals("span-2", actual.getResourceSpans(0).getScopeSpans(0).getSpans(1).getName()); + assertThat(actual).isNotNull(); + assertThat(actual.getResourceSpans(0).getScopeSpans(0).getSpans(0).getName()) + .isEqualTo("span-1"); + assertThat(actual.getResourceSpans(0).getScopeSpans(0).getSpans(1).getName()) + .isEqualTo("span-2"); } @Test void convertSpansToRequestForEmptySpans() { ExportTraceServiceRequest actual = testSubject.convertSpansToRequest(Collections.emptySet()); - assertNotNull(actual); - assertEquals(ExportTraceServiceRequest.getDefaultInstance(), actual); + assertThat(actual).isNotNull(); + assertThat(actual).isEqualTo(ExportTraceServiceRequest.getDefaultInstance()); } } diff --git a/processors/src/test/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessorTest.java b/processors/src/test/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessorTest.java index 50405d454..874895340 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessorTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessorTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.filter; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.logs.Logger; import io.opentelemetry.api.trace.Span; @@ -93,14 +93,14 @@ void verifyLogFilteringExistSpanContext() { sdk.getLogsBridge().get("test").logRecordBuilder().setBody("One Log").emit(); List finishedLogRecordItems = memoryLogRecordExporter.getFinishedLogRecordItems(); - assertEquals(1, finishedLogRecordItems.size()); + assertThat(finishedLogRecordItems.size()).isEqualTo(1); try (Scope scope = span.makeCurrent()) { } finally { span.end(); } List finishedSpans = spansExporter.getFinishedSpanItems(); - assertEquals(1, finishedSpans.size()); + assertThat(finishedSpans.size()).isEqualTo(1); } } @@ -109,6 +109,6 @@ void verifyFilteringNotExitSpanContext() { logger.logRecordBuilder().setBody("One Log").emit(); List finishedLogRecordItems = memoryLogRecordExporter.getFinishedLogRecordItems(); - assertEquals(0, finishedLogRecordItems.size()); + assertThat(finishedLogRecordItems.size()).isEqualTo(0); } } diff --git a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java index 3b81ce277..0096caa66 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableLogRecordExporterTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.interceptor; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -62,13 +62,13 @@ void verifyLogModification() { List finishedLogRecordItems = memoryLogRecordExporter.getFinishedLogRecordItems(); - assertEquals(1, finishedLogRecordItems.size()); + assertThat(finishedLogRecordItems.size()).isEqualTo(1); LogRecordData logRecordData = finishedLogRecordItems.get(0); - assertEquals(2, logRecordData.getAttributes().size()); - assertEquals( - "from interceptor", - logRecordData.getAttributes().get(AttributeKey.stringKey("global.attr"))); - assertEquals("local", logRecordData.getAttributes().get(AttributeKey.stringKey("local.attr"))); + assertThat(logRecordData.getAttributes().size()).isEqualTo(2); + assertThat(logRecordData.getAttributes().get(AttributeKey.stringKey("global.attr"))) + .isEqualTo("from interceptor"); + assertThat(logRecordData.getAttributes().get(AttributeKey.stringKey("local.attr"))) + .isEqualTo("local"); } @Test @@ -87,9 +87,9 @@ void verifyLogFiltering() { List finishedLogRecordItems = memoryLogRecordExporter.getFinishedLogRecordItems(); - assertEquals(2, finishedLogRecordItems.size()); - assertEquals(Value.of("One log"), finishedLogRecordItems.get(0).getBodyValue()); - assertEquals(Value.of("Another log"), finishedLogRecordItems.get(1).getBodyValue()); + assertThat(finishedLogRecordItems.size()).isEqualTo(2); + assertThat(finishedLogRecordItems.get(0).getBodyValue()).isEqualTo(Value.of("One log")); + assertThat(finishedLogRecordItems.get(1).getBodyValue()).isEqualTo(Value.of("Another log")); } private static class ModifiableLogRecordData implements LogRecordData { diff --git a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java index 6b12d5f1a..f321b8a7b 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableMetricExporterTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.interceptor; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.contrib.interceptor.common.ComposableInterceptor; @@ -55,8 +54,8 @@ void verifyMetricModification() { meterProvider.forceFlush(); List finishedMetricItems = memoryMetricExporter.getFinishedMetricItems(); - assertEquals(1, finishedMetricItems.size()); - assertEquals("ModifiedName", finishedMetricItems.get(0).getName()); + assertThat(finishedMetricItems.size()).isEqualTo(1); + assertThat(finishedMetricItems.get(0).getName()).isEqualTo("ModifiedName"); } @Test @@ -75,7 +74,7 @@ void verifyMetricFiltering() { meterProvider.forceFlush(); List finishedMetricItems = memoryMetricExporter.getFinishedMetricItems(); - assertEquals(2, finishedMetricItems.size()); + assertThat(finishedMetricItems.size()).isEqualTo(2); List names = new ArrayList<>(); for (MetricData item : finishedMetricItems) { names.add(item.getName()); diff --git a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java index a6c177181..26242174f 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/interceptor/InterceptableSpanExporterTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.interceptor; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -51,12 +51,12 @@ void verifySpanModification() { tracer.spanBuilder("Test span").setAttribute("local.attr", 10).startSpan().end(); List finishedSpanItems = memorySpanExporter.getFinishedSpanItems(); - assertEquals(1, finishedSpanItems.size()); + assertThat(finishedSpanItems.size()).isEqualTo(1); SpanData spanData = finishedSpanItems.get(0); - assertEquals(2, spanData.getAttributes().size()); - assertEquals( - "from interceptor", spanData.getAttributes().get(AttributeKey.stringKey("global.attr"))); - assertEquals(10, spanData.getAttributes().get(AttributeKey.longKey("local.attr"))); + assertThat(spanData.getAttributes().size()).isEqualTo(2); + assertThat(spanData.getAttributes().get(AttributeKey.stringKey("global.attr"))) + .isEqualTo("from interceptor"); + assertThat(spanData.getAttributes().get(AttributeKey.longKey("local.attr"))).isEqualTo(10L); } @Test @@ -74,9 +74,9 @@ void verifySpanFiltering() { tracer.spanBuilder("Another span").startSpan().end(); List finishedSpanItems = memorySpanExporter.getFinishedSpanItems(); - assertEquals(2, finishedSpanItems.size()); - assertEquals("One span", finishedSpanItems.get(0).getName()); - assertEquals("Another span", finishedSpanItems.get(1).getName()); + assertThat(finishedSpanItems.size()).isEqualTo(2); + assertThat(finishedSpanItems.get(0).getName()).isEqualTo("One span"); + assertThat(finishedSpanItems.get(1).getName()).isEqualTo("Another span"); } private static class ModifiableSpanData extends DelegatingSpanData { diff --git a/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/JettyServiceNameDetectorTest.java b/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/JettyServiceNameDetectorTest.java index b48f4685a..5a63d28e7 100644 --- a/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/JettyServiceNameDetectorTest.java +++ b/resource-providers/src/test/java/io/opentelemetry/contrib/resourceproviders/JettyServiceNameDetectorTest.java @@ -6,8 +6,7 @@ package io.opentelemetry.contrib.resourceproviders; import static io.opentelemetry.contrib.resourceproviders.JettyAppServer.parseJettyBase; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.nio.file.Files; @@ -19,17 +18,17 @@ public class JettyServiceNameDetectorTest { @Test void testJettyBase(@TempDir Path tempDir) throws IOException { - assertNull(parseJettyBase(null)); - assertNull(parseJettyBase("")); - assertNull(parseJettyBase("jetty.base=")); - assertEquals(tempDir.toString(), parseJettyBase("jetty.base=" + tempDir).toString()); - assertEquals( - tempDir.toString(), parseJettyBase("foo jetty.base=" + tempDir + " bar").toString()); + assertThat(parseJettyBase(null)).isNull(); + assertThat(parseJettyBase("")).isNull(); + assertThat(parseJettyBase("jetty.base=")).isNull(); + assertThat(parseJettyBase("jetty.base=" + tempDir).toString()).isEqualTo(tempDir.toString()); + assertThat(parseJettyBase("foo jetty.base=" + tempDir + " bar").toString()) + .isEqualTo(tempDir.toString()); Path otherDir = tempDir.resolve("jetty test"); Files.createDirectory(otherDir); - assertEquals(otherDir.toString(), parseJettyBase("jetty.base=" + otherDir).toString()); - assertEquals( - otherDir.toString(), parseJettyBase("foo jetty.base=" + otherDir + " bar").toString()); + assertThat(parseJettyBase("jetty.base=" + otherDir).toString()).isEqualTo(otherDir.toString()); + assertThat(parseJettyBase("foo jetty.base=" + otherDir + " bar").toString()) + .isEqualTo(otherDir.toString()); } } From a29442302f954f900527224725df7ecebce638ec Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 24 Aug 2025 09:21:34 -0700 Subject: [PATCH 04/12] visibility --- docs/style-guide.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/style-guide.md b/docs/style-guide.md index 8bf101218..b5d8a20da 100644 --- a/docs/style-guide.md +++ b/docs/style-guide.md @@ -59,6 +59,11 @@ methods. ## Java Language Conventions +### Visibility modifiers + +Follow the principle of minimal necessary visibility. Use the most restrictive access modifier that +still allows the code to function correctly. + ### Package conventions Classes in `.internal` packages are not considered public API and may change without notice. These @@ -117,6 +122,12 @@ Following the reasoning from Prefer AssertJ assertions over JUnit assertions (assertEquals, assertTrue, etc.) for better error messages. +### JUnit + +Test classes and test methods should generally be package-protected (no explicit visibility +modifier) rather than `public`. This follows the principle of minimal necessary visibility and is +sufficient for JUnit to discover and execute tests. + ### AutoService Use the `@AutoService` annotation when implementing SPI interfaces. This automatically generates the @@ -140,7 +151,7 @@ public class MyCustomizerProvider implements AutoConfigurationCustomizerProvider ## Configuration - Use `otel.` prefix for all configuration property keys -- Read config via the `ConfigProperties` interface +- Read configuration via the `ConfigProperties` interface - Provide sensible defaults and document all options - Validate configuration early with clear error messages From 066eb132f2033acc799f5f64e6c0bd93f0156592 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 24 Aug 2025 09:57:02 -0700 Subject: [PATCH 05/12] Also add basic coding agent instructions --- .github/copilot-instructions.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index f5c985dd5..f7ac77115 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -28,3 +28,11 @@ This repository provides observability instrumentation for Java applications. - OpenTelemetry specification and semantic convention compliance - Resource cleanup and lifecycle management - Comprehensive unit tests for new functionality + +## Coding Agent Instructions + +When implementing changes or new features: + +1. Follow all [Style Guide](../docs/style-guide.md) conventions and the Code Review Priorities above +2. Run tests to ensure they still pass (use `./gradlew test` and `./gradlew integrationTest` as needed) +3. **Always run `./gradlew spotlessApply`** after making code changes to ensure proper formatting From b71cc4191076128ee5002cd6f66fc68ddd677143 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 24 Aug 2025 11:06:59 -0700 Subject: [PATCH 06/12] clarifications --- docs/style-guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/style-guide.md b/docs/style-guide.md index b5d8a20da..33297c0af 100644 --- a/docs/style-guide.md +++ b/docs/style-guide.md @@ -33,7 +33,7 @@ Consider statically importing the following commonly used methods and constants: - `java.util.Arrays.*` (asList, etc.) - `java.util.Collections.*` (singletonList, emptyList, emptyMap, emptySet, etc.) - `java.util.stream.Collectors.*` (toList, toMap, toSet, etc.) - - `java.util.Objects` (requireNonNull, etc.) + - `java.util.Objects` (requireNonNull) - `java.util.logging.Level.*` (FINE, INFO, WARNING, etc.) - `java.nio.charset.StandardCharsets.*` (UTF_8, etc.) - **Time unit constants** @@ -75,9 +75,9 @@ packages contain implementation details that should not be used by external cons ### `final` keyword usage -Public API classes should be declared `final` where possible. +Public non-internal classes should be declared `final` where possible. -Methods should only be declared `final` if they are in non-final public API classes. +Methods should only be declared `final` if they are in public non-internal non-final classes. Fields should be declared `final` where possible. From 52463e1bf305fe3b52371948491d0fa9381ba531 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 24 Aug 2025 11:37:20 -0700 Subject: [PATCH 07/12] update --- docs/style-guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/style-guide.md b/docs/style-guide.md index 33297c0af..76eb3a5be 100644 --- a/docs/style-guide.md +++ b/docs/style-guide.md @@ -30,16 +30,16 @@ Consider statically importing the following commonly used methods and constants: - `org.mockito.ArgumentMatchers.*` (any, eq, anyLong, etc.) - **Utility methods** - `io.opentelemetry.api.common.AttributeKey.*` (stringKey, longKey, etc.) - - `java.util.Arrays.*` (asList, etc.) + - `java.util.Arrays.*` (asList, stream, etc.) - `java.util.Collections.*` (singletonList, emptyList, emptyMap, emptySet, etc.) - `java.util.stream.Collectors.*` (toList, toMap, toSet, etc.) - - `java.util.Objects` (requireNonNull) + - `java.util.Objects.requireNonNull` - `java.util.logging.Level.*` (FINE, INFO, WARNING, etc.) - `java.nio.charset.StandardCharsets.*` (UTF_8, etc.) - **Time unit constants** - `java.util.concurrent.TimeUnit.*` (SECONDS, etc.) - **OpenTelemetry semantic convention constants** - - All constants under `io.opentelemetry.semconv.**` + - All constants under `io.opentelemetry.semconv.**`, except for `io.opentelemetry.semconv.SchemaUrls.*` constants. ### Class organization From 218f229ea26b72157da401bbed93f4577d8bb7b7 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 24 Aug 2025 12:32:25 -0700 Subject: [PATCH 08/12] fix --- docs/style-guide.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docs/style-guide.md b/docs/style-guide.md index 76eb3a5be..6adfac631 100644 --- a/docs/style-guide.md +++ b/docs/style-guide.md @@ -96,14 +96,6 @@ Annotate all parameters and fields that can be `null` with `@Nullable` (specific **Defensive programming**: Public APIs should still check for `null` parameters even if not annotated with `@Nullable`. Internal APIs do not need these checks. -**Enforcement**: Use the `otel.errorprone-conventions` Gradle plugin in all modules: - -```kotlin -plugins { - id("otel.errorprone-conventions") -} -``` - ### `Optional` usage Following the reasoning from From ae9711bb8cf3ad52f0c5477eee7623714cda4391 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 24 Aug 2025 12:35:25 -0700 Subject: [PATCH 09/12] more --- docs/style-guide.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/style-guide.md b/docs/style-guide.md index 6adfac631..faffa0f9c 100644 --- a/docs/style-guide.md +++ b/docs/style-guide.md @@ -39,7 +39,8 @@ Consider statically importing the following commonly used methods and constants: - **Time unit constants** - `java.util.concurrent.TimeUnit.*` (SECONDS, etc.) - **OpenTelemetry semantic convention constants** - - All constants under `io.opentelemetry.semconv.**`, except for `io.opentelemetry.semconv.SchemaUrls.*` constants. + - All constants under `io.opentelemetry.semconv.**`, except for + `io.opentelemetry.semconv.SchemaUrls.*` constants. ### Class organization @@ -64,7 +65,7 @@ methods. Follow the principle of minimal necessary visibility. Use the most restrictive access modifier that still allows the code to function correctly. -### Package conventions +### Internal packages Classes in `.internal` packages are not considered public API and may change without notice. These packages contain implementation details that should not be used by external consumers. @@ -75,7 +76,8 @@ packages contain implementation details that should not be used by external cons ### `final` keyword usage -Public non-internal classes should be declared `final` where possible. +Public non-internal classes should be declared `final` where possible. Internal and non-public +classes should not be declared `final`. Methods should only be declared `final` if they are in public non-internal non-final classes. From 3631faa8191c92ae4e523387ceca3acc137c011c Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 24 Aug 2025 16:49:28 -0700 Subject: [PATCH 10/12] refine --- docs/style-guide.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/style-guide.md b/docs/style-guide.md index faffa0f9c..91bad07e0 100644 --- a/docs/style-guide.md +++ b/docs/style-guide.md @@ -24,20 +24,21 @@ need to run `./gradlew spotlessApply` periodically. Consider statically importing the following commonly used methods and constants: - **Test methods** - - `io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions` (assertThat, satisfies, etc.) - - `org.assertj.core.api.Assertions.*` (assertThat, assertThatThrownBy, entry, etc.) - - `org.mockito.Mockito.*` (when, mock, verify, times, etc.) - - `org.mockito.ArgumentMatchers.*` (any, eq, anyLong, etc.) + - `io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.*` + - `org.assertj.core.api.Assertions.*` + - `org.mockito.Mockito.*` + - `org.mockito.ArgumentMatchers.*` - **Utility methods** - - `io.opentelemetry.api.common.AttributeKey.*` (stringKey, longKey, etc.) - - `java.util.Arrays.*` (asList, stream, etc.) - - `java.util.Collections.*` (singletonList, emptyList, emptyMap, emptySet, etc.) - - `java.util.stream.Collectors.*` (toList, toMap, toSet, etc.) - - `java.util.Objects.requireNonNull` - - `java.util.logging.Level.*` (FINE, INFO, WARNING, etc.) - - `java.nio.charset.StandardCharsets.*` (UTF_8, etc.) -- **Time unit constants** - - `java.util.concurrent.TimeUnit.*` (SECONDS, etc.) + - `io.opentelemetry.api.common.AttributeKey.*` + - `java.util.Arrays` - asList, stream + - `java.util.Collections` - singleton*, empty*, unmodifiable*, synchronized*, checked* + - `java.util.Objects` - requireNonNull + - `java.util.stream.Collectors.*` +- **Utility constants** + - `java.util.Locale.*` + - `java.util.concurrent.TimeUnit.*` + - `java.util.logging.Level.*` + - `java.nio.charset.StandardCharsets.*` - **OpenTelemetry semantic convention constants** - All constants under `io.opentelemetry.semconv.**`, except for `io.opentelemetry.semconv.SchemaUrls.*` constants. From 6330da2db7f346147f801d2387207c973a2dc46c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 25 Aug 2025 01:51:23 +0000 Subject: [PATCH 11/12] Initial plan From 96945d1f97821e6b59ad3d6e461fb39c575086d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 25 Aug 2025 02:03:17 +0000 Subject: [PATCH 12/12] Update samplers module to follow style guide Co-authored-by: trask <218610+trask@users.noreply.github.com> --- samplers/build.gradle.kts | 4 ++++ .../io/opentelemetry/contrib/sampler/LinksBasedSampler.java | 2 +- .../contrib/sampler/LinksParentAlwaysOnSamplerProvider.java | 4 +++- .../java/io/opentelemetry/contrib/sampler/SamplingRule.java | 5 +++-- .../internal/RuleBasedRoutingSamplerComponentProvider.java | 3 +++ ...elemetry.sdk.autoconfigure.spi.internal.ComponentProvider | 1 - ....sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider | 1 - 7 files changed, 14 insertions(+), 6 deletions(-) delete mode 100644 samplers/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider delete mode 100644 samplers/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider diff --git a/samplers/build.gradle.kts b/samplers/build.gradle.kts index 6061e84ab..b6830f00d 100644 --- a/samplers/build.gradle.kts +++ b/samplers/build.gradle.kts @@ -13,6 +13,10 @@ dependencies { compileOnly("io.opentelemetry:opentelemetry-api-incubator") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") + annotationProcessor("com.google.auto.service:auto-service") + compileOnly("com.google.auto.service:auto-service-annotations") + + testImplementation("com.google.auto.service:auto-service") testImplementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") diff --git a/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksBasedSampler.java b/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksBasedSampler.java index 1dc5124f4..13ce4fc5e 100644 --- a/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksBasedSampler.java +++ b/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksBasedSampler.java @@ -37,7 +37,7 @@ public SamplingResult shouldSample( SpanKind spanKind, Attributes attributes, List parentLinks) { - if (parentLinks.size() > 0) { + if (!parentLinks.isEmpty()) { for (LinkData linkData : parentLinks) { if (linkData.getSpanContext().isSampled()) { return SamplingResult.recordAndSample(); diff --git a/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java b/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java index 45f341897..303046c9a 100644 --- a/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java +++ b/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java @@ -5,11 +5,13 @@ package io.opentelemetry.contrib.sampler; +import com.google.auto.service.AutoService; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider; import io.opentelemetry.sdk.trace.samplers.Sampler; -public class LinksParentAlwaysOnSamplerProvider implements ConfigurableSamplerProvider { +@AutoService(ConfigurableSamplerProvider.class) +public final class LinksParentAlwaysOnSamplerProvider implements ConfigurableSamplerProvider { @Override public Sampler createSampler(ConfigProperties config) { return LinksBasedSampler.create(Sampler.parentBased(Sampler.alwaysOn())); diff --git a/samplers/src/main/java/io/opentelemetry/contrib/sampler/SamplingRule.java b/samplers/src/main/java/io/opentelemetry/contrib/sampler/SamplingRule.java index d98656c83..04e2c3f69 100644 --- a/samplers/src/main/java/io/opentelemetry/contrib/sampler/SamplingRule.java +++ b/samplers/src/main/java/io/opentelemetry/contrib/sampler/SamplingRule.java @@ -5,9 +5,10 @@ package io.opentelemetry.contrib.sampler; +import static java.util.Objects.hash; + import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.sdk.trace.samplers.Sampler; -import java.util.Objects; import java.util.regex.Pattern; import javax.annotation.Nullable; @@ -48,6 +49,6 @@ public boolean equals(@Nullable Object o) { @Override public int hashCode() { - return Objects.hash(attributeKey, pattern); + return hash(attributeKey, pattern); } } diff --git a/samplers/src/main/java/io/opentelemetry/contrib/sampler/internal/RuleBasedRoutingSamplerComponentProvider.java b/samplers/src/main/java/io/opentelemetry/contrib/sampler/internal/RuleBasedRoutingSamplerComponentProvider.java index 9e7fb4971..27d80d12c 100644 --- a/samplers/src/main/java/io/opentelemetry/contrib/sampler/internal/RuleBasedRoutingSamplerComponentProvider.java +++ b/samplers/src/main/java/io/opentelemetry/contrib/sampler/internal/RuleBasedRoutingSamplerComponentProvider.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.sampler.internal; +import com.google.auto.service.AutoService; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.incubator.config.DeclarativeConfigException; import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; @@ -22,6 +23,8 @@ *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ +@SuppressWarnings("rawtypes") +@AutoService(ComponentProvider.class) public class RuleBasedRoutingSamplerComponentProvider implements ComponentProvider { private static final String ACTION_RECORD_AND_SAMPLE = "RECORD_AND_SAMPLE"; diff --git a/samplers/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider b/samplers/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider deleted file mode 100644 index 32c554481..000000000 --- a/samplers/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider +++ /dev/null @@ -1 +0,0 @@ -io.opentelemetry.contrib.sampler.internal.RuleBasedRoutingSamplerComponentProvider diff --git a/samplers/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider b/samplers/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider deleted file mode 100644 index 92990a4b5..000000000 --- a/samplers/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider +++ /dev/null @@ -1 +0,0 @@ -io.opentelemetry.contrib.sampler.LinksParentAlwaysOnSamplerProvider