diff --git a/.github/config/lychee.toml b/.github/config/lychee.toml new file mode 100644 index 000000000..bde272fc9 --- /dev/null +++ b/.github/config/lychee.toml @@ -0,0 +1,14 @@ +timeout = 30 +retry_wait_time = 5 +max_retries = 6 +max_concurrency = 4 + +# Check link anchors +include_fragments = true + +exclude = [ + # until https://github.com/open-telemetry/opentelemetry-java-contrib/issues/2221 is resolved + "^https?://www.ibm.com", + # excluding links to pull requests and issues is done for performance + "^https://github.com/open-telemetry/opentelemetry-java-contrib/(issues|pull)/\\d+$", +] diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..d7f693363 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,66 @@ +# 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 + +### Test suites + +This project uses gradle 9 which requires specifying test classes and paths explicitly. + +For example, this will NOT work because it registers a `Test` without specifying the test classes or paths: + +```kotlin +tasks.register("IntegrationTestUserCreds") { + dependsOn(tasks.shadowJar) + dependsOn(tasks.named("copyAgent")) + ... +} +``` + +This is fixed by specifying the test classes and classpath explicitly: + +```kotlin +tasks.register("IntegrationTestUserCreds") { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + dependsOn(tasks.shadowJar) + dependsOn(tasks.named("copyAgent")) + ... +} +``` + +## 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 +4. Run markdown lint to ensure it still passes: `npx markdownlint-cli@0.45.0 -c .github/config/markdownlint.yml **/*.md` diff --git a/.github/renovate.json5 b/.github/renovate.json5 index df236f85e..c6a64fbe0 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -85,7 +85,7 @@ ], enabled: false, matchPackageNames: [ - 'org.mockito:{/,}**', + 'org.mockito:**', ], }, { @@ -123,25 +123,33 @@ matchCurrentVersion: '3.5.0', enabled: false, matchPackageNames: [ - 'org.apache.maven:{/,}**', + 'org.apache.maven:**', ], }, { groupName: 'spotless packages', matchPackageNames: [ - 'com.diffplug.spotless{/,}**', + 'com.diffplug.spotless', + 'com.diffplug.spotless:**', ], }, { groupName: 'hipparchus packages', matchPackageNames: [ - 'org.hipparchus{/,}**', + 'org.hipparchus:**', ], }, { groupName: 'errorprone packages', matchPackageNames: [ - 'com.google.errorprone{/,}**', + 'com.google.errorprone:**', + ], + }, + { + groupName: 'jackson packages', + matchPackageNames: [ + 'com.fasterxml.jackson:**', + 'com.fasterxml.jackson.core:**', ], }, { @@ -151,7 +159,7 @@ ], enabled: false, matchPackageNames: [ - 'org.openjdk.jmc{/,}**', + 'org.openjdk.jmc:**', ], }, { @@ -162,7 +170,7 @@ matchCurrentVersion: '5.0.0', enabled: false, matchPackageNames: [ - 'jakarta.servlet:{/,}**', + 'jakarta.servlet:**', ], }, { @@ -175,7 +183,7 @@ ], enabled: false, matchPackageNames: [ - 'org.springframework.boot{/,}**', + 'org.springframework.boot:**', ], }, ], @@ -202,5 +210,15 @@ depNameTemplate: 'java', extractVersionTemplate: '^(?\\d+)', }, + { + customType: 'regex', + datasourceTemplate: 'github-releases', + managerFilePatterns: [ + '**/build.gradle.kts', + ], + matchStrings: [ + '"https://github.com/(?[^/]+/[^/]+)/zipball/(?.+?)"', + ], + }, ], } diff --git a/.github/scripts/dependencies.Dockerfile b/.github/scripts/dependencies.Dockerfile deleted file mode 100644 index d8e3bbfe1..000000000 --- a/.github/scripts/dependencies.Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -# this file exists so that Renovate can auto-update docker image versions that are then used elsewhere - -FROM lycheeverse/lychee:sha-2aa22f8@sha256:2e3786630482c41f9f2dd081e06d7da1c36d66996e8cf6573409b8bc418d48c4 AS lychee diff --git a/.github/scripts/draft-change-log-entries.sh b/.github/scripts/draft-change-log-entries.sh index 845c92672..489c1fe4d 100755 --- a/.github/scripts/draft-change-log-entries.sh +++ b/.github/scripts/draft-change-log-entries.sh @@ -35,6 +35,7 @@ component_names["consistent-sampling/"]="Consistent sampling" component_names["disk-buffering/"]="Disk buffering" component_names["gcp-resources/"]="GCP resources" component_names["gcp-auth-extension/"]="GCP authentication extension" +component_names["ibm-mq-metrics/"]="IBM MQ metrics" component_names["inferred-spans/"]="Inferred spans" component_names["jfr-connection/"]="JFR connection" component_names["jfr-events/"]="JFR events" @@ -44,6 +45,7 @@ component_names["kafka-exporter/"]="Kafka exporter" component_names["maven-extension/"]="Maven extension" component_names["micrometer-meter-provider/"]="Micrometer MeterProvider" component_names["noop-api/"]="No-op API" +component_names["opamp-client/"]="OpAMP client" component_names["processors/"]="Telemetry processors" component_names["prometheus-client-bridge/"]="Prometheus client bridge" component_names["runtime-attach/"]="Runtime attach" diff --git a/.github/scripts/link-check.sh b/.github/scripts/link-check.sh deleted file mode 100755 index 7e6b6910a..000000000 --- a/.github/scripts/link-check.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -set -e - -export MSYS_NO_PATHCONV=1 # for Git Bash on Windows - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ROOT_DIR="$SCRIPT_DIR/../.." -DEPENDENCIES_DOCKERFILE="$SCRIPT_DIR/dependencies.Dockerfile" - -# Parse command line arguments -LOCAL_LINKS_ONLY=false -TARGET="" - -while [[ $# -gt 0 ]]; do - case $1 in - --local-links-only) - LOCAL_LINKS_ONLY=true - shift - ;; - *) - # Treat any other arguments as file paths - TARGET="$TARGET $1" - shift - ;; - esac -done - -# Extract lychee version from dependencies.dockerfile -LYCHEE_VERSION=$(grep "FROM lycheeverse/lychee:" "$DEPENDENCIES_DOCKERFILE" | sed 's/.*FROM lycheeverse\/lychee:\([^ ]*\).*/\1/') - -if [[ -z "$TARGET" ]]; then - TARGET="." -fi - -# Build the lychee command with optional GitHub token -CMD="lycheeverse/lychee:$LYCHEE_VERSION --verbose --root-dir /data" - -# Add GitHub token if available -if [[ -n "$GITHUB_TOKEN" ]]; then - CMD="$CMD --github-token $GITHUB_TOKEN" -fi - -if [[ "$LOCAL_LINKS_ONLY" == "true" ]]; then - CMD="$CMD --scheme file --include-fragments" -else - CMD="$CMD --config .github/scripts/lychee-config.toml" -fi - -CMD="$CMD $TARGET" - -# Determine if we should allocate a TTY -DOCKER_FLAGS="--rm --init" -if [[ -t 0 ]]; then - DOCKER_FLAGS="$DOCKER_FLAGS -it" -else - DOCKER_FLAGS="$DOCKER_FLAGS -i" -fi - -# Run lychee with proper signal handling -# shellcheck disable=SC2086 -exec docker run $DOCKER_FLAGS -v "$ROOT_DIR":/data -w /data $CMD diff --git a/.github/scripts/lychee-config.toml b/.github/scripts/lychee-config.toml deleted file mode 100644 index d368a2404..000000000 --- a/.github/scripts/lychee-config.toml +++ /dev/null @@ -1,16 +0,0 @@ -timeout = 30 -retry_wait_time = 5 -max_retries = 6 -max_concurrency = 4 - -# Check link anchors -include_fragments = true - -# excluding links to pull requests and issues is done for performance -# sonatype snapshots are currrently unbrowseable -exclude = [ - "^https://github.com/open-telemetry/opentelemetry-java-contrib/(issues|pull)/\\d+$", - '^https://central.sonatype.com/service/rest/repository/browse/maven-snapshots/io/opentelemetry/contrib/$', -] - - diff --git a/.github/scripts/package-lock.json b/.github/scripts/package-lock.json new file mode 100644 index 000000000..f364e1106 --- /dev/null +++ b/.github/scripts/package-lock.json @@ -0,0 +1,27 @@ +{ + "name": "github-scripts", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "github-scripts", + "version": "1.0.0", + "dependencies": { + "yaml": "2.8.1" + } + }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + } + } +} diff --git a/.github/scripts/package.json b/.github/scripts/package.json new file mode 100644 index 000000000..efca3b345 --- /dev/null +++ b/.github/scripts/package.json @@ -0,0 +1,9 @@ +{ + "//": "Dependencies for GitHub Actions workflows that use actions/github-script", + "name": "github-scripts", + "version": "1.0.0", + "private": true, + "dependencies": { + "yaml": "2.8.1" + } +} diff --git a/.github/workflows/assign-issue-owners.yml b/.github/workflows/assign-issue-owners.yml index 232396d9c..7d7acba67 100644 --- a/.github/workflows/assign-issue-owners.yml +++ b/.github/workflows/assign-issue-owners.yml @@ -19,15 +19,15 @@ jobs: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Install js-yaml - run: npm install js-yaml + - name: Install yaml dependency used below + run: npm install .github/scripts - name: Parse component label and assign owners - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | const fs = require('fs'); - const yaml = require('js-yaml'); + const { parse } = require('yaml'); // Extract component name from label const labelName = context.payload.label.name; @@ -42,7 +42,7 @@ jobs: // Read and parse component_owners.yml const yamlContent = fs.readFileSync('.github/component_owners.yml', 'utf8'); - const data = yaml.load(yamlContent); + const data = parse(yamlContent); if (!data || !data.components) { core.setFailed('Invalid component_owners.yml structure'); diff --git a/.github/workflows/assign-reviewers.yml b/.github/workflows/assign-reviewers.yml index 5994bd2e1..d1cf86ce8 100644 --- a/.github/workflows/assign-reviewers.yml +++ b/.github/workflows/assign-reviewers.yml @@ -18,6 +18,7 @@ jobs: pull-requests: write # for assigning reviewers runs-on: ubuntu-latest steps: - - uses: open-telemetry/assign-reviewers-action@2f4f06ccc561740d5094d9ca5e66dc2392d13e8f # main + - uses: dyladan/component-owners@58bd86e9814d23f1525d0a970682cead459fa783 # v0.1.0 with: config-file: .github/component_owners.yml + assign-owners: false diff --git a/.github/workflows/auto-spotless-apply.yml b/.github/workflows/auto-spotless-apply.yml index 36da59e0d..b363b4977 100644 --- a/.github/workflows/auto-spotless-apply.yml +++ b/.github/workflows/auto-spotless-apply.yml @@ -32,7 +32,7 @@ jobs: echo "exists=true" >> $GITHUB_OUTPUT fi - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 if: steps.unzip-patch.outputs.exists == 'true' id: otelbot-token with: diff --git a/.github/workflows/auto-spotless-check.yml b/.github/workflows/auto-spotless-check.yml index f6b873119..f4e171bb0 100644 --- a/.github/workflows/auto-spotless-check.yml +++ b/.github/workflows/auto-spotless-check.yml @@ -19,13 +19,13 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 with: cache-read-only: true diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index eeb3ce5e3..a798378c6 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -12,7 +12,7 @@ permissions: jobs: backport: permissions: - contents: write # for Git to git push + contents: write # for git push to PR branch runs-on: ubuntu-latest steps: - run: | @@ -29,7 +29,7 @@ jobs: - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} @@ -48,6 +48,15 @@ jobs: git checkout -b $branch git cherry-pick $commit + + if git diff --name-only HEAD~1 HEAD | grep -q '^\.github/workflows/'; then + echo "::error::This PR contains changes to workflow files (.github/workflows/)." + echo "::error::Workflow files cannot be automatically backported because the standard" + echo "::error::GitHub token doesn't have the required 'workflow' write permission." + echo "::error::Please backport this PR manually." + exit 1 + fi + git push --set-upstream origin $branch gh pr create --title "[$GITHUB_REF_NAME] $title" \ --body "Clean cherry-pick of #$NUMBER to the \`$GITHUB_REF_NAME\` branch." \ diff --git a/.github/workflows/build-common.yml b/.github/workflows/build-common.yml index e66619ec9..bb50858cc 100644 --- a/.github/workflows/build-common.yml +++ b/.github/workflows/build-common.yml @@ -18,24 +18,59 @@ permissions: contents: read jobs: + spotless: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Set up JDK for running Gradle + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + with: + distribution: temurin + java-version: 17 + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 + with: + cache-read-only: ${{ inputs.cache-read-only }} + + - name: Spotless + run: ./gradlew spotlessCheck ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + build: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 with: cache-read-only: ${{ inputs.cache-read-only }} - - name: Gradle build and test - run: ./gradlew build -x test ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + - name: Build + run: ./gradlew build -x spotlessCheck -x test ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + + - name: Check for jApiCmp diffs + # The jApiCmp diff compares current to latest, which isn't appropriate for release branches + if: ${{ !startsWith(github.ref_name, 'release/') && !startsWith(github.base_ref, 'release/') }} + run: | + # need to "git add" in case any generated files did not already exist + git add docs/apidiffs + if git diff --cached --quiet + then + echo "No diff detected." + else + echo "Diff detected - did you run './gradlew jApiCmp'?" + git diff --cached --name-only + git diff --cached + exit 1 + fi test: name: Test @@ -44,8 +79,6 @@ jobs: fail-fast: false matrix: os: - - macos-latest - - macos-13 - ubuntu-latest - windows-latest test-java-version: @@ -54,41 +87,29 @@ jobs: - 17 - 21 - 24 # renovate: datasource=java-version - # macos-latest drops support for java 8 temurin. Run java 8 on macos-13. Run java 11, 17, 21 on macos-latest. - exclude: - - os: macos-latest - test-java-version: 8 - - os: macos-13 - test-java-version: 11 - - os: macos-13 - test-java-version: 17 - - os: macos-13 - test-java-version: 21 - - os: macos-13 - test-java-version: 24 # renovate: datasource=java-version steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - id: setup-java-test name: Set up Java ${{ matrix.test-java-version }} for tests - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: ${{ matrix.test-java-version }} - id: setup-java name: Set up Java for build - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 with: cache-read-only: ${{ inputs.cache-read-only }} - - name: Gradle test + - name: Test run: > ./gradlew test "-PtestJavaVersion=${{ matrix.test-java-version }}" @@ -97,25 +118,33 @@ jobs: "-PmaxTestRetries=${{ inputs.max-test-retries }}" ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + - name: Build scan + if: ${{ !cancelled() && hashFiles('build-scan.txt') != '' }} + run: cat build-scan.txt + integration-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 with: cache-read-only: ${{ inputs.cache-read-only }} - name: Integration test run: ./gradlew integrationTest "-PmaxTestRetries=${{ inputs.max-test-retries }}" ${{ inputs.no-build-cache && '--no-build-cache' || '' }} + - name: Build scan + if: ${{ !cancelled() && hashFiles('build-scan.txt') != '' }} + run: cat build-scan.txt + - name: Save integration test results uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: always() diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2620367bb..badd5f855 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,17 +21,19 @@ jobs: needs: - common runs-on: ubuntu-latest + # skipping release branches because the versions in those branches are not snapshots + if: github.ref_name == 'main' && github.repository == 'open-telemetry/opentelemetry-java-contrib' steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 - name: Build and publish snapshots run: ./gradlew assemble publishToSonatype diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 63d475c02..d22ef1ab5 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,10 +1,6 @@ name: CodeQL on: - push: - branches: - - main - - release/* pull_request: branches: - main @@ -15,6 +11,10 @@ on: # - https://github.com/github/codeql-action/issues/1537 # - https://github.com/github/codeql-action/issues/2691 # merge_group: + push: + branches: + - main + - release/* schedule: - cron: "29 13 * * 2" # weekly at 13:29 UTC on Tuesday @@ -40,17 +40,17 @@ jobs: - name: Set up Java 17 if: matrix.language == 'java' - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - name: Set up gradle if: matrix.language == 'java' - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 - name: Initialize CodeQL - uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 + uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3 with: languages: ${{ matrix.language }} # using "linked" helps to keep up with the latest Kotlin support @@ -65,6 +65,6 @@ jobs: run: ./gradlew assemble --no-build-cache --no-daemon - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 + uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 000000000..8638dc7ee --- /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@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + with: + distribution: temurin + java-version: 17 + + - name: Set up gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 + + - name: Build project and download dependencies + run: ./gradlew build -x test diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 45e549ad0..6fbd70463 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -17,4 +17,4 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - uses: gradle/actions/wrapper-validation@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - uses: gradle/actions/wrapper-validation@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 diff --git a/.github/workflows/issue-management-stale-action.yml b/.github/workflows/issue-management-stale-action.yml index 483df9b15..7282d3fcd 100644 --- a/.github/workflows/issue-management-stale-action.yml +++ b/.github/workflows/issue-management-stale-action.yml @@ -16,7 +16,7 @@ jobs: pull-requests: write # for actions/stale to close stale PRs runs-on: ubuntu-latest steps: - - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 + - uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 7 diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index 0c8d3af84..c186d16e2 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -23,7 +23,7 @@ jobs: with: persist-credentials: false - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: create-token with: # analyzing classic branch protections requires a token with admin read permissions @@ -52,6 +52,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 + uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3 with: sarif_file: results.sarif diff --git a/.github/workflows/owasp-dependency-check-daily.yml b/.github/workflows/owasp-dependency-check-daily.yml index 724b7605b..1494926ba 100644 --- a/.github/workflows/owasp-dependency-check-daily.yml +++ b/.github/workflows/owasp-dependency-check-daily.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 @@ -27,7 +27,7 @@ jobs: run: | sed -i "s/org.gradle.jvmargs=/org.gradle.jvmargs=-Xmx3g /" gradle.properties - - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + - uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 - run: ./gradlew dependencyCheckAnalyze env: diff --git a/.github/workflows/prepare-patch-release.yml b/.github/workflows/prepare-patch-release.yml index a6d2a64aa..70bfd208a 100644 --- a/.github/workflows/prepare-patch-release.yml +++ b/.github/workflows/prepare-patch-release.yml @@ -47,7 +47,7 @@ jobs: - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} diff --git a/.github/workflows/prepare-release-branch.yml b/.github/workflows/prepare-release-branch.yml index f1c5160d5..58c5dc8bb 100644 --- a/.github/workflows/prepare-release-branch.yml +++ b/.github/workflows/prepare-release-branch.yml @@ -59,7 +59,7 @@ jobs: - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} @@ -116,7 +116,7 @@ jobs: - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7b7f9af7a..68800fa37 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,64 +1,25 @@ name: Release on: workflow_dispatch: + inputs: + already-published: + description: 'Skip publishing, download artifacts from Maven Central instead' + default: false + type: boolean permissions: contents: read jobs: - build: - runs-on: ubuntu-latest - steps: - - 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: Gradle build - run: ./gradlew build - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - name: Save unit test results - if: always() - with: - name: test-results - path: jmx-metrics/build/reports/tests/test - - integration-test: - runs-on: ubuntu-latest - steps: - - 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: Integration test - run: ./gradlew integrationTest - - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - name: Save integration test results - if: always() - with: - name: integration-test-results - path: jmx-metrics/build/reports/tests/integrationTest + common: + uses: ./.github/workflows/build-common.yml release: permissions: contents: write # for creating the release runs-on: ubuntu-latest needs: - - build - - integration-test + - common outputs: version: ${{ steps.create-github-release.outputs.version }} steps: @@ -118,14 +79,16 @@ jobs: fetch-depth: 0 - name: Set up JDK for running Gradle - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: temurin java-version: 17 - name: Set up gradle - uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 + - name: Build and publish artifacts + if: ${{ !inputs.already-published }} run: ./gradlew assemble publishToSonatype closeAndReleaseSonatypeStagingRepository env: SONATYPE_USER: ${{ secrets.SONATYPE_USER }} @@ -133,6 +96,21 @@ jobs: GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} + - name: Download artifacts from Maven Central (when already published) + if: ${{ inputs.already-published }} + run: | + mkdir -p jmx-metrics/build/libs + mkdir -p jmx-scraper/build/libs + + curl -L -o jmx-metrics/build/libs/opentelemetry-jmx-metrics-$VERSION-alpha.jar \ + "https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-jmx-metrics/$VERSION-alpha/opentelemetry-jmx-metrics-$VERSION-alpha.jar" + curl -L -o jmx-metrics/build/libs/opentelemetry-jmx-metrics-$VERSION-alpha.jar.asc \ + "https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-jmx-metrics/$VERSION-alpha/opentelemetry-jmx-metrics-$VERSION-alpha.jar.asc" + curl -L -o jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar \ + "https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-jmx-scraper/$VERSION-alpha/opentelemetry-jmx-scraper-$VERSION-alpha.jar" + curl -L -o jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar.asc \ + "https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-jmx-scraper/$VERSION-alpha/opentelemetry-jmx-scraper-$VERSION-alpha.jar.asc" + - name: Generate release notes env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -182,27 +160,28 @@ jobs: cp jmx-metrics/build/libs/opentelemetry-jmx-metrics-$VERSION-alpha.jar opentelemetry-jmx-metrics.jar cp jmx-metrics/build/libs/opentelemetry-jmx-metrics-$VERSION-alpha.jar.asc opentelemetry-jmx-metrics.jar.asc cp jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar opentelemetry-jmx-scraper.jar - cp jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar opentelemetry-jmx-scraper.jar.asc + cp jmx-scraper/build/libs/opentelemetry-jmx-scraper-$VERSION-alpha.jar.asc opentelemetry-jmx-scraper.jar.asc gh release create --target $GITHUB_REF_NAME \ --title "Version $VERSION" \ --notes-file /tmp/release-notes.txt \ v$VERSION \ opentelemetry-jmx-metrics.jar \ - opentelemetry-jmx-metrics.jar.asc \ + opentelemetry-jmx-metrics.jar.asc \ opentelemetry-jmx-scraper.jar \ - opentelemetry-jmx-scraper.jar.asc - + opentelemetry-jmx-scraper.jar.asc echo "version=$VERSION" >> $GITHUB_OUTPUT - merge-change-log-to-main: + post-release-updates: permissions: contents: write # for git push to PR branch runs-on: ubuntu-latest needs: - release steps: + # add change log sync (if any) into this PR since the apidiff update + # is required before any other PR can be merged anyway - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Copy change log section from release branch @@ -224,10 +203,41 @@ jobs: release_date=$(gh release view v$VERSION --json publishedAt --jq .publishedAt | sed 's/T.*//') RELEASE_DATE=$release_date .github/scripts/merge-change-log-after-release.sh + - name: Wait for release to be available in maven central + env: + VERSION: ${{ needs.release.outputs.version }} + run: | + until curl --silent \ + --show-error \ + --output /dev/null \ + --head \ + --fail \ + https://repo1.maven.org/maven2/io/opentelemetry/contrib/opentelemetry-aws-xray/$VERSION/opentelemetry-aws-xray-$VERSION.jar + do + sleep 60 + done + + - name: Set up JDK for running Gradle + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + with: + distribution: temurin + java-version: 17 + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 + + - name: Update apidiff baseline + env: + VERSION: ${{ needs.release.outputs.version }} + PRIOR_VERSION: ${{ needs.release.outputs.prior-version }} + run: | + ./gradlew japicmp -PapiBaseVersion=$PRIOR_VERSION -PapiNewVersion=$VERSION + ./gradlew --refresh-dependencies japicmp + - name: Use CLA approved bot run: .github/scripts/use-cla-approved-bot.sh - - uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 id: otelbot-token with: app-id: ${{ vars.OTELBOT_APP_ID }} @@ -239,22 +249,14 @@ jobs: # not using secrets.GITHUB_TOKEN since pull requests from that token do not run workflows GH_TOKEN: ${{ steps.otelbot-token.outputs.token }} run: | - if git diff --quiet; then - if [[ $VERSION == *.0 ]]; then - echo there are no updates to merge, not creating pull request - exit 0 # success - else - echo patch release notes did not get applied for some reason - exit 1 # failure - fi - fi - - message="Merge change log updates from $GITHUB_REF_NAME" - body="Merge log updates from \`$GITHUB_REF_NAME\`." - branch="otelbot/merge-change-log-updates-from-${GITHUB_REF_NAME//\//-}" + message="Post-release updates for $VERSION" + body="Post-release updates for `$VERSION`." + branch="otelbot/update-apidiff-baseline-to-released-version-${VERSION}" git checkout -b $branch - git commit -a -m "$message" + git add CHANGELOG.md + git add docs/apidiffs + git commit -m "$message" git push --set-upstream origin $branch gh pr create --title "$message" \ --body "$body" \ diff --git a/.github/workflows/reusable-link-check.yml b/.github/workflows/reusable-link-check.yml index da70758ff..9cfd9ff48 100644 --- a/.github/workflows/reusable-link-check.yml +++ b/.github/workflows/reusable-link-check.yml @@ -14,11 +14,13 @@ jobs: with: fetch-depth: 0 # needed for merge-base below + - uses: jdx/mise-action@5ac50f778e26fac95da98d50503682459e86d566 # v3.2.0 + - name: Link check - relative links (all files) if: github.event_name == 'pull_request' env: GITHUB_TOKEN: ${{ github.token }} - run: ./.github/scripts/link-check.sh --local-links-only + run: mise run lint-local-links - name: Get modified files if: github.event_name == 'pull_request' @@ -26,20 +28,34 @@ jobs: run: | merge_base=$(git merge-base origin/${{ github.base_ref }} HEAD) # Using lychee's default extension filter here to match when it runs against all files - modified_files=$(git diff --name-only $merge_base...${{ github.event.pull_request.head.sha }} \ + # Note: --diff-filter=d filters out deleted files + modified_files=$(git diff --name-only --diff-filter=d $merge_base...${{ github.event.pull_request.head.sha }} \ | grep -E '\.(md|mkd|mdx|mdown|mdwn|mkdn|mkdown|markdown|html|htm|txt)$' \ | tr '\n' ' ' || true) echo "files=$modified_files" >> $GITHUB_OUTPUT echo "Modified files: $modified_files" + - name: Check if lychee config was modified + if: github.event_name == 'pull_request' + id: config-check + run: | + merge_base=$(git merge-base origin/${{ github.base_ref }} HEAD) + config_modified=$(git diff --name-only $merge_base...${{ github.event.pull_request.head.sha }} \ + | grep -E '^(\.github/config/lychee\.toml|mise\.toml)$' || true) + if [ -n "$config_modified" ]; then + echo "modified=true" >> $GITHUB_OUTPUT + else + echo "modified=false" >> $GITHUB_OUTPUT + fi + - name: Link check - all links (modified files only) if: github.event_name == 'pull_request' && steps.modified-files.outputs.files != '' env: GITHUB_TOKEN: ${{ github.token }} - run: ./.github/scripts/link-check.sh ${{ steps.modified-files.outputs.files }} + run: mise run lint-links ${{ steps.modified-files.outputs.files }} - name: Link check - all links (all files) - if: github.event_name != 'pull_request' + if: github.event_name != 'pull_request' || steps.config-check.outputs.modified == 'true' env: GITHUB_TOKEN: ${{ github.token }} - run: ./.github/scripts/link-check.sh + run: mise run lint-links diff --git a/.gitignore b/.gitignore index 641751d61..4743c99e3 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ bin .swp .gitpod.yml + +# Gradle build scans +build-scan.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index e6744eff5..1f34222ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,33 @@ ## Unreleased +## Version 1.49.0 (2025-08-25) + +### Consistent sampling + +- Add updateable threshold sampler for dynamic sampling configuration + ([#2137](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/2137)) + +### Disk buffering + +- Introduce API changes for improved disk buffering functionality + ([#2084](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/2084)) +- Implement more efficient serializer with direct disk write capabilities + ([#2138](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/2138)) + +### IBM MQ metrics - New 🌟 + +IBM MQ metrics collection utility. + +### Inferred spans + +- Update async profiler to version 4.1 for improved performance + ([#2096](https://github.com/open-telemetry/opentelemetry-java-contrib/pull/2096)) + +### OpAMP client - New 🌟 + +OpenTelemetry Agent Management Protocol (OpAMP) client implementation. + ## Version 1.48.0 (2025-07-23) ### AWS resources @@ -243,7 +270,7 @@ The extension takes care of the necessary configuration required to authenticate The future of the [JMX metrics](./jmx-metrics/README.md) component, built on top of the -[JMX metrics](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/jmx-metrics/javaagent#jmx-metric-insight) +[JMX metrics](https://github.com/open-telemetry/opentelemetry-java-instrumentation/tree/main/instrumentation/jmx-metrics#jmx-metric-insight) component from the opentelemetry-java-instrumentation repository. ### Maven extension 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..4ba3fdc12 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 @@ -84,7 +63,8 @@ For more information about the maintainer role, see the [community repository](h ### Approvers -- [John Watson](https://github.com/jkwatson), Verta.ai +- [Jay DeLuca](https://github.com/jaydeluca), Grafana +- [John Watson](https://github.com/jkwatson), Cloudera For more information about the approver role, see the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md#approver). diff --git a/all/README.md b/all/README.md deleted file mode 100644 index dca83da7b..000000000 --- a/all/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# opentelemetry-contrib-all (utility project) - -This is a utility project which depends on all other projects in this repository. -We use it for collecting all coverage reports from all modules for uploading to codecov. diff --git a/all/build.gradle.kts b/all/build.gradle.kts deleted file mode 100644 index 58f0f6d72..000000000 --- a/all/build.gradle.kts +++ /dev/null @@ -1,64 +0,0 @@ -plugins { - `jacoco-report-aggregation` - - id("otel.java-conventions") -} - -description = "OpenTelemetry Contrib All" - -dependencies { - rootProject.subprojects.forEach { subproject -> - // Generate aggregate coverage report for published modules that enable jacoco. - subproject.plugins.withId("jacoco") { - subproject.plugins.withId("maven-publish") { - // TODO(anuraaga): Figure out how to avoid transitive dependencies being pulled into jacoco due to the use - // of shadow plugin. - if (subproject.name != "jmx-metrics") { - implementation(project(subproject.path)) { - isTransitive = false - } - } - } - } - } -} - -tasks { - // We don't compile anything here. This project is mostly for - // aggregating jacoco reports and it doesn't work if this isn't at least as high as the - // highest supported Java version in any of our projects. Most of our projects target - // Java 8, but some target Java 11 or 17. - withType(JavaCompile::class) { - options.release.set(17) - } -} - -afterEvaluate { - tasks { - testCodeCoverageReport { - classDirectories.setFrom( - classDirectories.files.map { - zipTree(it).filter { - // Exclude mrjar (jacoco complains), shaded, and generated code - !it.absolutePath.contains("META-INF/versions/") && - !it.absolutePath.contains("AutoValue_") - } - }, - ) - - reports { - // xml is usually used to integrate code coverage with - // other tools like SonarQube, Coveralls or Codecov - xml.required.set(true) - - // HTML reports can be used to see code coverage - // without any external tools - html.required.set(true) - } - } - } -} - -dependencyCheck { - skip = true -} diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java index 9f294d4fb..7441b7c81 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/BeanstalkResource.java @@ -12,6 +12,7 @@ import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.SERVICE_INSTANCE_ID; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.SERVICE_NAMESPACE; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_VERSION; +import static java.util.logging.Level.WARNING; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -22,7 +23,6 @@ import io.opentelemetry.semconv.SchemaUrls; import java.io.File; import java.io.IOException; -import java.util.logging.Level; import java.util.logging.Logger; /** @@ -65,7 +65,7 @@ static Resource buildResource(String configPath) { parser.nextToken(); if (!parser.isExpectedStartObjectToken()) { - logger.log(Level.WARNING, "Invalid Beanstalk config: ", configPath); + logger.log(WARNING, "Invalid Beanstalk config: ", configPath); return Resource.create(attrBuilders.build(), SchemaUrls.V1_25_0); } @@ -87,7 +87,7 @@ static Resource buildResource(String configPath) { } } } catch (IOException e) { - logger.log(Level.WARNING, "Could not parse Beanstalk config.", e); + logger.log(WARNING, "Could not parse Beanstalk config.", e); return Resource.empty(); } diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/DockerHelper.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/DockerHelper.java index 5b8aefeac..a52cf1c18 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/DockerHelper.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/DockerHelper.java @@ -5,11 +5,12 @@ package io.opentelemetry.contrib.aws.resource; +import static java.util.logging.Level.WARNING; + import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.util.logging.Level; import java.util.logging.Logger; class DockerHelper { @@ -44,9 +45,9 @@ public String getContainerId() { } } } catch (FileNotFoundException e) { - logger.log(Level.WARNING, "Failed to read container id, cgroup file does not exist."); + logger.log(WARNING, "Failed to read container id, cgroup file does not exist."); } catch (IOException e) { - logger.log(Level.WARNING, "Unable to read container id: " + e.getMessage()); + logger.log(WARNING, "Unable to read container id: " + e.getMessage()); } return ""; diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java index d4bdb4228..5aa930b1c 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/Ec2Resource.java @@ -15,6 +15,7 @@ import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.HOST_IMAGE_ID; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.HOST_NAME; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.HOST_TYPE; +import static java.util.logging.Level.WARNING; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -28,7 +29,6 @@ import java.net.URL; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; /** @@ -125,7 +125,7 @@ static Resource buildResource(String endpoint) { } } } catch (IOException e) { - logger.log(Level.WARNING, "Could not parse identity document, resource not filled.", e); + logger.log(WARNING, "Could not parse identity document, resource not filled.", e); return Resource.empty(); } diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java index efb112de8..83440819b 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EcsResource.java @@ -26,6 +26,9 @@ import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CONTAINER_NAME; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CloudPlatformIncubatingValues.AWS_ECS; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CloudProviderIncubatingValues.AWS; +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonList; +import static java.util.logging.Level.WARNING; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -35,11 +38,9 @@ import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.SchemaUrls; import java.io.IOException; -import java.util.Collections; import java.util.Locale; import java.util.Map; import java.util.Optional; -import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -88,7 +89,7 @@ static Resource buildResource(Map sysEnv, SimpleHttpClient httpC static void fetchMetadata( SimpleHttpClient httpClient, String url, AttributesBuilder attrBuilders) { - String json = httpClient.fetchString("GET", url, Collections.emptyMap(), null); + String json = httpClient.fetchString("GET", url, emptyMap(), null); if (json.isEmpty()) { return; } @@ -103,17 +104,17 @@ static void fetchMetadata( .getLogGroupArn() .ifPresent( logGroupArn -> { - attrBuilders.put(AWS_LOG_GROUP_ARNS, Collections.singletonList(logGroupArn)); + attrBuilders.put(AWS_LOG_GROUP_ARNS, singletonList(logGroupArn)); }); logArnBuilder .getLogStreamArn() .ifPresent( logStreamArn -> { - attrBuilders.put(AWS_LOG_STREAM_ARNS, Collections.singletonList(logStreamArn)); + attrBuilders.put(AWS_LOG_STREAM_ARNS, singletonList(logStreamArn)); }); } catch (IOException e) { - logger.log(Level.WARNING, "Can't get ECS metadata", e); + logger.log(WARNING, "Can't get ECS metadata", e); } } @@ -156,7 +157,7 @@ static void parseResponse( JsonParser parser, AttributesBuilder attrBuilders, LogArnBuilder logArnBuilder) throws IOException { if (!parser.isExpectedStartObjectToken()) { - logger.log(Level.WARNING, "Couldn't parse ECS metadata, invalid JSON"); + logger.log(WARNING, "Couldn't parse ECS metadata, invalid JSON"); return; } @@ -339,7 +340,7 @@ static DockerImage parse(@Nullable String image) { } Matcher matcher = imagePattern.matcher(image); if (!matcher.matches()) { - logger.log(Level.WARNING, "Couldn't parse image '" + image + "'"); + logger.log(WARNING, "Couldn't parse image '" + image + "'"); return null; } String repository = matcher.group("repository"); diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java index 8ed3fb512..156755446 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/EksResource.java @@ -11,6 +11,8 @@ import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CloudPlatformIncubatingValues.AWS_EKS; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.CloudProviderIncubatingValues.AWS; import static io.opentelemetry.contrib.aws.resource.IncubatingAttributes.K8S_CLUSTER_NAME; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.WARNING; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; @@ -26,7 +28,6 @@ import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; /** @@ -91,7 +92,7 @@ static Resource buildResource( private static boolean isEks( String k8sTokenPath, String k8sKeystorePath, SimpleHttpClient httpClient) { if (!isK8s(k8sTokenPath, k8sKeystorePath)) { - logger.log(Level.FINE, "Not running on k8s."); + logger.log(FINE, "Not running on k8s."); return false; } @@ -145,7 +146,7 @@ private static String getClusterName(SimpleHttpClient httpClient) { } } } catch (IOException e) { - logger.log(Level.WARNING, "Can't get cluster name on EKS.", e); + logger.log(WARNING, "Can't get cluster name on EKS.", e); } return ""; } @@ -156,7 +157,7 @@ private static String getK8sCredHeader() { new String(Files.readAllBytes(Paths.get(K8S_TOKEN_PATH)), StandardCharsets.UTF_8); return "Bearer " + content; } catch (IOException e) { - logger.log(Level.WARNING, "Unable to load K8s client token.", e); + logger.log(WARNING, "Unable to load K8s client token.", e); } return ""; } diff --git a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java index 12bc6e34e..f78719d99 100644 --- a/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java +++ b/aws-resources/src/main/java/io/opentelemetry/contrib/aws/resource/SimpleHttpClient.java @@ -5,6 +5,9 @@ package io.opentelemetry.contrib.aws.resource; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.WARNING; + import java.io.FileInputStream; import java.io.IOException; import java.security.KeyStore; @@ -13,7 +16,6 @@ import java.time.Duration; import java.util.Collection; import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; import javax.net.ssl.SSLContext; @@ -72,7 +74,7 @@ public String fetchString( int responseCode = response.code(); if (responseCode != 200) { logger.log( - Level.FINE, + FINE, "Error response from " + urlStr + " code (" @@ -84,7 +86,7 @@ public String fetchString( ResponseBody body = response.body(); return body != null ? body.string() : ""; } catch (IOException e) { - logger.log(Level.FINE, "SimpleHttpClient fetch string failed.", e); + logger.log(FINE, "SimpleHttpClient fetch string failed.", e); } return ""; @@ -101,7 +103,7 @@ private static X509TrustManager buildTrustManager(@Nullable KeyStore keyStore) { tmf.init(keyStore); return (X509TrustManager) tmf.getTrustManagers()[0]; } catch (Exception e) { - logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e); + logger.log(WARNING, "Build SslSocketFactory for K8s restful client exception.", e); return null; } } @@ -117,7 +119,7 @@ private static SSLSocketFactory buildSslSocketFactory(@Nullable TrustManager tru return context.getSocketFactory(); } catch (Exception e) { - logger.log(Level.WARNING, "Build SslSocketFactory for K8s restful client exception.", e); + logger.log(WARNING, "Build SslSocketFactory for K8s restful client exception.", e); } return null; } @@ -138,7 +140,7 @@ private static KeyStore getKeystoreForTrustedCert(String certPath) { } return trustStore; } catch (Exception e) { - logger.log(Level.WARNING, "Cannot load KeyStore from " + certPath); + logger.log(WARNING, "Cannot load KeyStore from " + certPath); return null; } } diff --git a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java index 7eaec5e55..31b05be57 100644 --- a/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java +++ b/aws-resources/src/test/java/io/opentelemetry/contrib/aws/resource/EksResourceTest.java @@ -34,7 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class EksResourceTest { +class EksResourceTest { @Mock private DockerHelper mockDockerHelper; diff --git a/aws-xray-propagator/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaPropagator.java b/aws-xray-propagator/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaPropagator.java index a6b6a2ab4..b34bc961c 100644 --- a/aws-xray-propagator/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaPropagator.java +++ b/aws-xray-propagator/src/main/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayLambdaPropagator.java @@ -5,12 +5,13 @@ package io.opentelemetry.contrib.awsxray.propagator; +import static java.util.Collections.singletonMap; + import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.context.propagation.TextMapGetter; import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.context.propagation.TextMapSetter; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -75,7 +76,7 @@ public Context extract(Context context, @Nullable C carrier, TextMapGetter FIELDS = Collections.singletonList(TRACE_HEADER_KEY); + private static final List FIELDS = singletonList(TRACE_HEADER_KEY); private static final AwsXrayPropagator INSTANCE = new AwsXrayPropagator(); diff --git a/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayCompositePropagatorTest.java b/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayCompositePropagatorTest.java index 53e806fdc..99998d974 100644 --- a/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayCompositePropagatorTest.java +++ b/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/AwsXrayCompositePropagatorTest.java @@ -15,7 +15,7 @@ import java.util.LinkedHashMap; import org.junit.jupiter.api.Test; -public class AwsXrayCompositePropagatorTest extends AwsXrayPropagatorTest { +class AwsXrayCompositePropagatorTest extends AwsXrayPropagatorTest { @Override TextMapPropagator propagator() { diff --git a/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/internal/AwsComponentProviderTest.java b/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/internal/AwsComponentProviderTest.java index c2869d265..5bcd62137 100644 --- a/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/internal/AwsComponentProviderTest.java +++ b/aws-xray-propagator/src/test/java/io/opentelemetry/contrib/awsxray/propagator/internal/AwsComponentProviderTest.java @@ -21,7 +21,7 @@ class AwsComponentProviderTest { @Test void endToEnd() { String yaml = - "file_format: 0.4\n" + "file_format: 1.0-rc.1\n" + "propagator:\n" + " composite:\n" + " - xray:\n" diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsAttributeKeys.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsAttributeKeys.java index 101641f08..c9e762d63 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsAttributeKeys.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsAttributeKeys.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.awsxray; +import static io.opentelemetry.api.common.AttributeKey.stringKey; + import io.opentelemetry.api.common.AttributeKey; /** Utility class holding attribute keys with special meaning to AWS components */ @@ -12,28 +14,25 @@ final class AwsAttributeKeys { private AwsAttributeKeys() {} - static final AttributeKey AWS_SPAN_KIND = AttributeKey.stringKey("aws.span.kind"); + static final AttributeKey AWS_SPAN_KIND = stringKey("aws.span.kind"); - static final AttributeKey AWS_LOCAL_SERVICE = AttributeKey.stringKey("aws.local.service"); + static final AttributeKey AWS_LOCAL_SERVICE = stringKey("aws.local.service"); - static final AttributeKey AWS_LOCAL_OPERATION = - AttributeKey.stringKey("aws.local.operation"); + static final AttributeKey AWS_LOCAL_OPERATION = stringKey("aws.local.operation"); - static final AttributeKey AWS_REMOTE_SERVICE = - AttributeKey.stringKey("aws.remote.service"); + static final AttributeKey AWS_REMOTE_SERVICE = stringKey("aws.remote.service"); - static final AttributeKey AWS_REMOTE_OPERATION = - AttributeKey.stringKey("aws.remote.operation"); + static final AttributeKey AWS_REMOTE_OPERATION = stringKey("aws.remote.operation"); - static final AttributeKey AWS_REMOTE_TARGET = AttributeKey.stringKey("aws.remote.target"); + static final AttributeKey AWS_REMOTE_TARGET = stringKey("aws.remote.target"); // use the same AWS Resource attribute name defined by OTel java auto-instr for aws_sdk_v_1_1 // TODO: all AWS specific attributes should be defined in semconv package and reused cross all // otel packages. Related sim - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/8710 - static final AttributeKey AWS_BUCKET_NAME = AttributeKey.stringKey("aws.bucket.name"); - static final AttributeKey AWS_QUEUE_NAME = AttributeKey.stringKey("aws.queue.name"); - static final AttributeKey AWS_STREAM_NAME = AttributeKey.stringKey("aws.stream.name"); - static final AttributeKey AWS_TABLE_NAME = AttributeKey.stringKey("aws.table.name"); + static final AttributeKey AWS_BUCKET_NAME = stringKey("aws.bucket.name"); + static final AttributeKey AWS_QUEUE_NAME = stringKey("aws.queue.name"); + static final AttributeKey AWS_STREAM_NAME = stringKey("aws.stream.name"); + static final AttributeKey AWS_TABLE_NAME = stringKey("aws.table.name"); } diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java index 42275b4b1..3fed3b3f3 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGenerator.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.awsxray; +import static io.opentelemetry.api.common.AttributeKey.longKey; +import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_BUCKET_NAME; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_LOCAL_OPERATION; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_LOCAL_SERVICE; @@ -16,6 +18,7 @@ import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_STREAM_NAME; import static io.opentelemetry.contrib.awsxray.AwsAttributeKeys.AWS_TABLE_NAME; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; +import static java.util.logging.Level.FINEST; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -27,7 +30,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.Optional; -import java.util.logging.Level; import java.util.logging.Logger; /** @@ -54,36 +56,31 @@ final class AwsMetricAttributeGenerator implements MetricAttributeGenerator { private static final String UNKNOWN_REMOTE_OPERATION = "UnknownRemoteOperation"; // copied from DbIncubatingAttributes - private static final AttributeKey DB_OPERATION = AttributeKey.stringKey("db.operation"); - private static final AttributeKey DB_SYSTEM = AttributeKey.stringKey("db.system"); + private static final AttributeKey DB_OPERATION = stringKey("db.operation"); + private static final AttributeKey DB_SYSTEM = stringKey("db.system"); // copied from FaasIncubatingAttributes - private static final AttributeKey FAAS_INVOKED_NAME = - AttributeKey.stringKey("faas.invoked_name"); - private static final AttributeKey FAAS_TRIGGER = AttributeKey.stringKey("faas.trigger"); + private static final AttributeKey FAAS_INVOKED_NAME = stringKey("faas.invoked_name"); + private static final AttributeKey FAAS_TRIGGER = stringKey("faas.trigger"); // copied from GraphqlIncubatingAttributes private static final AttributeKey GRAPHQL_OPERATION_TYPE = - AttributeKey.stringKey("graphql.operation.type"); + stringKey("graphql.operation.type"); // copied from HttpIncubatingAttributes - private static final AttributeKey HTTP_METHOD = AttributeKey.stringKey("http.method"); - private static final AttributeKey HTTP_TARGET = AttributeKey.stringKey("http.target"); - private static final AttributeKey HTTP_URL = AttributeKey.stringKey("http.url"); + private static final AttributeKey HTTP_METHOD = stringKey("http.method"); + private static final AttributeKey HTTP_TARGET = stringKey("http.target"); + private static final AttributeKey HTTP_URL = stringKey("http.url"); // copied from MessagingIncubatingAttributes - private static final AttributeKey MESSAGING_OPERATION = - AttributeKey.stringKey("messaging.operation"); - private static final AttributeKey MESSAGING_SYSTEM = - AttributeKey.stringKey("messaging.system"); + private static final AttributeKey MESSAGING_OPERATION = stringKey("messaging.operation"); + private static final AttributeKey MESSAGING_SYSTEM = stringKey("messaging.system"); // copied from NetIncubatingAttributes - private static final AttributeKey NET_PEER_NAME = AttributeKey.stringKey("net.peer.name"); - private static final AttributeKey NET_PEER_PORT = AttributeKey.longKey("net.peer.port"); - private static final AttributeKey NET_SOCK_PEER_ADDR = - AttributeKey.stringKey("net.sock.peer.addr"); - private static final AttributeKey NET_SOCK_PEER_PORT = - AttributeKey.longKey("net.sock.peer.port"); + private static final AttributeKey NET_PEER_NAME = stringKey("net.peer.name"); + private static final AttributeKey NET_PEER_PORT = longKey("net.peer.port"); + private static final AttributeKey NET_SOCK_PEER_ADDR = stringKey("net.sock.peer.addr"); + private static final AttributeKey NET_SOCK_PEER_PORT = longKey("net.sock.peer.port"); // copied from PeerIncubatingAttributes - private static final AttributeKey PEER_SERVICE = AttributeKey.stringKey("peer.service"); + private static final AttributeKey PEER_SERVICE = stringKey("peer.service"); // copied from RpcIncubatingAttributes - private static final AttributeKey RPC_METHOD = AttributeKey.stringKey("rpc.method"); - private static final AttributeKey RPC_SERVICE = AttributeKey.stringKey("rpc.service"); + private static final AttributeKey RPC_METHOD = stringKey("rpc.method"); + private static final AttributeKey RPC_SERVICE = stringKey("rpc.service"); @Override public Attributes generateMetricAttributesFromSpan(SpanData span, Resource resource) { @@ -307,7 +304,7 @@ private static String generateRemoteOperation(SpanData span) { remoteOperation = extractApiPathValue(url.getPath()); } } catch (MalformedURLException e) { - logger.log(Level.FINEST, "invalid http.url attribute: ", httpUrl); + logger.log(FINEST, "invalid http.url attribute: ", httpUrl); } } if (isKeyPresent(span, HTTP_METHOD)) { @@ -387,6 +384,6 @@ private static void logUnknownAttribute(AttributeKey attributeKey, SpanD String[] params = { attributeKey.getKey(), span.getKind().name(), span.getSpanContext().getSpanId() }; - logger.log(Level.FINEST, "No valid {0} value found for {1} span {2}", params); + logger.log(FINEST, "No valid {0} value found for {1} span {2}", params); } } diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java index 244138a47..9a3e60519 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessor.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.awsxray; +import static io.opentelemetry.api.common.AttributeKey.longKey; + import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; @@ -40,8 +42,7 @@ @Immutable public final class AwsSpanMetricsProcessor implements SpanProcessor { - private static final AttributeKey HTTP_STATUS_CODE = - AttributeKey.longKey("http.status_code"); + private static final AttributeKey HTTP_STATUS_CODE = longKey("http.status_code"); private static final double NANOS_TO_MILLIS = 1_000_000.0; diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSampler.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSampler.java index ad9b72a2c..9c997f042 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSampler.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSampler.java @@ -5,6 +5,14 @@ package io.opentelemetry.contrib.awsxray; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.function.Function.identity; +import static java.util.logging.Level.FINE; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.toSet; + import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; @@ -29,17 +37,13 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; import javax.annotation.Nullable; /** Remote sampler that gets sampling configuration from AWS X-Ray. */ public final class AwsXrayRemoteSampler implements Sampler, Closeable { - static final long DEFAULT_TARGET_INTERVAL_NANOS = TimeUnit.SECONDS.toNanos(10); + static final long DEFAULT_TARGET_INTERVAL_NANOS = SECONDS.toNanos(10); private static final Logger logger = Logger.getLogger(AwsXrayRemoteSampler.class.getName()); @@ -134,7 +138,7 @@ private void getAndUpdateSampler() { initialSampler, response.getSamplingRules().stream() .map(SamplingRuleRecord::getRule) - .collect(Collectors.toList()))); + .collect(toList()))); previousRulesResponse = response; ScheduledFuture existingFetchTargetsFuture = fetchTargetsFuture; @@ -142,18 +146,17 @@ private void getAndUpdateSampler() { existingFetchTargetsFuture.cancel(false); } fetchTargetsFuture = - executor.schedule( - this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, TimeUnit.NANOSECONDS); + executor.schedule(this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, NANOSECONDS); } } catch (Throwable t) { - logger.log(Level.FINE, "Failed to update sampler", t); + logger.log(FINE, "Failed to update sampler", t); } scheduleSamplerUpdate(); } private void scheduleSamplerUpdate() { long delay = pollingIntervalNanos + jitterNanos.next(); - pollFuture = executor.schedule(this::getAndUpdateSampler, delay, TimeUnit.NANOSECONDS); + pollFuture = executor.schedule(this::getAndUpdateSampler, delay, NANOSECONDS); } /** @@ -168,7 +171,7 @@ Duration getNextSamplerUpdateScheduledDuration() { if (pollFuture == null) { return null; } - return Duration.ofNanos(pollFuture.getDelay(TimeUnit.NANOSECONDS)); + return Duration.ofNanos(pollFuture.getDelay(NANOSECONDS)); } private void fetchTargets() { @@ -181,28 +184,25 @@ private void fetchTargets() { Date now = Date.from(Instant.ofEpochSecond(0, clock.now())); List statistics = xrayRulesSampler.snapshot(now); Set requestedTargetRuleNames = - statistics.stream() - .map(SamplingStatisticsDocument::getRuleName) - .collect(Collectors.toSet()); + statistics.stream().map(SamplingStatisticsDocument::getRuleName).collect(toSet()); GetSamplingTargetsResponse response = client.getSamplingTargets(GetSamplingTargetsRequest.create(statistics)); Map targets = response.getDocuments().stream() - .collect(Collectors.toMap(SamplingTargetDocument::getRuleName, Function.identity())); + .collect(toMap(SamplingTargetDocument::getRuleName, identity())); updateInternalSamplers(xrayRulesSampler.withTargets(targets, requestedTargetRuleNames, now)); } catch (Throwable t) { // Might be a transient API failure, try again after a default interval. fetchTargetsFuture = - executor.schedule( - this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, TimeUnit.NANOSECONDS); + executor.schedule(this::fetchTargets, DEFAULT_TARGET_INTERVAL_NANOS, NANOSECONDS); return; } long nextTargetFetchIntervalNanos = xrayRulesSampler.nextTargetFetchTimeNanos() - clock.nanoTime(); fetchTargetsFuture = - executor.schedule(this::fetchTargets, nextTargetFetchIntervalNanos, TimeUnit.NANOSECONDS); + executor.schedule(this::fetchTargets, nextTargetFetchIntervalNanos, NANOSECONDS); } @Override diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerBuilder.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerBuilder.java index 1ce0d41c1..25485e4b0 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerBuilder.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/AwsXrayRemoteSamplerBuilder.java @@ -6,6 +6,8 @@ package io.opentelemetry.contrib.awsxray; import static java.util.Objects.requireNonNull; +import static java.util.concurrent.TimeUnit.NANOSECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.sdk.common.Clock; @@ -26,7 +28,7 @@ public final class AwsXrayRemoteSamplerBuilder { private Clock clock = Clock.getDefault(); private String endpoint = DEFAULT_ENDPOINT; @Nullable private Sampler initialSampler; - private long pollingIntervalNanos = TimeUnit.SECONDS.toNanos(DEFAULT_POLLING_INTERVAL_SECS); + private long pollingIntervalNanos = SECONDS.toNanos(DEFAULT_POLLING_INTERVAL_SECS); AwsXrayRemoteSamplerBuilder(Resource resource) { this.resource = resource; @@ -51,7 +53,7 @@ public AwsXrayRemoteSamplerBuilder setEndpoint(String endpoint) { @CanIgnoreReturnValue public AwsXrayRemoteSamplerBuilder setPollingInterval(Duration delay) { requireNonNull(delay, "delay"); - return setPollingInterval(delay.toNanos(), TimeUnit.NANOSECONDS); + return setPollingInterval(delay.toNanos(), NANOSECONDS); } /** diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java index 1d97c4aed..ae4cac018 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/SamplingRuleApplier.java @@ -5,7 +5,10 @@ package io.opentelemetry.contrib.awsxray; +import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; +import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.stream.Collectors.toMap; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -28,22 +31,18 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.LongAdder; import java.util.regex.Pattern; -import java.util.stream.Collectors; import javax.annotation.Nullable; final class SamplingRuleApplier { // copied from AwsIncubatingAttributes private static final AttributeKey AWS_ECS_CONTAINER_ARN = - AttributeKey.stringKey("aws.ecs.container.arn"); + stringKey("aws.ecs.container.arn"); // copied from CloudIncubatingAttributes - private static final AttributeKey CLOUD_PLATFORM = - AttributeKey.stringKey("cloud.platform"); - private static final AttributeKey CLOUD_RESOURCE_ID = - AttributeKey.stringKey("cloud.resource_id"); + private static final AttributeKey CLOUD_PLATFORM = stringKey("cloud.platform"); + private static final AttributeKey CLOUD_RESOURCE_ID = stringKey("cloud.resource_id"); // copied from CloudIncubatingAttributes.CloudPlatformIncubatingValues public static final String AWS_EC2 = "aws_ec2"; public static final String AWS_ECS = "aws_ecs"; @@ -51,12 +50,12 @@ final class SamplingRuleApplier { public static final String AWS_LAMBDA = "aws_lambda"; public static final String AWS_ELASTIC_BEANSTALK = "aws_elastic_beanstalk"; // copied from HttpIncubatingAttributes - private static final AttributeKey HTTP_HOST = AttributeKey.stringKey("http.host"); - private static final AttributeKey HTTP_METHOD = AttributeKey.stringKey("http.method"); - private static final AttributeKey HTTP_TARGET = AttributeKey.stringKey("http.target"); - private static final AttributeKey HTTP_URL = AttributeKey.stringKey("http.url"); + private static final AttributeKey HTTP_HOST = stringKey("http.host"); + private static final AttributeKey HTTP_METHOD = stringKey("http.method"); + private static final AttributeKey HTTP_TARGET = stringKey("http.target"); + private static final AttributeKey HTTP_URL = stringKey("http.url"); // copied from NetIncubatingAttributes - private static final AttributeKey NET_HOST_NAME = AttributeKey.stringKey("net.host.name"); + private static final AttributeKey NET_HOST_NAME = stringKey("net.host.name"); private static final Map XRAY_CLOUD_PLATFORM; @@ -131,7 +130,7 @@ final class SamplingRuleApplier { } else { attributeMatchers = rule.getAttributes().entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, e -> toMatcher(e.getValue()))); + .collect(toMap(Map.Entry::getKey, e -> toMatcher(e.getValue()))); } urlPathMatcher = toMatcher(rule.getUrlPath()); @@ -317,7 +316,7 @@ SamplingRuleApplier withTarget(SamplingTargetDocument target, Date now) { } long intervalNanos = target.getIntervalSecs() != null - ? TimeUnit.SECONDS.toNanos(target.getIntervalSecs()) + ? SECONDS.toNanos(target.getIntervalSecs()) : AwsXrayRemoteSampler.DEFAULT_TARGET_INTERVAL_NANOS; long newNextSnapshotTimeNanos = clock.nanoTime() + intervalNanos; diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XrayRulesSampler.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XrayRulesSampler.java index 75977dc0f..e187da972 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XrayRulesSampler.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XrayRulesSampler.java @@ -5,6 +5,9 @@ package io.opentelemetry.contrib.awsxray; +import static java.util.logging.Level.FINE; +import static java.util.stream.Collectors.toList; + import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; @@ -21,9 +24,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; final class XrayRulesSampler implements Sampler { @@ -84,7 +85,7 @@ public SamplingResult shouldSample( // In practice, X-Ray always returns a Default rule that matches all requests so it is a bug in // our code or X-Ray to reach here, fallback just in case. logger.log( - Level.FINE, + FINE, "No sampling rule matched the request. " + "This is a bug in either the OpenTelemetry SDK or X-Ray."); return fallbackSampler.shouldSample( @@ -100,7 +101,7 @@ List snapshot(Date now) { return Arrays.stream(ruleAppliers) .map(rule -> rule.snapshot(now)) .filter(Objects::nonNull) - .collect(Collectors.toList()); + .collect(toList()); } long nextTargetFetchTimeNanos() { diff --git a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XraySamplerClient.java b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XraySamplerClient.java index 5dbbbbbbf..84dbd0144 100644 --- a/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XraySamplerClient.java +++ b/aws-xray/src/main/java/io/opentelemetry/contrib/awsxray/XraySamplerClient.java @@ -25,6 +25,8 @@ package io.opentelemetry.contrib.awsxray; +import static java.util.logging.Level.FINE; + import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; @@ -37,7 +39,6 @@ import java.io.UncheckedIOException; import java.math.BigDecimal; import java.util.Date; -import java.util.logging.Level; import java.util.logging.Logger; import okhttp3.Call; import okhttp3.MediaType; @@ -51,7 +52,7 @@ final class XraySamplerClient { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() - .setSerializationInclusion(JsonInclude.Include.NON_EMPTY) + .setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY) // AWS APIs return timestamps as floats. .registerModule( new SimpleModule().addDeserializer(Date.class, new FloatDateDeserializer())) @@ -114,7 +115,7 @@ private T executeJsonRequest(String endpoint, Object request, Class respo private static String readResponse(Response response, String endpoint) throws IOException { if (!response.isSuccessful()) { logger.log( - Level.FINE, + FINE, "Error response from " + endpoint + " code (" diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AttributePropagatingSpanProcessorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AttributePropagatingSpanProcessorTest.java index b4f40e408..0bf394e0e 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AttributePropagatingSpanProcessorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AttributePropagatingSpanProcessorTest.java @@ -41,7 +41,7 @@ public void setup() { } @Test - public void testAttributesPropagation() { + void testAttributesPropagation() { Span spanWithAppOnly = tracer.spanBuilder("parent").startSpan(); spanWithAppOnly.setAttribute(testKey1, "testValue1"); validateSpanAttributesInheritance(spanWithAppOnly, null, "testValue1", null); @@ -57,7 +57,7 @@ public void testAttributesPropagation() { } @Test - public void testOverrideAttributes() { + void testOverrideAttributes() { Span parentSpan = tracer.spanBuilder("parent").startSpan(); parentSpan.setAttribute(testKey1, "testValue1"); parentSpan.setAttribute(testKey2, "testValue2"); @@ -75,13 +75,13 @@ public void testOverrideAttributes() { } @Test - public void testAttributesDoNotExist() { + void testAttributesDoNotExist() { Span span = tracer.spanBuilder("parent").startSpan(); validateSpanAttributesInheritance(span, null, null, null); } @Test - public void testSpanNamePropagationBySpanKind() { + void testSpanNamePropagationBySpanKind() { for (SpanKind value : SpanKind.values()) { Span span = tracer.spanBuilder("parent").setSpanKind(value).startSpan(); if (value == SpanKind.SERVER || value == SpanKind.CONSUMER) { @@ -93,7 +93,7 @@ public void testSpanNamePropagationBySpanKind() { } @Test - public void testSpanNamePropagationWithRemoteParentSpan() { + void testSpanNamePropagationWithRemoteParentSpan() { Span remoteParent = Span.wrap( SpanContext.createFromRemoteParent( diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java index 135a1eeff..4d38e89ff 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributeGeneratorTest.java @@ -79,7 +79,7 @@ public void setUpMocks() { } @Test - public void testConsumerSpanWithoutAttributes() { + void testConsumerSpanWithoutAttributes() { Attributes expectedAttributes = Attributes.of( AWS_SPAN_KIND, SpanKind.CONSUMER.name(), @@ -89,7 +89,7 @@ public void testConsumerSpanWithoutAttributes() { } @Test - public void testServerSpanWithoutAttributes() { + void testServerSpanWithoutAttributes() { Attributes expectedAttributes = Attributes.of( AWS_SPAN_KIND, SpanKind.SERVER.name(), @@ -99,7 +99,7 @@ public void testServerSpanWithoutAttributes() { } @Test - public void testProducerSpanWithoutAttributes() { + void testProducerSpanWithoutAttributes() { Attributes expectedAttributes = Attributes.of( AWS_SPAN_KIND, SpanKind.PRODUCER.name(), @@ -111,7 +111,7 @@ public void testProducerSpanWithoutAttributes() { } @Test - public void testClientSpanWithoutAttributes() { + void testClientSpanWithoutAttributes() { Attributes expectedAttributes = Attributes.of( AWS_SPAN_KIND, SpanKind.CLIENT.name(), @@ -123,13 +123,13 @@ public void testClientSpanWithoutAttributes() { } @Test - public void testInternalSpan() { + void testInternalSpan() { // Spans with internal span kind should not produce any attributes. validateAttributesProducedForSpanOfKind(Attributes.empty(), SpanKind.INTERNAL); } @Test - public void testConsumerSpanWithAttributes() { + void testConsumerSpanWithAttributes() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn(SPAN_NAME_VALUE); @@ -142,7 +142,7 @@ public void testConsumerSpanWithAttributes() { } @Test - public void testServerSpanWithAttributes() { + void testServerSpanWithAttributes() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn(SPAN_NAME_VALUE); @@ -155,7 +155,7 @@ public void testServerSpanWithAttributes() { } @Test - public void testServerSpanWithNullSpanName() { + void testServerSpanWithNullSpanName() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn(null); @@ -168,7 +168,7 @@ public void testServerSpanWithNullSpanName() { } @Test - public void testServerSpanWithSpanNameAsHttpMethod() { + void testServerSpanWithSpanNameAsHttpMethod() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn("GET"); mockAttribute(HTTP_METHOD, "GET"); @@ -183,7 +183,7 @@ public void testServerSpanWithSpanNameAsHttpMethod() { } @Test - public void testServerSpanWithSpanNameWithHttpTarget() { + void testServerSpanWithSpanNameWithHttpTarget() { updateResourceWithServiceName(); when(spanDataMock.getName()).thenReturn("POST"); mockAttribute(HTTP_METHOD, "POST"); @@ -203,7 +203,7 @@ public void testServerSpanWithSpanNameWithHttpTarget() { } @Test - public void testProducerSpanWithAttributes() { + void testProducerSpanWithAttributes() { updateResourceWithServiceName(); mockAttribute(AWS_LOCAL_OPERATION, AWS_LOCAL_OPERATION_VALUE); mockAttribute(AWS_REMOTE_SERVICE, AWS_REMOTE_SERVICE_VALUE); @@ -220,7 +220,7 @@ public void testProducerSpanWithAttributes() { } @Test - public void testClientSpanWithAttributes() { + void testClientSpanWithAttributes() { updateResourceWithServiceName(); mockAttribute(AWS_LOCAL_OPERATION, AWS_LOCAL_OPERATION_VALUE); mockAttribute(AWS_REMOTE_SERVICE, AWS_REMOTE_SERVICE_VALUE); @@ -237,7 +237,7 @@ public void testClientSpanWithAttributes() { } @Test - public void testRemoteAttributesCombinations() { + void testRemoteAttributesCombinations() { // Set all expected fields to a test string, we will overwrite them in descending order to test // the priority-order logic in AwsMetricAttributeGenerator remote attribute methods. mockAttribute(AWS_REMOTE_SERVICE, "TestString"); @@ -333,7 +333,7 @@ public void testRemoteAttributesCombinations() { } @Test - public void testPeerServiceDoesOverrideOtherRemoteServices() { + void testPeerServiceDoesOverrideOtherRemoteServices() { validatePeerServiceDoesOverride(RPC_SERVICE); validatePeerServiceDoesOverride(DB_SYSTEM); validatePeerServiceDoesOverride(FAAS_INVOKED_PROVIDER); @@ -346,7 +346,7 @@ public void testPeerServiceDoesOverrideOtherRemoteServices() { } @Test - public void testPeerServiceDoesNotOverrideAwsRemoteService() { + void testPeerServiceDoesNotOverrideAwsRemoteService() { mockAttribute(AWS_REMOTE_SERVICE, "TestString"); mockAttribute(PEER_SERVICE, "PeerService"); @@ -357,7 +357,7 @@ public void testPeerServiceDoesNotOverrideAwsRemoteService() { } @Test - public void testClientSpanWithRemoteTargetAttributes() { + void testClientSpanWithRemoteTargetAttributes() { // Validate behaviour of aws bucket name attribute, then remove it. mockAttribute(AWS_BUCKET_NAME, "aws_s3_bucket_name"); validateRemoteTargetAttributes(AWS_REMOTE_TARGET, "aws_s3_bucket_name"); diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributesSpanExporterTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributesSpanExporterTest.java index aedf5fa06..8502734d7 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributesSpanExporterTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsMetricAttributesSpanExporterTest.java @@ -62,7 +62,7 @@ public void setUpMocks() { } @Test - public void testPassthroughDelegations() { + void testPassthroughDelegations() { awsMetricAttributesSpanExporter.flush(); awsMetricAttributesSpanExporter.shutdown(); awsMetricAttributesSpanExporter.close(); @@ -72,7 +72,7 @@ public void testPassthroughDelegations() { } @Test - public void testExportDelegationWithoutAttributeOrModification() { + void testExportDelegationWithoutAttributeOrModification() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_NO_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); @@ -88,7 +88,7 @@ public void testExportDelegationWithoutAttributeOrModification() { } @Test - public void testExportDelegationWithAttributeButWithoutModification() { + void testExportDelegationWithAttributeButWithoutModification() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); @@ -104,7 +104,7 @@ public void testExportDelegationWithAttributeButWithoutModification() { } @Test - public void testExportDelegationWithoutAttributeButWithModification() { + void testExportDelegationWithoutAttributeButWithModification() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_NO_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -124,7 +124,7 @@ public void testExportDelegationWithoutAttributeButWithModification() { } @Test - public void testExportDelegationWithAttributeAndModification() { + void testExportDelegationWithAttributeAndModification() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -146,7 +146,7 @@ public void testExportDelegationWithAttributeAndModification() { } @Test - public void testExportDelegationWithMultipleSpans() { + void testExportDelegationWithMultipleSpans() { Attributes spanAttributes1 = buildSpanAttributes(CONTAINS_NO_ATTRIBUTES); SpanData spanDataMock1 = buildSpanDataMock(spanAttributes1); Attributes metricAttributes1 = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); @@ -185,7 +185,7 @@ public void testExportDelegationWithMultipleSpans() { } @Test - public void testOverridenAttributes() { + void testOverridenAttributes() { Attributes spanAttributes = Attributes.of( AttributeKey.stringKey("key1"), @@ -217,7 +217,7 @@ public void testOverridenAttributes() { } @Test - public void testExportDelegatingSpanDataBehaviour() { + void testExportDelegatingSpanDataBehaviour() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_ATTRIBUTES); SpanData spanDataMock = buildSpanDataMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java index 0836f5a8e..5d10a6a3d 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/AwsSpanMetricsProcessorTest.java @@ -101,13 +101,13 @@ public void setUpMocks() { } @Test - public void testIsRequired() { + void testIsRequired() { assertThat(awsSpanMetricsProcessor.isStartRequired()).isFalse(); assertThat(awsSpanMetricsProcessor.isEndRequired()).isTrue(); } @Test - public void testStartDoesNothingToSpan() { + void testStartDoesNothingToSpan() { Context parentContextMock = mock(Context.class); ReadWriteSpan spanMock = mock(ReadWriteSpan.class); awsSpanMetricsProcessor.onStart(parentContextMock, spanMock); @@ -115,7 +115,7 @@ public void testStartDoesNothingToSpan() { } @Test - public void testTearDown() { + void testTearDown() { assertThat(awsSpanMetricsProcessor.shutdown()).isEqualTo(CompletableResultCode.ofSuccess()); assertThat(awsSpanMetricsProcessor.forceFlush()).isEqualTo(CompletableResultCode.ofSuccess()); @@ -128,7 +128,7 @@ public void testTearDown() { * AwsSpanMetricsProcessor's onEnd method pertaining to metrics generation. */ @Test - public void testOnEndMetricsGenerationWithoutSpanAttributes() { + void testOnEndMetricsGenerationWithoutSpanAttributes() { Attributes spanAttributes = buildSpanAttributes(CONTAINS_NO_ATTRIBUTES); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -141,7 +141,7 @@ public void testOnEndMetricsGenerationWithoutSpanAttributes() { } @Test - public void testOnEndMetricsGenerationWithoutMetricAttributes() { + void testOnEndMetricsGenerationWithoutMetricAttributes() { Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 500L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_NO_ATTRIBUTES); @@ -154,7 +154,7 @@ public void testOnEndMetricsGenerationWithoutMetricAttributes() { } @Test - public void testOnEndMetricsGenerationWithoutEndRequired() { + void testOnEndMetricsGenerationWithoutEndRequired() { Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 500L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -167,7 +167,7 @@ public void testOnEndMetricsGenerationWithoutEndRequired() { } @Test - public void testOnEndMetricsGenerationWithLatency() { + void testOnEndMetricsGenerationWithLatency() { Attributes spanAttributes = Attributes.of(HTTP_STATUS_CODE, 200L); ReadableSpan readableSpanMock = buildReadableSpanMock(spanAttributes); Attributes metricAttributes = buildMetricAttributes(CONTAINS_ATTRIBUTES); @@ -182,7 +182,7 @@ public void testOnEndMetricsGenerationWithLatency() { } @Test - public void testOnEndMetricsGenerationWithAwsStatusCodes() { + void testOnEndMetricsGenerationWithAwsStatusCodes() { validateMetricsGeneratedForAwsStatusCode(399L, ExpectedStatusMetric.NEITHER); validateMetricsGeneratedForAwsStatusCode(400L, ExpectedStatusMetric.ERROR); validateMetricsGeneratedForAwsStatusCode(499L, ExpectedStatusMetric.ERROR); @@ -192,7 +192,7 @@ public void testOnEndMetricsGenerationWithAwsStatusCodes() { } @Test - public void testOnEndMetricsGenerationWithStatusCodes() { + void testOnEndMetricsGenerationWithStatusCodes() { // Invalid HTTP status codes validateMetricsGeneratedForHttpStatusCode(null, ExpectedStatusMetric.NEITHER); diff --git a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/ResourceHolderTest.java b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/ResourceHolderTest.java index 1140abc5f..f81f3d370 100644 --- a/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/ResourceHolderTest.java +++ b/aws-xray/src/test/java/io/opentelemetry/contrib/awsxray/ResourceHolderTest.java @@ -21,11 +21,11 @@ * Unit tests for {@link ResourceHolder}. Note that there isn't a great way to test the "default" * fallback logic, as when the test suite is run, the customize logic appears to be invoked. */ -public class ResourceHolderTest { +class ResourceHolderTest { @Test @SuppressWarnings("unchecked") - public void testCustomized() { + void testCustomized() { Resource customizedResource = Resource.create(Attributes.empty()); AutoConfigurationCustomizer mockCustomizer = mock(AutoConfigurationCustomizer.class); ResourceHolder resourceHolder = new ResourceHolder(); diff --git a/azure-resources/build.gradle.kts b/azure-resources/build.gradle.kts index c17d14787..43a154970 100644 --- a/azure-resources/build.gradle.kts +++ b/azure-resources/build.gradle.kts @@ -5,8 +5,8 @@ plugins { id("maven-publish") } -description = "OpenTelemetry GCP Resources Support" -otelJava.moduleName.set("io.opentelemetry.contrib.gcp.resource") +description = "OpenTelemetry Azure Resources Support" +otelJava.moduleName.set("io.opentelemetry.contrib.azure.resource") // enable publishing to maven local java { diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAksResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAksResourceProvider.java index 9823c6f9e..987492dd8 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAksResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAksResourceProvider.java @@ -14,7 +14,7 @@ import java.util.Optional; import java.util.function.Supplier; -public class AzureAksResourceProvider extends CloudResourceProvider { +public final class AzureAksResourceProvider extends CloudResourceProvider { private static final Map COMPUTE_MAPPING = new HashMap<>(); diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProvider.java index 74ad96334..3a658428a 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProvider.java @@ -12,6 +12,7 @@ import static io.opentelemetry.contrib.azure.resource.IncubatingAttributes.HOST_ID; import static io.opentelemetry.contrib.azure.resource.IncubatingAttributes.SERVICE_INSTANCE_ID; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; +import static java.util.Objects.requireNonNull; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; @@ -20,10 +21,9 @@ import io.opentelemetry.sdk.resources.Resource; import java.util.HashMap; import java.util.Map; -import java.util.Objects; import javax.annotation.Nullable; -public class AzureAppServiceResourceProvider extends CloudResourceProvider { +public final class AzureAppServiceResourceProvider extends CloudResourceProvider { static final AttributeKey AZURE_APP_SERVICE_STAMP_RESOURCE_ATTRIBUTE = AttributeKey.stringKey("azure.app.service.stamp"); @@ -68,7 +68,7 @@ public Attributes getAttributes() { if (detect != AzureEnvVarPlatform.APP_SERVICE) { return Attributes.empty(); } - String name = Objects.requireNonNull(env.get(WEBSITE_SITE_NAME)); + String name = requireNonNull(env.get(WEBSITE_SITE_NAME)); AttributesBuilder builder = AzureVmResourceProvider.azureAttributeBuilder(AZURE_APP_SERVICE); builder.put(SERVICE_NAME, name); diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProvider.java index 63d0f4428..014ec5b41 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProvider.java @@ -16,7 +16,7 @@ import java.util.HashMap; import java.util.Map; -public class AzureContainersResourceProvider extends CloudResourceProvider { +public final class AzureContainersResourceProvider extends CloudResourceProvider { static final String CONTAINER_APP_NAME = "CONTAINER_APP_NAME"; diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProvider.java index e35fe95c4..d98a41be4 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProvider.java @@ -19,7 +19,7 @@ import java.util.HashMap; import java.util.Map; -public class AzureFunctionsResourceProvider extends CloudResourceProvider { +public final class AzureFunctionsResourceProvider extends CloudResourceProvider { static final String FUNCTIONS_VERSION = "FUNCTIONS_EXTENSION_VERSION"; private static final String FUNCTIONS_MEM_LIMIT = "WEBSITE_MEMORY_LIMIT_MB"; diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureMetadataService.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureMetadataService.java index d5bf44520..a93413a24 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureMetadataService.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureMetadataService.java @@ -5,12 +5,13 @@ package io.opentelemetry.contrib.azure.resource; +import static java.util.Objects.requireNonNull; + import com.fasterxml.jackson.core.JsonFactory; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.time.Duration; -import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; import java.util.logging.Level; @@ -19,9 +20,11 @@ import okhttp3.Request; import okhttp3.Response; -public class AzureMetadataService { +public final class AzureMetadataService { static final JsonFactory JSON_FACTORY = new JsonFactory(); private static final URL METADATA_URL; + private static final Duration TIMEOUT = Duration.ofSeconds(5); + private static final Logger logger = Logger.getLogger(AzureMetadataService.class.getName()); static { try { @@ -31,12 +34,6 @@ public class AzureMetadataService { } } - private AzureMetadataService() {} - - private static final Duration TIMEOUT = Duration.ofSeconds(5); - - private static final Logger logger = Logger.getLogger(AzureMetadataService.class.getName()); - static Supplier> defaultClient() { return () -> fetchMetadata(METADATA_URL); } @@ -66,10 +63,12 @@ static Optional fetchMetadata(URL url) { return Optional.empty(); } - return Optional.of(Objects.requireNonNull(response.body()).string()); + return Optional.of(requireNonNull(response.body()).string()); } catch (IOException e) { logger.log(Level.FINE, "Failed to fetch Azure VM metadata", e); return Optional.empty(); } } + + private AzureMetadataService() {} } diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureResourceDetector.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureResourceDetector.java index 556e1d60c..27da91c4c 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureResourceDetector.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureResourceDetector.java @@ -11,7 +11,7 @@ import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.resources.ResourceBuilder; -public class AzureResourceDetector implements ComponentProvider { +public final class AzureResourceDetector implements ComponentProvider { @Override public Class getType() { diff --git a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureVmResourceProvider.java b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureVmResourceProvider.java index 38c983b4a..2a87a0488 100644 --- a/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureVmResourceProvider.java +++ b/azure-resources/src/main/java/io/opentelemetry/contrib/azure/resource/AzureVmResourceProvider.java @@ -34,21 +34,7 @@ import java.util.logging.Logger; import org.jetbrains.annotations.NotNull; -public class AzureVmResourceProvider extends CloudResourceProvider { - - static class Entry { - final AttributeKey key; - final Function transform; - - Entry(AttributeKey key) { - this(key, Function.identity()); - } - - Entry(AttributeKey key, Function transform) { - this.key = key; - this.transform = transform; - } - } +public final class AzureVmResourceProvider extends CloudResourceProvider { private static final Map COMPUTE_MAPPING = new HashMap<>(); @@ -161,4 +147,18 @@ private static void consumeJson(JsonParser parser, BiConsumer co consumer.accept(parser.currentName(), parser.nextTextValue()); } } + + static class Entry { + final AttributeKey key; + final Function transform; + + Entry(AttributeKey key) { + this(key, Function.identity()); + } + + Entry(AttributeKey key, Function transform) { + this.key = key; + this.transform = transform; + } + } } diff --git a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProviderTest.java b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProviderTest.java index 20d856cba..75360f0e9 100644 --- a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProviderTest.java +++ b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureAppServiceResourceProviderTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.azure.resource; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PLATFORM; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PROVIDER; @@ -16,7 +17,6 @@ import com.google.common.collect.ImmutableMap; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; -import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import java.util.HashMap; import java.util.Map; import org.jetbrains.annotations.NotNull; @@ -98,7 +98,7 @@ void isFunction() { @NotNull private static AttributesAssert createResource(Map map) { - return OpenTelemetryAssertions.assertThat( + return assertThat( new AzureAppServiceResourceProvider(map).createResource(null).getAttributes()); } } diff --git a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProviderTest.java b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProviderTest.java index 5ac1a4be7..082ceaf6a 100644 --- a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProviderTest.java +++ b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureContainersResourceProviderTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.azure.resource; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_NAME; import static io.opentelemetry.semconv.ServiceAttributes.SERVICE_VERSION; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PLATFORM; @@ -13,7 +14,6 @@ import com.google.common.collect.ImmutableMap; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; -import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import java.util.HashMap; import java.util.Map; import org.jetbrains.annotations.NotNull; @@ -50,7 +50,7 @@ void isNotContainer() { @NotNull private static AttributesAssert createResource(Map map) { - return OpenTelemetryAssertions.assertThat( + return assertThat( new AzureContainersResourceProvider(map).createResource(null).getAttributes()); } } diff --git a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProviderTest.java b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProviderTest.java index 520e44543..e2c39cc7a 100644 --- a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProviderTest.java +++ b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/AzureFunctionsResourceProviderTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.azure.resource; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PLATFORM; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PROVIDER; import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_INSTANCE; @@ -14,7 +15,6 @@ import com.google.common.collect.ImmutableMap; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; -import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import java.util.HashMap; import java.util.Map; import org.jetbrains.annotations.NotNull; @@ -55,7 +55,6 @@ void isNotFunction() { @NotNull private static AttributesAssert createResource(Map map) { - return OpenTelemetryAssertions.assertThat( - new AzureFunctionsResourceProvider(map).createResource(null).getAttributes()); + return assertThat(new AzureFunctionsResourceProvider(map).createResource(null).getAttributes()); } } diff --git a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/MetadataBasedResourceProviderTest.java b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/MetadataBasedResourceProviderTest.java index d827e8fd4..3d65c1e0a 100644 --- a/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/MetadataBasedResourceProviderTest.java +++ b/azure-resources/src/test/java/io/opentelemetry/contrib/azure/resource/MetadataBasedResourceProviderTest.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.azure.resource; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PLATFORM; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_PROVIDER; @@ -16,7 +17,6 @@ import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; -import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; @@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -public abstract class MetadataBasedResourceProviderTest { +abstract class MetadataBasedResourceProviderTest { @RegisterExtension public static final MockWebServerExtension server = new MockWebServerExtension(); @@ -47,7 +47,7 @@ private AttributesAssert mockServerResponse() { @NotNull private AttributesAssert createResource(Supplier> client) { Resource resource = getResourceProvider(client).createResource(null); - return OpenTelemetryAssertions.assertThat(resource.getAttributes()); + return assertThat(resource.getAttributes()); } @NotNull @@ -79,30 +79,30 @@ protected static String okResponse() { } @Test - public void successFromFile() { + void successFromFile() { assertDefaultAttributes(createResource(() -> Optional.of(okResponse()))); } @Test - public void successFromMockServer() { + void successFromMockServer() { server.enqueue(HttpResponse.of(MediaType.JSON, okResponse())); assertDefaultAttributes(mockServerResponse()); } @Test - public void responseNotFound() { + void responseNotFound() { server.enqueue(HttpResponse.of(HttpStatus.NOT_FOUND)); mockServerResponse().isEmpty(); } @Test - public void responseEmpty() { + void responseEmpty() { server.enqueue(HttpResponse.of("")); assertOnlyProvider(mockServerResponse()); } @Test - public void responseEmptyJson() { + void responseEmptyJson() { server.enqueue(HttpResponse.of("{}")); assertOnlyProvider(mockServerResponse()); } diff --git a/baggage-processor/README.md b/baggage-processor/README.md index 44719770b..10e98910d 100644 --- a/baggage-processor/README.md +++ b/baggage-processor/README.md @@ -25,6 +25,36 @@ processors through configuration. | `otel.java.experimental.span-attributes.copy-from-baggage.include` | Add baggage entries as span attributes, e.g. `key1,key2` or `*` to add all baggage items as keys. | | `otel.java.experimental.log-attributes.copy-from-baggage.include` | Add baggage entries as log attributes, e.g. `key1,key2` or `*` to add all baggage items as keys. | +### Usage with declarative configuration + +You can configure the baggage span and log record processors using declarative YAML configuration with the OpenTelemetry SDK. + +For the tracer provider (span processor): + +```yaml +file_format: 1.0-rc.1 +tracer_provider: + processors: + - baggage: + included: [foo] + excluded: [bar] +``` + +For the logger provider (log record processor): + +```yaml +file_format: 1.0-rc.1 +logger_provider: + processors: + - baggage: + included: [foo] + excluded: [bar] +``` + +This will configure the respective processor to include baggage keys listed in `included` and +exclude those in `excluded` as explained in +[Properties which pattern matching](https://github.com/open-telemetry/opentelemetry-configuration/blob/main/CONTRIBUTING.md#properties-which-pattern-matching). + ### Usage through programmatic activation Add the span and log processor when configuring the tracer and logger providers. diff --git a/baggage-processor/build.gradle.kts b/baggage-processor/build.gradle.kts index 017158399..0ff9dd52a 100644 --- a/baggage-processor/build.gradle.kts +++ b/baggage-processor/build.gradle.kts @@ -8,11 +8,19 @@ description = "OpenTelemetry Baggage Span Processor" otelJava.moduleName.set("io.opentelemetry.contrib.baggage.processor") dependencies { + annotationProcessor("com.google.auto.service:auto-service") + compileOnly("com.google.auto.service:auto-service-annotations") api("io.opentelemetry:opentelemetry-api") api("io.opentelemetry:opentelemetry-sdk") implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") + compileOnly("io.opentelemetry:opentelemetry-sdk-common") + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") + testAnnotationProcessor("com.google.auto.service:auto-service") + testCompileOnly("com.google.auto.service:auto-service-annotations") + testImplementation("io.opentelemetry:opentelemetry-sdk-common") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("org.mockito:mockito-inline") testImplementation("com.google.guava:guava") diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java new file mode 100644 index 000000000..be40ab97c --- /dev/null +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.internal.IncludeExcludePredicate; +import io.opentelemetry.sdk.logs.LogRecordProcessor; + +@SuppressWarnings("rawtypes") +@AutoService(ComponentProvider.class) +public class BaggageLogRecordComponentProvider implements ComponentProvider { + @Override + public String getName() { + return "baggage"; + } + + @Override + public LogRecordProcessor create(DeclarativeConfigProperties config) { + return new BaggageLogRecordProcessor( + IncludeExcludePredicate.createPatternMatching( + config.getScalarList("included", String.class), + config.getScalarList("excluded", String.class))); + } + + @Override + public Class getType() { + return LogRecordProcessor.class; + } +} diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java index 4e8c91505..474f4caef 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordProcessor.java @@ -16,15 +16,7 @@ * This log record processor copies attributes stored in {@link Baggage} into each newly created log * record. */ -public class BaggageLogRecordProcessor implements LogRecordProcessor { - - /** - * Creates a new {@link BaggageLogRecordProcessor} that copies all baggage entries into the newly - * created log record. - */ - public static BaggageLogRecordProcessor allowAllBaggageKeys() { - return new BaggageLogRecordProcessor(baggageKey -> true); - } +public final class BaggageLogRecordProcessor implements LogRecordProcessor { private final Predicate baggageKeyPredicate; @@ -36,6 +28,14 @@ public BaggageLogRecordProcessor(Predicate baggageKeyPredicate) { this.baggageKeyPredicate = baggageKeyPredicate; } + /** + * Creates a new {@link BaggageLogRecordProcessor} that copies all baggage entries into the newly + * created log record. + */ + public static BaggageLogRecordProcessor allowAllBaggageKeys() { + return new BaggageLogRecordProcessor(baggageKey -> true); + } + @Override public void onEmit(Context context, ReadWriteLogRecord logRecord) { Baggage.fromContext(context) diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java index da35512a3..2e07722e6 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizer.java @@ -5,6 +5,7 @@ package io.opentelemetry.contrib.baggage.processor; +import com.google.auto.service.AutoService; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -12,7 +13,8 @@ import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import java.util.List; -public class BaggageProcessorCustomizer implements AutoConfigurationCustomizerProvider { +@AutoService(AutoConfigurationCustomizerProvider.class) +public final class BaggageProcessorCustomizer implements AutoConfigurationCustomizerProvider { @Override public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { autoConfigurationCustomizer @@ -37,7 +39,8 @@ private static void addSpanProcessor( return; } - sdkTracerProviderBuilder.addSpanProcessor(createBaggageSpanProcessor(keys)); + // need to add before the batch span processor + sdkTracerProviderBuilder.addSpanProcessorFirst(createBaggageSpanProcessor(keys)); } static BaggageSpanProcessor createBaggageSpanProcessor(List keys) { @@ -56,7 +59,8 @@ private static void addLogRecordProcessor( return; } - sdkLoggerProviderBuilder.addLogRecordProcessor(createBaggageLogRecordProcessor(keys)); + // need to add before the batch log processor + sdkLoggerProviderBuilder.addLogRecordProcessorFirst(createBaggageLogRecordProcessor(keys)); } static BaggageLogRecordProcessor createBaggageLogRecordProcessor(List keys) { diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java new file mode 100644 index 000000000..19acb6ba7 --- /dev/null +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.internal.IncludeExcludePredicate; +import io.opentelemetry.sdk.trace.SpanProcessor; + +@SuppressWarnings("rawtypes") +@AutoService(ComponentProvider.class) +public class BaggageSpanComponentProvider implements ComponentProvider { + @Override + public String getName() { + return "baggage"; + } + + @Override + public SpanProcessor create(DeclarativeConfigProperties config) { + return new BaggageSpanProcessor( + IncludeExcludePredicate.createPatternMatching( + config.getScalarList("included", String.class), + config.getScalarList("excluded", String.class))); + } + + @Override + public Class getType() { + return SpanProcessor.class; + } +} diff --git a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java index 5f0f53d03..1ba62b19d 100644 --- a/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java +++ b/baggage-processor/src/main/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessor.java @@ -16,7 +16,7 @@ * This span processor copies attributes stored in {@link Baggage} into each newly created {@link * io.opentelemetry.api.trace.Span}. */ -public class BaggageSpanProcessor implements SpanProcessor { +public final class BaggageSpanProcessor implements SpanProcessor { private final Predicate baggageKeyPredicate; /** diff --git a/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider b/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider deleted file mode 100644 index 8eb4afb06..000000000 --- a/baggage-processor/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider +++ /dev/null @@ -1 +0,0 @@ -io.opentelemetry.contrib.baggage.processor.BaggageProcessorCustomizer diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProviderTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProviderTest.java new file mode 100644 index 000000000..1c8bd28bb --- /dev/null +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageLogRecordComponentProviderTest.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.Test; + +class BaggageLogRecordComponentProviderTest { + + @Test + void declarativeConfig() { + String yaml = + "file_format: 1.0-rc.1\n" + + "logger_provider:\n" + + " processors:\n" + + " - baggage:\n" + + " included: [foo]\n" + + " excluded: [bar]\n"; + + OpenTelemetrySdk sdk = + DeclarativeConfiguration.parseAndCreate( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + + assertThat(sdk).asString().contains("BaggageLogRecordProcessor"); + } +} diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java index bfa8835ae..645ff5334 100644 --- a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageProcessorCustomizerTest.java @@ -48,11 +48,15 @@ class BaggageProcessorCustomizerTest { private static final String MEMORY_EXPORTER = "memory"; @Test - void test_customizer() { + void test_empty_customizer() { assertCustomizer( Collections.emptyMap(), span -> assertThat(span).hasTotalAttributeCount(0), logRecord -> assertThat(logRecord).hasTotalAttributeCount(0)); + } + + @Test + void test_customizer() { Map properties = new HashMap<>(); properties.put("otel.java.experimental.span-attributes.copy-from-baggage.include", "key"); properties.put("otel.java.experimental.log-attributes.copy-from-baggage.include", "key"); @@ -117,7 +121,7 @@ private static OpenTelemetrySdk getOpenTelemetrySdk( new ComponentLoader() { @Override public List load(Class spiClass) { - if (spiClass == ConfigurableSpanExporterProvider.class) { + if (spiClass.equals(ConfigurableSpanExporterProvider.class)) { return Collections.singletonList( spiClass.cast( new ConfigurableSpanExporterProvider() { @@ -132,7 +136,7 @@ public String getName() { return MEMORY_EXPORTER; } })); - } else if (spiClass == ConfigurableLogRecordExporterProvider.class) { + } else if (spiClass.equals(ConfigurableLogRecordExporterProvider.class)) { return Collections.singletonList( spiClass.cast( new ConfigurableLogRecordExporterProvider() { @@ -155,7 +159,7 @@ public String getName() { } @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) { + void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) { try (BaggageSpanProcessor processor = BaggageProcessorCustomizer.createBaggageSpanProcessor(Collections.singletonList("*"))) { try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) { @@ -166,7 +170,7 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSp } @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches( + void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches( @Mock ReadWriteSpan span) { try (BaggageSpanProcessor processor = BaggageProcessorCustomizer.createBaggageSpanProcessor(Collections.singletonList("key"))) { @@ -184,7 +188,7 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_m } @Test - public void test_baggageLogRecordProcessor_adds_attributes_to_logRecord( + void test_baggageLogRecordProcessor_adds_attributes_to_logRecord( @Mock ReadWriteLogRecord logRecord) { try (BaggageLogRecordProcessor processor = BaggageProcessorCustomizer.createBaggageLogRecordProcessor( @@ -197,7 +201,7 @@ public void test_baggageLogRecordProcessor_adds_attributes_to_logRecord( } @Test - public void test_baggageLogRecordProcessor_adds_attributes_to_spans_when_key_filter_matches( + void test_baggageLogRecordProcessor_adds_attributes_to_spans_when_key_filter_matches( @Mock ReadWriteLogRecord logRecord) { try (BaggageLogRecordProcessor processor = BaggageProcessorCustomizer.createBaggageLogRecordProcessor( diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProviderTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProviderTest.java new file mode 100644 index 000000000..77399305e --- /dev/null +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanComponentProviderTest.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.baggage.processor; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.Test; + +class BaggageSpanComponentProviderTest { + + @Test + void declarativeConfig() { + String yaml = + "file_format: 1.0-rc.1\n" + + "tracer_provider:\n" + + " processors:\n" + + " - baggage:\n" + + " included: [foo]\n" + + " excluded: [bar]\n"; + + OpenTelemetrySdk sdk = + DeclarativeConfiguration.parseAndCreate( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + + assertThat(sdk).asString().contains("BaggageSpanProcessor"); + } +} diff --git a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessorTest.java b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessorTest.java index ca1180dcc..dd7ea3826 100644 --- a/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessorTest.java +++ b/baggage-processor/src/test/java/io/opentelemetry/contrib/baggage/processor/BaggageSpanProcessorTest.java @@ -17,10 +17,10 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class BaggageSpanProcessorTest { +class BaggageSpanProcessorTest { @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) { + void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSpan span) { try (BaggageSpanProcessor processor = BaggageSpanProcessor.allowAllBaggageKeys()) { try (Scope ignore = Baggage.current().toBuilder().put("key", "value").build().makeCurrent()) { processor.onStart(Context.current(), span); @@ -30,7 +30,7 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans(@Mock ReadWriteSp } @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches( + void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches( @Mock ReadWriteSpan span) { try (BaggageSpanProcessor processor = new BaggageSpanProcessor(key -> key.startsWith("k"))) { try (Scope ignore = @@ -47,7 +47,7 @@ public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_m } @Test - public void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches_regex( + void test_baggageSpanProcessor_adds_attributes_to_spans_when_key_filter_matches_regex( @Mock ReadWriteSpan span) { Pattern pattern = Pattern.compile("k.*"); try (BaggageSpanProcessor processor = diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 6de6f8e1e..03f959388 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -14,10 +14,12 @@ dependencies { // When updating, update above in plugins too implementation("com.diffplug.spotless:spotless-plugin-gradle:7.2.1") implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.3.0") - implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.2.0") + implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.3.0") implementation("org.owasp:dependency-check-gradle:12.1.3") implementation("ru.vyarus.animalsniffer:ru.vyarus.animalsniffer.gradle.plugin:2.0.1") implementation("com.gradle:develocity-gradle-plugin:4.1.1") + implementation("me.champeau.gradle:japicmp-gradle-plugin:0.4.6") + implementation("com.google.auto.value:auto-value-annotations:1.11.0") } spotless { diff --git a/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts new file mode 100644 index 000000000..3905c2526 --- /dev/null +++ b/buildSrc/src/main/kotlin/otel.japicmp-conventions.gradle.kts @@ -0,0 +1,158 @@ +import com.google.auto.value.AutoValue +import japicmp.model.* +import me.champeau.gradle.japicmp.JapicmpTask +import me.champeau.gradle.japicmp.report.Violation +import me.champeau.gradle.japicmp.report.stdrules.* + + +plugins { + base + + id("me.champeau.gradle.japicmp") +} + +/** + * The latest *released* version of the project. Evaluated lazily so the work is only done if necessary. + */ +val latestReleasedVersion: String by lazy { + // hack to find the current released version of the project + val temp: Configuration = configurations.create("tempConfig") { + resolutionStrategy.cacheChangingModulesFor(0, "seconds") + resolutionStrategy.cacheDynamicVersionsFor(0, "seconds") + } + // pick aws-xray, since it's a stable module that's always there. + dependencies.add(temp.name, "io.opentelemetry.contrib:opentelemetry-aws-xray:latest.release") + val moduleVersion = configurations["tempConfig"].resolvedConfiguration.firstLevelModuleDependencies.elementAt(0).moduleVersion + configurations.remove(temp) + logger.debug("Discovered latest release version: " + moduleVersion) + moduleVersion +} + +class AllowNewAbstractMethodOnAutovalueClasses : AbstractRecordingSeenMembers() { + override fun maybeAddViolation(member: JApiCompatibility): Violation? { + val allowableAutovalueChanges = setOf(JApiCompatibilityChangeType.METHOD_ABSTRACT_ADDED_TO_CLASS, + JApiCompatibilityChangeType.METHOD_ADDED_TO_PUBLIC_CLASS, JApiCompatibilityChangeType.ANNOTATION_ADDED) + if (member.compatibilityChanges.filter { !allowableAutovalueChanges.contains(it.type) }.isEmpty() && + member is JApiMethod && isAutoValueClass(member.getjApiClass())) + { + return Violation.accept(member, "Autovalue will automatically add implementation") + } + if (member.compatibilityChanges.isEmpty() && + member is JApiClass && isAutoValueClass(member)) { + return Violation.accept(member, "Autovalue class modification is allowed") + } + return null + } + + fun isAutoValueClass(japiClass: JApiClass): Boolean { + return japiClass.newClass.get().getAnnotation(AutoValue::class.java) != null || + japiClass.newClass.get().getAnnotation(AutoValue.Builder::class.java) != null + } +} + +class SourceIncompatibleRule : AbstractRecordingSeenMembers() { + override fun maybeAddViolation(member: JApiCompatibility): Violation? { + if (!member.isSourceCompatible()) { + return Violation.error(member, "Not source compatible: $member") + } + return null + } +} + +/** + * Locate the project's artifact of a particular version. + */ +fun findArtifact(version: String): File { + val existingGroup = group + try { + // Temporarily change the group name because we want to fetch an artifact with the same + // Maven coordinates as the project, which Gradle would not allow otherwise. + group = "virtual_group" + val depModule = "io.opentelemetry.contrib:${base.archivesName.get()}:$version@jar" + val depJar = "${base.archivesName.get()}-$version.jar" + val configuration: Configuration = configurations.detachedConfiguration( + dependencies.create(depModule), + ) + return files(configuration.files).filter { + it.name.equals(depJar) + }.singleFile + } finally { + group = existingGroup + } +} + +// generate the api diff report for any module that is stable and publishes a jar. +if (project.findProperty("otel.stable") == "true" && !project.name.startsWith("bom")) { + afterEvaluate { + tasks { + val jApiCmp by registering(JapicmpTask::class) { + dependsOn("jar") + + // the japicmp "new" version is either the user-specified one, or the locally built jar. + val apiNewVersion: String? by project + val newArtifact = apiNewVersion?.let { findArtifact(it) } + ?: file(getByName("jar").archiveFile) + newClasspath.from(files(newArtifact)) + + // only output changes, not everything + onlyModified.set(true) + + // the japicmp "old" version is either the user-specified one, or the latest release. + val apiBaseVersion: String? by project + val baselineVersion = apiBaseVersion ?: latestReleasedVersion + oldClasspath.from( + try { + files(findArtifact(baselineVersion)) + } catch (e: Exception) { + // if we can't find the baseline artifact, this is probably one that's never been published before, + // so publish the whole API. We do that by flipping this flag, and comparing the current against nothing. + onlyModified.set(false) + files() + }, + ) + + // Reproduce defaults from https://github.com/melix/japicmp-gradle-plugin/blob/09f52739ef1fccda6b4310cf3f4b19dc97377024/src/main/java/me/champeau/gradle/japicmp/report/ViolationsGenerator.java#L130 + // with some changes. + val exclusions = mutableListOf() + // Generics are not detected correctly + exclusions.add("CLASS_GENERIC_TEMPLATE_CHANGED") + // Allow new default methods on interfaces + exclusions.add("METHOD_NEW_DEFAULT") + // Allow adding default implementations for default methods + exclusions.add("METHOD_ABSTRACT_NOW_DEFAULT") + // Bug prevents recognizing default methods of superinterface. + // Fixed in https://github.com/siom79/japicmp/pull/343 but not yet available in me.champeau.gradle.japicmp + exclusions.add("METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE") + compatibilityChangeExcludes.set(exclusions) + richReport { + addSetupRule(RecordSeenMembersSetup::class.java) + addRule(JApiChangeStatus.NEW, SourceCompatibleRule::class.java) + addRule(JApiChangeStatus.MODIFIED, SourceCompatibleRule::class.java) + addRule(JApiChangeStatus.UNCHANGED, UnchangedMemberRule::class.java) + // Allow new abstract methods on autovalue + addRule(AllowNewAbstractMethodOnAutovalueClasses::class.java) + addRule(BinaryIncompatibleRule::class.java) + // Disallow source incompatible changes, which are allowed by default for some reason + addRule(SourceIncompatibleRule::class.java) + } + + // this is needed so that we only consider the current artifact, and not dependencies + ignoreMissingClasses.set(true) + packageExcludes.addAll( + "*.internal", + "*.internal.*" + ) + annotationExcludes.add("@kotlin.Metadata") + val baseVersionString = if (apiBaseVersion == null) "latest" else baselineVersion + txtOutputFile.set( + apiNewVersion?.let { file("$rootDir/docs/apidiffs/${apiNewVersion}_vs_$baselineVersion/${base.archivesName.get()}.txt") } + ?: file("$rootDir/docs/apidiffs/current_vs_$baseVersionString/${base.archivesName.get()}.txt"), + ) + } + // have the check task depend on the api comparison task, to make it more likely it will get used. + named("check") { + dependsOn(jApiCmp) + } + } + } +} diff --git a/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts index e3639a9d5..48f443d67 100644 --- a/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts @@ -7,6 +7,7 @@ plugins { id("otel.errorprone-conventions") id("otel.spotless-conventions") + id("otel.japicmp-conventions") id("org.owasp.dependencycheck") } @@ -106,12 +107,13 @@ plugins.withId("otel.publish-conventions") { register("generateVersionResource") { val moduleName = otelJava.moduleName val propertiesDir = moduleName.map { layout.buildDirectory.file("generated/properties/${it.replace('.', '/')}") } + val projectVersion = project.version.toString() - inputs.property("project.version", project.version.toString()) + inputs.property("project.version", projectVersion) outputs.dir(propertiesDir) doLast { - File(propertiesDir.get().get().asFile, "version.properties").writeText("contrib.version=${project.version}") + File(propertiesDir.get().get().asFile, "version.properties").writeText("contrib.version=${projectVersion}") } } } @@ -151,7 +153,7 @@ testing { implementation(enforcedPlatform("org.junit:junit-bom:5.13.4")) implementation(enforcedPlatform("org.testcontainers:testcontainers-bom:1.21.3")) implementation(enforcedPlatform("com.google.guava:guava-bom:33.4.8-jre")) - implementation(enforcedPlatform("com.linecorp.armeria:armeria-bom:1.33.1")) + implementation(enforcedPlatform("com.linecorp.armeria:armeria-bom:1.33.2")) compileOnly("com.google.auto.value:auto-value-annotations") compileOnly("com.google.errorprone:error_prone_annotations") diff --git a/buildSrc/src/main/kotlin/otel.spotless-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.spotless-conventions.gradle.kts index b1c39dcd0..f3d387872 100644 --- a/buildSrc/src/main/kotlin/otel.spotless-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/otel.spotless-conventions.gradle.kts @@ -8,11 +8,12 @@ spotless { licenseHeaderFile(rootProject.file("buildscripts/spotless.license.java"), "(package|import|public|// Includes work from:)") target("src/**/*.java") } - plugins.withId("groovy") { - groovy { - licenseHeaderFile(rootProject.file("buildscripts/spotless.license.java"), "(package|import|class)") - } - } + // commented out for now due to incompatibility with gradle cache configuration + // plugins.withId("groovy") { + // groovy { + // licenseHeaderFile(rootProject.file("buildscripts/spotless.license.java"), "(package|import|class)") + // } + // } plugins.withId("scala") { scala { scalafmt() diff --git a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResource.java b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResource.java index 7d6313928..c8e7bd2f2 100644 --- a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResource.java +++ b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResource.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.cloudfoundry.resources; +import static io.opentelemetry.api.common.AttributeKey.stringKey; + import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; @@ -22,24 +24,22 @@ public final class CloudFoundryResource { private static final String ENV_VCAP_APPLICATION = "VCAP_APPLICATION"; // copied from CloudfoundryIncubatingAttributes - private static final AttributeKey CLOUDFOUNDRY_APP_ID = - AttributeKey.stringKey("cloudfoundry.app.id"); + private static final AttributeKey CLOUDFOUNDRY_APP_ID = stringKey("cloudfoundry.app.id"); private static final AttributeKey CLOUDFOUNDRY_APP_INSTANCE_ID = - AttributeKey.stringKey("cloudfoundry.app.instance.id"); + stringKey("cloudfoundry.app.instance.id"); private static final AttributeKey CLOUDFOUNDRY_APP_NAME = - AttributeKey.stringKey("cloudfoundry.app.name"); - private static final AttributeKey CLOUDFOUNDRY_ORG_ID = - AttributeKey.stringKey("cloudfoundry.org.id"); + stringKey("cloudfoundry.app.name"); + private static final AttributeKey CLOUDFOUNDRY_ORG_ID = stringKey("cloudfoundry.org.id"); private static final AttributeKey CLOUDFOUNDRY_ORG_NAME = - AttributeKey.stringKey("cloudfoundry.org.name"); + stringKey("cloudfoundry.org.name"); private static final AttributeKey CLOUDFOUNDRY_PROCESS_ID = - AttributeKey.stringKey("cloudfoundry.process.id"); + stringKey("cloudfoundry.process.id"); private static final AttributeKey CLOUDFOUNDRY_PROCESS_TYPE = - AttributeKey.stringKey("cloudfoundry.process.type"); + stringKey("cloudfoundry.process.type"); private static final AttributeKey CLOUDFOUNDRY_SPACE_ID = - AttributeKey.stringKey("cloudfoundry.space.id"); + stringKey("cloudfoundry.space.id"); private static final AttributeKey CLOUDFOUNDRY_SPACE_NAME = - AttributeKey.stringKey("cloudfoundry.space.name"); + stringKey("cloudfoundry.space.name"); private static final Logger LOG = Logger.getLogger(CloudFoundryResource.class.getName()); private static final JsonFactory JSON_FACTORY = new JsonFactory(); private static final Resource INSTANCE = buildResource(System::getenv); diff --git a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceDetector.java b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceDetector.java index 02b9a6b09..357d83533 100644 --- a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceDetector.java +++ b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceDetector.java @@ -9,7 +9,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.resources.Resource; -public class CloudFoundryResourceDetector implements ComponentProvider { +public final class CloudFoundryResourceDetector implements ComponentProvider { @Override public Class getType() { diff --git a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceProvider.java b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceProvider.java index e3f3e3c64..992eb93dc 100644 --- a/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceProvider.java +++ b/cloudfoundry-resources/src/main/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceProvider.java @@ -9,7 +9,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; -public class CloudFoundryResourceProvider implements ResourceProvider { +public final class CloudFoundryResourceProvider implements ResourceProvider { @Override public Resource createResource(ConfigProperties configProperties) { diff --git a/cloudfoundry-resources/src/test/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceTest.java b/cloudfoundry-resources/src/test/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceTest.java index 1c533cd8a..96474c966 100644 --- a/cloudfoundry-resources/src/test/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceTest.java +++ b/cloudfoundry-resources/src/test/java/io/opentelemetry/contrib/cloudfoundry/resources/CloudFoundryResourceTest.java @@ -5,7 +5,9 @@ package io.opentelemetry.contrib.cloudfoundry.resources; +import static java.util.stream.Collectors.joining; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.SchemaUrls; @@ -18,8 +20,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.stream.Collectors; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; class CloudFoundryResourceTest { @@ -36,11 +36,11 @@ private static String loadVcapApplicationSample(String filename) { if (is != null) { return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)) .lines() - .collect(Collectors.joining()); + .collect(joining()); } - Assertions.fail("Cannot load resource " + filename); + fail("Cannot load resource " + filename); } catch (IOException e) { - Assertions.fail("Error reading " + filename); + fail("Error reading " + filename); } return ""; } diff --git a/consistent-sampling/build.gradle.kts b/consistent-sampling/build.gradle.kts index 66fca90c9..5fc4135bb 100644 --- a/consistent-sampling/build.gradle.kts +++ b/consistent-sampling/build.gradle.kts @@ -9,8 +9,8 @@ otelJava.moduleName.set("io.opentelemetry.contrib.sampler") dependencies { api("io.opentelemetry:opentelemetry-sdk-trace") api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") - testImplementation("org.hipparchus:hipparchus-core:4.0.1") - testImplementation("org.hipparchus:hipparchus-stat:4.0.1") + testImplementation("org.hipparchus:hipparchus-core:4.0.2") + testImplementation("org.hipparchus:hipparchus-stat:4.0.2") } tasks { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentProbabilityBasedSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentProbabilityBasedSamplerTest.java index 4b9d3e425..a05506bc8 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentProbabilityBasedSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentProbabilityBasedSamplerTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.sampler.consistent; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; @@ -25,7 +24,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class ConsistentProbabilityBasedSamplerTest { +class ConsistentProbabilityBasedSamplerTest { private Context parentContext; private String traceId; @@ -63,8 +62,8 @@ private void test(SplittableRandom rng, double samplingProbability) { .getUpdatedTraceState(TraceState.getDefault()) .get(OtelTraceState.TRACE_STATE_KEY); OtelTraceState traceState = OtelTraceState.parse(traceStateString); - assertTrue(traceState.hasValidR()); - assertTrue(traceState.hasValidP()); + assertThat(traceState.hasValidR()).isTrue(); + assertThat(traceState.hasValidP()).isTrue(); observedPvalues.merge(traceState.getP(), 1L, Long::sum); } } @@ -72,7 +71,7 @@ private void test(SplittableRandom rng, double samplingProbability) { } @Test - public void test() { + void test() { // fix seed to get reproducible results SplittableRandom random = new SplittableRandom(0); diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentReservoirSamplingSpanProcessorTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentReservoirSamplingSpanProcessorTest.java index 5eaefd482..1415d0f6f 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentReservoirSamplingSpanProcessorTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentReservoirSamplingSpanProcessorTest.java @@ -11,7 +11,6 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.argThat; @@ -566,8 +565,8 @@ private void testConsistentSampling( String traceStateString = spanData.getSpanContext().getTraceState().get(OtelTraceState.TRACE_STATE_KEY); OtelTraceState traceState = OtelTraceState.parse(traceStateString); - assertTrue(traceState.hasValidR()); - assertTrue(traceState.hasValidP()); + assertThat(traceState.hasValidR()).isTrue(); + assertThat(traceState.hasValidP()).isTrue(); observedPvalues.merge(traceState.getP(), 1L, Long::sum); totalAdjustedCount += 1L << traceState.getP(); spanNameCounts.merge(spanData.getName(), 1L, Long::sum); diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentSamplerTest.java index 082ac3068..1a61868c8 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/ConsistentSamplerTest.java @@ -8,9 +8,7 @@ import static io.opentelemetry.contrib.sampler.consistent.OtelTraceState.getInvalidP; import static io.opentelemetry.contrib.sampler.consistent.OtelTraceState.getInvalidR; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.Span; @@ -32,45 +30,50 @@ class ConsistentSamplerTest { @Test void testGetSamplingRate() { - assertThrows( - IllegalArgumentException.class, () -> ConsistentSampler.getSamplingProbability(-1)); + assertThatThrownBy(() -> ConsistentSampler.getSamplingProbability(-1)) + .isInstanceOf(IllegalArgumentException.class); for (int i = 0; i < OtelTraceState.getMaxP() - 1; i += 1) { - assertEquals(Math.pow(0.5, i), ConsistentSampler.getSamplingProbability(i)); + assertThat(ConsistentSampler.getSamplingProbability(i)).isEqualTo(Math.pow(0.5, i)); } - assertEquals(0., ConsistentSampler.getSamplingProbability(OtelTraceState.getMaxP())); - assertThrows( - IllegalArgumentException.class, - () -> ConsistentSampler.getSamplingProbability(OtelTraceState.getMaxP() + 1)); + assertThat(ConsistentSampler.getSamplingProbability(OtelTraceState.getMaxP())).isEqualTo(0.); + assertThatThrownBy(() -> ConsistentSampler.getSamplingProbability(OtelTraceState.getMaxP() + 1)) + .isInstanceOf(IllegalArgumentException.class); } @Test void testGetLowerBoundP() { - assertEquals(0, ConsistentSampler.getLowerBoundP(1.0)); - assertEquals(0, ConsistentSampler.getLowerBoundP(Math.nextDown(1.0))); + assertThat(ConsistentSampler.getLowerBoundP(1.0)).isEqualTo(0); + assertThat(ConsistentSampler.getLowerBoundP(Math.nextDown(1.0))).isEqualTo(0); for (int i = 1; i < OtelTraceState.getMaxP() - 1; i += 1) { double samplingProbability = Math.pow(0.5, i); - assertEquals(i, ConsistentSampler.getLowerBoundP(samplingProbability)); - assertEquals(i - 1, ConsistentSampler.getLowerBoundP(Math.nextUp(samplingProbability))); - assertEquals(i, ConsistentSampler.getLowerBoundP(Math.nextDown(samplingProbability))); + assertThat(ConsistentSampler.getLowerBoundP(samplingProbability)).isEqualTo(i); + assertThat(ConsistentSampler.getLowerBoundP(Math.nextUp(samplingProbability))) + .isEqualTo(i - 1); + assertThat(ConsistentSampler.getLowerBoundP(Math.nextDown(samplingProbability))).isEqualTo(i); } - assertEquals(OtelTraceState.getMaxP() - 1, ConsistentSampler.getLowerBoundP(Double.MIN_NORMAL)); - assertEquals(OtelTraceState.getMaxP() - 1, ConsistentSampler.getLowerBoundP(Double.MIN_VALUE)); - assertEquals(OtelTraceState.getMaxP(), ConsistentSampler.getLowerBoundP(0.0)); + assertThat(ConsistentSampler.getLowerBoundP(Double.MIN_NORMAL)) + .isEqualTo(OtelTraceState.getMaxP() - 1); + assertThat(ConsistentSampler.getLowerBoundP(Double.MIN_VALUE)) + .isEqualTo(OtelTraceState.getMaxP() - 1); + assertThat(ConsistentSampler.getLowerBoundP(0.0)).isEqualTo(OtelTraceState.getMaxP()); } @Test void testGetUpperBoundP() { - assertEquals(0, ConsistentSampler.getUpperBoundP(1.0)); - assertEquals(1, ConsistentSampler.getUpperBoundP(Math.nextDown(1.0))); + assertThat(ConsistentSampler.getUpperBoundP(1.0)).isEqualTo(0); + assertThat(ConsistentSampler.getUpperBoundP(Math.nextDown(1.0))).isEqualTo(1); for (int i = 1; i < OtelTraceState.getMaxP() - 1; i += 1) { double samplingProbability = Math.pow(0.5, i); - assertEquals(i, ConsistentSampler.getUpperBoundP(samplingProbability)); - assertEquals(i, ConsistentSampler.getUpperBoundP(Math.nextUp(samplingProbability))); - assertEquals(i + 1, ConsistentSampler.getUpperBoundP(Math.nextDown(samplingProbability))); + assertThat(ConsistentSampler.getUpperBoundP(samplingProbability)).isEqualTo(i); + assertThat(ConsistentSampler.getUpperBoundP(Math.nextUp(samplingProbability))).isEqualTo(i); + assertThat(ConsistentSampler.getUpperBoundP(Math.nextDown(samplingProbability))) + .isEqualTo(i + 1); } - assertEquals(OtelTraceState.getMaxP(), ConsistentSampler.getUpperBoundP(Double.MIN_NORMAL)); - assertEquals(OtelTraceState.getMaxP(), ConsistentSampler.getUpperBoundP(Double.MIN_VALUE)); - assertEquals(OtelTraceState.getMaxP(), ConsistentSampler.getUpperBoundP(0.0)); + assertThat(ConsistentSampler.getUpperBoundP(Double.MIN_NORMAL)) + .isEqualTo(OtelTraceState.getMaxP()); + assertThat(ConsistentSampler.getUpperBoundP(Double.MIN_VALUE)) + .isEqualTo(OtelTraceState.getMaxP()); + assertThat(ConsistentSampler.getUpperBoundP(0.0)).isEqualTo(OtelTraceState.getMaxP()); } @Test @@ -168,18 +171,18 @@ private static void assertConsistentSampling( SamplingResult samplingResult = sampler.shouldSample(parentContext, traceId, name, spanKind, attributes, parentLinks); - assertEquals(expectSampled, getSampledFlag(samplingResult)); + assertThat(getSampledFlag(samplingResult)).isEqualTo(expectSampled); OptionalInt p = getP(samplingResult, parentContext); if (OtelTraceState.isValidP(expectedP)) { - assertEquals(expectedP, p.getAsInt()); + assertThat(p.getAsInt()).isEqualTo(expectedP); } else { - assertFalse(p.isPresent()); + assertThat(p.isPresent()).isFalse(); } OptionalInt r = getR(samplingResult, parentContext); if (OtelTraceState.isValidR(expectedR)) { - assertEquals(expectedR, r.getAsInt()); + assertThat(r.getAsInt()).isEqualTo(expectedR); } else { - assertFalse(r.isPresent()); + assertThat(r.isPresent()).isFalse(); } } diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/OtelTraceStateTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/OtelTraceStateTest.java index a6fd85d47..fbb6b6dc7 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/OtelTraceStateTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/OtelTraceStateTest.java @@ -5,75 +5,72 @@ package io.opentelemetry.contrib.sampler.consistent; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class OtelTraceStateTest { +class OtelTraceStateTest { private static String getXString(int len) { return Stream.generate(() -> "X").limit(len).collect(Collectors.joining()); } @Test - public void test() { + void test() { - Assertions.assertEquals("", OtelTraceState.parse("").serialize()); - assertEquals("", OtelTraceState.parse("").serialize()); + assertThat(OtelTraceState.parse("").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("").serialize()).isEqualTo(""); - assertEquals("", OtelTraceState.parse("a").serialize()); - assertEquals("", OtelTraceState.parse("#").serialize()); - assertEquals("", OtelTraceState.parse(" ").serialize()); + assertThat(OtelTraceState.parse("a").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("#").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse(" ").serialize()).isEqualTo(""); - assertEquals("p:5", OtelTraceState.parse("p:5").serialize()); - assertEquals("p:63", OtelTraceState.parse("p:63").serialize()); - assertEquals("", OtelTraceState.parse("p:64").serialize()); - assertEquals("", OtelTraceState.parse("p:5;").serialize()); - assertEquals("", OtelTraceState.parse("p:99").serialize()); - assertEquals("", OtelTraceState.parse("p:").serialize()); - assertEquals("", OtelTraceState.parse("p:232").serialize()); - assertEquals("", OtelTraceState.parse("x;p:5").serialize()); - assertEquals("", OtelTraceState.parse("p:5;x").serialize()); - assertEquals("p:5;x:3", OtelTraceState.parse("x:3;p:5").serialize()); - assertEquals("p:5;x:3", OtelTraceState.parse("p:5;x:3").serialize()); - assertEquals("", OtelTraceState.parse("p:5;x:3;").serialize()); - assertEquals( - "p:5;a:" + getXString(246) + ";x:3", - OtelTraceState.parse("a:" + getXString(246) + ";p:5;x:3").serialize()); - assertEquals("", OtelTraceState.parse("a:" + getXString(247) + ";p:5;x:3").serialize()); + assertThat(OtelTraceState.parse("p:5").serialize()).isEqualTo("p:5"); + assertThat(OtelTraceState.parse("p:63").serialize()).isEqualTo("p:63"); + assertThat(OtelTraceState.parse("p:64").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:5;").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:99").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:232").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("x;p:5").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p:5;x").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("x:3;p:5").serialize()).isEqualTo("p:5;x:3"); + assertThat(OtelTraceState.parse("p:5;x:3").serialize()).isEqualTo("p:5;x:3"); + assertThat(OtelTraceState.parse("p:5;x:3;").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("a:" + getXString(246) + ";p:5;x:3").serialize()) + .isEqualTo("p:5;a:" + getXString(246) + ";x:3"); + assertThat(OtelTraceState.parse("a:" + getXString(247) + ";p:5;x:3").serialize()).isEqualTo(""); - assertEquals("r:5", OtelTraceState.parse("r:5").serialize()); - assertEquals("r:62", OtelTraceState.parse("r:62").serialize()); - assertEquals("", OtelTraceState.parse("r:63").serialize()); - assertEquals("", OtelTraceState.parse("r:5;").serialize()); - assertEquals("", OtelTraceState.parse("r:99").serialize()); - assertEquals("", OtelTraceState.parse("r:").serialize()); - assertEquals("", OtelTraceState.parse("r:232").serialize()); - assertEquals("", OtelTraceState.parse("x;r:5").serialize()); - assertEquals("", OtelTraceState.parse("r:5;x").serialize()); - assertEquals("r:5;x:3", OtelTraceState.parse("x:3;r:5").serialize()); - assertEquals("r:5;x:3", OtelTraceState.parse("r:5;x:3").serialize()); - assertEquals("", OtelTraceState.parse("r:5;x:3;").serialize()); - assertEquals( - "r:5;a:" + getXString(246) + ";x:3", - OtelTraceState.parse("a:" + getXString(246) + ";r:5;x:3").serialize()); - assertEquals("", OtelTraceState.parse("a:" + getXString(247) + ";r:5;x:3").serialize()); + assertThat(OtelTraceState.parse("r:5").serialize()).isEqualTo("r:5"); + assertThat(OtelTraceState.parse("r:62").serialize()).isEqualTo("r:62"); + assertThat(OtelTraceState.parse("r:63").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:5;").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:99").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:232").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("x;r:5").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("r:5;x").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("x:3;r:5").serialize()).isEqualTo("r:5;x:3"); + assertThat(OtelTraceState.parse("r:5;x:3").serialize()).isEqualTo("r:5;x:3"); + assertThat(OtelTraceState.parse("r:5;x:3;").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("a:" + getXString(246) + ";r:5;x:3").serialize()) + .isEqualTo("r:5;a:" + getXString(246) + ";x:3"); + assertThat(OtelTraceState.parse("a:" + getXString(247) + ";r:5;x:3").serialize()).isEqualTo(""); - assertEquals("p:7;r:5", OtelTraceState.parse("r:5;p:7").serialize()); - assertEquals("p:4;r:5", OtelTraceState.parse("r:5;p:4").serialize()); - assertEquals("p:7;r:5", OtelTraceState.parse("r:5;p:7").serialize()); - assertEquals("p:4;r:5", OtelTraceState.parse("r:5;p:4").serialize()); + assertThat(OtelTraceState.parse("r:5;p:7").serialize()).isEqualTo("p:7;r:5"); + assertThat(OtelTraceState.parse("r:5;p:4").serialize()).isEqualTo("p:4;r:5"); + assertThat(OtelTraceState.parse("r:5;p:7").serialize()).isEqualTo("p:7;r:5"); + assertThat(OtelTraceState.parse("r:5;p:4").serialize()).isEqualTo("p:4;r:5"); - assertEquals("r:6", OtelTraceState.parse("r:5;r:6").serialize()); - assertEquals("p:6;r:10", OtelTraceState.parse("p:5;p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse("p5;p:6;r:10").serialize()); - assertEquals("p:6;r:10;p5:3", OtelTraceState.parse("p5:3;p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse(":p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse(";p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse("_;p:6;r:10").serialize()); - assertEquals("", OtelTraceState.parse("5;p:6;r:10").serialize()); + assertThat(OtelTraceState.parse("r:5;r:6").serialize()).isEqualTo("r:6"); + assertThat(OtelTraceState.parse("p:5;p:6;r:10").serialize()).isEqualTo("p:6;r:10"); + assertThat(OtelTraceState.parse("p5;p:6;r:10").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("p5:3;p:6;r:10").serialize()).isEqualTo("p:6;r:10;p5:3"); + assertThat(OtelTraceState.parse(":p:6;r:10").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse(";p:6;r:10").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("_;p:6;r:10").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("5;p:6;r:10").serialize()).isEqualTo(""); } } diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/RandomGeneratorTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/RandomGeneratorTest.java index f94e7eef4..e2f336727 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/RandomGeneratorTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent/RandomGeneratorTest.java @@ -14,7 +14,7 @@ import org.hipparchus.stat.inference.GTest; import org.junit.jupiter.api.Test; -public class RandomGeneratorTest { +class RandomGeneratorTest { private static void testGenerateRandomBitSet(long seed, int numBits, int numOneBits) { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java index 9b5fc050b..d0425aa0b 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOffSamplerTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; -public class ConsistentAlwaysOffSamplerTest { +class ConsistentAlwaysOffSamplerTest { @Test void testDescription() { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java index 3a6b8531b..115c39c41 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentAlwaysOnSamplerTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; -public class ConsistentAlwaysOnSamplerTest { +class ConsistentAlwaysOnSamplerTest { @Test void testDescription() { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java index 7eac3ffb1..3d78de81a 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentFixedThresholdSamplerTest.java @@ -25,7 +25,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class ConsistentFixedThresholdSamplerTest { +class ConsistentFixedThresholdSamplerTest { private Context parentContext; private String name; @@ -75,7 +75,7 @@ private void testSampling(SplittableRandom rng, double samplingProbability) { } @Test - public void testSampling() { + void testSampling() { // fix seed to get reproducible results SplittableRandom random = new SplittableRandom(0); @@ -92,7 +92,7 @@ public void testSampling() { } @Test - public void testDescription() { + void testDescription() { assertThat(ConsistentSampler.probabilityBased(1.0).getDescription()) .isEqualTo("ConsistentFixedThresholdSampler{threshold=0, sampling probability=1.0}"); assertThat(ConsistentSampler.probabilityBased(0.5).getDescription()) diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java index fcf2dcd8d..d612f9e0a 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/ConsistentSamplingUtilTest.java @@ -19,7 +19,7 @@ import org.junit.jupiter.api.Test; -public class ConsistentSamplingUtilTest { +class ConsistentSamplingUtilTest { @Test void testCalculateSamplingProbability() { diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java index a131e9b78..8e8b3ef96 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/OtelTraceStateTest.java @@ -5,71 +5,79 @@ package io.opentelemetry.contrib.sampler.consistent56; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.Test; -public class OtelTraceStateTest { +class OtelTraceStateTest { private static String getXString(int len) { return Stream.generate(() -> "X").limit(len).collect(Collectors.joining()); } @Test - public void test() { + void test() { - assertEquals("", OtelTraceState.parse("").serialize()); - assertEquals("", OtelTraceState.parse("").serialize()); + assertThat(OtelTraceState.parse("").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("").serialize()).isEqualTo(""); - assertEquals("", OtelTraceState.parse("a").serialize()); - assertEquals("", OtelTraceState.parse("#").serialize()); - assertEquals("", OtelTraceState.parse(" ").serialize()); + assertThat(OtelTraceState.parse("a").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("#").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse(" ").serialize()).isEqualTo(""); - assertEquals("rv:1234567890abcd", OtelTraceState.parse("rv:1234567890abcd").serialize()); - assertEquals("rv:01020304050607", OtelTraceState.parse("rv:01020304050607").serialize()); - assertEquals("", OtelTraceState.parse("rv:1234567890abcde").serialize()); + assertThat(OtelTraceState.parse("rv:1234567890abcd").serialize()) + .isEqualTo("rv:1234567890abcd"); + assertThat(OtelTraceState.parse("rv:01020304050607").serialize()) + .isEqualTo("rv:01020304050607"); + assertThat(OtelTraceState.parse("rv:1234567890abcde").serialize()).isEqualTo(""); - assertEquals("th:1234567890abcd", OtelTraceState.parse("th:1234567890abcd").serialize()); - assertEquals("th:01020304050607", OtelTraceState.parse("th:01020304050607").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000000000000").serialize()); - assertEquals("th:12345", OtelTraceState.parse("th:1234500000000").serialize()); - assertEquals("th:0", OtelTraceState.parse("th:0").serialize()); // TODO - assertEquals("", OtelTraceState.parse("th:100000000000000").serialize()); - assertEquals("", OtelTraceState.parse("th:1234567890abcde").serialize()); + assertThat(OtelTraceState.parse("th:1234567890abcd").serialize()) + .isEqualTo("th:1234567890abcd"); + assertThat(OtelTraceState.parse("th:01020304050607").serialize()) + .isEqualTo("th:01020304050607"); + assertThat(OtelTraceState.parse("th:10000000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1234500000000").serialize()).isEqualTo("th:12345"); + assertThat(OtelTraceState.parse("th:0").serialize()).isEqualTo("th:0"); // TODO + assertThat(OtelTraceState.parse("th:100000000000000").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("th:1234567890abcde").serialize()).isEqualTo(""); - assertEquals( - "th:1234567890abcd;rv:1234567890abcd;a:" + getXString(214) + ";x:3", - OtelTraceState.parse("a:" + getXString(214) + ";rv:1234567890abcd;th:1234567890abcd;x:3") - .serialize()); - assertEquals( - "", - OtelTraceState.parse("a:" + getXString(215) + ";rv:1234567890abcd;th:1234567890abcd;x:3") - .serialize()); + assertThat( + OtelTraceState.parse( + "a:" + getXString(214) + ";rv:1234567890abcd;th:1234567890abcd;x:3") + .serialize()) + .isEqualTo("th:1234567890abcd;rv:1234567890abcd;a:" + getXString(214) + ";x:3"); + assertThat( + OtelTraceState.parse( + "a:" + getXString(215) + ";rv:1234567890abcd;th:1234567890abcd;x:3") + .serialize()) + .isEqualTo(""); - assertEquals("", OtelTraceState.parse("th:x").serialize()); - assertEquals("", OtelTraceState.parse("th:100000000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1000000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:100000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1000000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:100000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1000000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:100000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1000").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:100").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:10").serialize()); - assertEquals("th:1", OtelTraceState.parse("th:1").serialize()); + assertThat(OtelTraceState.parse("th:x").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("th:100000000000000").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("th:10000000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1000000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:100000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:10000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1000000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:100000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:10000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1000000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:100000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:10000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1000").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:100").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:10").serialize()).isEqualTo("th:1"); + assertThat(OtelTraceState.parse("th:1").serialize()).isEqualTo("th:1"); - assertEquals("th:10000000000001", OtelTraceState.parse("th:10000000000001").serialize()); - assertEquals("th:1000000000001", OtelTraceState.parse("th:10000000000010").serialize()); - assertEquals("", OtelTraceState.parse("rv:x").serialize()); - assertEquals("", OtelTraceState.parse("rv:100000000000000").serialize()); - assertEquals("rv:10000000000000", OtelTraceState.parse("rv:10000000000000").serialize()); - assertEquals("", OtelTraceState.parse("rv:1000000000000").serialize()); + assertThat(OtelTraceState.parse("th:10000000000001").serialize()) + .isEqualTo("th:10000000000001"); + assertThat(OtelTraceState.parse("th:10000000000010").serialize()).isEqualTo("th:1000000000001"); + assertThat(OtelTraceState.parse("rv:x").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("rv:100000000000000").serialize()).isEqualTo(""); + assertThat(OtelTraceState.parse("rv:10000000000000").serialize()) + .isEqualTo("rv:10000000000000"); + assertThat(OtelTraceState.parse("rv:1000000000000").serialize()).isEqualTo(""); } } diff --git a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java index ab7d378b6..d9a34255f 100644 --- a/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java +++ b/consistent-sampling/src/test/java/io/opentelemetry/contrib/sampler/consistent56/RandomValueGeneratorsTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; -public class RandomValueGeneratorsTest { +class RandomValueGeneratorsTest { @Test void testRandomRange() { int attempts = 10000; diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 58d3e04d7..015c3b773 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -2,8 +2,8 @@ plugins { `java-platform` } -val otelInstrumentationVersion = "2.19.0-alpha" -val semconvVersion = "1.34.0" +val otelInstrumentationVersion = "2.20.0-alpha" +val semconvVersion = "1.37.0" javaPlatform { allowDependencies() @@ -15,8 +15,8 @@ dependencies { // (the constraints section below doesn't have this issue, and will only show up // as runtime dependencies if they are actually used as runtime dependencies) api(enforcedPlatform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:${otelInstrumentationVersion}")) - api(enforcedPlatform("com.fasterxml.jackson:jackson-bom:2.19.2")) - api(enforcedPlatform("com.google.protobuf:protobuf-bom:4.32.0")) + api(enforcedPlatform("com.fasterxml.jackson:jackson-bom:2.20.0")) + api(enforcedPlatform("com.google.protobuf:protobuf-bom:4.32.1")) api(enforcedPlatform("com.squareup.okhttp3:okhttp-bom:5.1.0")) constraints { @@ -30,7 +30,7 @@ dependencies { api("com.google.errorprone:error_prone_annotations:2.41.0") api("com.google.errorprone:error_prone_core:2.41.0") api("io.github.netmikey.logunit:logunit-jul:2.0.0") - api("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + api("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") api("io.prometheus:simpleclient:0.16.0") api("io.prometheus:simpleclient_common:0.16.0") api("io.prometheus:simpleclient_httpserver:0.16.0") @@ -51,7 +51,7 @@ dependencies { api("org.bouncycastle:bcpkix-jdk15on:1.70") api("org.junit-pioneer:junit-pioneer:1.9.1") api("org.skyscreamer:jsonassert:1.5.3") - api("org.apache.kafka:kafka-clients:4.0.0") + api("org.apache.kafka:kafka-clients:4.1.0") api("org.testcontainers:kafka:1.21.3") api("com.lmax:disruptor:3.4.4") api("org.jctools:jctools-core:4.0.5") diff --git a/disk-buffering/build.gradle.kts b/disk-buffering/build.gradle.kts index 0a883cf73..c36d73588 100644 --- a/disk-buffering/build.gradle.kts +++ b/disk-buffering/build.gradle.kts @@ -6,7 +6,7 @@ plugins { id("otel.animalsniffer-conventions") id("com.gradleup.shadow") id("me.champeau.jmh") version "0.7.3" - id("com.squareup.wire") version "5.3.11" + id("com.squareup.wire") version "5.4.0" } description = "Exporter implementations that store signals on disk" @@ -23,7 +23,7 @@ dependencies { testImplementation("org.mockito:mockito-inline") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") - protos("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha@jar") + protos("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha@jar") } jmh { diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordFromDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordFromDiskExporter.java index c26a383d6..6c38be04a 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordFromDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordFromDiskExporter.java @@ -14,7 +14,7 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; -public class LogRecordFromDiskExporter implements FromDiskExporter { +public final class LogRecordFromDiskExporter implements FromDiskExporter { private final FromDiskExporterImpl delegate; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordToDiskExporter.java index 665e90f76..1524723e8 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/LogRecordToDiskExporter.java @@ -18,7 +18,8 @@ * This class implements a {@link LogRecordExporter} that delegates to an instance of {@code * ToDiskExporter}. */ -public class LogRecordToDiskExporter implements LogRecordExporter { +public final class LogRecordToDiskExporter implements LogRecordExporter { + private final ToDiskExporter delegate; /** diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricFromDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricFromDiskExporter.java index 8bb4f3dcd..36d478e7b 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricFromDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricFromDiskExporter.java @@ -14,7 +14,7 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; -public class MetricFromDiskExporter implements FromDiskExporter { +public final class MetricFromDiskExporter implements FromDiskExporter { private final FromDiskExporterImpl delegate; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricToDiskExporter.java index 83d2fc73c..2e0848684 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/MetricToDiskExporter.java @@ -21,7 +21,7 @@ * This class implements a {@link MetricExporter} that delegates to an instance of {@code * ToDiskExporter}. */ -public class MetricToDiskExporter implements MetricExporter { +public final class MetricToDiskExporter implements MetricExporter { private final ToDiskExporter delegate; private final AggregationTemporalitySelector aggregationTemporalitySelector; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanFromDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanFromDiskExporter.java index e3c7992ba..9523c8a2f 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanFromDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanFromDiskExporter.java @@ -14,7 +14,7 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; -public class SpanFromDiskExporter implements FromDiskExporter { +public final class SpanFromDiskExporter implements FromDiskExporter { private final FromDiskExporterImpl delegate; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanToDiskExporter.java index d5ca81518..dcd79d3b0 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/SpanToDiskExporter.java @@ -18,7 +18,7 @@ * This class implements a SpanExporter that delegates to an instance of {@code * ToDiskExporter}. */ -public class SpanToDiskExporter implements SpanExporter { +public final class SpanToDiskExporter implements SpanExporter { private final ToDiskExporter delegate; diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/config/StorageConfiguration.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/config/StorageConfiguration.java index 4853ee72f..e8a7f0bd0 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/config/StorageConfiguration.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/config/StorageConfiguration.java @@ -5,9 +5,11 @@ package io.opentelemetry.contrib.disk.buffering.config; +import static java.util.concurrent.TimeUnit.HOURS; +import static java.util.concurrent.TimeUnit.SECONDS; + import com.google.auto.value.AutoValue; import java.io.File; -import java.util.concurrent.TimeUnit; /** Defines how the storage should be managed. */ @AutoValue @@ -56,9 +58,9 @@ public static Builder builder() { return new AutoValue_StorageConfiguration.Builder() .setMaxFileSize(1024 * 1024) // 1MB .setMaxFolderSize(10 * 1024 * 1024) // 10MB - .setMaxFileAgeForWriteMillis(TimeUnit.SECONDS.toMillis(30)) - .setMinFileAgeForReadMillis(TimeUnit.SECONDS.toMillis(33)) - .setMaxFileAgeForReadMillis(TimeUnit.HOURS.toMillis(18)) + .setMaxFileAgeForWriteMillis(SECONDS.toMillis(30)) + .setMinFileAgeForReadMillis(SECONDS.toMillis(33)) + .setMaxFileAgeForReadMillis(HOURS.toMillis(18)) .setDebugEnabled(false); } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SignalStorageExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SignalStorageExporter.java index 51d135299..c508d042f 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SignalStorageExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SignalStorageExporter.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.disk.buffering.exporters; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import io.opentelemetry.contrib.disk.buffering.SignalType; import io.opentelemetry.contrib.disk.buffering.storage.SignalStorage; import io.opentelemetry.contrib.disk.buffering.storage.result.WriteResult; @@ -13,7 +15,6 @@ import java.util.Collection; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** Internal utility for common export to disk operations across all exporters. */ @@ -34,7 +35,7 @@ public SignalStorageExporter( public CompletableResultCode exportToStorage(Collection items) { CompletableFuture future = storage.write(items); try { - WriteResult operation = future.get(writeTimeout.toMillis(), TimeUnit.MILLISECONDS); + WriteResult operation = future.get(writeTimeout.toMillis(), MILLISECONDS); if (operation.isSuccessful()) { callback.onExportSuccess(type); return CompletableResultCode.ofSuccess(); diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SpanToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SpanToDiskExporter.java index 2bda19da9..3efe5c367 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SpanToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/exporters/SpanToDiskExporter.java @@ -16,9 +16,10 @@ /** Exporter that stores spans into disk. */ public final class SpanToDiskExporter implements SpanExporter { + private static final SignalType TYPE = SignalType.SPAN; + private final SignalStorageExporter storageExporter; private final ExporterCallback callback; - private static final SignalType TYPE = SignalType.SPAN; private SpanToDiskExporter( SignalStorageExporter storageExporter, ExporterCallback callback) { @@ -26,7 +27,7 @@ private SpanToDiskExporter( this.callback = callback; } - public Builder builder(SignalStorage.Span storage) { + public static Builder builder(SignalStorage.Span storage) { return new Builder(storage); } @@ -51,6 +52,10 @@ public static final class Builder { private ExporterCallback callback = ExporterCallback.noop(); private Duration writeTimeout = Duration.ofSeconds(10); + private Builder(SignalStorage.Span storage) { + this.storage = storage; + } + @CanIgnoreReturnValue public Builder setExporterCallback(ExporterCallback value) { callback = value; @@ -68,9 +73,5 @@ public SpanToDiskExporter build() { new SignalStorageExporter<>(storage, callback, writeTimeout, TYPE); return new SpanToDiskExporter(storageExporter, callback); } - - private Builder(SignalStorage.Span storage) { - this.storage = storage; - } } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/exporter/ToDiskExporter.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/exporter/ToDiskExporter.java index 5b2dcd186..a3104a892 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/exporter/ToDiskExporter.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/exporter/ToDiskExporter.java @@ -5,6 +5,9 @@ package io.opentelemetry.contrib.disk.buffering.internal.exporter; +import static java.util.logging.Level.FINER; +import static java.util.logging.Level.WARNING; + import io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers.SignalSerializer; import io.opentelemetry.contrib.disk.buffering.internal.storage.Storage; import io.opentelemetry.contrib.disk.buffering.internal.utils.DebugLogger; @@ -12,7 +15,6 @@ import java.io.IOException; import java.util.Collection; import java.util.function.Function; -import java.util.logging.Level; import java.util.logging.Logger; public class ToDiskExporter { @@ -39,7 +41,7 @@ public static ToDiskExporterBuilder builder(Storage storage) { } public synchronized CompletableResultCode export(Collection data) { - logger.log("Intercepting exporter batch.", Level.FINER); + logger.log("Intercepting exporter batch.", FINER); try { serializer.initialize(data); if (storage.write(serializer)) { @@ -50,7 +52,7 @@ public synchronized CompletableResultCode export(Collection data) { } catch (IOException e) { logger.log( "An unexpected error happened while attempting to write the data in disk. Exporting it right away.", - Level.WARNING, + WARNING, e); return exportFunction.apply(data); } finally { diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializer.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializer.java index cbbb4a0ad..075a0f103 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializer.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializer.java @@ -26,7 +26,7 @@ public List deserialize(byte[] source) throws DeserializationExce try { return ProtoLogsDataMapper.getInstance() .fromProto(ExportLogsServiceRequest.ADAPTER.decode(source)); - } catch (IOException e) { + } catch (IOException | IllegalStateException e) { throw new DeserializationException(e); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializer.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializer.java index d6410d4e7..463c07b75 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializer.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializer.java @@ -26,7 +26,7 @@ public List deserialize(byte[] source) throws DeserializationExcepti try { return ProtoMetricsDataMapper.getInstance() .fromProto(ExportMetricsServiceRequest.ADAPTER.decode(source)); - } catch (IOException e) { + } catch (IOException | IllegalStateException e) { throw new DeserializationException(e); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializer.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializer.java index eb4406ff3..b703c3ade 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializer.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializer.java @@ -26,7 +26,7 @@ public List deserialize(byte[] source) throws DeserializationException try { return ProtoSpansDataMapper.getInstance() .fromProto(ExportTraceServiceRequest.ADAPTER.decode(source)); - } catch (IOException e) { + } catch (IOException | IllegalStateException e) { throw new DeserializationException(e); } } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageBuilder.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageBuilder.java index d43bc18b2..ebea37171 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageBuilder.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageBuilder.java @@ -5,13 +5,14 @@ package io.opentelemetry.contrib.disk.buffering.internal.storage; +import static java.util.logging.Level.INFO; + import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.contrib.disk.buffering.config.StorageConfiguration; import io.opentelemetry.contrib.disk.buffering.internal.utils.SignalTypes; import io.opentelemetry.sdk.common.Clock; import java.io.File; import java.io.IOException; -import java.util.logging.Level; import java.util.logging.Logger; public class StorageBuilder { @@ -43,7 +44,7 @@ public Storage build() throws IOException { File folder = ensureSubdir(configuration.getRootDir(), folderName); FolderManager folderManager = new FolderManager(folder, configuration, clock); if (configuration.isDebugEnabled()) { - logger.log(Level.INFO, "Building storage with configuration => " + configuration); + logger.log(INFO, "Building storage with configuration => " + configuration); } return new Storage(folderManager, configuration.isDebugEnabled()); } diff --git a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/DebugLogger.java b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/DebugLogger.java index 46ff72ebf..b0bb67624 100644 --- a/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/DebugLogger.java +++ b/disk-buffering/src/main/java/io/opentelemetry/contrib/disk/buffering/internal/utils/DebugLogger.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.disk.buffering.internal.utils; +import static java.util.logging.Level.INFO; + import java.util.logging.Level; import java.util.logging.Logger; @@ -22,7 +24,7 @@ public static DebugLogger wrap(Logger logger, boolean debugEnabled) { } public void log(String msg) { - log(msg, Level.INFO); + log(msg, INFO); } public void log(String msg, Level level) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java index b46cba12f..ee4deb57a 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/IntegrationTest.java @@ -6,9 +6,7 @@ package io.opentelemetry.contrib.disk.buffering; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -53,7 +51,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -public class IntegrationTest { +class IntegrationTest { private InMemorySpanExporter memorySpanExporter; private Tracer tracer; private InMemoryMetricExporter memoryMetricExporter; @@ -168,20 +166,20 @@ void verifyLogRecordsIntegration() throws IOException { private void assertExporter(FromDiskExporterImpl exporter, Supplier finishedItems) throws IOException { // Verify no data has been received in the original exporter until this point. - assertEquals(0, finishedItems.get()); + assertThat(finishedItems.get()).isEqualTo(0); // Go to the future when we can read the stored items. fastForwardTimeByMillis(storageConfig.getMinFileAgeForReadMillis()); // Read and send stored data. - assertTrue(exporter.exportStoredBatch(1, TimeUnit.SECONDS)); + assertThat(exporter.exportStoredBatch(1, TimeUnit.SECONDS)).isTrue(); // Now the data must have been delegated to the original exporter. - assertEquals(1, finishedItems.get()); + assertThat(finishedItems.get()).isEqualTo(1); // Bonus: Try to read again, no more data should be available. - assertFalse(exporter.exportStoredBatch(1, TimeUnit.SECONDS)); - assertEquals(1, finishedItems.get()); + assertThat(exporter.exportStoredBatch(1, TimeUnit.SECONDS)).isFalse(); + assertThat(finishedItems.get()).isEqualTo(1); } @SuppressWarnings("DirectInvocationOnMock") diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializerTest.java new file mode 100644 index 000000000..a428956a7 --- /dev/null +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/LogRecordDataDeserializerTest.java @@ -0,0 +1,61 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.disk.buffering.internal.serialization.deserializers; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import io.opentelemetry.api.common.Value; +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.logs.models.LogRecordDataImpl; +import io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers.SignalSerializer; +import io.opentelemetry.contrib.disk.buffering.testutils.BaseSignalSerializerTest; +import io.opentelemetry.contrib.disk.buffering.testutils.TestData; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import org.junit.jupiter.api.Test; + +class LogRecordDataDeserializerTest extends BaseSignalSerializerTest { + private static final LogRecordData LOG_RECORD = + LogRecordDataImpl.builder() + .setResource(TestData.RESOURCE_FULL) + .setSpanContext(TestData.SPAN_CONTEXT) + .setInstrumentationScopeInfo(TestData.INSTRUMENTATION_SCOPE_INFO_FULL) + .setAttributes(TestData.ATTRIBUTES) + .setBodyValue(Value.of("Log body")) + .setSeverity(Severity.DEBUG) + .setSeverityText("Log severity text") + .setTimestampEpochNanos(100L) + .setObservedTimestampEpochNanos(200L) + .setTotalAttributeCount(3) + .setEventName("event") + .build(); + + @Test + void verifyDeserialization() { + assertSerializeDeserialize(LOG_RECORD, LOG_RECORD); + } + + @Test + void whenDecodingMalformedMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeMalformedSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Test + void whenDecodingTooShortMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeTooShortSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Override + protected SignalSerializer getSerializer() { + return SignalSerializer.ofLogs(); + } + + @Override + protected SignalDeserializer getDeserializer() { + return SignalDeserializer.ofLogs(); + } +} diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializerTest.java new file mode 100644 index 000000000..7364d865f --- /dev/null +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/MetricDataDeserializerTest.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.disk.buffering.internal.serialization.deserializers; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers.SignalSerializer; +import io.opentelemetry.contrib.disk.buffering.testutils.BaseSignalSerializerTest; +import io.opentelemetry.contrib.disk.buffering.testutils.TestData; +import io.opentelemetry.sdk.metrics.data.MetricData; +import org.junit.jupiter.api.Test; + +class MetricDataDeserializerTest extends BaseSignalSerializerTest { + + @Test + void whenDecodingMalformedMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeMalformedSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Test + void whenDecodingTooShortMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeTooShortSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Override + protected SignalSerializer getSerializer() { + return SignalSerializer.ofMetrics(); + } + + @Override + protected SignalDeserializer getDeserializer() { + return SignalDeserializer.ofMetrics(); + } +} diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializerTest.java new file mode 100644 index 000000000..1b9c61874 --- /dev/null +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/deserializers/SpanDataDeserializerTest.java @@ -0,0 +1,66 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.disk.buffering.internal.serialization.deserializers; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans.models.SpanDataImpl; +import io.opentelemetry.contrib.disk.buffering.internal.serialization.serializers.SignalSerializer; +import io.opentelemetry.contrib.disk.buffering.testutils.BaseSignalSerializerTest; +import io.opentelemetry.contrib.disk.buffering.testutils.TestData; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.data.StatusData; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class SpanDataDeserializerTest extends BaseSignalSerializerTest { + private static final SpanData SPAN_DATA = + SpanDataImpl.builder() + .setSpanContext(TestData.SPAN_CONTEXT) + .setParentSpanContext(TestData.PARENT_SPAN_CONTEXT) + .setName("Test span") + .setKind(SpanKind.SERVER) + .setStartEpochNanos(100L) + .setEndEpochNanos(200L) + .setStatus(StatusData.ok()) + .setAttributes(TestData.ATTRIBUTES) + .setResource(TestData.RESOURCE_FULL) + .setInstrumentationScopeInfo(TestData.INSTRUMENTATION_SCOPE_INFO_FULL) + .setTotalRecordedLinks(0) + .setTotalRecordedEvents(0) + .setTotalAttributeCount(0) + .setEvents(Collections.emptyList()) + .setLinks(Collections.emptyList()) + .build(); + + @Test + void verifyDeserialization() { + assertSerializeDeserialize(SPAN_DATA, SPAN_DATA); + } + + @Test + void whenDecodingMalformedMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeMalformedSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Test + void whenDecodingTooShortMessage_wrapIntoDeserializationException() { + assertThatThrownBy(() -> getDeserializer().deserialize(TestData.makeTooShortSignalBinary())) + .isInstanceOf(DeserializationException.class); + } + + @Override + protected SignalSerializer getSerializer() { + return SignalSerializer.ofSpans(); + } + + @Override + protected SignalDeserializer getDeserializer() { + return SignalDeserializer.ofSpans(); + } +} diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapperTest.java index 2857cf8da..ceb758642 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/AttributesMapperTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.common; -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; @@ -28,7 +28,7 @@ void verifyMapping() { List proto = mapToProto(attributes); - assertEquals(attributes, mapFromProto(proto)); + assertThat(mapFromProto(proto)).isEqualTo(attributes); } @Test @@ -45,7 +45,7 @@ void verifyArrayMapping() { List serialized = mapToProto(attributes); - assertEquals(attributes, mapFromProto(serialized)); + assertThat(mapFromProto(serialized)).isEqualTo(attributes); } private static List mapToProto(Attributes attributes) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapperTest.java index e9feb8be4..9776cd068 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/common/ResourceMapperTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.common; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.contrib.disk.buffering.testutils.TestData; import io.opentelemetry.proto.resource.v1.Resource; @@ -17,7 +17,8 @@ class ResourceMapperTest { void verifyMapping() { Resource proto = mapToProto(TestData.RESOURCE_FULL); - assertEquals(TestData.RESOURCE_FULL, mapToSdk(proto, TestData.RESOURCE_FULL.getSchemaUrl())); + assertThat(mapToSdk(proto, TestData.RESOURCE_FULL.getSchemaUrl())) + .isEqualTo(TestData.RESOURCE_FULL); } private static Resource mapToProto(io.opentelemetry.sdk.resources.Resource sdkResource) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapperTest.java index 0041c61bf..56710355f 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/LogRecordDataMapperTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.logs; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.Value; import io.opentelemetry.api.logs.Severity; @@ -38,9 +38,8 @@ class LogRecordDataMapperTest { void verifyMapping() { LogRecord proto = mapToProto(LOG_RECORD); - assertEquals( - LOG_RECORD, - mapToSdk(proto, LOG_RECORD.getResource(), LOG_RECORD.getInstrumentationScopeInfo())); + assertThat(mapToSdk(proto, LOG_RECORD.getResource(), LOG_RECORD.getInstrumentationScopeInfo())) + .isEqualTo(LOG_RECORD); } private static LogRecord mapToProto(LogRecordData data) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java index 9a5d93cd8..7242bd65e 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/logs/ProtoLogsDataMapperTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.logs; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.common.Value; import io.opentelemetry.api.logs.Severity; @@ -107,9 +106,9 @@ void verifyConversionDataStructure() { ExportLogsServiceRequest result = mapToProto(signals); List resourceLogsList = result.resource_logs; - assertEquals(1, resourceLogsList.size()); - assertEquals(1, resourceLogsList.get(0).scope_logs.size()); - assertEquals(1, resourceLogsList.get(0).scope_logs.get(0).log_records.size()); + assertThat(resourceLogsList).hasSize(1); + assertThat(resourceLogsList.get(0).scope_logs).hasSize(1); + assertThat(resourceLogsList.get(0).scope_logs.get(0).log_records).hasSize(1); assertThat(mapFromProto(result)).containsExactlyInAnyOrderElementsOf(signals); } @@ -121,15 +120,15 @@ void verifyMultipleLogsWithSameResourceAndScope() { ExportLogsServiceRequest proto = mapToProto(signals); List resourceLogsList = proto.resource_logs; - assertEquals(1, resourceLogsList.size()); + assertThat(resourceLogsList).hasSize(1); List scopeLogsList = resourceLogsList.get(0).scope_logs; - assertEquals(1, scopeLogsList.size()); + assertThat(scopeLogsList).hasSize(1); List logRecords = scopeLogsList.get(0).log_records; - assertEquals(2, logRecords.size()); - assertEquals("Log body", logRecords.get(0).body.string_value); - assertEquals("Other log body", logRecords.get(1).body.string_value); + assertThat(logRecords).hasSize(2); + assertThat(logRecords.get(0).body.string_value).isEqualTo("Log body"); + assertThat(logRecords.get(1).body.string_value).isEqualTo("Other log body"); - assertEquals(2, mapFromProto(proto).size()); + assertThat(mapFromProto(proto)).hasSize(2); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -142,15 +141,15 @@ void verifyMultipleLogsWithSameResourceDifferentScope() { ExportLogsServiceRequest proto = mapToProto(signals); List resourceLogsList = proto.resource_logs; - assertEquals(1, resourceLogsList.size()); + assertThat(resourceLogsList).hasSize(1); List scopeLogsList = resourceLogsList.get(0).scope_logs; - assertEquals(2, scopeLogsList.size()); + assertThat(scopeLogsList).hasSize(2); ScopeLogs firstScope = scopeLogsList.get(0); ScopeLogs secondScope = scopeLogsList.get(1); List firstScopeLogs = firstScope.log_records; List secondScopeLogs = secondScope.log_records; - assertEquals(1, firstScopeLogs.size()); - assertEquals(1, secondScopeLogs.size()); + assertThat(firstScopeLogs).hasSize(1); + assertThat(secondScopeLogs).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -162,19 +161,19 @@ void verifyMultipleLogsWithDifferentResource() { ExportLogsServiceRequest proto = mapToProto(signals); List resourceLogsList = proto.resource_logs; - assertEquals(2, resourceLogsList.size()); + assertThat(resourceLogsList).hasSize(2); ResourceLogs firstResourceLogs = resourceLogsList.get(0); ResourceLogs secondResourceLogs = resourceLogsList.get(1); List firstScopeLogsList = firstResourceLogs.scope_logs; List secondScopeLogsList = secondResourceLogs.scope_logs; - assertEquals(1, firstScopeLogsList.size()); - assertEquals(1, secondScopeLogsList.size()); + assertThat(firstScopeLogsList).hasSize(1); + assertThat(secondScopeLogsList).hasSize(1); ScopeLogs firstScope = firstScopeLogsList.get(0); ScopeLogs secondScope = secondScopeLogsList.get(0); List firstScopeLogs = firstScope.log_records; List secondScopeLogs = secondScope.log_records; - assertEquals(1, firstScopeLogs.size()); - assertEquals(1, secondScopeLogs.size()); + assertThat(firstScopeLogs).hasSize(1); + assertThat(secondScopeLogs).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -188,7 +187,7 @@ void verifyLogWithEventName() { List resourceLogsList = result.resource_logs; LogRecord firstLog = resourceLogsList.get(0).scope_logs.get(0).log_records.get(0); - assertEquals("test.event.name", firstLog.event_name); + assertThat(firstLog.event_name).isEqualTo("test.event.name"); assertThat(mapFromProto(result)).containsExactlyInAnyOrderElementsOf(signals); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapperTest.java index b4f7f64d9..b5e804e29 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/MetricDataMapperTest.java @@ -9,7 +9,6 @@ import static io.opentelemetry.contrib.disk.buffering.testutils.TestData.makeLongGauge; import static io.opentelemetry.contrib.disk.buffering.testutils.TestData.makeLongPointData; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.api.trace.TraceFlags; @@ -121,9 +120,10 @@ void verifySummaryMapping() { Metric proto = mapToProto(summaryMetric); - assertEquals( - summaryMetric, - mapToSdk(proto, summaryMetric.getResource(), summaryMetric.getInstrumentationScopeInfo())); + assertThat( + mapToSdk( + proto, summaryMetric.getResource(), summaryMetric.getInstrumentationScopeInfo())) + .isEqualTo(summaryMetric); } @Test diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java index 59d369704..f114fe04d 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/metrics/ProtoMetricsDataMapperTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.metrics; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.contrib.disk.buffering.testutils.TestData; @@ -33,9 +32,9 @@ void verifyConversionDataStructure() { ExportMetricsServiceRequest proto = mapToProto(signals); List resourceMetrics = proto.resource_metrics; - assertEquals(1, resourceMetrics.size()); - assertEquals(1, resourceMetrics.get(0).scope_metrics.size()); - assertEquals(1, resourceMetrics.get(0).scope_metrics.get(0).metrics.size()); + assertThat(resourceMetrics).hasSize(1); + assertThat(resourceMetrics.get(0).scope_metrics).hasSize(1); + assertThat(resourceMetrics.get(0).scope_metrics.get(0).metrics).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(expectedSignals); } @@ -52,11 +51,11 @@ void verifyMultipleMetricsWithSameResourceAndScope() { ExportMetricsServiceRequest proto = mapToProto(signals); List resourceMetrics = proto.resource_metrics; - assertEquals(1, resourceMetrics.size()); + assertThat(resourceMetrics).hasSize(1); List scopeMetrics = resourceMetrics.get(0).scope_metrics; - assertEquals(1, scopeMetrics.size()); + assertThat(scopeMetrics).hasSize(1); List metrics = scopeMetrics.get(0).metrics; - assertEquals(2, metrics.size()); + assertThat(metrics).hasSize(2); List result = mapFromProto(proto); @@ -81,15 +80,15 @@ void verifyMultipleMetricsWithSameResourceDifferentScope() { ExportMetricsServiceRequest proto = mapToProto(signals); List resourceMetrics = proto.resource_metrics; - assertEquals(1, resourceMetrics.size()); + assertThat(resourceMetrics).hasSize(1); List scopeMetrics = resourceMetrics.get(0).scope_metrics; - assertEquals(2, scopeMetrics.size()); + assertThat(scopeMetrics).hasSize(2); ScopeMetrics firstScope = scopeMetrics.get(0); ScopeMetrics secondScope = scopeMetrics.get(1); List firstScopeMetrics = firstScope.metrics; List secondScopeMetrics = secondScope.metrics; - assertEquals(1, firstScopeMetrics.size()); - assertEquals(1, secondScopeMetrics.size()); + assertThat(firstScopeMetrics).hasSize(1); + assertThat(secondScopeMetrics).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(expectedSignals); } @@ -116,19 +115,19 @@ void verifyMultipleMetricsWithDifferentResource() { ExportMetricsServiceRequest proto = mapToProto(signals); List resourceMetrics = proto.resource_metrics; - assertEquals(2, resourceMetrics.size()); + assertThat(resourceMetrics).hasSize(2); ResourceMetrics firstResourceMetrics = resourceMetrics.get(0); ResourceMetrics secondResourceMetrics = resourceMetrics.get(1); List firstScopeMetrics = firstResourceMetrics.scope_metrics; List secondScopeMetrics = secondResourceMetrics.scope_metrics; - assertEquals(1, firstScopeMetrics.size()); - assertEquals(1, secondScopeMetrics.size()); + assertThat(firstScopeMetrics).hasSize(1); + assertThat(secondScopeMetrics).hasSize(1); ScopeMetrics firstScope = firstScopeMetrics.get(0); ScopeMetrics secondScope = secondScopeMetrics.get(0); List firstMetrics = firstScope.metrics; List secondMetrics = secondScope.metrics; - assertEquals(1, firstMetrics.size()); - assertEquals(1, secondMetrics.size()); + assertThat(firstMetrics).hasSize(1); + assertThat(secondMetrics).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(expectedSignals); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java index ca325496b..910455463 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/ProtoSpansDataMapperTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans.models.SpanDataImpl; @@ -119,9 +118,9 @@ void verifyConversionDataStructure() { ExportTraceServiceRequest proto = mapToProto(signals); List resourceSpans = proto.resource_spans; - assertEquals(1, resourceSpans.size()); - assertEquals(1, resourceSpans.get(0).scope_spans.size()); - assertEquals(1, resourceSpans.get(0).scope_spans.get(0).spans.size()); + assertThat(resourceSpans).hasSize(1); + assertThat(resourceSpans.get(0).scope_spans).hasSize(1); + assertThat(resourceSpans.get(0).scope_spans.get(0).spans).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -133,11 +132,11 @@ void verifyMultipleSpansWithSameResourceAndScope() { ExportTraceServiceRequest proto = mapToProto(signals); List resourceSpans = proto.resource_spans; - assertEquals(1, resourceSpans.size()); + assertThat(resourceSpans).hasSize(1); List scopeSpans = resourceSpans.get(0).scope_spans; - assertEquals(1, scopeSpans.size()); + assertThat(scopeSpans).hasSize(1); List spans = scopeSpans.get(0).spans; - assertEquals(2, spans.size()); + assertThat(spans).hasSize(2); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -149,15 +148,15 @@ void verifyMultipleSpansWithSameResourceDifferentScope() { ExportTraceServiceRequest proto = mapToProto(signals); List resourceSpans = proto.resource_spans; - assertEquals(1, resourceSpans.size()); + assertThat(resourceSpans).hasSize(1); List scopeSpans = resourceSpans.get(0).scope_spans; - assertEquals(2, scopeSpans.size()); + assertThat(scopeSpans).hasSize(2); ScopeSpans firstScope = scopeSpans.get(0); ScopeSpans secondScope = scopeSpans.get(1); List firstScopeSpans = firstScope.spans; List secondScopeSpans = secondScope.spans; - assertEquals(1, firstScopeSpans.size()); - assertEquals(1, secondScopeSpans.size()); + assertThat(firstScopeSpans).hasSize(1); + assertThat(secondScopeSpans).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } @@ -169,19 +168,19 @@ void verifyMultipleSpansWithDifferentResource() { ExportTraceServiceRequest proto = mapToProto(signals); List resourceSpans = proto.resource_spans; - assertEquals(2, resourceSpans.size()); + assertThat(resourceSpans).hasSize(2); ResourceSpans firstResourceSpans = resourceSpans.get(0); ResourceSpans secondResourceSpans = resourceSpans.get(1); List firstScopeSpans = firstResourceSpans.scope_spans; List secondScopeSpans = secondResourceSpans.scope_spans; - assertEquals(1, firstScopeSpans.size()); - assertEquals(1, secondScopeSpans.size()); + assertThat(firstScopeSpans).hasSize(1); + assertThat(secondScopeSpans).hasSize(1); ScopeSpans firstScope = firstScopeSpans.get(0); ScopeSpans secondScope = secondScopeSpans.get(0); List firstSpans = firstScope.spans; List secondSpans = secondScope.spans; - assertEquals(1, firstSpans.size()); - assertEquals(1, secondSpans.size()); + assertThat(firstSpans).hasSize(1); + assertThat(secondSpans).hasSize(1); assertThat(mapFromProto(proto)).containsExactlyInAnyOrderElementsOf(signals); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapperTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapperTest.java index de8f8ff78..43394431f 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapperTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/serialization/mapping/spans/SpanDataMapperTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.contrib.disk.buffering.internal.serialization.mapping.spans.models.SpanDataImpl; @@ -74,21 +74,20 @@ class SpanDataMapperTest { void verifyMapping() { Span proto = mapToProto(SPAN_DATA); - assertEquals( - SPAN_DATA, - mapToSdk(proto, SPAN_DATA.getResource(), SPAN_DATA.getInstrumentationScopeInfo())); + assertThat(mapToSdk(proto, SPAN_DATA.getResource(), SPAN_DATA.getInstrumentationScopeInfo())) + .isEqualTo(SPAN_DATA); } @Test void verifyMappingWithTraceState() { Span proto = mapToProto(SPAN_DATA_WITH_TRACE_STATE); - assertEquals( - SPAN_DATA_WITH_TRACE_STATE, - mapToSdk( - proto, - SPAN_DATA_WITH_TRACE_STATE.getResource(), - SPAN_DATA_WITH_TRACE_STATE.getInstrumentationScopeInfo())); + assertThat( + mapToSdk( + proto, + SPAN_DATA_WITH_TRACE_STATE.getResource(), + SPAN_DATA_WITH_TRACE_STATE.getInstrumentationScopeInfo())) + .isEqualTo(SPAN_DATA_WITH_TRACE_STATE); } private static Span mapToProto(SpanData source) { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java index ad994c38d..d8a95a9cc 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/FolderManagerTest.java @@ -9,12 +9,8 @@ import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MAX_FILE_SIZE; import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MIN_FILE_AGE_FOR_READ_MILLIS; import static java.util.concurrent.TimeUnit.MILLISECONDS; -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.assertNull; -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 static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -52,7 +48,7 @@ void createWritableFile_withTimeMillisAsName() throws IOException { when(clock.now()).thenReturn(MILLISECONDS.toNanos(1000L)); WritableFile file = folderManager.createWritableFile(); - assertEquals("1000", file.getFile().getName()); + assertThat(file.getFile().getName()).isEqualTo("1000"); } @Test @@ -69,12 +65,12 @@ void createWritableFile_andRemoveOldestOne_whenTheAvailableFolderSpaceIsNotEnoug WritableFile file = folderManager.createWritableFile(); - assertNotEquals(existingFile1, file.getFile()); - assertNotEquals(existingFile2, file.getFile()); - assertNotEquals(existingFile3, file.getFile()); - assertTrue(existingFile2.exists()); - assertTrue(existingFile3.exists()); - assertFalse(existingFile1.exists()); + assertThat(file.getFile()).isNotEqualTo(existingFile1); + assertThat(file.getFile()).isNotEqualTo(existingFile2); + assertThat(file.getFile()).isNotEqualTo(existingFile3); + assertThat(existingFile2.exists()).isTrue(); + assertThat(existingFile3.exists()).isTrue(); + assertThat(existingFile1.exists()).isFalse(); } @Test @@ -91,8 +87,8 @@ void closeCurrentlyWritableFile_whenItIsReadyToBeRead_andNoOtherReadableFilesAre ReadableFile readableFile = folderManager.getReadableFile(); - assertEquals(writableFile.getFile(), readableFile.getFile()); - assertTrue(writableFile.isClosed()); + assertThat(readableFile.getFile()).isEqualTo(writableFile.getFile()); + assertThat(writableFile.isClosed()).isTrue(); } @Test @@ -109,14 +105,14 @@ void closeCurrentlyWritableFile_whenItIsReadyToBeRead_andNoOtherReadableFilesAre when(clock.now()).thenReturn(MILLISECONDS.toNanos(1000L + MIN_FILE_AGE_FOR_READ_MILLIS)); ReadableFile readableFile = folderManager.getReadableFile(); - assertEquals(existingFile1, readableFile.getFile()); + assertThat(readableFile.getFile()).isEqualTo(existingFile1); folderManager.createWritableFile(); - assertTrue(existingFile2.exists()); - assertTrue(existingFile3.exists()); - assertFalse(existingFile1.exists()); - assertTrue(readableFile.isClosed()); + assertThat(existingFile2.exists()).isTrue(); + assertThat(existingFile3.exists()).isTrue(); + assertThat(existingFile1.exists()).isFalse(); + assertThat(readableFile.isClosed()).isTrue(); } @Test @@ -133,12 +129,12 @@ void createWritableFile_andDoNotRemoveOldestOne_ifAtLeastOneExpiredFileIsPurged( WritableFile file = folderManager.createWritableFile(); - assertNotEquals(existingFile1, file.getFile()); - assertNotEquals(existingFile2, file.getFile()); - assertNotEquals(existingFile3, file.getFile()); - assertTrue(existingFile2.exists()); - assertTrue(existingFile1.exists()); - assertFalse(existingFile3.exists()); + assertThat(file.getFile()).isNotEqualTo(existingFile1); + assertThat(file.getFile()).isNotEqualTo(existingFile2); + assertThat(file.getFile()).isNotEqualTo(existingFile3); + assertThat(existingFile2.exists()).isTrue(); + assertThat(existingFile1.exists()).isTrue(); + assertThat(existingFile3.exists()).isFalse(); } @Test @@ -152,9 +148,9 @@ void purgeExpiredForReadFiles_whenCreatingNewOne() throws IOException { WritableFile file = folderManager.createWritableFile(); - assertFalse(expiredReadableFile.exists()); - assertTrue(expiredWritableFile.exists()); - assertNotEquals(expiredWritableFile, file.getFile()); + assertThat(expiredReadableFile.exists()).isFalse(); + assertThat(expiredWritableFile.exists()).isTrue(); + assertThat(file.getFile()).isNotEqualTo(expiredWritableFile); } @Test @@ -167,17 +163,17 @@ void closeExpiredReadableFileInUseIfAny_whenPurgingExpiredForReadFiles_whenCreat when(clock.now()).thenReturn(MILLISECONDS.toNanos(900 + MIN_FILE_AGE_FOR_READ_MILLIS)); ReadableFile readableFile = folderManager.getReadableFile(); - assertEquals(expiredReadableFileBeingRead, readableFile.getFile()); + assertThat(readableFile.getFile()).isEqualTo(expiredReadableFileBeingRead); when(clock.now()).thenReturn(MILLISECONDS.toNanos(11_500L)); WritableFile file = folderManager.createWritableFile(); - assertFalse(expiredReadableFile.exists()); - assertFalse(expiredReadableFileBeingRead.exists()); - assertTrue(expiredWritableFile.exists()); - assertNotEquals(expiredWritableFile, file.getFile()); - assertTrue(readableFile.isClosed()); + assertThat(expiredReadableFile.exists()).isFalse(); + assertThat(expiredReadableFileBeingRead.exists()).isFalse(); + assertThat(expiredWritableFile.exists()).isTrue(); + assertThat(file.getFile()).isNotEqualTo(expiredWritableFile); + assertThat(readableFile.isClosed()).isTrue(); } @Test @@ -192,7 +188,7 @@ void provideFileForRead_afterItsMinFileAgeForReadTimePassed() throws IOException ReadableFile file = folderManager.getReadableFile(); - assertEquals(readableFile, file.getFile()); + assertThat(file.getFile()).isEqualTo(readableFile); } @Test @@ -209,12 +205,12 @@ void provideOldestFileForRead_whenMultipleReadableFilesAreAvailable() throws IOE ReadableFile file = folderManager.getReadableFile(); - assertEquals(readableFileOlder, file.getFile()); + assertThat(file.getFile()).isEqualTo(readableFileOlder); } @Test void provideNullFileForRead_whenNoFilesAreAvailable() throws IOException { - assertNull(folderManager.getReadableFile()); + assertThat(folderManager.getReadableFile()).isNull(); } @Test @@ -223,7 +219,7 @@ void provideNullFileForRead_whenOnlyReadableFilesAreAvailable() throws IOExcepti File writableFile = new File(rootDir, String.valueOf(currentTime)); createFiles(writableFile); - assertNull(folderManager.getReadableFile()); + assertThat(folderManager.getReadableFile()).isNull(); } @Test @@ -234,7 +230,7 @@ void provideNullFileForRead_whenReadableFilesAreExpired() throws IOException { createFiles(expiredReadableFile1, expiredReadableFile2); when(clock.now()).thenReturn(creationReferenceTime + MAX_FILE_AGE_FOR_READ_MILLIS); - assertNull(folderManager.getReadableFile()); + assertThat(folderManager.getReadableFile()).isNull(); } private static void fillWithBytes(File file, int size) throws IOException { diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java index d96b9a1bc..b33387a8c 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/StorageTest.java @@ -6,9 +6,8 @@ package io.opentelemetry.contrib.disk.buffering.internal.storage; import static io.opentelemetry.contrib.disk.buffering.internal.storage.responses.ReadableResult.TRY_LATER; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -58,7 +57,7 @@ void tearDown() throws IOException { void whenReadingAndProcessingSuccessfully_returnSuccess() throws IOException { when(folderManager.getReadableFile()).thenReturn(readableFile); - assertEquals(ReadableResult.SUCCEEDED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.SUCCEEDED); verify(readableFile).readAndProcess(processing); } @@ -68,7 +67,7 @@ void whenReadableFileProcessingFails_returnTryLater() throws IOException { when(folderManager.getReadableFile()).thenReturn(readableFile); when(readableFile.readAndProcess(processing)).thenReturn(TRY_LATER); - assertEquals(TRY_LATER, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(TRY_LATER); verify(readableFile).readAndProcess(processing); } @@ -78,8 +77,8 @@ void whenReadingMultipleTimes_reuseReader() throws IOException { ReadableFile anotherReadable = mock(); when(folderManager.getReadableFile()).thenReturn(readableFile).thenReturn(anotherReadable); - assertEquals(ReadableResult.SUCCEEDED, storage.readAndProcess(processing)); - assertEquals(ReadableResult.SUCCEEDED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.SUCCEEDED); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.SUCCEEDED); verify(readableFile, times(2)).readAndProcess(processing); verify(folderManager, times(1)).getReadableFile(); @@ -103,18 +102,18 @@ void whenWritingMultipleTimes_reuseWriter() throws IOException { @Test void whenAttemptingToReadAfterClosed_returnFailed() throws IOException { storage.close(); - assertEquals(ReadableResult.FAILED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.FAILED); } @Test void whenAttemptingToWriteAfterClosed_returnFalse() throws IOException { storage.close(); - assertFalse(storage.write(new ByteArraySerializer(new byte[1]))); + assertThat(storage.write(new ByteArraySerializer(new byte[1]))).isFalse(); } @Test void whenNoFileAvailableForReading_returnFailed() throws IOException { - assertEquals(ReadableResult.FAILED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.FAILED); } @Test @@ -152,7 +151,7 @@ void whenEveryNewFileFoundCannotBeRead_returnContentNotAvailable() throws IOExce when(folderManager.getReadableFile()).thenReturn(readableFile); when(readableFile.readAndProcess(processing)).thenReturn(ReadableResult.FAILED); - assertEquals(ReadableResult.FAILED, storage.readAndProcess(processing)); + assertThat(storage.readAndProcess(processing)).isEqualTo(ReadableResult.FAILED); verify(folderManager, times(3)).getReadableFile(); } @@ -215,7 +214,7 @@ void whenEveryAttemptToWriteFails_returnFalse() throws IOException { when(folderManager.createWritableFile()).thenReturn(writableFile); when(writableFile.append(data)).thenReturn(WritableResult.FAILED); - assertFalse(storage.write(data)); + assertThat(storage.write(data)).isFalse(); verify(folderManager, times(3)).createWritableFile(); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java index a9d0eb5da..8fdc1d41e 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/ReadableFileTest.java @@ -8,10 +8,8 @@ import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MAX_FILE_AGE_FOR_READ_MILLIS; import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.getConfiguration; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -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 static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -120,27 +118,27 @@ private static void addFileContents(File source) throws IOException { void readSingleItemAndRemoveIt() throws IOException { readableFile.readAndProcess( bytes -> { - assertEquals(FIRST_LOG_RECORD, deserialize(bytes)); + assertThat(deserialize(bytes)).isEqualTo(FIRST_LOG_RECORD); return ProcessResult.SUCCEEDED; }); List logs = getRemainingDataAndClose(readableFile); - assertEquals(2, logs.size()); - assertEquals(SECOND_LOG_RECORD, logs.get(0)); - assertEquals(THIRD_LOG_RECORD, logs.get(1)); + assertThat(logs.size()).isEqualTo(2); + assertThat(logs.get(0)).isEqualTo(SECOND_LOG_RECORD); + assertThat(logs.get(1)).isEqualTo(THIRD_LOG_RECORD); } @Test void whenProcessingSucceeds_returnSuccessStatus() throws IOException { - assertEquals( - ReadableResult.SUCCEEDED, readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)) + .isEqualTo(ReadableResult.SUCCEEDED); } @Test void whenProcessingFails_returnTryLaterStatus() throws IOException { - assertEquals( - ReadableResult.TRY_LATER, readableFile.readAndProcess(bytes -> ProcessResult.TRY_LATER)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.TRY_LATER)) + .isEqualTo(ReadableResult.TRY_LATER); } @Test @@ -158,8 +156,8 @@ void readMultipleLinesAndRemoveThem() throws IOException { List logs = getRemainingDataAndClose(readableFile); - assertEquals(1, logs.size()); - assertEquals(THIRD_LOG_RECORD, logs.get(0)); + assertThat(logs.size()).isEqualTo(1); + assertThat(logs.get(0)).isEqualTo(THIRD_LOG_RECORD); } @Test @@ -168,24 +166,24 @@ void whenConsumerReturnsFalse_doNotRemoveLineFromSource() throws IOException { List logs = getRemainingDataAndClose(readableFile); - assertEquals(3, logs.size()); + assertThat(logs.size()).isEqualTo(3); } @Test void whenReadingLastLine_deleteOriginalFile_and_close() throws IOException { getRemainingDataAndClose(readableFile); - assertFalse(source.exists()); - assertTrue(readableFile.isClosed()); + assertThat(source.exists()).isFalse(); + assertThat(readableFile.isClosed()).isTrue(); } @Test void whenTheFileContentIsInvalid_deleteOriginalFile_and_close() throws IOException { - assertEquals( - ReadableResult.FAILED, readableFile.readAndProcess(bytes -> ProcessResult.CONTENT_INVALID)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.CONTENT_INVALID)) + .isEqualTo(ReadableResult.FAILED); - assertFalse(source.exists()); - assertTrue(readableFile.isClosed()); + assertThat(source.exists()).isFalse(); + assertThat(readableFile.isClosed()).isTrue(); } @Test @@ -199,11 +197,11 @@ void whenNoMoreLinesAvailableToRead_deleteOriginalFile_close_and_returnNoContent ReadableFile emptyReadableFile = new ReadableFile(emptyFile, CREATED_TIME_MILLIS, clock, getConfiguration(dir)); - assertEquals( - ReadableResult.FAILED, emptyReadableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)); + assertThat(emptyReadableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)) + .isEqualTo(ReadableResult.FAILED); - assertTrue(emptyReadableFile.isClosed()); - assertFalse(emptyFile.exists()); + assertThat(emptyReadableFile.isClosed()).isTrue(); + assertThat(emptyFile.exists()).isFalse(); } @Test @@ -214,10 +212,10 @@ void whenNoMoreLinesAvailableToRead_deleteOriginalFile_close_and_returnNoContent when(clock.now()) .thenReturn(MILLISECONDS.toNanos(CREATED_TIME_MILLIS + MAX_FILE_AGE_FOR_READ_MILLIS)); - assertEquals( - ReadableResult.FAILED, readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)) + .isEqualTo(ReadableResult.FAILED); - assertTrue(readableFile.isClosed()); + assertThat(readableFile.isClosed()).isTrue(); } @Test @@ -225,14 +223,14 @@ void whenReadingAfterClosed_returnFailedStatus() throws IOException { readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED); readableFile.close(); - assertEquals( - ReadableResult.FAILED, readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)); + assertThat(readableFile.readAndProcess(bytes -> ProcessResult.SUCCEEDED)) + .isEqualTo(ReadableResult.FAILED); } private static void assertDeserializedData(LogRecordData expected, byte[] bytes) { try { List deserialized = DESERIALIZER.deserialize(bytes); - assertEquals(expected, deserialized.get(0)); + assertThat(deserialized.get(0)).isEqualTo(expected); } catch (DeserializationException e) { throw new RuntimeException(e); } diff --git a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java index cae1e9f64..91ec94f09 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/internal/storage/files/WritableFileTest.java @@ -8,9 +8,7 @@ import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MAX_FILE_AGE_FOR_WRITE_MILLIS; import static io.opentelemetry.contrib.disk.buffering.internal.storage.TestData.MAX_FILE_SIZE; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -58,14 +56,14 @@ void tearDown() throws IOException { void hasNotExpired_whenWriteAgeHasNotExpired() { when(clock.now()).thenReturn(MILLISECONDS.toNanos(1500L)); - assertFalse(writableFile.hasExpired()); + assertThat(writableFile.hasExpired()).isFalse(); } @Test void hasExpired_whenWriteAgeHasExpired() { when(clock.now()).thenReturn(MILLISECONDS.toNanos(2000L)); - assertTrue(writableFile.hasExpired()); + assertThat(writableFile.hasExpired()).isTrue(); } @Test @@ -78,22 +76,22 @@ void appendDataInNewLines_andIncreaseSize() throws IOException { List lines = getWrittenLines(); - assertEquals(2, lines.size()); - assertEquals("First line", lines.get(0)); - assertEquals("Second line", lines.get(1)); - assertEquals(line1.length + line2.length, writableFile.getSize()); + assertThat(lines).hasSize(2); + assertThat(lines.get(0)).isEqualTo("First line"); + assertThat(lines.get(1)).isEqualTo("Second line"); + assertThat(writableFile.getSize()).isEqualTo(line1.length + line2.length); } @Test void whenAppendingData_andNotEnoughSpaceIsAvailable_closeAndReturnFailed() throws IOException { - assertEquals( - WritableResult.SUCCEEDED, - writableFile.append(new ByteArraySerializer(new byte[MAX_FILE_SIZE]))); + assertThat(writableFile.append(new ByteArraySerializer(new byte[MAX_FILE_SIZE]))) + .isEqualTo(WritableResult.SUCCEEDED); - assertEquals(WritableResult.FAILED, writableFile.append(new ByteArraySerializer(new byte[1]))); + assertThat(writableFile.append(new ByteArraySerializer(new byte[1]))) + .isEqualTo(WritableResult.FAILED); - assertEquals(1, getWrittenLines().size()); - assertEquals(MAX_FILE_SIZE, writableFile.getSize()); + assertThat(getWrittenLines()).hasSize(1); + assertThat(writableFile.getSize()).isEqualTo(MAX_FILE_SIZE); } @Test @@ -102,9 +100,10 @@ void whenAppendingData_andHasExpired_closeAndReturnExpiredStatus() throws IOExce when(clock.now()) .thenReturn(MILLISECONDS.toNanos(CREATED_TIME_MILLIS + MAX_FILE_AGE_FOR_WRITE_MILLIS)); - assertEquals(WritableResult.FAILED, writableFile.append(new ByteArraySerializer(new byte[1]))); + assertThat(writableFile.append(new ByteArraySerializer(new byte[1]))) + .isEqualTo(WritableResult.FAILED); - assertEquals(1, getWrittenLines().size()); + assertThat(getWrittenLines()).hasSize(1); } @Test @@ -112,7 +111,8 @@ void whenAppendingData_andIsAlreadyClosed_returnFailedStatus() throws IOExceptio writableFile.append(new ByteArraySerializer(new byte[1])); writableFile.close(); - assertEquals(WritableResult.FAILED, writableFile.append(new ByteArraySerializer(new byte[2]))); + assertThat(writableFile.append(new ByteArraySerializer(new byte[2]))) + .isEqualTo(WritableResult.FAILED); } private static byte[] getByteArrayLine(String line) { 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/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/testutils/TestData.java b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/testutils/TestData.java index 15c32c421..ec69e8024 100644 --- a/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/testutils/TestData.java +++ b/disk-buffering/src/test/java/io/opentelemetry/contrib/disk/buffering/testutils/TestData.java @@ -131,5 +131,24 @@ private static LongExemplarData makeLongExemplarData(TraceFlags flags) { return ImmutableLongExemplarData.create(ATTRIBUTES, 100L, context, 1L); } + @NotNull + public static byte[] makeTooShortSignalBinary() { + return new byte[] { + (byte) 0x0A, // type + (byte) 0xFF, // defining length 255, but message is shorter + (byte) 0x01 // content + }; + } + + @NotNull + public static byte[] makeMalformedSignalBinary() { + return new byte[] { + (byte) 0x0A, // type + (byte) 0x02, // length + (byte) 0x08, // field 1, wire type 0 (varint) - this should be a nested message but isn't + (byte) 0x01 // content + }; + } + private TestData() {} } diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-aws-xray.txt b/docs/apidiffs/current_vs_latest/opentelemetry-aws-xray.txt new file mode 100644 index 000000000..fb005385c --- /dev/null +++ b/docs/apidiffs/current_vs_latest/opentelemetry-aws-xray.txt @@ -0,0 +1,2 @@ +Comparing source compatibility of opentelemetry-aws-xray-1.50.0-SNAPSHOT.jar against opentelemetry-aws-xray-1.49.0.jar +No changes. \ No newline at end of file diff --git a/docs/style-guide.md b/docs/style-guide.md new file mode 100644 index 000000000..9acf641ae --- /dev/null +++ b/docs/style-guide.md @@ -0,0 +1,166 @@ +# 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.*` + - `org.assertj.core.api.Assertions.*` + - `org.mockito.Mockito.*` + - `org.mockito.ArgumentMatchers.*` +- **Utility methods** + - `io.opentelemetry.api.common.AttributeKey.*` + - `java.util.Arrays` - asList, stream + - `java.util.Collections` - singleton*, empty*, unmodifiable*, synchronized*, checked* + - `java.util.Objects` - requireNonNull + - `java.util.function.Function` - identity + - `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. + +### 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 + +### Visibility modifiers + +Follow the principle of minimal necessary visibility. Use the most restrictive access modifier that +still allows the code to function correctly. + +### 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. + +- 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 non-internal non-test classes should be declared `final` where possible. + +Methods should only be declared `final` if they are in public non-internal non-test non-final 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. + +### `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. + +### 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. + +### 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 configuration 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) diff --git a/example/README.md b/example/README.md deleted file mode 100644 index 43333d2c2..000000000 --- a/example/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Example Library - -This is an example library intended to be used as a template for easy additions to the OpenTelemetry Java Contrib project. diff --git a/example/build.gradle.kts b/example/build.gradle.kts deleted file mode 100644 index 898191643..000000000 --- a/example/build.gradle.kts +++ /dev/null @@ -1,13 +0,0 @@ -plugins { - id("otel.java-conventions") -} - -description = "An example OpenTelemetry Java Contrib library" - -tasks { - jar { - manifest { - attributes["Main-Class"] = "io.opentelemetry.contrib.example.Library" - } - } -} diff --git a/example/src/main/java/io/opentelemetry/contrib/example/Library.java b/example/src/main/java/io/opentelemetry/contrib/example/Library.java deleted file mode 100644 index 289f72ea8..000000000 --- a/example/src/main/java/io/opentelemetry/contrib/example/Library.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.example; - -public class Library { - - public boolean myMethod() { - return true; - } - - @SuppressWarnings("SystemOut") - public static void main(String... args) { - System.out.println("ExampleLibrary.main"); - } -} diff --git a/example/src/test/java/io/opentelemetry/contrib/example/LibraryTest.java b/example/src/test/java/io/opentelemetry/contrib/example/LibraryTest.java deleted file mode 100644 index a9c897576..000000000 --- a/example/src/test/java/io/opentelemetry/contrib/example/LibraryTest.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.example; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -class LibraryTest { - - @Test - void myMethod() { - Library library = new Library(); - assertThat(library.myMethod()).isTrue(); - } -} diff --git a/gcp-auth-extension/build.gradle.kts b/gcp-auth-extension/build.gradle.kts index f81e5e521..ed97129fc 100644 --- a/gcp-auth-extension/build.gradle.kts +++ b/gcp-auth-extension/build.gradle.kts @@ -21,10 +21,12 @@ dependencies { compileOnly("com.google.auto.service:auto-service-annotations") compileOnly("io.opentelemetry:opentelemetry-api") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator") + compileOnly("io.opentelemetry.instrumentation:opentelemetry-declarative-config-bridge") compileOnly("io.opentelemetry:opentelemetry-exporter-otlp") // Only dependencies added to `implementation` configuration will be picked up by Shadow plugin - implementation("com.google.auth:google-auth-library-oauth2-http:1.37.1") + implementation("com.google.auth:google-auth-library-oauth2-http:1.39.0") // Test dependencies testCompileOnly("com.google.auto.service:auto-service-annotations") @@ -36,13 +38,15 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-exporter-otlp") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") testImplementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations") + testImplementation("io.opentelemetry.instrumentation:opentelemetry-declarative-config-bridge") testImplementation("org.awaitility:awaitility") testImplementation("org.mockito:mockito-inline") testImplementation("org.mockito:mockito-junit-jupiter") testImplementation("org.mock-server:mockserver-netty:5.15.0") - testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") testImplementation("org.springframework.boot:spring-boot-starter-web:2.7.18") testImplementation("org.springframework.boot:spring-boot-starter:2.7.18") testImplementation("org.springframework.boot:spring-boot-starter-test:2.7.18") @@ -103,6 +107,9 @@ tasks.register("copyAgent") { } tasks.register("IntegrationTestUserCreds") { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + dependsOn(tasks.shadowJar) dependsOn(tasks.named("copyAgent")) diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java index 639207909..c1f3826de 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/ConfigurableOption.java @@ -5,11 +5,12 @@ package io.opentelemetry.contrib.gcp.auth; +import static java.util.Locale.ROOT; + import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; -import java.util.Locale; -import java.util.Optional; -import java.util.function.Supplier; +import java.util.function.BiFunction; +import javax.annotation.Nullable; /** * An enum representing configurable options for a GCP Authentication Extension. Each option has a @@ -60,8 +61,7 @@ enum ConfigurableOption { ConfigurableOption(String userReadableName) { this.userReadableName = userReadableName; this.environmentVariableName = this.name(); - this.systemPropertyName = - this.environmentVariableName.toLowerCase(Locale.ROOT).replace('_', '.'); + this.systemPropertyName = this.environmentVariableName.toLowerCase(ROOT).replace('_', '.'); } /** @@ -92,57 +92,41 @@ String getUserReadableName() { } /** - * Retrieves the configured value for this option. This method checks the environment variable - * first and then the system property. + * Retrieves the configured value for this option. * * @return The configured value as a string, or throws an exception if not configured. * @throws ConfigurationException if neither the environment variable nor the system property is * set. */ - String getConfiguredValue(ConfigProperties configProperties) { - String configuredValue = configProperties.getString(this.getSystemProperty()); - if (configuredValue != null && !configuredValue.isEmpty()) { - return configuredValue; - } else { + T getRequiredConfiguredValue( + ConfigProperties configProperties, BiFunction extractor) { + T configuredValue = getConfiguredValue(configProperties, extractor); + if (configuredValue == null) { throw new ConfigurationException( String.format( - "GCP Authentication Extension not configured properly: %s not configured. Configure it by exporting environment variable %s or system property %s", + "GCP Authentication Extension not configured properly: %s not configured. " + + "Configure it by exporting environment variable %s or system property %s", this.userReadableName, this.getEnvironmentVariable(), this.getSystemProperty())); } + return configuredValue; } /** - * Retrieves the value for this option, prioritizing environment variables and system properties. - * If neither an environment variable nor a system property is set for this option, the provided - * fallback function is used to determine the value. + * Retrieves the configured value for this option. * - * @param fallback A {@link Supplier} that provides the default value for the option when it is - * not explicitly configured via an environment variable or system property. - * @return The configured value for the option, obtained from the environment variable, system - * property, or the fallback function, in that order of precedence. + * @return The configured value as a string, or {@code null} if not configured. */ - String getConfiguredValueWithFallback( - ConfigProperties configProperties, Supplier fallback) { - try { - return this.getConfiguredValue(configProperties); - } catch (ConfigurationException e) { - return fallback.get(); + @Nullable + T getConfiguredValue( + ConfigProperties configProperties, BiFunction extractor) { + T configuredValue = extractor.apply(configProperties, this.getSystemProperty()); + if (configuredValue instanceof String) { + String value = (String) configuredValue; + if (value.isEmpty()) { + configuredValue = null; // Treat empty string as not configured + } } - } - /** - * Retrieves the value for this option, prioritizing environment variables before system - * properties. If neither an environment variable nor a system property is set for this option, - * then an empty {@link Optional} is returned. - * - * @return The configured value for the option, if set, obtained from the environment variable, - * system property, or empty {@link Optional}, in that order of precedence. - */ - Optional getConfiguredValueAsOptional(ConfigProperties configProperties) { - try { - return Optional.of(this.getConfiguredValue(configProperties)); - } catch (ConfigurationException e) { - return Optional.empty(); - } + return configuredValue; } } diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java index 1de583029..ae904c6bc 100644 --- a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProvider.java @@ -5,9 +5,14 @@ package io.opentelemetry.contrib.gcp.auth; +import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static java.util.Collections.singletonList; +import static java.util.stream.Collectors.joining; +import static java.util.stream.Collectors.toMap; + import com.google.auth.oauth2.GoogleCredentials; import com.google.auto.service.AutoService; -import io.opentelemetry.api.common.AttributeKey; +import com.google.common.annotations.VisibleForTesting; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.contrib.gcp.auth.GoogleAuthException.Reason; import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; @@ -25,14 +30,12 @@ import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.export.SpanExporter; import java.io.IOException; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; import javax.annotation.Nonnull; /** @@ -84,8 +87,8 @@ public class GcpAuthAutoConfigurationCustomizerProvider * customizes only the signal specific exporter. * * - * The 'customization' performed includes customizing the exporters by adding required headers to - * the export calls made and customizing the resource by adding required resource attributes to + *

The 'customization' performed includes customizing the exporters by adding required headers + * to the export calls made and customizing the resource by adding required resource attributes to * enable GCP integration. * * @param autoConfiguration the AutoConfigurationCustomizer to customize. @@ -96,12 +99,7 @@ public class GcpAuthAutoConfigurationCustomizerProvider */ @Override public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) { - GoogleCredentials credentials; - try { - credentials = GoogleCredentials.getApplicationDefault(); - } catch (IOException e) { - throw new GoogleAuthException(Reason.FAILED_ADC_RETRIEVAL, e); - } + GoogleCredentials credentials = getCredentials(); autoConfiguration .addSpanExporterCustomizer( (spanExporter, configProperties) -> @@ -112,6 +110,16 @@ public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) { .addResourceCustomizer(GcpAuthAutoConfigurationCustomizerProvider::customizeResource); } + static GoogleCredentials getCredentials() { + GoogleCredentials credentials; + try { + credentials = GoogleCredentials.getApplicationDefault(); + } catch (IOException e) { + throw new GoogleAuthException(Reason.FAILED_ADC_RETRIEVAL, e); + } + return credentials; + } + @Override public int order() { return Integer.MAX_VALUE - 1; @@ -119,44 +127,62 @@ public int order() { private static SpanExporter customizeSpanExporter( SpanExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) { - if (isSignalTargeted(SIGNAL_TYPE_TRACES, configProperties)) { + if (shouldCustomizeExporter( + SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { return addAuthorizationHeaders(exporter, credentials, configProperties); - } else { - String[] params = {SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; - logger.log( - Level.WARNING, - "GCP Authentication Extension is not configured for signal type: {0}. {1}", - params); } return exporter; } private static MetricExporter customizeMetricExporter( MetricExporter exporter, GoogleCredentials credentials, ConfigProperties configProperties) { - if (isSignalTargeted(SIGNAL_TYPE_METRICS, configProperties)) { + if (shouldCustomizeExporter( + SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION, configProperties)) { return addAuthorizationHeaders(exporter, credentials, configProperties); + } + return exporter; + } + + /** + * Utility method to check whether OTLP exporters should be customized for the given target + * signal. + * + * @param signal The target signal to check against. Could be one of {@value SIGNAL_TYPE_TRACES}, + * {@value SIGNAL_TYPE_METRICS} or {@value SIGNAL_TYPE_ALL}. + * @param fixSuggestion A warning to alert the user that auth extension is not configured for the + * provided target signal. + * @param configProperties The {@link ConfigProperties} object used to configure the extension. + * @return A boolean indicating whether the OTLP exporters should be customized or not. + */ + static boolean shouldCustomizeExporter( + String signal, String fixSuggestion, ConfigProperties configProperties) { + if (isSignalTargeted(signal, configProperties)) { + return true; } else { - String[] params = {SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_FIX_SUGGESTION}; logger.log( Level.WARNING, "GCP Authentication Extension is not configured for signal type: {0}. {1}", - params); + new String[] {signal, fixSuggestion}); + return false; } - return exporter; } // Checks if the auth extension is configured to target the passed signal for authentication. private static boolean isSignalTargeted(String checkSignal, ConfigProperties configProperties) { - String userSpecifiedTargetedSignals = - ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValueWithFallback( - configProperties, () -> SIGNAL_TYPE_ALL); - return Arrays.stream(userSpecifiedTargetedSignals.split(",")) - .map(String::trim) + return targetSignals(configProperties).stream() .anyMatch( targetedSignal -> targetedSignal.equals(checkSignal) || targetedSignal.equals(SIGNAL_TYPE_ALL)); } + @VisibleForTesting + static List targetSignals(ConfigProperties configProperties) { + return Objects.requireNonNull( + ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getConfiguredValue( + configProperties, + (properties, name) -> properties.getList(name, singletonList(SIGNAL_TYPE_ALL)))); + } + // Adds authorization headers to the calls made by the OtlpGrpcSpanExporter and // OtlpHttpSpanExporter. private static SpanExporter addAuthorizationHeaders( @@ -193,7 +219,7 @@ private static MetricExporter addAuthorizationHeaders( return exporter; } - private static Map getRequiredHeaderMap( + static Map getRequiredHeaderMap( GoogleCredentials credentials, ConfigProperties configProperties) { Map> gcpHeaders; try { @@ -202,37 +228,43 @@ private static Map getRequiredHeaderMap( } catch (IOException e) { throw new GoogleAuthException(Reason.FAILED_ADC_REFRESH, e); } - // flatten list Map flattenedHeaders = gcpHeaders.entrySet().stream() .collect( - Collectors.toMap( + toMap( Map.Entry::getKey, entry -> entry.getValue().stream() .filter(Objects::nonNull) // Filter nulls .filter(s -> !s.isEmpty()) // Filter empty strings - .collect(Collectors.joining(",")))); + .collect(joining(",")))); // Add quota user project header if not detected by the auth library and user provided it via // system properties. if (!flattenedHeaders.containsKey(QUOTA_USER_PROJECT_HEADER)) { - Optional maybeConfiguredQuotaProjectId = - ConfigurableOption.GOOGLE_CLOUD_QUOTA_PROJECT.getConfiguredValueAsOptional( - configProperties); - maybeConfiguredQuotaProjectId.ifPresent( - configuredQuotaProjectId -> - flattenedHeaders.put(QUOTA_USER_PROJECT_HEADER, configuredQuotaProjectId)); + getQuotaProjectId(configProperties) + .ifPresent( + configuredQuotaProjectId -> + flattenedHeaders.put(QUOTA_USER_PROJECT_HEADER, configuredQuotaProjectId)); } return flattenedHeaders; } + static Optional getQuotaProjectId(ConfigProperties configProperties) { + return Optional.ofNullable( + ConfigurableOption.GOOGLE_CLOUD_QUOTA_PROJECT.getConfiguredValue( + configProperties, ConfigProperties::getString)); + } + // Updates the current resource with the attributes required for ingesting OTLP data on GCP. private static Resource customizeResource(Resource resource, ConfigProperties configProperties) { - String gcpProjectId = - ConfigurableOption.GOOGLE_CLOUD_PROJECT.getConfiguredValue(configProperties); Resource res = Resource.create( - Attributes.of(AttributeKey.stringKey(GCP_USER_PROJECT_ID_KEY), gcpProjectId)); + Attributes.of(stringKey(GCP_USER_PROJECT_ID_KEY), getProjectId(configProperties))); return resource.merge(res); } + + static String getProjectId(ConfigProperties configProperties) { + return ConfigurableOption.GOOGLE_CLOUD_PROJECT.getRequiredConfiguredValue( + configProperties, ConfigProperties::getString); + } } diff --git a/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java new file mode 100644 index 000000000..786df2739 --- /dev/null +++ b/gcp-auth-extension/src/main/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProvider.java @@ -0,0 +1,172 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.gcp.auth; + +import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_METRICS; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_TRACES; +import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.shouldCustomizeExporter; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.auto.service.AutoService; +import com.google.common.annotations.VisibleForTesting; +import io.opentelemetry.instrumentation.config.bridge.ConfigPropertiesUtil; +import io.opentelemetry.instrumentation.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchSpanProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MeterProviderModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReaderModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.NameStringValuePairModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpGrpcExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpGrpcMetricExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpHttpExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpHttpMetricExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PushMetricExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleSpanProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +@AutoService(DeclarativeConfigurationCustomizerProvider.class) +public class GcpAuthDeclarativeConfigurationCustomizerProvider + implements DeclarativeConfigurationCustomizerProvider { + + static final String SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION = + String.format( + "You may safely ignore this warning if it is intentional, otherwise please configure the '%s' by setting %s in the configuration file.", + ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getUserReadableName(), + ConfigPropertiesUtil.propertyYamlPath( + ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty())); + + @Override + public void customize(DeclarativeConfigurationCustomizer customizer) { + customizer.addModelCustomizer( + model -> { + customize( + model, + GcpAuthAutoConfigurationCustomizerProvider.getCredentials(), + getConfigProperties(model)); + + return model; + }); + } + + @VisibleForTesting + static void customize( + OpenTelemetryConfigurationModel model, + GoogleCredentials credentials, + ConfigProperties configProperties) { + Map headerMap = + GcpAuthAutoConfigurationCustomizerProvider.getRequiredHeaderMap( + credentials, configProperties); + customizeMeter(model, headerMap, configProperties); + customizeTracer(model, headerMap, configProperties); + } + + static ConfigProperties getConfigProperties(OpenTelemetryConfigurationModel model) { + return new DeclarativeConfigPropertiesBridgeBuilder() + .buildFromInstrumentationConfig(SdkConfigProvider.create(model).getInstrumentationConfig()); + } + + private static void customizeMeter( + OpenTelemetryConfigurationModel model, + Map headerMap, + ConfigProperties configProperties) { + MeterProviderModel meterProvider = model.getMeterProvider(); + if (meterProvider == null) { + return; + } + + if (shouldCustomizeExporter( + SIGNAL_TYPE_METRICS, SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION, configProperties)) { + for (MetricReaderModel reader : meterProvider.getReaders()) { + if (reader.getPeriodic() != null) { + addAuth(meterModelHeaders(reader.getPeriodic().getExporter()), headerMap); + } + } + } + } + + private static List> meterModelHeaders( + @Nullable PushMetricExporterModel exporter) { + ArrayList> list = new ArrayList<>(); + if (exporter == null) { + return list; + } + OtlpGrpcMetricExporterModel grpc = exporter.getOtlpGrpc(); + if (grpc != null) { + list.add(grpc.getHeaders()); + } + OtlpHttpMetricExporterModel http = exporter.getOtlpHttp(); + if (http != null) { + list.add(http.getHeaders()); + } + return list; + } + + private static void customizeTracer( + OpenTelemetryConfigurationModel model, + Map headerMap, + ConfigProperties configProperties) { + TracerProviderModel tracerProvider = model.getTracerProvider(); + if (tracerProvider == null) { + return; + } + + if (shouldCustomizeExporter( + SIGNAL_TYPE_TRACES, SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION, configProperties)) { + for (SpanProcessorModel processor : tracerProvider.getProcessors()) { + BatchSpanProcessorModel batch = processor.getBatch(); + if (batch != null) { + addAuth(spanExporterModelHeaders(batch.getExporter()), headerMap); + } + SimpleSpanProcessorModel simple = processor.getSimple(); + if (simple != null) { + addAuth(spanExporterModelHeaders(simple.getExporter()), headerMap); + } + } + } + } + + private static List> spanExporterModelHeaders( + @Nullable SpanExporterModel exporter) { + ArrayList> list = new ArrayList<>(); + + if (exporter == null) { + return list; + } + OtlpGrpcExporterModel grpc = exporter.getOtlpGrpc(); + if (grpc != null) { + list.add(grpc.getHeaders()); + } + OtlpHttpExporterModel http = exporter.getOtlpHttp(); + if (http != null) { + list.add(http.getHeaders()); + } + return list; + } + + private static void addAuth( + List> headerConsumers, Map headerMap) { + headerConsumers.forEach(headers -> addHeaders(headers, headerMap)); + } + + private static void addHeaders(List headers, Map add) { + add.forEach( + (key, value) -> { + if (headers.stream().noneMatch(header -> key.equals(header.getName()))) { + headers.add(new NameStringValuePairModel().withName(key).withValue(value)); + } + }); + } +} diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProviderTest.java index 4fb687925..d7a4f07fd 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProviderTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthAutoConfigurationCustomizerProviderTest.java @@ -11,9 +11,10 @@ import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_METRICS; import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.SIGNAL_TYPE_TRACES; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; @@ -127,7 +128,7 @@ public void setup() { // TODO: Use parameterized test for testing traces customizer for http & grpc. @Test - public void testTraceCustomizerOtlpHttp() { + void testTraceCustomizerOtlpHttp() { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -135,15 +136,15 @@ public void testTraceCustomizerOtlpHttp() { ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty(), SIGNAL_TYPE_TRACES); // Prepare mocks prepareMockBehaviorForGoogleCredentials(); - OtlpHttpSpanExporter mockOtlpHttpSpanExporter = Mockito.mock(OtlpHttpSpanExporter.class); + OtlpHttpSpanExporter mockOtlpHttpSpanExporter = mock(OtlpHttpSpanExporter.class); OtlpHttpSpanExporterBuilder otlpSpanExporterBuilder = OtlpHttpSpanExporter.builder(); OtlpHttpSpanExporterBuilder spyOtlpHttpSpanExporterBuilder = Mockito.spy(otlpSpanExporterBuilder); - Mockito.when(spyOtlpHttpSpanExporterBuilder.build()).thenReturn(mockOtlpHttpSpanExporter); + when(spyOtlpHttpSpanExporterBuilder.build()).thenReturn(mockOtlpHttpSpanExporter); - Mockito.when(mockOtlpHttpSpanExporter.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); + when(mockOtlpHttpSpanExporter.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); List exportedSpans = new ArrayList<>(); - Mockito.when(mockOtlpHttpSpanExporter.export(Mockito.anyCollection())) + when(mockOtlpHttpSpanExporter.export(any())) .thenAnswer( invocationOnMock -> { exportedSpans.addAll(invocationOnMock.getArgument(0)); @@ -162,12 +163,12 @@ public void testTraceCustomizerOtlpHttp() { generateTestSpan(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(mockOtlpHttpSpanExporter, Mockito.times(1)).toBuilder(); Mockito.verify(spyOtlpHttpSpanExporterBuilder, Mockito.times(1)) .setHeaders(traceHeaderSupplierCaptor.capture()); - assertEquals(2, traceHeaderSupplierCaptor.getValue().get().size()); + assertThat(traceHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(traceHeaderSupplierCaptor.getValue().get())) .isTrue(); @@ -189,7 +190,7 @@ public void testTraceCustomizerOtlpHttp() { } @Test - public void testTraceCustomizerOtlpGrpc() { + void testTraceCustomizerOtlpGrpc() { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -215,12 +216,12 @@ public void testTraceCustomizerOtlpGrpc() { generateTestSpan(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(mockOtlpGrpcSpanExporter, Mockito.times(1)).toBuilder(); Mockito.verify(spyOtlpGrpcSpanExporterBuilder, Mockito.times(1)) .setHeaders(traceHeaderSupplierCaptor.capture()); - assertEquals(2, traceHeaderSupplierCaptor.getValue().get().size()); + assertThat(traceHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(traceHeaderSupplierCaptor.getValue().get())) .isTrue(); @@ -243,7 +244,7 @@ public void testTraceCustomizerOtlpGrpc() { // TODO: Use parameterized test for testing metrics customizer for http & grpc. @Test - public void testMetricCustomizerOtlpHttp() { + void testMetricCustomizerOtlpHttp() { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -271,12 +272,12 @@ public void testMetricCustomizerOtlpHttp() { generateTestMetric(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(mockOtlpHttpMetricExporter, Mockito.times(1)).toBuilder(); Mockito.verify(spyOtlpHttpMetricExporterBuilder, Mockito.times(1)) .setHeaders(metricHeaderSupplierCaptor.capture()); - assertEquals(2, metricHeaderSupplierCaptor.getValue().get().size()); + assertThat(metricHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(metricHeaderSupplierCaptor.getValue().get())) .isTrue(); @@ -304,7 +305,7 @@ public void testMetricCustomizerOtlpHttp() { } @Test - public void testMetricCustomizerOtlpGrpc() { + void testMetricCustomizerOtlpGrpc() { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -332,12 +333,12 @@ public void testMetricCustomizerOtlpGrpc() { generateTestMetric(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(mockOtlpGrpcMetricExporter, Mockito.times(1)).toBuilder(); Mockito.verify(spyOtlpGrpcMetricExporterBuilder, Mockito.times(1)) .setHeaders(metricHeaderSupplierCaptor.capture()); - assertEquals(2, metricHeaderSupplierCaptor.getValue().get().size()); + assertThat(metricHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(metricHeaderSupplierCaptor.getValue().get())) .isTrue(); @@ -365,7 +366,7 @@ public void testMetricCustomizerOtlpGrpc() { } @Test - public void testCustomizerFailWithMissingResourceProject() { + void testCustomizerFailWithMissingResourceProject() { System.setProperty( ConfigurableOption.GOOGLE_OTEL_AUTH_TARGET_SIGNALS.getSystemProperty(), SIGNAL_TYPE_ALL); OtlpGrpcSpanExporter mockOtlpGrpcSpanExporter = Mockito.mock(OtlpGrpcSpanExporter.class); @@ -375,16 +376,15 @@ public void testCustomizerFailWithMissingResourceProject() { .when(GoogleCredentials::getApplicationDefault) .thenReturn(mockedGoogleCredentials); - assertThrows( - ConfigurationException.class, - () -> buildOpenTelemetrySdkWithExporter(mockOtlpGrpcSpanExporter)); + assertThatThrownBy(() -> buildOpenTelemetrySdkWithExporter(mockOtlpGrpcSpanExporter)) + .isInstanceOf(ConfigurationException.class); } } @ParameterizedTest @MethodSource("provideQuotaBehaviorTestCases") @SuppressWarnings("CannotMockMethod") - public void testQuotaProjectBehavior(QuotaProjectIdTestBehavior testCase) throws IOException { + void testQuotaProjectBehavior(QuotaProjectIdTestBehavior testCase) throws IOException { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -437,7 +437,7 @@ public void testQuotaProjectBehavior(QuotaProjectIdTestBehavior testCase) throws generateTestSpan(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); Mockito.verify(spyOtlpGrpcSpanExporterBuilder, Mockito.times(1)) .setHeaders(traceHeaderSupplierCaptor.capture()); @@ -458,7 +458,7 @@ public void testQuotaProjectBehavior(QuotaProjectIdTestBehavior testCase) throws @ParameterizedTest @MethodSource("provideTargetSignalBehaviorTestCases") - public void testTargetSignalsBehavior(TargetSignalBehavior testCase) { + void testTargetSignalsBehavior(TargetSignalBehavior testCase) { // Set resource project system property System.setProperty( ConfigurableOption.GOOGLE_CLOUD_PROJECT.getSystemProperty(), DUMMY_GCP_RESOURCE_PROJECT_ID); @@ -506,14 +506,14 @@ public void testTargetSignalsBehavior(TargetSignalBehavior testCase) { generateTestSpan(sdk); CompletableResultCode code = sdk.shutdown(); CompletableResultCode joinResult = code.join(10, TimeUnit.SECONDS); - assertTrue(joinResult.isSuccess()); + assertThat(joinResult.isSuccess()).isTrue(); // Check Traces modification conditions if (testCase.getExpectedIsTraceSignalModified()) { // If traces signal is expected to be modified, auth headers must be present Mockito.verify(spyOtlpGrpcSpanExporterBuilder, Mockito.times(1)) .setHeaders(traceHeaderSupplierCaptor.capture()); - assertEquals(2, traceHeaderSupplierCaptor.getValue().get().size()); + assertThat(traceHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(traceHeaderSupplierCaptor.getValue().get())) .isTrue(); } else { @@ -527,7 +527,7 @@ public void testTargetSignalsBehavior(TargetSignalBehavior testCase) { // If metrics signal is expected to be modified, auth headers must be present Mockito.verify(spyOtlpGrpcMetricExporterBuilder, Mockito.times(1)) .setHeaders(metricHeaderSupplierCaptor.capture()); - assertEquals(2, metricHeaderSupplierCaptor.getValue().get().size()); + assertThat(metricHeaderSupplierCaptor.getValue().get().size()).isEqualTo(2); assertThat(authHeadersQuotaProjectIsPresent(metricHeaderSupplierCaptor.getValue().get())) .isTrue(); } else { diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java new file mode 100644 index 000000000..ca234a0e3 --- /dev/null +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthDeclarativeConfigurationCustomizerProviderTest.java @@ -0,0 +1,86 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.gcp.auth; + +import static io.opentelemetry.contrib.gcp.auth.GcpAuthDeclarativeConfigurationCustomizerProvider.SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.auth.oauth2.GoogleCredentials; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class GcpAuthDeclarativeConfigurationCustomizerProviderTest { + + @Test + void declarativeConfig() throws IOException { + String yaml = + "file_format: 0.4\n" + + "tracer_provider:\n" + + " processors:\n" + + " - simple:\n" + + " exporter:\n" + + " otlp_http:\n" + + "meter_provider:\n" + + " readers:\n" + + " - periodic:\n" + + " exporter:\n" + + " otlp_http:\n" + + "instrumentation/development:\n" + + " java:\n" + + " google:\n" + + " cloud:\n" + + " project: p\n" + + " quota:\n" + + " project: qp\n" + + " otel:\n" + + " auth:\n" + + " target:\n" + + " signals: [metrics, traces]\n"; + + OpenTelemetryConfigurationModel model = + DeclarativeConfiguration.parse( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))); + ConfigProperties properties = + GcpAuthDeclarativeConfigurationCustomizerProvider.getConfigProperties(model); + + assertThat(GcpAuthAutoConfigurationCustomizerProvider.targetSignals(properties)) + .containsExactly("metrics", "traces"); + assertThat(GcpAuthAutoConfigurationCustomizerProvider.getProjectId(properties)).isEqualTo("p"); + assertThat(GcpAuthAutoConfigurationCustomizerProvider.getQuotaProjectId(properties)) + .contains("qp"); + + GoogleCredentials credentials = mock(GoogleCredentials.class); + when(credentials.getRequestMetadata()) + .thenReturn( + Collections.singletonMap("x-goog-user-project", Collections.singletonList("qp"))); + + GcpAuthDeclarativeConfigurationCustomizerProvider.customize(model, credentials, properties); + + String header = + "headers=\\[io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.NameStringValuePairModel@.*\\[name=x-goog-user-project,value=qp]"; + // both metrics and traces should have the header + assertThat(model.toString()).matches(String.format(".*%s.*%s.*", header, header)); + } + + @Test + void fixSuggestion() { + assertThat(SIGNAL_TARGET_WARNING_YAML_FIX_SUGGESTION) + .isEqualTo( + "You may safely ignore this warning if it is intentional, " + + "otherwise please configure the 'Target Signals for Google Authentication Extension' " + + "by setting " + + "'instrumentation/development' / 'java' / 'google' / 'otel' / 'auth' / 'target' / " + + "'signals' in the configuration file."); + } +} diff --git a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthExtensionEndToEndTest.java b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthExtensionEndToEndTest.java index e04baed93..f87762474 100644 --- a/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthExtensionEndToEndTest.java +++ b/gcp-auth-extension/src/test/java/io/opentelemetry/contrib/gcp/auth/GcpAuthExtensionEndToEndTest.java @@ -7,9 +7,8 @@ import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.GCP_USER_PROJECT_ID_KEY; import static io.opentelemetry.contrib.gcp.auth.GcpAuthAutoConfigurationCustomizerProvider.QUOTA_USER_PROJECT_HEADER; +import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockserver.model.HttpRequest.request; import static org.mockserver.model.HttpResponse.response; import static org.mockserver.stop.Stop.stopQuietly; @@ -51,7 +50,7 @@ @SpringBootTest( classes = {Application.class}, webEnvironment = WebEnvironment.RANDOM_PORT) -public class GcpAuthExtensionEndToEndTest { +class GcpAuthExtensionEndToEndTest { @LocalServerPort private int testApplicationPort; // port at which the spring app is running @@ -115,7 +114,7 @@ public static void teardown() { } @Test - public void authExtensionSmokeTest() { + void authExtensionSmokeTest() { template.getForEntity( URI.create("http://localhost:" + testApplicationPort + "/ping"), String.class); @@ -160,24 +159,22 @@ public X509Certificate[] getAcceptedIssuers() { private static void verifyResourceAttributes(List extractedResourceSpans) { extractedResourceSpans.forEach( resourceSpan -> - assertTrue( - resourceSpan - .getResource() - .getAttributesList() - .contains( - KeyValue.newBuilder() - .setKey(GCP_USER_PROJECT_ID_KEY) - .setValue(AnyValue.newBuilder().setStringValue(DUMMY_GCP_PROJECT)) - .build()))); + assertThat(resourceSpan.getResource().getAttributesList()) + .contains( + KeyValue.newBuilder() + .setKey(GCP_USER_PROJECT_ID_KEY) + .setValue(AnyValue.newBuilder().setStringValue(DUMMY_GCP_PROJECT)) + .build())); } private static void verifyRequestHeaders(List extractedHeaders) { - assertFalse(extractedHeaders.isEmpty()); + assertThat(extractedHeaders).isNotEmpty(); // verify if extension added the required headers extractedHeaders.forEach( headers -> { - assertTrue(headers.containsEntry(QUOTA_USER_PROJECT_HEADER, DUMMY_GCP_QUOTA_PROJECT)); - assertTrue(headers.containsEntry("Authorization", "Bearer fake.access_token")); + assertThat(headers.containsEntry(QUOTA_USER_PROJECT_HEADER, DUMMY_GCP_QUOTA_PROJECT)) + .isTrue(); + assertThat(headers.containsEntry("Authorization", "Bearer fake.access_token")).isTrue(); }); } diff --git a/gcp-resources/README.md b/gcp-resources/README.md index 6a80e1baf..9f670e088 100644 --- a/gcp-resources/README.md +++ b/gcp-resources/README.md @@ -47,7 +47,7 @@ env: ## Usage with Manual Instrumentation -It is recommended to use this resource detector with the [OpenTelemetry Autoconfiguration SPI](https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md#resource-provider-spi). The GCP resource detector automatically provides the detected resources via the [autoconfigure-spi](https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure-spi) SDK extension. +It is recommended to use this resource detector with the [OpenTelemetry SDK autoconfiguration](https://opentelemetry.io/docs/languages/java/configuration/#zero-code-sdk-autoconfigure). The GCP resource detector automatically provides the detected resources via the [autoconfigure-spi](https://opentelemetry.io/docs/languages/java/configuration/#spi-service-provider-interface) SDK extension. For a reference example showcasing the detected resource attributes and usage with `autoconfigure-spi`, see the [Resource detection example](https://github.com/open-telemetry/opentelemetry-java-examples/tree/main/resource-detection-gcp). diff --git a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java index b7e49c1a9..4b92ade57 100644 --- a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java +++ b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/GCPResourceProvider.java @@ -65,6 +65,7 @@ public class GCPResourceProvider implements ConditionalResourceProvider { private static final Logger LOGGER = Logger.getLogger(GCPResourceProvider.class.getSimpleName()); + private final GCPPlatformDetector detector; // for testing only diff --git a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java index 745d440fd..2f0f937f0 100644 --- a/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java +++ b/gcp-resources/src/main/java/io/opentelemetry/contrib/gcp/resource/IncubatingAttributes.java @@ -13,8 +13,6 @@ */ class IncubatingAttributes { - private IncubatingAttributes() {} - public static final AttributeKey CLOUD_ACCOUNT_ID = AttributeKey.stringKey("cloud.account.id"); public static final AttributeKey CLOUD_AVAILABILITY_ZONE = @@ -26,7 +24,6 @@ private IncubatingAttributes() {} public static final AttributeKey CLOUD_REGION = AttributeKey.stringKey("cloud.region"); public static final class CloudPlatformIncubatingValues { - private CloudPlatformIncubatingValues() {} public static final String GCP_COMPUTE_ENGINE = "gcp_compute_engine"; public static final String GCP_CLOUD_RUN = "gcp_cloud_run"; @@ -34,6 +31,8 @@ private CloudPlatformIncubatingValues() {} public static final String GCP_CLOUD_FUNCTIONS = "gcp_cloud_functions"; public static final String GCP_APP_ENGINE = "gcp_app_engine"; public static final String GCP = "gcp"; + + private CloudPlatformIncubatingValues() {} } public static final AttributeKey FAAS_INSTANCE = AttributeKey.stringKey("faas.instance"); @@ -56,4 +55,6 @@ private CloudPlatformIncubatingValues() {} public static final AttributeKey K8S_CLUSTER_NAME = AttributeKey.stringKey("k8s.cluster.name"); + + private IncubatingAttributes() {} } 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..9314a1b67 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; @@ -186,7 +186,7 @@ private static DetectedPlatform generateMockUnknownPlatform() { } @Test - public void testGceResourceAttributesMapping() { + void testGceResourceAttributesMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGcePlatform(); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -210,7 +210,7 @@ public void testGceResourceAttributesMapping() { } @Test - public void testGkeResourceAttributesMapping_LocationTypeRegion() { + void testGkeResourceAttributesMapping_LocationTypeRegion() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGkePlatform(GKE_LOCATION_TYPE_REGION); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -227,7 +227,7 @@ public void testGkeResourceAttributesMapping_LocationTypeRegion() { } @Test - public void testGkeResourceAttributesMapping_LocationTypeZone() { + void testGkeResourceAttributesMapping_LocationTypeZone() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGkePlatform(GKE_LOCATION_TYPE_ZONE); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -245,7 +245,7 @@ public void testGkeResourceAttributesMapping_LocationTypeZone() { } @Test - public void testGkeResourceAttributesMapping_LocationTypeInvalid() { + void testGkeResourceAttributesMapping_LocationTypeInvalid() { Map mockGKEAttributes = new HashMap<>(mockGKECommonAttributes); mockGKEAttributes.put(GKE_CLUSTER_LOCATION_TYPE, "INVALID"); mockGKEAttributes.put(GKE_CLUSTER_LOCATION, "some-location"); @@ -270,7 +270,7 @@ public void testGkeResourceAttributesMapping_LocationTypeInvalid() { } @Test - public void testGkeResourceAttributesMapping_LocationMissing() { + void testGkeResourceAttributesMapping_LocationMissing() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGkePlatform(""); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -295,7 +295,7 @@ private static void verifyGkeMapping(Resource gotResource, DetectedPlatform dete } @Test - public void testGcrServiceResourceAttributesMapping() { + void testGcrServiceResourceAttributesMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockServerlessPlatform(GCPPlatformDetector.SupportedPlatform.GOOGLE_CLOUD_RUN); @@ -312,7 +312,7 @@ public void testGcrServiceResourceAttributesMapping() { } @Test - public void testGcfResourceAttributeMapping() { + void testGcfResourceAttributeMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockServerlessPlatform( @@ -343,7 +343,7 @@ private static void verifyServerlessMapping( } @Test - public void testGcrJobResourceAttributesMapping() { + void testGcrJobResourceAttributesMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGcrJobPlatform(); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -368,7 +368,7 @@ public void testGcrJobResourceAttributesMapping() { } @Test - public void testGaeResourceAttributeMapping() { + void testGaeResourceAttributeMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockGaePlatform(); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -390,7 +390,7 @@ public void testGaeResourceAttributeMapping() { } @Test - public void testUnknownPlatformResourceAttributesMapping() { + void testUnknownPlatformResourceAttributesMapping() { GCPPlatformDetector mockDetector = Mockito.mock(GCPPlatformDetector.class); DetectedPlatform mockPlatform = generateMockUnknownPlatform(); Mockito.when(mockDetector.detectPlatform()).thenReturn(mockPlatform); @@ -400,7 +400,7 @@ public void testUnknownPlatformResourceAttributesMapping() { } @Test - public void findsWithServiceLoader() { + void findsWithServiceLoader() { ServiceLoader services = ServiceLoader.load(ResourceProvider.class, getClass().getClassLoader()); while (services.iterator().hasNext()) { diff --git a/gradle.properties b/gradle.properties index 0b5e135ed..bc596d5e4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,7 @@ org.gradle.parallel=true org.gradle.caching=true +org.gradle.configuration-cache=true +org.gradle.configuration-cache.parallel=true org.gradle.priority=low diff --git a/ibm-mq-metrics/build.gradle.kts b/ibm-mq-metrics/build.gradle.kts index 7e3afe148..2370f2893 100644 --- a/ibm-mq-metrics/build.gradle.kts +++ b/ibm-mq-metrics/build.gradle.kts @@ -31,10 +31,10 @@ val ibmClientJar: Configuration by configurations.creating { dependencies { api("com.google.code.findbugs:jsr305:3.0.2") api("io.swagger:swagger-annotations:1.6.16") - api("org.jetbrains:annotations:26.0.2") - api("com.ibm.mq:com.ibm.mq.allclient:9.4.3.0") - api("org.yaml:snakeyaml:2.4") - api("com.fasterxml.jackson.core:jackson-databind:2.19.2") + api("org.jetbrains:annotations:26.0.2-1") + api("com.ibm.mq:com.ibm.mq.allclient:9.4.3.1") + api("org.yaml:snakeyaml:2.5") + api("com.fasterxml.jackson.core:jackson-databind:2.20.0") api("io.opentelemetry:opentelemetry-sdk") api("io.opentelemetry:opentelemetry-exporter-otlp") api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") @@ -45,11 +45,11 @@ dependencies { integrationTestImplementation("org.assertj:assertj-core:3.27.4") integrationTestImplementation("org.junit.jupiter:junit-jupiter-api:5.13.4") integrationTestImplementation("io.opentelemetry:opentelemetry-sdk-testing") - integrationTestImplementation("com.ibm.mq:com.ibm.mq.jakarta.client:9.4.3.0") + integrationTestImplementation("com.ibm.mq:com.ibm.mq.jakarta.client:9.4.3.1") integrationTestImplementation("jakarta.jms:jakarta.jms-api:3.1.0") integrationTestImplementation("org.junit.jupiter:junit-jupiter-engine:5.13.4") integrationTestRuntimeOnly("org.junit.platform:junit-platform-launcher:1.13.4") - ibmClientJar("com.ibm.mq:com.ibm.mq.allclient:9.4.3.0") { + ibmClientJar("com.ibm.mq:com.ibm.mq.allclient:9.4.3.1") { artifact { name = "com.ibm.mq.allclient" extension = "jar" @@ -60,7 +60,7 @@ dependencies { tasks.shadowJar { dependencies { - exclude(dependency("com.ibm.mq:com.ibm.mq.allclient:9.4.3.0")) + exclude(dependency("com.ibm.mq:com.ibm.mq.allclient:9.4.3.1")) } } diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqContext.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqContext.java index 6ded88547..b3fafadb6 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqContext.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqContext.java @@ -17,7 +17,7 @@ * authorization.
* It also validates the arguments passed for various scenarios. */ -public class WmqContext { +public final class WmqContext { private static final String TRANSPORT_TYPE_CLIENT = "Client"; private static final String TRANSPORT_TYPE_BINDINGS = "Bindings"; diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqMonitor.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqMonitor.java index 832527fb3..9611604cb 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqMonitor.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/WmqMonitor.java @@ -43,7 +43,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class WmqMonitor { +public final class WmqMonitor { private static final Logger logger = LoggerFactory.getLogger(WmqMonitor.class); diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ExcludeFilters.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ExcludeFilters.java index f02f05cc0..862edd30a 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ExcludeFilters.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ExcludeFilters.java @@ -12,7 +12,7 @@ import java.util.Set; /** A jackson databind class used for config. */ -public class ExcludeFilters { +public final class ExcludeFilters { private String type = "UNKNOWN"; private Set values = new HashSet<>(); diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/QueueManager.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/QueueManager.java index 685840977..11769832f 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/QueueManager.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/QueueManager.java @@ -10,7 +10,7 @@ /** This is a jackson databind class used purely for config. */ @JsonIgnoreProperties(ignoreUnknown = true) -public class QueueManager { +public final class QueueManager { @Nullable private String host; private int port = -1; diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ResourceFilters.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ResourceFilters.java index 72a3a9f42..86a30360e 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ResourceFilters.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/config/ResourceFilters.java @@ -8,7 +8,7 @@ import java.util.HashSet; import java.util.Set; -public class ResourceFilters { +public final class ResourceFilters { private Set include = new HashSet<>(); private Set exclude = new HashSet<>(); diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/metricscollector/MessageBuddy.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/metricscollector/MessageBuddy.java index 6ed74dad9..688f9541d 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/metricscollector/MessageBuddy.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/metricscollector/MessageBuddy.java @@ -12,7 +12,7 @@ import com.ibm.mq.headers.pcf.PCFMessage; import java.time.Instant; -public class MessageBuddy { +public final class MessageBuddy { private MessageBuddy() {} diff --git a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/util/WmqUtil.java b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/util/WmqUtil.java index cefa9e5d9..cf633b953 100644 --- a/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/util/WmqUtil.java +++ b/ibm-mq-metrics/src/main/java/io/opentelemetry/ibm/mq/util/WmqUtil.java @@ -16,7 +16,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class WmqUtil { +public final class WmqUtil { private static final Logger logger = LoggerFactory.getLogger(WmqUtil.class); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/InquireChannelCmdCollectorTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/InquireChannelCmdCollectorTest.java index a0e06e336..b9964537f 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/InquireChannelCmdCollectorTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/InquireChannelCmdCollectorTest.java @@ -54,7 +54,7 @@ public void setup() throws Exception { } @Test - public void testProcessPCFRequestAndPublishQMetricsForInquireQStatusCmd() throws Exception { + void testProcessPCFRequestAndPublishQMetricsForInquireQStatusCmd() throws Exception { when(pcfMessageAgent.send(any(PCFMessage.class))) .thenReturn(createPCFResponseForInquireChannelCmd()); classUnderTest = new InquireChannelCmdCollector(meter); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/ListenerMetricsCollectorTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/ListenerMetricsCollectorTest.java index 6170e31f4..ea46450d3 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/ListenerMetricsCollectorTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/ListenerMetricsCollectorTest.java @@ -47,7 +47,7 @@ public void setup() throws Exception { } @Test - public void testPublishMetrics() throws Exception { + void testPublishMetrics() throws Exception { when(pcfMessageAgent.send(any(PCFMessage.class))) .thenReturn(createPCFResponseForInquireListenerStatusCmd()); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/MetricAssert.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/MetricAssert.java index 25d173d3d..e6ddfae17 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/MetricAssert.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/MetricAssert.java @@ -5,9 +5,10 @@ package io.opentelemetry.ibm.mq.metricscollector; +import static org.assertj.core.api.Assertions.assertThat; + import io.opentelemetry.sdk.metrics.data.LongPointData; import io.opentelemetry.sdk.metrics.data.MetricData; -import org.assertj.core.api.Assertions; public class MetricAssert { @@ -24,12 +25,12 @@ static MetricAssert assertThatMetric(MetricData metric, int pointOffset) { } MetricAssert hasName(String name) { - Assertions.assertThat(metric.getName()).isEqualTo(name); + assertThat(metric.getName()).isEqualTo(name); return this; } MetricAssert hasValue(long value) { - Assertions.assertThat( + assertThat( ((LongPointData) metric.getLongGaugeData().getPoints().toArray()[this.pointOffset]) .getValue()) .isEqualTo(value); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueCollectionBuddyTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueCollectionBuddyTest.java index bd0c1ef97..5d18d73da 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueCollectionBuddyTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueCollectionBuddyTest.java @@ -33,7 +33,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class QueueCollectionBuddyTest { +class QueueCollectionBuddyTest { @RegisterExtension static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create(); diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueManagerMetricsCollectorTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueManagerMetricsCollectorTest.java index dde400b02..3c6ef1503 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueManagerMetricsCollectorTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/QueueManagerMetricsCollectorTest.java @@ -51,7 +51,7 @@ public void setup() throws Exception { } @Test - public void testProcessPCFRequestAndPublishQMetricsForInquireQStatusCmd() throws Exception { + void testProcessPCFRequestAndPublishQMetricsForInquireQStatusCmd() throws Exception { when(pcfMessageAgent.send(any(PCFMessage.class))) .thenReturn(createPCFResponseForInquireQMgrStatusCmd()); classUnderTest = diff --git a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/TopicMetricsCollectorTest.java b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/TopicMetricsCollectorTest.java index 865501573..646d4ee98 100644 --- a/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/TopicMetricsCollectorTest.java +++ b/ibm-mq-metrics/src/test/java/io/opentelemetry/ibm/mq/metricscollector/TopicMetricsCollectorTest.java @@ -34,7 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class TopicMetricsCollectorTest { +class TopicMetricsCollectorTest { @RegisterExtension static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create(); diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpans.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpans.java new file mode 100644 index 000000000..76f55db83 --- /dev/null +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpans.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.inferredspans; + +import java.time.Duration; +import javax.annotation.Nullable; + +/** + * A global accessor for the {@link InferredSpansProcessor} instance. + * + *

This class is for internal use only and may be removed in a future release. + */ +public final class InferredSpans { + + @Nullable private static volatile InferredSpansProcessor instance; + + private InferredSpans() {} + + /** + * Sets the {@link InferredSpansProcessor} instance. + * + * @param processor the processor instance + */ + public static void setInstance(@Nullable InferredSpansProcessor processor) { + instance = processor; + } + + /** + * Returns whether inferred spans are enabled. + * + * @return whether inferred spans are enabled + */ + public static boolean isEnabled() { + return instance != null; + } + + /** + * Sets the profiler interval. + * + * @param interval the new profiler interval + */ + public static void setProfilerInterval(Duration interval) { + InferredSpansProcessor p = instance; + if (p != null) { + p.setProfilerInterval(interval); + } + } +} diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java index 9c8118ec5..7ee78943e 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfig.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.inferredspans; +import static java.util.stream.Collectors.toList; + import com.google.auto.service.AutoService; import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; @@ -17,7 +19,6 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.logging.Logger; -import java.util.stream.Collectors; import javax.annotation.Nullable; @AutoService(AutoConfigurationCustomizerProvider.class) @@ -117,7 +118,7 @@ void applyWildcards(String configKey, Consumer> fu Arrays.stream(wildcardListString.split(",")) .filter(str -> !str.isEmpty()) .map(WildcardMatcher::valueOf) - .collect(Collectors.toList()); + .collect(toList()); if (!values.isEmpty()) { funcToApply.accept(values); } diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java index 22f59ba53..19baf3174 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessor.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.inferredspans; +import static java.util.Objects.requireNonNull; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.api.trace.TracerProvider; @@ -19,7 +21,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.Objects; +import java.time.Duration; import java.util.Properties; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; @@ -33,14 +35,13 @@ public class InferredSpansProcessor implements SpanProcessor { private static final Logger logger = Logger.getLogger(InferredSpansProcessor.class.getName()); public static final String TRACER_NAME = "inferred-spans"; - public static final String TRACER_VERSION = readInferredSpansVersion(); // Visible for testing final SamplingProfiler profiler; + private final InferredSpansConfiguration config; private Supplier tracerProvider = GlobalOpenTelemetry::getTracerProvider; - @Nullable private volatile Tracer tracer; InferredSpansProcessor( @@ -49,12 +50,18 @@ public class InferredSpansProcessor implements SpanProcessor { boolean startScheduledProfiling, @Nullable File activationEventsFile, @Nullable File jfrFile) { + this.config = config; profiler = new SamplingProfiler(config, clock, this::getTracer, activationEventsFile, jfrFile); if (startScheduledProfiling) { profiler.start(); } } + public void setProfilerInterval(Duration interval) { + config.setProfilerInterval(interval); + profiler.reschedule(); + } + public static InferredSpansProcessorBuilder builder() { return new InferredSpansProcessorBuilder(); } @@ -134,7 +141,7 @@ private static String readInferredSpansVersion() { Properties properties = new Properties(); properties.load(is); String version = (String) properties.get("contrib.version"); - Objects.requireNonNull(version); + requireNonNull(version); return version; } catch (IOException e) { throw new IllegalStateException(e); diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessorBuilder.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessorBuilder.java index b464f0f42..e8f52ed68 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessorBuilder.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/InferredSpansProcessorBuilder.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.inferredspans; +import static java.util.Arrays.asList; + import io.opentelemetry.api.trace.SpanBuilder; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.contrib.inferredspans.internal.CallTree; @@ -12,7 +14,6 @@ import io.opentelemetry.contrib.inferredspans.internal.SpanAnchoredClock; import java.io.File; import java.time.Duration; -import java.util.Arrays; import java.util.List; import java.util.function.BiConsumer; import javax.annotation.Nullable; @@ -27,7 +28,7 @@ public class InferredSpansProcessorBuilder { private Duration inferredSpansMinDuration = Duration.ZERO; private List includedClasses = WildcardMatcher.matchAllList(); private List excludedClasses = - Arrays.asList( + asList( WildcardMatcher.caseSensitiveMatcher("java.*"), WildcardMatcher.caseSensitiveMatcher("javax.*"), WildcardMatcher.caseSensitiveMatcher("sun.*"), @@ -43,13 +44,11 @@ public class InferredSpansProcessorBuilder { WildcardMatcher.caseSensitiveMatcher("io.undertow.*")); private Duration profilerInterval = Duration.ofSeconds(5); private Duration profilingDuration = Duration.ofSeconds(5); - @Nullable private String profilerLibDirectory = null; // The following options are only intended to be modified in tests private SpanAnchoredClock clock = new SpanAnchoredClock(); private boolean startScheduledProfiling = true; - @Nullable private File activationEventsFile = null; @Nullable private File jfrFile = null; private BiConsumer parentOverrideHandler = @@ -72,8 +71,11 @@ public InferredSpansProcessor build() { profilingDuration, profilerLibDirectory, parentOverrideHandler); - return new InferredSpansProcessor( - config, clock, startScheduledProfiling, activationEventsFile, jfrFile); + InferredSpansProcessor processor = + new InferredSpansProcessor( + config, clock, startScheduledProfiling, activationEventsFile, jfrFile); + InferredSpans.setInstance(processor); + return processor; } /** diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/WildcardMatcher.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/WildcardMatcher.java index b6b788c55..7e82a0ec1 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/WildcardMatcher.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/WildcardMatcher.java @@ -5,8 +5,9 @@ package io.opentelemetry.contrib.inferredspans; +import static java.util.Collections.singletonList; + import java.util.ArrayList; -import java.util.Collections; import java.util.List; import javax.annotation.Nullable; @@ -32,7 +33,7 @@ public abstract class WildcardMatcher { private static final String CASE_SENSITIVE_PREFIX = "(?-i)"; private static final String WILDCARD = "*"; private static final WildcardMatcher MATCH_ALL = valueOf(WILDCARD); - private static final List MATCH_ALL_LIST = Collections.singletonList(MATCH_ALL); + private static final List MATCH_ALL_LIST = singletonList(MATCH_ALL); public static WildcardMatcher caseSensitiveMatcher(String matcher) { return valueOf(CASE_SENSITIVE_PREFIX + matcher); diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/InferredSpansConfiguration.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/InferredSpansConfiguration.java index 5091a36a5..819a5b8cf 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/InferredSpansConfiguration.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/InferredSpansConfiguration.java @@ -23,7 +23,7 @@ public class InferredSpansConfiguration { private final Duration inferredSpansMinDuration; private final List includedClasses; private final List excludedClasses; - private final Duration profilerInterval; + private volatile Duration profilerInterval; private final Duration profilingDuration; @Nullable private final String profilerLibDirectory; private final BiConsumer parentOverrideHandler; @@ -84,6 +84,10 @@ public Duration getProfilingInterval() { return profilerInterval; } + public void setProfilerInterval(Duration profilerInterval) { + this.profilerInterval = profilerInterval; + } + public Duration getProfilingDuration() { return profilingDuration; } diff --git a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java index 61e5f75a7..27d0e5305 100644 --- a/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java +++ b/inferred-spans/src/main/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfiler.java @@ -39,6 +39,7 @@ import java.util.Locale; import java.util.Objects; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; @@ -151,6 +152,7 @@ public class SamplingProfiler implements Runnable { private final Supplier tracerProvider; private final AsyncProfiler profiler; + @Nullable private volatile Future profilingTask; /** * Creates a sampling profiler, optionally relying on existing files. @@ -385,7 +387,7 @@ public void run() { if (!interrupted && !scheduler.isShutdown()) { long delay = config.getProfilingInterval().toMillis() - profilingDuration.toMillis(); - scheduler.schedule(this, delay, TimeUnit.MILLISECONDS); + profilingTask = scheduler.schedule(this, delay, TimeUnit.MILLISECONDS); } } @@ -723,7 +725,19 @@ public void copyFromFiles(Path activationEvents, Path traces) throws IOException @SuppressWarnings("FutureReturnValueIgnored") public void start() { - scheduler.submit(this); + profilingTask = scheduler.submit(this); + } + + @SuppressWarnings({"FutureReturnValueIgnored", "Interruption"}) + public void reschedule() { + Future future = this.profilingTask; + if (future != null) { + if (future.cancel(true)) { + Duration profilingDuration = config.getProfilingDuration(); + long delay = config.getProfilingInterval().toMillis() - profilingDuration.toMillis(); + profilingTask = scheduler.schedule(this, delay, TimeUnit.MILLISECONDS); + } + } } public void stop() throws InterruptedException, IOException { diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java index 76a6333ba..b5ce0c650 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansAutoConfigTest.java @@ -35,7 +35,7 @@ import org.junit.jupiter.api.io.TempDir; @DisabledOnOs(WINDOWS) // Uses async-profiler, which is not supported on Windows -public class InferredSpansAutoConfigTest { +class InferredSpansAutoConfigTest { @BeforeEach @AfterEach @@ -99,7 +99,7 @@ public void checkAllOptions(@TempDir Path tmpDir) { } @Test - public void checkDisabledbyDefault() { + void checkDisabledbyDefault() { try (AutoConfigTestProperties props = new AutoConfigTestProperties()) { OpenTelemetry otel = GlobalOpenTelemetry.get(); List processors = OtelReflectionUtils.getSpanProcessors(otel); @@ -109,7 +109,7 @@ public void checkDisabledbyDefault() { @DisabledOnOpenJ9 @Test - public void checkProfilerWorking() { + void checkProfilerWorking() { try (AutoConfigTestProperties props = new AutoConfigTestProperties() .put(InferredSpansAutoConfig.ENABLED_OPTION, "true") diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansTest.java new file mode 100644 index 000000000..e0de5997e --- /dev/null +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/InferredSpansTest.java @@ -0,0 +1,88 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.inferredspans; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +import io.opentelemetry.contrib.inferredspans.internal.SamplingProfiler; +import io.opentelemetry.contrib.inferredspans.internal.util.DisabledOnOpenJ9; +import java.time.Duration; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; + +@DisabledOnOs(OS.WINDOWS) +@DisabledOnOpenJ9 +class InferredSpansTest { + + private ProfilerTestSetup setup; + + @BeforeEach + void setUp() { + InferredSpans.setInstance(null); + } + + @AfterEach + void tearDown() { + if (setup != null) { + setup.close(); + } + InferredSpans.setInstance(null); + } + + @Test + void testIsEnabled() { + assertThat(InferredSpans.isEnabled()).isFalse(); + + setup = ProfilerTestSetup.create(c -> {}); + + assertThat(InferredSpans.isEnabled()).isTrue(); + + setup.close(); + setup = null; + + // In a real-world scenario, the close() method would lead to the processor being garbage + // collected, but to make it deterministic, we manually set the instance to null + InferredSpans.setInstance(null); + assertThat(InferredSpans.isEnabled()).isFalse(); + } + + @Test + void testSetProfilerIntervalWhenDisabled() { + InferredSpans.setProfilerInterval(Duration.ofMillis(10)); + + setup = + ProfilerTestSetup.create( + c -> + c.profilerInterval(Duration.ofSeconds(10)) + .profilingDuration(Duration.ofMillis(500))); + + // assert that the interval set before the profiler was initialized is ignored + assertThat(setup.profiler.getConfig().getProfilingInterval()).isEqualTo(Duration.ofSeconds(10)); + } + + @Test + void testSetProfilerInterval() { + setup = + ProfilerTestSetup.create( + c -> + c.profilerInterval(Duration.ofSeconds(10)) + .profilingDuration(Duration.ofMillis(500))); + + SamplingProfiler profiler = setup.profiler; + await() + .untilAsserted(() -> assertThat(profiler.getProfilingSessions()).isGreaterThanOrEqualTo(1)); + + InferredSpans.setProfilerInterval(Duration.ofMillis(100)); + + await() + .timeout(Duration.ofSeconds(2)) + .untilAsserted(() -> assertThat(profiler.getProfilingSessions()).isGreaterThanOrEqualTo(2)); + } +} diff --git a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerQueueTest.java b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerQueueTest.java index 614f75e72..bcf56691b 100644 --- a/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerQueueTest.java +++ b/inferred-spans/src/test/java/io/opentelemetry/contrib/inferredspans/internal/SamplingProfilerQueueTest.java @@ -17,7 +17,7 @@ import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; -public class SamplingProfilerQueueTest { +class SamplingProfilerQueueTest { @Test @DisabledOnOs(OS.WINDOWS) 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/jfr-events/src/test/java/io/opentelemetry/contrib/jfrevent/JfrSpanProcessorTest.java b/jfr-events/src/test/java/io/opentelemetry/contrib/jfrevent/JfrSpanProcessorTest.java index 939a60af6..7225e72fa 100644 --- a/jfr-events/src/test/java/io/opentelemetry/contrib/jfrevent/JfrSpanProcessorTest.java +++ b/jfr-events/src/test/java/io/opentelemetry/contrib/jfrevent/JfrSpanProcessorTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.contrib.jfrevent; -import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Tracer; @@ -52,7 +52,7 @@ void tearDown() { * @throws java.io.IOException on io error */ @Test - public void basicSpan() throws IOException { + void basicSpan() throws IOException { Path output = Files.createTempFile("test-basic-span", ".jfr"); try { @@ -89,7 +89,7 @@ public void basicSpan() throws IOException { * @throws java.lang.InterruptedException interrupted sleep */ @Test - public void basicSpanWithScope() throws IOException, InterruptedException { + void basicSpanWithScope() throws IOException, InterruptedException { Path output = Files.createTempFile("test-basic-span-with-scope", ".jfr"); try { diff --git a/jmx-metrics/build.gradle.kts b/jmx-metrics/build.gradle.kts index d5376e670..bc895cfc5 100644 --- a/jmx-metrics/build.gradle.kts +++ b/jmx-metrics/build.gradle.kts @@ -47,7 +47,7 @@ testing { dependencies { implementation("com.linecorp.armeria:armeria-grpc") implementation("com.linecorp.armeria:armeria-junit5") - implementation("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + implementation("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") implementation("org.testcontainers:junit-jupiter") implementation("org.slf4j:slf4j-simple") } diff --git a/jmx-metrics/docs/target-systems/jetty.md b/jmx-metrics/docs/target-systems/jetty.md index 46724daf3..eb74f4f51 100644 --- a/jmx-metrics/docs/target-systems/jetty.md +++ b/jmx-metrics/docs/target-systems/jetty.md @@ -1,7 +1,7 @@ # Jetty Metrics The JMX Metric Gatherer provides built in Jetty metric gathering capabilities. -Details about using JMX with WildFly can be found here: https://www.eclipse.org/jetty/documentation/jetty-11/operations-guide/index.html#og-jmx +Details about using JMX with WildFly can be found here: https://jetty.org/docs/jetty/11/operations-guide/jmx/index.html ### Metrics * Name: `jetty.select.count` diff --git a/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/KafkaIntegrationTest.java b/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/KafkaIntegrationTest.java index 4c2c9293c..4dddd975a 100644 --- a/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/KafkaIntegrationTest.java +++ b/jmx-metrics/src/integrationTest/java/io/opentelemetry/contrib/jmxmetrics/target_systems/KafkaIntegrationTest.java @@ -44,7 +44,7 @@ protected KafkaIntegrationTest(String configName) { @Container GenericContainer kafka = - new GenericContainer<>("bitnami/kafka:2.8.1") + new GenericContainer<>("bitnamilegacy/kafka:2.8.1") .withNetwork(Network.SHARED) .withEnv("KAFKA_CFG_ZOOKEEPER_CONNECT", "zookeeper:2181") .withEnv("ALLOW_PLAINTEXT_LISTENER", "yes") @@ -80,7 +80,7 @@ public Set getDependencies() { }; protected GenericContainer kafkaProducerContainer() { - return new GenericContainer<>("bitnami/kafka:2.8.1") + return new GenericContainer<>("bitnamilegacy/kafka:2.8.1") .withNetwork(Network.SHARED) .withEnv("KAFKA_CFG_ZOOKEEPER_CONNECT", "zookeeper:2181") .withEnv("ALLOW_PLAINTEXT_LISTENER", "yes") @@ -207,7 +207,7 @@ static class KafkaConsumerIntegrationTest extends KafkaIntegrationTest { @Container GenericContainer consumer = - new GenericContainer<>("bitnami/kafka:2.8.1") + new GenericContainer<>("bitnamilegacy/kafka:2.8.1") .withNetwork(Network.SHARED) .withEnv("KAFKA_CFG_ZOOKEEPER_CONNECT", "zookeeper:2181") .withEnv("ALLOW_PLAINTEXT_LISTENER", "yes") diff --git a/jmx-scraper/README.md b/jmx-scraper/README.md index a2f98f5b1..a69736e15 100644 --- a/jmx-scraper/README.md +++ b/jmx-scraper/README.md @@ -9,13 +9,18 @@ This is an alternative to the [JMX Gatherer](../jmx-metrics/README.md) utility. ## Release This project is released as part of the [OpenTelemetry Java Contrib](https://github.com/open-telemetry/opentelemetry-java-contrib) project. -The latest release is available from [Maven Central](https://central.sonatype.com/artifact/io.opentelemetry.contrib/opentelemetry-jmx-scraper) -or can be browsed via [MVN Repository](https://mvnrepository.com/artifact/io.opentelemetry.contrib/opentelemetry-jmx-scraper). +The latest release is available from: + +- [GitHub Release assets](https://github.com/open-telemetry/opentelemetry-java-contrib/releases/latest/download/opentelemetry-jmx-scraper.jar) +- [Maven Central](https://central.sonatype.com/artifact/io.opentelemetry.contrib/opentelemetry-jmx-scraper) ## Usage The general command to invoke JMX scraper is `java -jar scraper.jar `, where `scraper.jar` -is the `build/libs/opentelemetry-jmx-scraper-.jar` packaged binary when building this module. +is the packaged binary: + +- `build/libs/opentelemetry-jmx-scraper-.jar` when building from sources +- `.jar` file downloaded from Maven central or Release assets Minimal configuration required diff --git a/jmx-scraper/build.gradle.kts b/jmx-scraper/build.gradle.kts index 9e2878549..687b30612 100644 --- a/jmx-scraper/build.gradle.kts +++ b/jmx-scraper/build.gradle.kts @@ -39,7 +39,7 @@ testing { implementation("org.slf4j:slf4j-simple") implementation("com.linecorp.armeria:armeria-junit5") implementation("com.linecorp.armeria:armeria-grpc") - implementation("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + implementation("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") implementation("org.bouncycastle:bcprov-jdk18on:1.81") implementation("org.bouncycastle:bcpkix-jdk18on:1.81") } diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/JmxConnectionTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/JmxConnectionTest.java index d1431647b..c984724e3 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/JmxConnectionTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/JmxConnectionTest.java @@ -28,7 +28,7 @@ * JmxConnectionBuilder and relies on containers to minimize the JMX/RMI network complications which * are not NAT-friendly. */ -public class JmxConnectionTest { +class JmxConnectionTest { // OTLP endpoint is not used in test mode, but still has to be provided private static final String DUMMY_OTLP_ENDPOINT = "http://dummy-otlp-endpoint:8080/"; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java index 4f909fdc5..19d98bf38 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java @@ -15,7 +15,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; -public class ActiveMqIntegrationTest extends TargetSystemIntegrationTest { +class ActiveMqIntegrationTest extends TargetSystemIntegrationTest { private static final int ACTIVEMQ_PORT = 61616; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CassandraIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CassandraIntegrationTest.java index 90f1fca73..5ff8f2dcc 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CassandraIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CassandraIntegrationTest.java @@ -15,7 +15,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; -public class CassandraIntegrationTest extends TargetSystemIntegrationTest { +class CassandraIntegrationTest extends TargetSystemIntegrationTest { private static final int CASSANDRA_PORT = 9042; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CustomIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CustomIntegrationTest.java index dcecc8f5f..d238e8a72 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CustomIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/CustomIntegrationTest.java @@ -11,7 +11,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; -public class CustomIntegrationTest extends TargetSystemIntegrationTest { +class CustomIntegrationTest extends TargetSystemIntegrationTest { @Override protected GenericContainer createTargetContainer(int jmxPort) { diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HBaseIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HBaseIntegrationTest.java index 803137539..4bab7e574 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HBaseIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HBaseIntegrationTest.java @@ -15,7 +15,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; -public class HBaseIntegrationTest extends TargetSystemIntegrationTest { +class HBaseIntegrationTest extends TargetSystemIntegrationTest { @Override protected GenericContainer createTargetContainer(int jmxPort) { return new GenericContainer<>("dajobe/hbase") diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HadoopIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HadoopIntegrationTest.java index b89225629..bc44ea36c 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HadoopIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/HadoopIntegrationTest.java @@ -16,7 +16,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.MountableFile; -public class HadoopIntegrationTest extends TargetSystemIntegrationTest { +class HadoopIntegrationTest extends TargetSystemIntegrationTest { private static final int HADOOP_PORT = 50070; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JettyIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JettyIntegrationTest.java index 86097cbaa..8c91e0c85 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JettyIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JettyIntegrationTest.java @@ -16,7 +16,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; -public class JettyIntegrationTest extends TargetSystemIntegrationTest { +class JettyIntegrationTest extends TargetSystemIntegrationTest { private static final int JETTY_PORT = 8080; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java index e29021a93..be8a04a53 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java @@ -15,7 +15,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; -public class JvmIntegrationTest extends TargetSystemIntegrationTest { +class JvmIntegrationTest extends TargetSystemIntegrationTest { @Override protected GenericContainer createTargetContainer(int jmxPort) { diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/SolrIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/SolrIntegrationTest.java index fbec81e2e..9cba55701 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/SolrIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/SolrIntegrationTest.java @@ -18,7 +18,7 @@ import org.testcontainers.containers.Network; import org.testcontainers.containers.wait.strategy.Wait; -public class SolrIntegrationTest extends TargetSystemIntegrationTest { +class SolrIntegrationTest extends TargetSystemIntegrationTest { @Override protected GenericContainer createTargetContainer(int jmxPort) { diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java index bec9453f8..b01f4485f 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java @@ -16,7 +16,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; -public class TomcatIntegrationTest extends TargetSystemIntegrationTest { +class TomcatIntegrationTest extends TargetSystemIntegrationTest { private static final int TOMCAT_PORT = 8080; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/WildflyIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/WildflyIntegrationTest.java index 73e546b85..bb2787b0a 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/WildflyIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/WildflyIntegrationTest.java @@ -22,7 +22,7 @@ import org.testcontainers.images.builder.ImageFromDockerfile; import org.testcontainers.utility.MountableFile; -public class WildflyIntegrationTest extends TargetSystemIntegrationTest { +class WildflyIntegrationTest extends TargetSystemIntegrationTest { private static final int WILDFLY_SERVICE_PORT = 8080; private static final int WILDFLY_MANAGEMENT_PORT = 9990; diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaConsumerIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaConsumerIntegrationTest.java index ed61aabbb..9319baf65 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaConsumerIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaConsumerIntegrationTest.java @@ -25,7 +25,7 @@ import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.wait.strategy.Wait; -public class KafkaConsumerIntegrationTest extends TargetSystemIntegrationTest { +class KafkaConsumerIntegrationTest extends TargetSystemIntegrationTest { @Override protected Collection> createPrerequisiteContainers() { diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaContainerFactory.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaContainerFactory.java index 8eb9432a5..e46ed07b6 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaContainerFactory.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaContainerFactory.java @@ -12,7 +12,7 @@ public class KafkaContainerFactory { private static final int KAFKA_PORT = 9092; private static final String KAFKA_BROKER = "kafka:" + KAFKA_PORT; - private static final String KAFKA_DOCKER_IMAGE = "bitnami/kafka:2.8.1"; + private static final String KAFKA_DOCKER_IMAGE = "bitnamilegacy/kafka:2.8.1"; private KafkaContainerFactory() {} diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaIntegrationTest.java index f59040509..17d38d995 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaIntegrationTest.java @@ -21,7 +21,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.output.Slf4jLogConsumer; -public class KafkaIntegrationTest extends TargetSystemIntegrationTest { +class KafkaIntegrationTest extends TargetSystemIntegrationTest { @Override protected Collection> createPrerequisiteContainers() { GenericContainer zookeeper = diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaProducerIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaProducerIntegrationTest.java index 155cb9fc5..37b141b01 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaProducerIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/kafka/KafkaProducerIntegrationTest.java @@ -24,7 +24,7 @@ import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.containers.wait.strategy.Wait; -public class KafkaProducerIntegrationTest extends TargetSystemIntegrationTest { +class KafkaProducerIntegrationTest extends TargetSystemIntegrationTest { @Override protected Collection> createPrerequisiteContainers() { diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/InvalidArgumentException.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/InvalidArgumentException.java index bdfb93272..d3358741f 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/InvalidArgumentException.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/InvalidArgumentException.java @@ -9,7 +9,7 @@ * Exception indicating something is wrong with the provided arguments or reading the configuration * from them */ -public class InvalidArgumentException extends Exception { +public final class InvalidArgumentException extends Exception { private static final long serialVersionUID = 0L; diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxConnectorBuilder.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxConnectorBuilder.java index ceba4b2fe..92ff4f387 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxConnectorBuilder.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxConnectorBuilder.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.jmxscraper; +import static java.util.logging.Level.WARNING; + import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.io.IOException; import java.net.MalformedURLException; @@ -17,7 +19,6 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; import javax.management.remote.JMXConnector; @@ -33,7 +34,7 @@ import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.sasl.RealmCallback; -public class JmxConnectorBuilder { +public final class JmxConnectorBuilder { private static final Logger logger = Logger.getLogger(JmxConnectorBuilder.class.getName()); @@ -146,7 +147,7 @@ private Map buildEnv() { } }); } catch (ReflectiveOperationException e) { - logger.log(Level.WARNING, "SASL unsupported in current environment: " + e.getMessage()); + logger.log(WARNING, "SASL unsupported in current environment: " + e.getMessage()); } return env; } diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java index 85c47ba0e..0835d9d92 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java @@ -5,6 +5,12 @@ package io.opentelemetry.contrib.jmxscraper; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static java.util.Optional.ofNullable; +import static java.util.logging.Level.INFO; +import static java.util.logging.Level.SEVERE; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.contrib.jmxscraper.config.JmxScraperConfig; import io.opentelemetry.contrib.jmxscraper.config.PropertiesCustomizer; @@ -21,19 +27,15 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.Level; import java.util.logging.Logger; import javax.management.MBeanServerConnection; import javax.management.remote.JMXConnector; -public class JmxScraper { +public final class JmxScraper { private static final Logger logger = Logger.getLogger(JmxScraper.class.getName()); private static final String CONFIG_ARG = "-config"; private static final String TEST_ARG = "-test"; @@ -55,7 +57,7 @@ public static void main(String[] args) { // set log format System.setProperty("java.util.logging.SimpleFormatter.format", "%1$tF %1$tT %4$s %5$s%n"); - List effectiveArgs = new ArrayList<>(Arrays.asList(args)); + List effectiveArgs = new ArrayList<>(asList(args)); boolean testMode = effectiveArgs.remove(TEST_ARG); try { @@ -73,7 +75,7 @@ public static void main(String[] args) { JmxScraperConfig scraperConfig = configCustomizer.getScraperConfig(); long exportSeconds = scraperConfig.getSamplingInterval().toMillis() / 1000; - logger.log(Level.INFO, "metrics export interval (seconds) = " + exportSeconds); + logger.log(INFO, "metrics export interval (seconds) = " + exportSeconds); JmxMetricInsight service = JmxMetricInsight.createService( @@ -81,8 +83,8 @@ public static void main(String[] args) { JmxConnectorBuilder connectorBuilder = JmxConnectorBuilder.createNew(scraperConfig.getServiceUrl()); - Optional.ofNullable(scraperConfig.getUsername()).ifPresent(connectorBuilder::withUser); - Optional.ofNullable(scraperConfig.getPassword()).ifPresent(connectorBuilder::withPassword); + ofNullable(scraperConfig.getUsername()).ifPresent(connectorBuilder::withUser); + ofNullable(scraperConfig.getPassword()).ifPresent(connectorBuilder::withPassword); if (scraperConfig.isRegistrySsl()) { connectorBuilder.withSslRegistry(); @@ -95,20 +97,20 @@ public static void main(String[] args) { jmxScraper.start(); } } catch (ConfigurationException e) { - logger.log(Level.SEVERE, "invalid configuration: " + e.getMessage(), e); + logger.log(SEVERE, "invalid configuration: " + e.getMessage(), e); System.exit(1); } catch (InvalidArgumentException e) { - logger.log(Level.SEVERE, e.getMessage(), e); + logger.log(SEVERE, e.getMessage(), e); logger.info("Usage: java -jar [-test] [-config ]"); logger.info(" -test test JMX connection with provided configuration and exit"); logger.info( " -config provide configuration, where is - for stdin, or "); System.exit(1); } catch (IOException e) { - logger.log(Level.SEVERE, "Unable to connect ", e); + logger.log(SEVERE, "Unable to connect ", e); System.exit(2); } catch (RuntimeException e) { - logger.log(Level.SEVERE, e.getMessage(), e); + logger.log(SEVERE, e.getMessage(), e); System.exit(3); } } @@ -119,14 +121,14 @@ private static boolean testConnection(JmxConnectorBuilder connectorBuilder) { MBeanServerConnection connection = connector.getMBeanServerConnection(); Integer mbeanCount = connection.getMBeanCount(); if (mbeanCount > 0) { - logger.log(Level.INFO, "JMX connection test OK"); + logger.log(INFO, "JMX connection test OK"); return true; } else { - logger.log(Level.SEVERE, "JMX connection test ERROR"); + logger.log(SEVERE, "JMX connection test ERROR"); return false; } } catch (IOException e) { - logger.log(Level.SEVERE, "JMX connection test ERROR", e); + logger.log(SEVERE, "JMX connection test ERROR", e); return false; } } @@ -210,7 +212,7 @@ private void start() throws IOException { try (JMXConnector connector = client.build()) { MBeanServerConnection connection = connector.getMBeanServerConnection(); - service.startRemote(getMetricConfig(config), () -> Collections.singletonList(connection)); + service.startRemote(getMetricConfig(config), () -> singletonList(connection)); running.set(true); logger.info("JMX scraping started"); diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/JmxScraperConfig.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/JmxScraperConfig.java index 09a97eb83..53c19096b 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/JmxScraperConfig.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/JmxScraperConfig.java @@ -5,21 +5,25 @@ package io.opentelemetry.contrib.jmxscraper.config; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptySet; +import static java.util.Collections.unmodifiableList; +import static java.util.Collections.unmodifiableSet; +import static java.util.Locale.ROOT; + import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import java.io.InputStream; import java.time.Duration; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Set; import java.util.logging.Logger; import javax.annotation.Nullable; /** This class keeps application settings */ -public class JmxScraperConfig { +public final class JmxScraperConfig { private static final Logger logger = Logger.getLogger(JmxScraperConfig.class.getName()); @@ -49,9 +53,9 @@ public class JmxScraperConfig { private String serviceUrl = ""; - private List jmxConfig = Collections.emptyList(); + private List jmxConfig = emptyList(); - private Set targetSystems = Collections.emptySet(); + private Set targetSystems = emptySet(); private TargetSystemSource targetSystemSource = TargetSystemSource.AUTO; @@ -73,7 +77,7 @@ public enum TargetSystemSource { static TargetSystemSource fromString(String source) { try { - return TargetSystemSource.valueOf(source.toUpperCase(Locale.ROOT)); + return TargetSystemSource.valueOf(source.toUpperCase(ROOT)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Invalid target system source: " + source, e); } @@ -217,8 +221,8 @@ public static JmxScraperConfig fromConfig(ConfigProperties config) { "at least one of '" + JMX_TARGET_SYSTEM + "' or '" + JMX_CONFIG + "' must be set"); } - scraperConfig.jmxConfig = Collections.unmodifiableList(jmxConfig); - scraperConfig.targetSystems = Collections.unmodifiableSet(new HashSet<>(targetSystem)); + scraperConfig.jmxConfig = unmodifiableList(jmxConfig); + scraperConfig.targetSystems = unmodifiableSet(new HashSet<>(targetSystem)); scraperConfig.username = config.getString("otel.jmx.username"); scraperConfig.password = config.getString("otel.jmx.password"); diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesCustomizer.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesCustomizer.java index 9d6812146..141ad025f 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesCustomizer.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesCustomizer.java @@ -16,7 +16,7 @@ import javax.annotation.Nullable; /** Customizer of default SDK configuration and provider of effective scraper config */ -public class PropertiesCustomizer implements Function> { +public final class PropertiesCustomizer implements Function> { private static final Logger logger = Logger.getLogger(PropertiesCustomizer.class.getName()); diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesSupplier.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesSupplier.java index 071e2b8fa..f4ad68faa 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesSupplier.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/config/PropertiesSupplier.java @@ -11,7 +11,7 @@ import java.util.function.Supplier; /** Configuration supplier for java properties */ -public class PropertiesSupplier implements Supplier> { +public final class PropertiesSupplier implements Supplier> { private final Properties properties; diff --git a/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java b/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java index b51144360..430476d51 100644 --- a/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java +++ b/jmx-scraper/src/test/java/io/opentelemetry/contrib/jmxscraper/JmxScraperTest.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.jmxscraper; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -12,8 +14,6 @@ import io.opentelemetry.contrib.jmxscraper.config.TestUtil; import java.io.IOException; import java.io.InputStream; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Properties; import org.junit.jupiter.api.Test; @@ -32,7 +32,7 @@ void shouldThrowExceptionWhenInvalidCommandLineArgsProvided() { @Test void emptyArgumentsAllowed() throws InvalidArgumentException { - assertThat(JmxScraper.argsToConfig(Collections.emptyList())) + assertThat(JmxScraper.argsToConfig(emptyList())) .describedAs("empty config allowed to use JVM properties") .isEmpty(); } @@ -43,7 +43,7 @@ void shouldThrowExceptionWhenMissingProperties() { } private static void testInvalidArguments(String... args) { - assertThatThrownBy(() -> JmxScraper.argsToConfig(Arrays.asList(args))) + assertThatThrownBy(() -> JmxScraper.argsToConfig(asList(args))) .isInstanceOf(InvalidArgumentException.class); } @@ -54,7 +54,7 @@ void shouldCreateConfig_propertiesLoadedFromFile() throws InvalidArgumentExcepti // Windows returns /C:/path/to/file, which is not a valid path for Path.get() in Java. String filePath = ClassLoader.getSystemClassLoader().getResource("validConfig.properties").getPath(); - List args = Arrays.asList("-config", filePath); + List args = asList("-config", filePath); // When Properties parsedConfig = JmxScraper.argsToConfig(args); @@ -73,7 +73,7 @@ void shouldCreateConfig_propertiesLoadedFromStdIn() throws InvalidArgumentExcept ClassLoader.getSystemClassLoader().getResourceAsStream("validConfig.properties")) { // Given System.setIn(stream); - List args = Arrays.asList("-config", "-"); + List args = asList("-config", "-"); // When Properties parsedConfig = JmxScraper.argsToConfig(args); diff --git a/kafka-exporter/build.gradle.kts b/kafka-exporter/build.gradle.kts index d4aed3f54..5f189f97a 100644 --- a/kafka-exporter/build.gradle.kts +++ b/kafka-exporter/build.gradle.kts @@ -14,7 +14,7 @@ otelJava { dependencies { api("io.opentelemetry:opentelemetry-sdk-trace") api("io.opentelemetry:opentelemetry-sdk-common") - api("io.opentelemetry.proto:opentelemetry-proto:1.7.0-alpha") + api("io.opentelemetry.proto:opentelemetry-proto:1.8.0-alpha") api("org.apache.kafka:kafka-clients") compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") diff --git a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporter.java b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporter.java index b5559832e..28e123fe8 100644 --- a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporter.java +++ b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporter.java @@ -26,7 +26,7 @@ @ThreadSafe @SuppressWarnings("FutureReturnValueIgnored") -public class KafkaSpanExporter implements SpanExporter { +public final class KafkaSpanExporter implements SpanExporter { private static final Logger logger = LoggerFactory.getLogger(KafkaSpanExporter.class); private final String topicName; private final Producer> producer; @@ -59,20 +59,28 @@ public CompletableResultCode export(@Nonnull Collection spans) { CompletableResultCode result = new CompletableResultCode(); CompletableFuture.runAsync( - () -> - producer.send( - producerRecord, - (metadata, exception) -> { - if (exception == null) { - result.succeed(); - } else { - logger.error( - String.format("Error while sending spans to Kafka topic %s", topicName), - exception); - result.fail(); - } - }), - executorService); + () -> + producer.send( + producerRecord, + (metadata, exception) -> { + if (exception == null) { + result.succeed(); + } else { + logger.error( + String.format("Error while sending spans to Kafka topic %s", topicName), + exception); + result.fail(); + } + }), + executorService) + .whenComplete( + (ignore, exception) -> { + if (exception != null) { + logger.error( + "Executor task failed while sending to Kafka topic {}", topicName, exception); + result.fail(); + } + }); return result; } diff --git a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilder.java b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilder.java index e6b49d6dc..d7f1d3c17 100644 --- a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilder.java +++ b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterBuilder.java @@ -20,7 +20,7 @@ import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.common.serialization.Serializer; -public class KafkaSpanExporterBuilder { +public final class KafkaSpanExporterBuilder { private static final long DEFAULT_TIMEOUT_IN_SECONDS = 5L; private String topicName; private Producer> producer; diff --git a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataDeserializer.java b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataDeserializer.java index 4c5ff7112..9da3f266f 100644 --- a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataDeserializer.java +++ b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataDeserializer.java @@ -11,7 +11,7 @@ import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.serialization.Deserializer; -public class SpanDataDeserializer implements Deserializer { +public final class SpanDataDeserializer implements Deserializer { @SuppressWarnings("NullAway") @Override public ExportTraceServiceRequest deserialize(String topic, byte[] data) { diff --git a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataSerializer.java b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataSerializer.java index 4c689f16a..8f31eb412 100644 --- a/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataSerializer.java +++ b/kafka-exporter/src/main/java/io/opentelemetry/contrib/kafka/SpanDataSerializer.java @@ -20,7 +20,7 @@ import org.apache.kafka.common.errors.SerializationException; import org.apache.kafka.common.serialization.Serializer; -public class SpanDataSerializer implements Serializer> { +public final class SpanDataSerializer implements Serializer> { @Override public byte[] serialize(String topic, Collection data) { if (Objects.isNull(data)) { 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/KafkaSpanExporterIntegrationTest.java b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterIntegrationTest.java index 4514efdcf..f8c010f89 100644 --- a/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterIntegrationTest.java +++ b/kafka-exporter/src/test/java/io/opentelemetry/contrib/kafka/KafkaSpanExporterIntegrationTest.java @@ -19,6 +19,7 @@ import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.trace.data.SpanData; import java.time.Duration; +import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -29,7 +30,9 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.clients.producer.MockProducer; import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.errors.ApiException; import org.apache.kafka.common.serialization.StringDeserializer; import org.apache.kafka.common.serialization.StringSerializer; @@ -46,7 +49,7 @@ @TestInstance(TestInstance.Lifecycle.PER_CLASS) class KafkaSpanExporterIntegrationTest { private static final DockerImageName KAFKA_TEST_IMAGE = - DockerImageName.parse("apache/kafka:3.8.1"); + DockerImageName.parse("apache/kafka:3.9.1"); private static final String TOPIC = "span_topic"; private KafkaContainer kafka; private KafkaConsumer consumer; @@ -155,6 +158,28 @@ void exportWhenProducerInError() { testSubject.shutdown(); } + @Test + void exportWhenProducerFailsToSend() { + var mockProducer = new MockProducer>(); + mockProducer.sendException = new KafkaException("Simulated kafka exception"); + var testSubjectWithMockProducer = + KafkaSpanExporter.newBuilder().setTopicName(TOPIC).setProducer(mockProducer).build(); + + ImmutableList spans = + ImmutableList.of(makeBasicSpan("span-1"), makeBasicSpan("span-2")); + + CompletableResultCode actual = testSubjectWithMockProducer.export(spans); + + await() + .untilAsserted( + () -> { + assertThat(actual.isSuccess()).isFalse(); + assertThat(actual.isDone()).isTrue(); + }); + + testSubjectWithMockProducer.shutdown(); + } + @Test void flush() { CompletableResultCode actual = testSubject.flush(); 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/maven-extension/README.md b/maven-extension/README.md index 91ec71744..fd0150355 100644 --- a/maven-extension/README.md +++ b/maven-extension/README.md @@ -12,7 +12,7 @@ The Maven OpenTelemetry Extension is configured using environment variables or J * (since Maven 3.3.1) configuring the extension in `.mvn/extensions.xml`. In the code snippets below, replace `OPENTELEMETRY_MAVEN_VERSION` with the [latest -release](https://search.maven.org/search?q=g:io.opentelemetry.contrib%20AND%20a:opentelemetry-maven-extension). +release](https://central.sonatype.com/artifact/io.opentelemetry.contrib/opentelemetry-maven-extension). ### Adding the extension to the classpath @@ -109,8 +109,8 @@ In addition to the span attributes captured on every Maven plugin goal executio |----------------------------------------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------| | `http.method` | string | `POST` | | `http.url` | string | Base URL of the uploaded artifact `${maven.build.repository.url}/${groupId}/${artifactId}/${version}` where the `.` of `${groupId}` are replaced by `/` | -| `maven.build.repository.id` | string | ID of the Maven repository to which the artifact is deployed. See [Maven POM reference / Repository](https://maven.apache.org/pom.html#repository) | -| `maven.build.repository.url` | string | URL of the Maven repository to which the artifact is deployed. See [Maven POM reference / Repository](https://maven.apache.org/pom.html#repository) | +| `maven.build.repository.id` | string | ID of the Maven repository to which the artifact is deployed. See [Maven POM reference / Repository](https://maven.apache.org/pom.html#Repository) | +| `maven.build.repository.url` | string | URL of the Maven repository to which the artifact is deployed. See [Maven POM reference / Repository](https://maven.apache.org/pom.html#Repository) | | `peer.service` | string | Maven repository hostname deduced from the Repository URL | The `span.kind` is set to `client` @@ -200,7 +200,7 @@ Steps to instrument a Maven Mojo: * Add the OpenTelemetry API dependency in the `pom.xml` of the Maven plugin. Replace `OPENTELEMETRY_VERSION` with the [latest - release](https://search.maven.org/search?q=g:io.opentelemetry%20AND%20a:opentelemetry-api). + release](https://central.sonatype.com/artifact/io.opentelemetry/opentelemetry-api). ```xml diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java b/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java index e2cc37a28..0b94dce54 100644 --- a/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java +++ b/maven-extension/src/test/java/io/opentelemetry/maven/OpenTelemetrySdkServiceTest.java @@ -17,11 +17,11 @@ * Note: if otel-java-contrib bumps to Java 11+, we could use junit-pioneer's * {@code @SetSystemProperty} and {@code @ClearSystemProperty} but no bump is planned for now. */ -public class OpenTelemetrySdkServiceTest { +class OpenTelemetrySdkServiceTest { /** Verify default config */ @Test - public void testDefaultConfiguration() { + void testDefaultConfiguration() { System.clearProperty("otel.exporter.otlp.endpoint"); System.clearProperty("otel.service.name"); System.clearProperty("otel.resource.attributes"); @@ -40,7 +40,7 @@ public void testDefaultConfiguration() { /** Verify overwritten `service.name`,`key1` and `key2` */ @Test - public void testOverwrittenResourceAttributes() { + void testOverwrittenResourceAttributes() { System.setProperty("otel.service.name", "my-maven"); System.setProperty("otel.resource.attributes", "key1=val1,key2=val2"); @@ -59,7 +59,7 @@ public void testOverwrittenResourceAttributes() { /** Verify defining `otel.exporter.otlp.endpoint` works */ @Test - public void testOverwrittenExporterConfiguration_1() { + void testOverwrittenExporterConfiguration_1() { System.setProperty("otel.exporter.otlp.endpoint", "https://example.com:4317"); try (OpenTelemetrySdkService openTelemetrySdkService = new OpenTelemetrySdkService()) { @@ -78,7 +78,7 @@ public void testOverwrittenExporterConfiguration_1() { /** Verify defining `otel.exporter.otlp.traces.endpoint` works */ @Test - public void testOverwrittenExporterConfiguration_2() { + void testOverwrittenExporterConfiguration_2() { System.clearProperty("otel.exporter.otlp.endpoint"); System.clearProperty("otel.traces.exporter"); System.setProperty("otel.exporter.otlp.traces.endpoint", "https://example.com:4317/"); @@ -102,7 +102,7 @@ public void testOverwrittenExporterConfiguration_2() { /** Verify defining `otel.exporter.otlp.traces.endpoint` and `otel.traces.exporter` works */ @Test - public void testOverwrittenExporterConfiguration_3() { + void testOverwrittenExporterConfiguration_3() { System.clearProperty("otel.exporter.otlp.endpoint"); System.setProperty("otel.traces.exporter", "otlp"); System.setProperty("otel.exporter.otlp.traces.endpoint", "https://example.com:4317/"); diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/SpanRegistryTest.java b/maven-extension/src/test/java/io/opentelemetry/maven/SpanRegistryTest.java index 864ce8df8..2a01a1754 100644 --- a/maven-extension/src/test/java/io/opentelemetry/maven/SpanRegistryTest.java +++ b/maven-extension/src/test/java/io/opentelemetry/maven/SpanRegistryTest.java @@ -12,11 +12,11 @@ import io.opentelemetry.api.trace.Tracer; import org.junit.jupiter.api.Test; -public class SpanRegistryTest { +class SpanRegistryTest { /** MVND reuses the same Maven process and thus the Span Registry is reused. */ @Test - public void testSpanRegistryReuseWhenUsingMvnDaemon() { + void testSpanRegistryReuseWhenUsingMvnDaemon() { SpanRegistry spanRegistry = new SpanRegistry(); Tracer tracer = OpenTelemetry.noop().getTracer("test"); diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerConfigurationTest.java b/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerConfigurationTest.java index 21748cebb..46877575a 100644 --- a/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerConfigurationTest.java +++ b/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerConfigurationTest.java @@ -12,10 +12,9 @@ import java.util.Map; import org.junit.jupiter.api.Test; -public class MojoGoalExecutionHandlerConfigurationTest { - +class MojoGoalExecutionHandlerConfigurationTest { @Test - public void mojoGoalExecutionHandlers() { + void mojoGoalExecutionHandlers() { Map actual = MojoGoalExecutionHandlerConfiguration.loadMojoGoalExecutionHandler( OtelExecutionListener.class.getClassLoader()); diff --git a/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerTest.java b/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerTest.java index b193ccdb5..645ecfa0d 100644 --- a/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerTest.java +++ b/maven-extension/src/test/java/io/opentelemetry/maven/handler/MojoGoalExecutionHandlerTest.java @@ -47,10 +47,10 @@ * https://github.com/takari/takari-lifecycle/blob/master/takari-lifecycle-plugin/src/test/java/io/takari/maven/plugins/plugin/PluginDescriptorMojoTest.java */ @SuppressWarnings({"DeduplicateConstants", "deprecation"}) -public class MojoGoalExecutionHandlerTest { +class MojoGoalExecutionHandlerTest { @Test - public void testMavenDeploy() throws Exception { + void testMavenDeploy() throws Exception { String pomXmlPath = "projects/jar/pom.xml"; String mojoGroupId = "org.apache.maven.plugins"; @@ -92,7 +92,7 @@ public void testMavenDeploy() throws Exception { } @Test - public void testSpringBootBuildImage_springboot_1() throws Exception { + void testSpringBootBuildImage_springboot_1() throws Exception { String pomXmlPath = "projects/springboot_1/pom.xml"; String mojoGroupId = "org.springframework.boot"; @@ -136,7 +136,7 @@ public void testSpringBootBuildImage_springboot_1() throws Exception { } @Test - public void testSpringBootBuildImage_springboot_2() throws Exception { + void testSpringBootBuildImage_springboot_2() throws Exception { String pomXmlPath = "projects/springboot_2/pom.xml"; String mojoGroupId = "org.springframework.boot"; @@ -180,7 +180,7 @@ public void testSpringBootBuildImage_springboot_2() throws Exception { } @Test - public void testGoogleJibBuild_jib_1() throws Exception { + void testGoogleJibBuild_jib_1() throws Exception { String pomXmlPath = "projects/jib_1/pom.xml"; String mojoGroupId = "com.google.cloud.tools"; @@ -221,7 +221,7 @@ public void testGoogleJibBuild_jib_1() throws Exception { } @Test - public void testGoogleJibBuild_jib_2() throws Exception { + void testGoogleJibBuild_jib_2() throws Exception { String pomXmlPath = "projects/jib_2/pom.xml"; String mojoGroupId = "com.google.cloud.tools"; @@ -262,7 +262,7 @@ public void testGoogleJibBuild_jib_2() throws Exception { } @Test - public void testSnykTest_snyk_1() throws Exception { + void testSnykTest_snyk_1() throws Exception { String pomXmlPath = "projects/snyk_1/pom.xml"; String mojoGroupId = "io.snyk"; @@ -298,7 +298,7 @@ public void testSnykTest_snyk_1() throws Exception { } @Test - public void testSnykMonitor_snyk_1() throws Exception { + void testSnykMonitor_snyk_1() throws Exception { String pomXmlPath = "projects/snyk_1/pom.xml"; String mojoGroupId = "io.snyk"; diff --git a/micrometer-meter-provider/build.gradle.kts b/micrometer-meter-provider/build.gradle.kts index 6d585cca5..27e61bf1f 100644 --- a/micrometer-meter-provider/build.gradle.kts +++ b/micrometer-meter-provider/build.gradle.kts @@ -20,14 +20,14 @@ dependencies { annotationProcessor("com.google.auto.value:auto-value") compileOnly("com.google.auto.value:auto-value-annotations") - testImplementation("io.micrometer:micrometer-core:1.15.3") + testImplementation("io.micrometer:micrometer-core:1.15.4") } testing { suites { val integrationTest by registering(JvmTestSuite::class) { dependencies { - implementation("io.micrometer:micrometer-registry-prometheus:1.15.3") + implementation("io.micrometer:micrometer-registry-prometheus:1.15.4") } } } diff --git a/micrometer-meter-provider/src/integrationTest/java/io/opentelemetry/contrib/metrics/micrometer/PrometheusIntegrationTest.java b/micrometer-meter-provider/src/integrationTest/java/io/opentelemetry/contrib/metrics/micrometer/PrometheusIntegrationTest.java index 12be80e01..defefe634 100644 --- a/micrometer-meter-provider/src/integrationTest/java/io/opentelemetry/contrib/metrics/micrometer/PrometheusIntegrationTest.java +++ b/micrometer-meter-provider/src/integrationTest/java/io/opentelemetry/contrib/metrics/micrometer/PrometheusIntegrationTest.java @@ -48,7 +48,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class PrometheusIntegrationTest { +class PrometheusIntegrationTest { private static final AttributeKey KEY1 = AttributeKey.stringKey("key1"); private static final AttributeKey KEY2 = AttributeKey.stringKey("key2"); private static final String VALUE1 = "value1"; diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeter.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeter.java index e8a6b827c..2a080c8e8 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeter.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeter.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.metrics.micrometer; +import static java.util.Objects.requireNonNull; + import io.opentelemetry.api.metrics.DoubleGaugeBuilder; import io.opentelemetry.api.metrics.DoubleHistogramBuilder; import io.opentelemetry.api.metrics.LongCounterBuilder; @@ -15,7 +17,6 @@ import io.opentelemetry.contrib.metrics.micrometer.internal.instruments.MicrometerLongCounter; import io.opentelemetry.contrib.metrics.micrometer.internal.instruments.MicrometerLongUpDownCounter; import io.opentelemetry.contrib.metrics.micrometer.internal.state.MeterSharedState; -import java.util.Objects; final class MicrometerMeter implements Meter { final MeterSharedState meterSharedState; @@ -26,25 +27,25 @@ final class MicrometerMeter implements Meter { @Override public LongCounterBuilder counterBuilder(String name) { - Objects.requireNonNull(name, "name"); + requireNonNull(name, "name"); return MicrometerLongCounter.builder(meterSharedState, name); } @Override public LongUpDownCounterBuilder upDownCounterBuilder(String name) { - Objects.requireNonNull(name, "name"); + requireNonNull(name, "name"); return MicrometerLongUpDownCounter.builder(meterSharedState, name); } @Override public DoubleHistogramBuilder histogramBuilder(String name) { - Objects.requireNonNull(name, "name"); + requireNonNull(name, "name"); return MicrometerDoubleHistogram.builder(meterSharedState, name); } @Override public DoubleGaugeBuilder gaugeBuilder(String name) { - Objects.requireNonNull(name, "name"); + requireNonNull(name, "name"); return MicrometerDoubleGauge.builder(meterSharedState, name); } } diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProvider.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProvider.java index d76e19a34..2817754e2 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProvider.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProvider.java @@ -5,12 +5,13 @@ package io.opentelemetry.contrib.metrics.micrometer; +import static java.util.Objects.requireNonNull; + import io.micrometer.core.instrument.MeterRegistry; import io.opentelemetry.api.metrics.MeterBuilder; import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.contrib.metrics.micrometer.internal.MemoizingSupplier; import io.opentelemetry.contrib.metrics.micrometer.internal.state.MeterProviderSharedState; -import java.util.Objects; import java.util.function.Supplier; /** @@ -44,13 +45,13 @@ public void close() { /** {@inheritDoc} */ @Override public MeterBuilder meterBuilder(String instrumentationScopeName) { - Objects.requireNonNull(instrumentationScopeName, "instrumentationScopeName"); + requireNonNull(instrumentationScopeName, "instrumentationScopeName"); return new MicrometerMeterBuilder(meterProviderSharedState, instrumentationScopeName); } /** Returns a new builder instance for this provider with the specified {@link MeterRegistry}. */ public static MicrometerMeterProviderBuilder builder(MeterRegistry meterRegistry) { - Objects.requireNonNull(meterRegistry, "meterRegistry"); + requireNonNull(meterRegistry, "meterRegistry"); return new MicrometerMeterProviderBuilder(() -> meterRegistry); } @@ -62,7 +63,7 @@ public static MicrometerMeterProviderBuilder builder(MeterRegistry meterRegistry */ public static MicrometerMeterProviderBuilder builder( Supplier meterRegistrySupplier) { - Objects.requireNonNull(meterRegistrySupplier, "meterRegistrySupplier"); + requireNonNull(meterRegistrySupplier, "meterRegistrySupplier"); return new MicrometerMeterProviderBuilder(new MemoizingSupplier<>(meterRegistrySupplier)); } } diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderBuilder.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderBuilder.java index 655c8cd32..25bd8b4d3 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderBuilder.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderBuilder.java @@ -12,7 +12,7 @@ import javax.annotation.Nullable; /** Builder utility class for creating instances of {@link MicrometerMeterProvider}. */ -public class MicrometerMeterProviderBuilder { +public final class MicrometerMeterProviderBuilder { private final Supplier meterRegistrySupplier; @Nullable private CallbackRegistrar callbackRegistrar; diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrar.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrar.java index d9021a234..e3c34b2bb 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrar.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrar.java @@ -5,8 +5,9 @@ package io.opentelemetry.contrib.metrics.micrometer; +import static java.util.Objects.requireNonNull; + import java.util.List; -import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -39,7 +40,7 @@ public final class ScheduledCallbackRegistrar implements CallbackRegistrar { public static ScheduledCallbackRegistrarBuilder builder( ScheduledExecutorService scheduledExecutorService) { - Objects.requireNonNull(scheduledExecutorService, "scheduledExecutorService"); + requireNonNull(scheduledExecutorService, "scheduledExecutorService"); return new ScheduledCallbackRegistrarBuilder(scheduledExecutorService); } diff --git a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrarBuilder.java b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrarBuilder.java index de0da54f7..fb7ff0326 100644 --- a/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrarBuilder.java +++ b/micrometer-meter-provider/src/main/java/io/opentelemetry/contrib/metrics/micrometer/ScheduledCallbackRegistrarBuilder.java @@ -5,9 +5,10 @@ package io.opentelemetry.contrib.metrics.micrometer; +import static java.util.Objects.requireNonNull; + import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.time.Duration; -import java.util.Objects; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -27,7 +28,7 @@ public final class ScheduledCallbackRegistrarBuilder { /** Sets the period between successive executions of each registered callback */ @CanIgnoreReturnValue public ScheduledCallbackRegistrarBuilder setPeriod(long period, TimeUnit unit) { - Objects.requireNonNull(unit, "unit"); + requireNonNull(unit, "unit"); this.period = period; this.timeUnit = unit; return this; @@ -36,7 +37,7 @@ public ScheduledCallbackRegistrarBuilder setPeriod(long period, TimeUnit unit) { /** Sets the period between successive executions of each registered callback */ @CanIgnoreReturnValue public ScheduledCallbackRegistrarBuilder setPeriod(Duration period) { - Objects.requireNonNull(period, "period"); + requireNonNull(period, "period"); this.period = period.toMillis(); this.timeUnit = TimeUnit.MILLISECONDS; return this; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderTest.java index f323fbaba..4f1743cbc 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterProviderTest.java @@ -18,7 +18,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerMeterProviderTest { +class MicrometerMeterProviderTest { SimpleMeterRegistry meterRegistry; CallbackRegistrar callbackRegistrar; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterTest.java index 56b173e29..c23ef99dc 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/MicrometerMeterTest.java @@ -31,7 +31,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -public class MicrometerMeterTest { +class MicrometerMeterTest { SimpleMeterRegistry meterRegistry; List callbacks; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleCounterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleCounterTest.java index fd7585605..5b755da5f 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleCounterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleCounterTest.java @@ -29,7 +29,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerDoubleCounterTest { +class MicrometerDoubleCounterTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleGaugeTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleGaugeTest.java index df358a1b9..393479db7 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleGaugeTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleGaugeTest.java @@ -26,7 +26,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerDoubleGaugeTest { +class MicrometerDoubleGaugeTest { SimpleMeterRegistry meterRegistry; List callbacks; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleHistogramTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleHistogramTest.java index bc88fccc7..dc62b91ee 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleHistogramTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleHistogramTest.java @@ -28,7 +28,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerDoubleHistogramTest { +class MicrometerDoubleHistogramTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleUpDownCounterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleUpDownCounterTest.java index 57cf8922e..536f18d91 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleUpDownCounterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerDoubleUpDownCounterTest.java @@ -28,7 +28,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerDoubleUpDownCounterTest { +class MicrometerDoubleUpDownCounterTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongCounterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongCounterTest.java index 803cc0952..34423fb14 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongCounterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongCounterTest.java @@ -30,7 +30,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerLongCounterTest { +class MicrometerLongCounterTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongGaugeTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongGaugeTest.java index f55087dcf..96b56b1a9 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongGaugeTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongGaugeTest.java @@ -27,7 +27,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerLongGaugeTest { +class MicrometerLongGaugeTest { SimpleMeterRegistry meterRegistry; List callbacks; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongHistogramTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongHistogramTest.java index 880e7d766..a2651d4b6 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongHistogramTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongHistogramTest.java @@ -28,7 +28,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerLongHistogramTest { +class MicrometerLongHistogramTest { SimpleMeterRegistry meterRegistry; diff --git a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongUpDownCounterTest.java b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongUpDownCounterTest.java index e4bce0d99..bc73dcb5d 100644 --- a/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongUpDownCounterTest.java +++ b/micrometer-meter-provider/src/test/java/io/opentelemetry/contrib/metrics/micrometer/internal/instruments/MicrometerLongUpDownCounterTest.java @@ -29,7 +29,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class MicrometerLongUpDownCounterTest { +class MicrometerLongUpDownCounterTest { SimpleMeterRegistry meterRegistry; diff --git a/mise.toml b/mise.toml new file mode 100644 index 000000000..e00ac63b2 --- /dev/null +++ b/mise.toml @@ -0,0 +1,12 @@ +[tools] +lychee = "0.18.1" + +[tasks.lint-local-links] +run = 'lychee --verbose --scheme file --include-fragments {{arg(name="files", default=".")}}' + +[tasks.lint-links] +run = 'lychee --verbose --config .github/config/lychee.toml {{arg(name="files", var=true, default=".")}}' + +[settings] +# Only install tools explicitly defined in the [tools] section above +idiomatic_version_file_enable_tools = [] diff --git a/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopContextStorageProvider.java b/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopContextStorageProvider.java index 32a33dde2..358730308 100644 --- a/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopContextStorageProvider.java +++ b/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopContextStorageProvider.java @@ -15,7 +15,7 @@ /** * A {@link ContextStorageProvider} that returns a {@link ContextStorage} which is completely no-op. */ -public class NoopContextStorageProvider implements ContextStorageProvider { +public final class NoopContextStorageProvider implements ContextStorageProvider { /** Returns a no-op context storage. */ @Override diff --git a/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopOpenTelemetry.java b/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopOpenTelemetry.java index b84fef8b1..41da9ca7e 100644 --- a/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopOpenTelemetry.java +++ b/noop-api/src/main/java/io/opentelemetry/contrib/noopapi/NoopOpenTelemetry.java @@ -42,7 +42,7 @@ *

The above will succeed both with the {@linkplain OpenTelemetry#noop() default implementation} * and this one, but with this implementation there will be no overhead at all. */ -public class NoopOpenTelemetry implements OpenTelemetry { +public final class NoopOpenTelemetry implements OpenTelemetry { private static final OpenTelemetry INSTANCE = new NoopOpenTelemetry(); diff --git a/opamp-client/build.gradle.kts b/opamp-client/build.gradle.kts index 1aeed0c40..8abbbee65 100644 --- a/opamp-client/build.gradle.kts +++ b/opamp-client/build.gradle.kts @@ -1,13 +1,12 @@ -import de.undercouch.gradle.tasks.download.DownloadExtension -import java.net.HttpURLConnection +import java.io.FileOutputStream +import java.io.InputStream import java.net.URL plugins { id("otel.java-conventions") id("otel.publish-conventions") id("otel.animalsniffer-conventions") - id("de.undercouch.download") version "5.6.0" - id("com.squareup.wire") version "5.3.11" + id("com.squareup.wire") version "5.4.0" } description = "Client implementation of the OpAMP spec." @@ -25,11 +24,11 @@ dependencies { testImplementation("com.squareup.okhttp3:mockwebserver3-junit5") } -val opampProtos = tasks.register("opampProtoDownload", download) -opampProtos.configure { +val opampProtos = tasks.register("opampProtoDownload") { group = "opamp" outputProtosDir.set(project.layout.buildDirectory.dir("opamp/protos")) - downloadedZipFile.set(project.layout.buildDirectory.file("intermediate/$name/release.zip")) + downloadedZipFile.set(project.layout.buildDirectory.file("intermediate/opampProtoDownload/release.zip")) + zipUrl.set("https://github.com/open-telemetry/opamp-spec/zipball/v0.14.0") } wire { @@ -39,8 +38,7 @@ wire { } } -abstract class DownloadOpampProtos @Inject constructor( - private val download: DownloadExtension, +abstract class DownloadAndExtractOpampProtos @Inject constructor( private val archiveOps: ArchiveOperations, private val fileOps: FileSystemOperations, ) : DefaultTask() { @@ -51,26 +49,20 @@ abstract class DownloadOpampProtos @Inject constructor( @get:Internal abstract val downloadedZipFile: RegularFileProperty + @get:Input + abstract val zipUrl: Property + @TaskAction fun execute() { - // Get the latest release tag by following the redirect from GitHub's latest release URL - val latestReleaseUrl = "https://github.com/open-telemetry/opamp-spec/releases/latest" - val connection = URL(latestReleaseUrl).openConnection() as HttpURLConnection - connection.instanceFollowRedirects = false - connection.requestMethod = "HEAD" - - val redirectLocation = connection.getHeaderField("Location") - connection.disconnect() + val url = URL(zipUrl.get()) + downloadedZipFile.get().asFile.parentFile.mkdirs() - // Extract tag from URL like: https://github.com/open-telemetry/opamp-spec/releases/tag/v0.12.0 - val latestTag = redirectLocation.substringAfterLast("/") - // Download the source code for the latest release - val zipUrl = "https://github.com/open-telemetry/opamp-spec/zipball/$latestTag" - - download.run { - src(zipUrl) - dest(downloadedZipFile) + url.openStream().use { input: InputStream -> + downloadedZipFile.get().asFile.outputStream().use { output: FileOutputStream -> + input.copyTo(output) + } } + val protos = archiveOps.zipTree(downloadedZipFile).matching { setIncludes(listOf("**/*.proto")) } diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClient.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClient.java similarity index 98% rename from opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClient.java rename to opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClient.java index 5889642d8..19d63eb11 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClient.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClient.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.opamp.client.internal; +package io.opentelemetry.opamp.client; import io.opentelemetry.opamp.client.internal.response.MessageData; import java.io.Closeable; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClientBuilder.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java similarity index 98% rename from opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClientBuilder.java rename to opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java index 3e4d0f4aa..d6af850fa 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/OpampClientBuilder.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/OpampClientBuilder.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.opamp.client.internal; +package io.opentelemetry.opamp.client; import com.github.f4b6a3.uuid.UuidCreator; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -11,9 +11,9 @@ import io.opentelemetry.opamp.client.internal.impl.OpampClientImpl; import io.opentelemetry.opamp.client.internal.impl.OpampClientState; import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; -import io.opentelemetry.opamp.client.internal.request.service.RequestService; import io.opentelemetry.opamp.client.internal.request.service.WebSocketRequestService; import io.opentelemetry.opamp.client.internal.state.State; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; @@ -28,12 +28,7 @@ import opamp.proto.KeyValue; import opamp.proto.RemoteConfigStatus; -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - * - *

Builds an {@link OpampClient} instance. - */ +/** Builds an {@link OpampClient} instance. */ public final class OpampClientBuilder { private final Map identifyingAttributes = new HashMap<>(); private final Map nonIdentifyingAttributes = new HashMap<>(); diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java index ec453bf6f..8ff386251 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/connectivity/websocket/OkHttpWebSocket.java @@ -5,7 +5,8 @@ package io.opentelemetry.opamp.client.internal.connectivity.websocket; -import java.util.Objects; +import static java.util.Objects.requireNonNull; + import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -65,7 +66,7 @@ public void close(int code, @Nullable String reason) { } private okhttp3.WebSocket getWebSocket() { - return Objects.requireNonNull(webSocket.get()); + return requireNonNull(webSocket.get()); } private class ListenerAdapter extends WebSocketListener { diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java index 7ada06c42..e224135ff 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImpl.java @@ -5,7 +5,7 @@ package io.opentelemetry.opamp.client.internal.impl; -import io.opentelemetry.opamp.client.internal.OpampClient; +import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.impl.recipe.AgentToServerAppenders; import io.opentelemetry.opamp.client.internal.impl.recipe.RecipeManager; import io.opentelemetry.opamp.client.internal.impl.recipe.RequestRecipe; @@ -19,12 +19,12 @@ import io.opentelemetry.opamp.client.internal.impl.recipe.appenders.SequenceNumberAppender; import io.opentelemetry.opamp.client.internal.request.Field; import io.opentelemetry.opamp.client.internal.request.Request; -import io.opentelemetry.opamp.client.internal.request.service.RequestService; import io.opentelemetry.opamp.client.internal.response.MessageData; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; import io.opentelemetry.opamp.client.internal.state.ObservableState; import io.opentelemetry.opamp.client.internal.state.State; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java index 569447342..e9f79c254 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestService.java @@ -14,6 +14,7 @@ import io.opentelemetry.opamp.client.internal.request.delay.RetryPeriodicDelay; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.IOException; import java.time.Duration; import java.util.Objects; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java index 13ef9b117..280725884 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestService.java @@ -13,6 +13,7 @@ import io.opentelemetry.opamp.client.internal.request.delay.RetryPeriodicDelay; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.Duration; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/response/MessageData.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/response/MessageData.java index df9fb8ba1..af47027ef 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/response/MessageData.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/response/MessageData.java @@ -6,7 +6,7 @@ package io.opentelemetry.opamp.client.internal.response; import com.google.auto.value.AutoValue; -import io.opentelemetry.opamp.client.internal.OpampClient; +import io.opentelemetry.opamp.client.OpampClient; import javax.annotation.Nullable; import opamp.proto.AgentRemoteConfig; diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/state/InMemoryState.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/state/InMemoryState.java index 89ba8b1cb..be2d34215 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/state/InMemoryState.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/state/InMemoryState.java @@ -5,7 +5,8 @@ package io.opentelemetry.opamp.client.internal.state; -import java.util.Objects; +import static java.util.Objects.requireNonNull; + import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nonnull; @@ -33,6 +34,6 @@ public void set(T value) { @Nonnull @Override public T get() { - return Objects.requireNonNull(state.get()); + return requireNonNull(state.get()); } } diff --git a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/RequestService.java b/opamp-client/src/main/java/io/opentelemetry/opamp/client/request/service/RequestService.java similarity index 91% rename from opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/RequestService.java rename to opamp-client/src/main/java/io/opentelemetry/opamp/client/request/service/RequestService.java index ee47e4249..76d1650e3 100644 --- a/opamp-client/src/main/java/io/opentelemetry/opamp/client/internal/request/service/RequestService.java +++ b/opamp-client/src/main/java/io/opentelemetry/opamp/client/request/service/RequestService.java @@ -3,10 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.opamp.client.internal.request.service; +package io.opentelemetry.opamp.client.request.service; -import io.opentelemetry.opamp.client.internal.OpampClient; +import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.request.Request; +import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; +import io.opentelemetry.opamp.client.internal.request.service.WebSocketRequestService; import io.opentelemetry.opamp.client.internal.response.Response; import java.util.function.Supplier; diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java index 9a076f757..dd5c0b956 100644 --- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java +++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/impl/OpampClientImplTest.java @@ -12,13 +12,13 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import io.opentelemetry.opamp.client.internal.OpampClient; +import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.connectivity.http.OkHttpSender; import io.opentelemetry.opamp.client.internal.request.Request; import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; -import io.opentelemetry.opamp.client.internal.request.service.RequestService; import io.opentelemetry.opamp.client.internal.response.MessageData; import io.opentelemetry.opamp.client.internal.state.State; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.IOException; import java.time.Duration; import java.util.ArrayList; diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java index c0107673b..9c5ea516d 100644 --- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java +++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/HttpRequestServiceTest.java @@ -6,7 +6,7 @@ package io.opentelemetry.opamp.client.internal.request.service; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doThrow; @@ -21,6 +21,7 @@ import io.opentelemetry.opamp.client.internal.request.Request; import io.opentelemetry.opamp.client.internal.request.delay.PeriodicDelay; import io.opentelemetry.opamp.client.internal.response.Response; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.ByteArrayInputStream; import java.time.Duration; import java.util.ArrayList; diff --git a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java index c00cc0cc0..6e96554ea 100644 --- a/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java +++ b/opamp-client/src/test/java/io/opentelemetry/opamp/client/internal/request/service/WebSocketRequestServiceTest.java @@ -6,7 +6,7 @@ package io.opentelemetry.opamp.client.internal.request.service; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.inOrder; @@ -23,6 +23,7 @@ import io.opentelemetry.opamp.client.internal.request.Request; import io.opentelemetry.opamp.client.internal.response.OpampServerResponseException; import io.opentelemetry.opamp.client.internal.response.Response; +import io.opentelemetry.opamp.client.request.service.RequestService; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.time.Duration; diff --git a/processors/src/main/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessor.java b/processors/src/main/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessor.java index a213ec21a..61347388a 100644 --- a/processors/src/main/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessor.java +++ b/processors/src/main/java/io/opentelemetry/contrib/filter/FilteringLogRecordProcessor.java @@ -11,10 +11,10 @@ import io.opentelemetry.sdk.logs.data.LogRecordData; import java.util.function.Predicate; -public class FilteringLogRecordProcessor implements LogRecordProcessor { +public final class FilteringLogRecordProcessor implements LogRecordProcessor { - public final LogRecordProcessor delegate; - public final Predicate predicate; + private final LogRecordProcessor delegate; + private final Predicate predicate; public FilteringLogRecordProcessor( LogRecordProcessor delegate, Predicate predicate) { diff --git a/processors/src/test/java/io/opentelemetry/contrib/eventbridge/internal/EventToSpanBridgeComponentProviderTest.java b/processors/src/test/java/io/opentelemetry/contrib/eventbridge/internal/EventToSpanBridgeComponentProviderTest.java index 55746e61d..1e503a51c 100644 --- a/processors/src/test/java/io/opentelemetry/contrib/eventbridge/internal/EventToSpanBridgeComponentProviderTest.java +++ b/processors/src/test/java/io/opentelemetry/contrib/eventbridge/internal/EventToSpanBridgeComponentProviderTest.java @@ -18,7 +18,7 @@ class EventToSpanBridgeComponentProviderTest { @Test void endToEnd() { String yaml = - "file_format: 0.4\n" + "file_format: 1.0-rc.1\n" + "logger_provider:\n" + " processors:\n" + " - event_to_span_event_bridge:\n"; 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..05bee8aa8 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; @@ -31,7 +31,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class FilteringLogRecordProcessorTest { +class FilteringLogRecordProcessorTest { private final InMemoryLogRecordExporter memoryLogRecordExporter = InMemoryLogRecordExporter.create(); @@ -79,7 +79,7 @@ public SdkLoggerProviderBuilder apply( logRecordData -> { SpanContext spanContext = logRecordData.getSpanContext(); return spanContext.isSampled(); - }) {}) + })) .build() .get("TestScope"); } @@ -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/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/MetricAdapter.java b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/MetricAdapter.java index c0b381e7d..e71331964 100644 --- a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/MetricAdapter.java +++ b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/MetricAdapter.java @@ -6,6 +6,8 @@ package io.opentelemetry.contrib.metrics.prometheus.clientbridge; import static io.prometheus.client.Collector.doubleToGoString; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanContext; @@ -28,7 +30,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.TimeUnit; import java.util.function.Function; import javax.annotation.Nullable; @@ -54,6 +55,8 @@ final class MetricAdapter { static final String LABEL_NAME_QUANTILE = "quantile"; static final String LABEL_NAME_LE = "le"; + static final Function sanitizer = new NameSanitizer(); + // Converts a MetricData to a Prometheus MetricFamilySamples. static MetricFamilySamples toMetricFamilySamples(MetricData metricData) { String cleanMetricName = cleanMetricName(metricData.getName()); @@ -99,8 +102,6 @@ static Collector.Type toMetricFamilyType(MetricData metricData) { return Collector.Type.UNKNOWN; } - static final Function sanitizer = new NameSanitizer(); - // Converts a list of points from MetricData to a list of Prometheus Samples. static List toSamples( String name, MetricDataType type, Collection points) { @@ -291,7 +292,7 @@ private static Sample createSample( labelValues, value, toPrometheusExemplar(exemplar), - TimeUnit.MILLISECONDS.convert(timestampNanos, TimeUnit.NANOSECONDS)); + MILLISECONDS.convert(timestampNanos, NANOSECONDS)); } return new Sample( name, @@ -299,7 +300,7 @@ private static Sample createSample( labelValues, value, null, - TimeUnit.MILLISECONDS.convert(timestampNanos, TimeUnit.NANOSECONDS)); + MILLISECONDS.convert(timestampNanos, NANOSECONDS)); } private static io.prometheus.client.exemplars.Exemplar toPrometheusExemplar( @@ -309,7 +310,7 @@ private static io.prometheus.client.exemplars.Exemplar toPrometheusExemplar( return new io.prometheus.client.exemplars.Exemplar( getExemplarValue(exemplar), // Convert to ms for prometheus, truncate nanosecond precision. - TimeUnit.NANOSECONDS.toMillis(exemplar.getEpochNanos()), + NANOSECONDS.toMillis(exemplar.getEpochNanos()), "trace_id", spanContext.getTraceId(), "span_id", diff --git a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java index 3acc1096a..e9c574f92 100644 --- a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java +++ b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/PrometheusCollector.java @@ -5,6 +5,8 @@ package io.opentelemetry.contrib.metrics.prometheus.clientbridge; +import static java.util.Collections.unmodifiableList; + import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; @@ -15,7 +17,6 @@ import io.prometheus.client.CollectorRegistry; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.function.Supplier; @@ -79,7 +80,7 @@ public List collect() { for (MetricData metricData : allMetrics) { allSamples.add(MetricAdapter.toMetricFamilySamples(metricData)); } - return Collections.unmodifiableList(allSamples); + return unmodifiableList(allSamples); } } } diff --git a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/Serializer.java b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/Serializer.java index d696a14b7..d79892a27 100644 --- a/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/Serializer.java +++ b/prometheus-client-bridge/src/main/java/io/opentelemetry/contrib/metrics/prometheus/clientbridge/Serializer.java @@ -21,11 +21,12 @@ package io.opentelemetry.contrib.metrics.prometheus.clientbridge; +import static java.util.Collections.emptyList; + import io.opentelemetry.sdk.metrics.data.HistogramPointData; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.PointData; import java.util.Collection; -import java.util.Collections; import java.util.List; /** Serializes metrics into Prometheus exposition formats. */ @@ -71,7 +72,7 @@ static Collection getPoints(MetricData metricData) { case EXPONENTIAL_HISTOGRAM: return metricData.getExponentialHistogramData().getPoints(); } - return Collections.emptyList(); + return emptyList(); } private Serializer() {} diff --git a/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerResourceDetector.java b/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerResourceDetector.java index 7d5d399c4..d97785cca 100644 --- a/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerResourceDetector.java +++ b/resource-providers/src/main/java/io/opentelemetry/contrib/resourceproviders/AppServerResourceDetector.java @@ -12,7 +12,7 @@ @SuppressWarnings("rawtypes") @AutoService(ComponentProvider.class) -public class AppServerResourceDetector implements ComponentProvider { +public final class AppServerResourceDetector implements ComponentProvider { @Override public Class getType() { 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..75d5664a2 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; @@ -15,21 +14,21 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -public class JettyServiceNameDetectorTest { +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()); } } diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AbstractAttachmentTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AbstractAttachmentTest.java index 43d89b2ef..611dde652 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AbstractAttachmentTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AbstractAttachmentTest.java @@ -8,7 +8,7 @@ import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.trace.Span; import org.junit.jupiter.api.BeforeAll; -public class AbstractAttachmentTest { +class AbstractAttachmentTest { @BeforeAll static void disableMainThreadCheck() { diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java index 41571a2e4..91a67d3cd 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledByEnvironmentVariableTest.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.annotations.WithSpan; import org.junit.jupiter.api.Test; -public class AgentDisabledByEnvironmentVariableTest extends AbstractAttachmentTest { +class AgentDisabledByEnvironmentVariableTest extends AbstractAttachmentTest { @Test void shouldNotAttachWhenAgentDisabledWithEnvVariable() { diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java index a24c81296..39d941ff3 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/AgentDisabledBySystemPropertyTest.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.annotations.WithSpan; import org.junit.jupiter.api.Test; -public class AgentDisabledBySystemPropertyTest extends AbstractAttachmentTest { +class AgentDisabledBySystemPropertyTest extends AbstractAttachmentTest { @Test void shouldNotAttachWhenAgentDisabledWithProperty() { diff --git a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java index 5d8f201ae..65eabcf02 100644 --- a/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java +++ b/runtime-attach/runtime-attach/src/test/java/io/opentelemetry/contrib/attach/RunTimeAttachBasicTest.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.annotations.WithSpan; import org.junit.jupiter.api.Test; -public class RunTimeAttachBasicTest extends AbstractAttachmentTest { +class RunTimeAttachBasicTest extends AbstractAttachmentTest { @Test void shouldAttach() { diff --git a/samplers/README.md b/samplers/README.md index 854d44e61..aee9dee5f 100644 --- a/samplers/README.md +++ b/samplers/README.md @@ -9,7 +9,7 @@ The following samplers support [declarative configuration](https://opentelemetry To use: * Add a dependency on `io.opentelemetry.contrib:opentelemetry-samplers:` -* Follow the [instructions](https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/incubator/README.md#file-configuration) to configure OpenTelemetry with declarative configuration. +* Follow the [instructions](https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/incubator/README.md#declarative-configuration) to configure OpenTelemetry with declarative configuration. * Configure the `.tracer_provider.sampler` to include the `rule_based_routing` sampler. NOTE: Not yet available for use with the OTEL java agent, but should be in the near future. Please check back for updates. 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..8024ab590 100644 --- a/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java +++ b/samplers/src/main/java/io/opentelemetry/contrib/sampler/LinksParentAlwaysOnSamplerProvider.java @@ -9,7 +9,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider; import io.opentelemetry.sdk.trace.samplers.Sampler; -public class LinksParentAlwaysOnSamplerProvider implements ConfigurableSamplerProvider { +public final class LinksParentAlwaysOnSamplerProvider implements ConfigurableSamplerProvider { @Override public Sampler createSampler(ConfigProperties config) { return LinksBasedSampler.create(Sampler.parentBased(Sampler.alwaysOn())); diff --git a/samplers/src/test/java/internal/RuleBasedRoutingSamplerComponentProviderTest.java b/samplers/src/test/java/internal/RuleBasedRoutingSamplerComponentProviderTest.java index 02611c9d5..c39603352 100644 --- a/samplers/src/test/java/internal/RuleBasedRoutingSamplerComponentProviderTest.java +++ b/samplers/src/test/java/internal/RuleBasedRoutingSamplerComponentProviderTest.java @@ -38,7 +38,7 @@ class RuleBasedRoutingSamplerComponentProviderTest { @Test void endToEnd() { String yaml = - "file_format: 0.4\n" + "file_format: 1.0-rc.1\n" + "tracer_provider:\n" + " sampler:\n" + " parent_based:\n" diff --git a/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java b/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java index 05a4301e6..62b1bee31 100644 --- a/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java +++ b/samplers/src/test/java/io/opentelemetry/contrib/sampler/RuleBasedRoutingSamplerTest.java @@ -63,7 +63,7 @@ public void setup() { } @Test - public void testThatThrowsOnNullParameter() { + void testThatThrowsOnNullParameter() { assertThatExceptionOfType(NullPointerException.class) .isThrownBy(() -> new RuleBasedRoutingSampler(patterns, SPAN_KIND, null)); @@ -98,7 +98,7 @@ public void testThatThrowsOnNullParameter() { } @Test - public void testThatDelegatesIfNoRulesGiven() { + void testThatDelegatesIfNoRulesGiven() { RuleBasedRoutingSampler sampler = RuleBasedRoutingSampler.builder(SPAN_KIND, delegate).build(); // no http.url attribute @@ -117,7 +117,7 @@ public void testThatDelegatesIfNoRulesGiven() { } @Test - public void testDropOnExactMatch() { + void testDropOnExactMatch() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SPAN_KIND, delegate)).build(); assertThat(shouldSample(sampler, "https://example.com/healthcheck").getDecision()) @@ -125,7 +125,7 @@ public void testDropOnExactMatch() { } @Test - public void testDelegateOnDifferentKind() { + void testDelegateOnDifferentKind() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SpanKind.CLIENT, delegate)).build(); assertThat(shouldSample(sampler, "https://example.com/healthcheck").getDecision()) @@ -134,7 +134,7 @@ public void testDelegateOnDifferentKind() { } @Test - public void testDelegateOnNoMatch() { + void testDelegateOnNoMatch() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SPAN_KIND, delegate)).build(); assertThat(shouldSample(sampler, "https://example.com/customers").getDecision()) @@ -143,7 +143,7 @@ public void testDelegateOnNoMatch() { } @Test - public void testDelegateOnMalformedUrl() { + void testDelegateOnMalformedUrl() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SPAN_KIND, delegate)).build(); assertThat(shouldSample(sampler, "abracadabra").getDecision()) @@ -158,7 +158,7 @@ public void testDelegateOnMalformedUrl() { } @Test - public void testVerifiesAllGivenAttributes() { + void testVerifiesAllGivenAttributes() { RuleBasedRoutingSampler sampler = addRules(RuleBasedRoutingSampler.builder(SPAN_KIND, delegate)).build(); Attributes attributes = Attributes.of(URL_PATH, "/actuator/info"); diff --git a/settings.gradle.kts b/settings.gradle.kts index 5502252e7..13de5fd7e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,6 @@ pluginManagement { plugins { - id("com.gradleup.shadow") version "9.0.2" + id("com.gradleup.shadow") version "9.1.0" id("io.github.gradle-nexus.publish-plugin") version "2.0.0" id("com.gradle.develocity") version "4.1.1" } @@ -29,12 +29,17 @@ develocity { publishing.onlyIf { System.getenv("CI") != null } termsOfUseUrl.set("https://gradle.com/help/legal-terms-of-use") termsOfUseAgree.set("yes") + + buildScanPublished { + File("build-scan.txt").printWriter().use { writer -> + writer.println(buildScanUri) + } + } } } rootProject.name = "opentelemetry-java-contrib" -include(":all") include(":aws-resources") include(":aws-xray") include(":aws-xray-propagator") @@ -45,7 +50,6 @@ include(":cloudfoundry-resources") include(":consistent-sampling") include(":dependencyManagement") include(":disk-buffering") -include(":example") include(":ibm-mq-metrics") include(":jfr-events") include(":jfr-connection") diff --git a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java index 2315d2a10..3a427b7e3 100644 --- a/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java +++ b/span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java @@ -5,6 +5,9 @@ package io.opentelemetry.contrib.stacktrace; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.SEVERE; + import com.google.auto.service.AutoService; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; @@ -50,7 +53,7 @@ static long getMinDuration(ConfigProperties properties) { log.fine("Stack traces capture is disabled"); } else { log.log( - Level.FINE, + FINE, "Stack traces will be added to spans with a minimum duration of {0} nanos", minDuration); } @@ -70,7 +73,7 @@ static Predicate getFilterPredicate(ConfigProperties properties) { if (filter == null) { // if value is set, lack of filtering is likely an error and must be reported - Level disabledLogLevel = filterClass != null ? Level.SEVERE : Level.FINE; + Level disabledLogLevel = filterClass != null ? SEVERE : FINE; log.log(disabledLogLevel, "Span stacktrace filtering disabled"); return span -> true; } else { diff --git a/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfigTest.java b/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfigTest.java index 4b8f999f4..ca1517480 100644 --- a/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfigTest.java +++ b/span-stacktrace/src/test/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfigTest.java @@ -15,7 +15,7 @@ import java.util.function.Predicate; import org.junit.jupiter.api.Test; -public class StackTraceAutoConfigTest { +class StackTraceAutoConfigTest { @Test void defaultConfig() { diff --git a/version.gradle.kts b/version.gradle.kts index e4f74f0e1..9ea6b805e 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -1,5 +1,5 @@ -val stableVersion = "1.49.0-SNAPSHOT" -val alphaVersion = "1.49.0-alpha-SNAPSHOT" +val stableVersion = "1.50.0-SNAPSHOT" +val alphaVersion = "1.50.0-alpha-SNAPSHOT" allprojects { if (findProperty("otel.stable") != "true") {