diff --git a/.github/workflows/auto-update-otel-sdk.yml b/.github/workflows/auto-update-otel-sdk.yml index cd6c7663a0a0..c9146adec20e 100644 --- a/.github/workflows/auto-update-otel-sdk.yml +++ b/.github/workflows/auto-update-otel-sdk.yml @@ -64,13 +64,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Update license report - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: generateLicenseReport diff --git a/.github/workflows/build-common.yml b/.github/workflows/build-common.yml index c6001c037f0a..e8cce9b1f0b3 100644 --- a/.github/workflows/build-common.yml +++ b/.github/workflows/build-common.yml @@ -33,13 +33,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Spotless - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 env: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GE_CACHE_USERNAME: ${{ secrets.GE_CACHE_USERNAME }} @@ -55,7 +55,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: gradle/wrapper-validation-action@v1.1.0 + - uses: gradle/wrapper-validation-action@v2.1.1 license-check: runs-on: ubuntu-latest @@ -66,13 +66,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Generate license report - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 env: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GE_CACHE_USERNAME: ${{ secrets.GE_CACHE_USERNAME }} @@ -136,7 +136,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 @@ -146,7 +146,7 @@ jobs: sed -i "s/org.gradle.jvmargs=/org.gradle.jvmargs=-Xmx3g /" gradle.properties - name: Build - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 env: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GE_CACHE_USERNAME: ${{ secrets.GE_CACHE_USERNAME }} @@ -173,7 +173,7 @@ jobs: fi - name: Upload agent jar - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: javaagent/build/libs/opentelemetry-javaagent-*-SNAPSHOT.jar @@ -208,14 +208,14 @@ jobs: - id: setup-test-java name: Set up JDK ${{ matrix.test-java-version }}-${{ matrix.vm }} for running tests - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: # using zulu because new releases get published quickly distribution: ${{ matrix.vm == 'hotspot' && 'zulu' || 'adopt-openj9'}} java-version: ${{ matrix.test-java-version }} - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 @@ -228,7 +228,7 @@ jobs: # vaadin tests use pnpm - name: Cache pnpm modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.pnpm-store key: ${{ runner.os }}-test-cache-pnpm-modules @@ -241,7 +241,7 @@ jobs: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GE_CACHE_USERNAME: ${{ secrets.GE_CACHE_USERNAME }} GE_CACHE_PASSWORD: ${{ secrets.GE_CACHE_PASSWORD }} - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: # "check" is needed to activate all tests for listing purposes # listTestsInPartition writes test tasks that apply to the given partition to a file named @@ -261,7 +261,7 @@ jobs: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GE_CACHE_USERNAME: ${{ secrets.GE_CACHE_USERNAME }} GE_CACHE_PASSWORD: ${{ secrets.GE_CACHE_PASSWORD }} - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: # spotless is checked separately since it's a common source of failure arguments: > @@ -278,7 +278,7 @@ jobs: - name: Upload deadlock detector artifacts if any if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: deadlock-detector-test-${{ matrix.test-java-version }}-${{ matrix.vm }}-${{ matrix.test-partition }} path: /tmp/deadlock-detector-* @@ -286,7 +286,7 @@ jobs: - name: Upload jvm crash dump files if any if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: javacore-test-${{ matrix.test-java-version }}-${{ matrix.test-partition }} path: | @@ -329,13 +329,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Set up Gradle cache - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: # only push cache for one matrix option per OS since github action cache space is limited cache-read-only: ${{ inputs.cache-read-only || matrix.smoke-test-suite != 'tomcat' }} @@ -359,7 +359,7 @@ jobs: - name: Upload jvm crash dump files if any if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: javacore-smoke-test-${{ matrix.smoke-test-suite }}-${{ matrix.os }} # we expect crash dumps either in root director or in smoke-tests @@ -386,13 +386,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Build - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: build ${{ inputs.no-build-cache && '--no-build-cache' || '' }} build-root-directory: gradle-plugins @@ -407,13 +407,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Set up Gradle cache - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: cache-read-only: ${{ inputs.cache-read-only }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 68e42ad81806..009ce60c61ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,7 +71,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 @@ -83,7 +83,7 @@ jobs: SONATYPE_KEY: ${{ secrets.SONATYPE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: assemble publishToSonatype # gradle enterprise is used for the build cache @@ -96,7 +96,7 @@ jobs: SONATYPE_KEY: ${{ secrets.SONATYPE_KEY }} GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: build-root-directory: gradle-plugins arguments: build publishToSonatype diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index 878c5ca0acf0..848faff188f0 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -17,26 +17,26 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up Java 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: java # using "latest" helps to keep up with the latest Kotlin support # see https://github.com/github/codeql-action/issues/1555#issuecomment-1452228433 tools: latest - - uses: gradle/gradle-build-action@v2 + - uses: gradle/gradle-build-action@v3 with: # skipping build cache is needed so that all modules will be analyzed arguments: assemble -x javadoc --no-build-cache --no-daemon - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 workflow-notification: needs: diff --git a/.github/workflows/issue-management-stale-action.yml b/.github/workflows/issue-management-stale-action.yml index 18061d131526..20d0fbacaa05 100644 --- a/.github/workflows/issue-management-stale-action.yml +++ b/.github/workflows/issue-management-stale-action.yml @@ -9,7 +9,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 7 diff --git a/.github/workflows/overhead-benchmark-daily.yml b/.github/workflows/overhead-benchmark-daily.yml index ed496380ec2a..a8640ae6f857 100644 --- a/.github/workflows/overhead-benchmark-daily.yml +++ b/.github/workflows/overhead-benchmark-daily.yml @@ -24,7 +24,7 @@ jobs: rsync -avv gh-pages/benchmark-overhead/results/ benchmark-overhead/results/ - name: Run tests - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: test build-root-directory: benchmark-overhead diff --git a/.github/workflows/owasp-dependency-check-daily.yml b/.github/workflows/owasp-dependency-check-daily.yml index 35cd2e8c2360..3992b65a5251 100644 --- a/.github/workflows/owasp-dependency-check-daily.yml +++ b/.github/workflows/owasp-dependency-check-daily.yml @@ -19,18 +19,18 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - - uses: gradle/gradle-build-action@v2 + - uses: gradle/gradle-build-action@v3 with: arguments: ":javaagent:dependencyCheckAnalyze" - name: Upload report if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: javaagent/build/reports diff --git a/.github/workflows/pr-smoke-test-fake-backend-images.yml b/.github/workflows/pr-smoke-test-fake-backend-images.yml index 6049ae428ed9..adc0f4aac66f 100644 --- a/.github/workflows/pr-smoke-test-fake-backend-images.yml +++ b/.github/workflows/pr-smoke-test-fake-backend-images.yml @@ -16,13 +16,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Build Docker image - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: ":smoke-tests:images:fake-backend:jibDockerBuild -Djib.httpTimeout=120000 -Djib.console=plain" cache-read-only: true @@ -41,13 +41,13 @@ jobs: - uses: actions/checkout@v4 - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Build Docker image - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: ":smoke-tests:images:fake-backend:windowsBackendImageBuild" cache-read-only: true diff --git a/.github/workflows/pr-smoke-test-servlet-images.yml b/.github/workflows/pr-smoke-test-servlet-images.yml index 23fd6cf8bb03..ed00b046fe41 100644 --- a/.github/workflows/pr-smoke-test-servlet-images.yml +++ b/.github/workflows/pr-smoke-test-servlet-images.yml @@ -37,13 +37,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Set up Gradle cache - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: cache-read-only: true diff --git a/.github/workflows/publish-smoke-test-fake-backend-images.yml b/.github/workflows/publish-smoke-test-fake-backend-images.yml index d1d39021f44c..df269314a6f2 100644 --- a/.github/workflows/publish-smoke-test-fake-backend-images.yml +++ b/.github/workflows/publish-smoke-test-fake-backend-images.yml @@ -19,7 +19,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 @@ -35,7 +35,7 @@ jobs: run: echo "TAG=$(date '+%Y%m%d').$GITHUB_RUN_ID" >> $GITHUB_ENV - name: Build Docker image - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: ":smoke-tests:images:fake-backend:jib -Djib.httpTimeout=120000 -Djib.console=plain -PextraTag=${{ env.TAG }}" @@ -51,7 +51,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 @@ -67,7 +67,7 @@ jobs: run: echo "TAG=$(date '+%Y%m%d').$GITHUB_RUN_ID" >> $GITHUB_ENV - name: Build Docker image - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: ":smoke-tests:images:fake-backend:dockerPush -PextraTag=${{ env.TAG }}" diff --git a/.github/workflows/publish-smoke-test-servlet-images.yml b/.github/workflows/publish-smoke-test-servlet-images.yml index 728c222c6a32..04db499952d6 100644 --- a/.github/workflows/publish-smoke-test-servlet-images.yml +++ b/.github/workflows/publish-smoke-test-servlet-images.yml @@ -54,7 +54,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 @@ -67,7 +67,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Gradle cache - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: # only push cache for one matrix option per OS since github action cache space is limited cache-read-only: ${{ matrix.smoke-test-suite != 'tomcat' }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0d81b2d4e024..f8ed2cbc4ef8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -80,13 +80,13 @@ jobs: - name: Free disk space run: .github/scripts/gha-free-disk-space.sh - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Build and publish artifacts - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: assemble publishToSonatype closeAndReleaseSonatypeStagingRepository env: @@ -96,7 +96,7 @@ jobs: GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} - name: Build and publish gradle plugins - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 env: SONATYPE_USER: ${{ secrets.SONATYPE_USER }} SONATYPE_KEY: ${{ secrets.SONATYPE_KEY }} diff --git a/.github/workflows/reusable-muzzle.yml b/.github/workflows/reusable-muzzle.yml index 08d2527eec3c..fca0c6b80dcc 100644 --- a/.github/workflows/reusable-muzzle.yml +++ b/.github/workflows/reusable-muzzle.yml @@ -25,13 +25,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 - name: Run muzzle - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: ${{ matrix.task }} cache-read-only: ${{ inputs.cache-read-only }} diff --git a/.github/workflows/reusable-smoke-test-images.yml b/.github/workflows/reusable-smoke-test-images.yml index c4760b9b0aa1..ccb4875dcf0c 100644 --- a/.github/workflows/reusable-smoke-test-images.yml +++ b/.github/workflows/reusable-smoke-test-images.yml @@ -32,7 +32,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 @@ -49,7 +49,7 @@ jobs: run: echo "TAG=$(date '+%Y%m%d').$GITHUB_RUN_ID" >> $GITHUB_ENV - name: Set up Gradle cache - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: cache-read-only: ${{ inputs.cache-read-only }} diff --git a/.github/workflows/reusable-test-indy.yml b/.github/workflows/reusable-test-indy.yml index e17f0ea6d473..80580e3b7dea 100644 --- a/.github/workflows/reusable-test-indy.yml +++ b/.github/workflows/reusable-test-indy.yml @@ -37,7 +37,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 @@ -54,7 +54,7 @@ jobs: # vaadin tests use pnpm - name: Cache pnpm modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.pnpm-store key: ${{ runner.os }}-test-latest-cache-pnpm-modules @@ -64,7 +64,7 @@ jobs: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GE_CACHE_USERNAME: ${{ secrets.GE_CACHE_USERNAME }} GE_CACHE_PASSWORD: ${{ secrets.GE_CACHE_PASSWORD }} - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: > check -x spotlessCheck @@ -77,7 +77,7 @@ jobs: echo "test-tasks=$(cat test-tasks.txt | xargs echo | sed 's/\n/ /g')" >> $GITHUB_ENV - name: Test - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 env: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GE_CACHE_USERNAME: ${{ secrets.GE_CACHE_USERNAME }} diff --git a/.github/workflows/reusable-test-latest-deps.yml b/.github/workflows/reusable-test-latest-deps.yml index fee45b362c08..2efaf3bee018 100644 --- a/.github/workflows/reusable-test-latest-deps.yml +++ b/.github/workflows/reusable-test-latest-deps.yml @@ -36,7 +36,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17.0.6 @@ -47,7 +47,7 @@ jobs: # vaadin tests use pnpm - name: Cache pnpm modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.pnpm-store key: ${{ runner.os }}-test-latest-cache-pnpm-modules @@ -57,7 +57,7 @@ jobs: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GE_CACHE_USERNAME: ${{ secrets.GE_CACHE_USERNAME }} GE_CACHE_PASSWORD: ${{ secrets.GE_CACHE_PASSWORD }} - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 with: arguments: > check -x spotlessCheck @@ -71,7 +71,7 @@ jobs: echo "test-tasks=$(cat test-tasks.txt | xargs echo | sed 's/\n/ /g')" >> $GITHUB_ENV - name: Test - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@v3 env: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GE_CACHE_USERNAME: ${{ secrets.GE_CACHE_USERNAME }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0633900ec0c9..6babf4d821bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,153 @@ # Changelog -## Unreleased +## Version 1.32.1 (2024-02-02) + +### 📈 Enhancements + +- Backport: update jackson packages to v2.16.1 + ([#10198](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10198), + [#10199](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10199)) +- Backport: implement forEach support for aws sqs tracing list + ([#10195](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10195)) +- Backport: Bridge metric advice in OpenTelemetry API 1.32 + ([#10026](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10026)) +- Update the OpenTelemetry SDK version to 1.34.1 + ([#10320](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10320)) + +### 🛠️ Bug fixes + +- Backport: Handle authority from request when HttpHost is null + ([#10204](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10204)) +- Backport: Null check for nullable response object in aws sdk 1.1 instrumentation + ([#10029](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10029)) +- Backport: Make Netty Instrumentation HttpServerRequestTracingHandler propagate "Channel Inactive" event to downstream according to parent contract + ([#10303](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10303)) +- Backport: Fix Netty addListener instrumentation + ([#10254](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10254)) +- Backport: Update azure-core-tracing-opentelemetry version and fix sync suppression + ([#10350](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/10350)) + +## Version 1.32.0 (2023-11-17) + +### Migration notes + +- Old server/client socket getter methods deprecated + ([#9716](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9716)) + +### 📈 Enhancements + +- Allow enabling receive telemetry in kafka library instrumentation + ([#9693](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9693)) +- Add JdbcTelemetry and JdbcTelemetryBuilder + ([#9685](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9685)) +- Rename http.resend_count to http.request.resend_count + ([#9700](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9700)) +- Define `url.scheme` in terms of logical operation in HTTP server semconv + (when opting in to new semconv) + ([#9698](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9698)) +- Generate only consumer span for sqs receive message + ([#9652](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9652)) +- Replace `(client|server).socket.(address|port)` attributes with `network.(peer|local).(address|port)` + (when opting in to new semconv) + ([#9676](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9676)) +- Add capability for invokedynamic InstrumentationModules to inject proxies + ([#9565](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9565)) +- Make `network.transport` and `network.type` opt-in (when opting in to new semconv) + ([#9719](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9719)) +- Factor in `X-Forwarded-Host`/`Forwarded` when capturing `server.address` and `server.port` + (when opting in to new semconv) + ([#9721](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9721)) +- Move class that should've been internal to internal package + ([#9725](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9725)) +- Only set `server.port` when `server.address` is set (when opting in to new semconv) + ([#9737](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9737)) +- Add messaging conventions to sqs spans + ([#9712](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9712)) +- Make the JDBC driver config work with the OTel starter + ([#9625](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9625)) +- Don't normalize the '-' character in HTTP header names when opting in to new semconv + ([#9735](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9735)) +- Add instrumentation for jaxws metro 3.0+ + ([#9705](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9705)) +- Change `user_agent.original` from recommended to opt-in on HTTP client spans + ([#9776](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9776)) +- Change the precedence between `:authority` and `Host` headers + ([#9774](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9774)) +- Move capturing enduser.id attribute behind a flag + ([#9751](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9751), + [#9788](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9788)) +- Remove conditional requirement on `network.peer.address` and `network.peer.port` + (when opting in to new semconv) + ([#9775](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9775)) +- Change `client.port` from recommended to opt-in on HTTP server spans + (when opting in to new semconv) + ([#9786](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9786)) +- Make `url.scheme` opt in for HTTP client metrics and make `server.port` required + (when opting in to new semconv) + ([#9784](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9784)) +- Change `http.request.body.size` and `http.response.body.size` attributes from recommended to opt-in + (when opting in to new semconv) + ([#9799](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9799)) +- Capture `http.route` in spring-cloud-gateway + ([#9597](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9597)) +- Always set messaging operation + ([#9791](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9791)) +- Change `network.protocol.name` from opt-in to conditionally required + (when opting in to new semconv) + ([#9797](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9797)) +- Support specifying `spring.application.name` in the `bootstrap.properties`, `bootstrap.yml` + and `bootstrap.yaml` + ([#9801](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9801)) +- Add process spans to aws-1 sqs instrumentation + ([#9796](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9796)) +- Implement capturing message headers for aws1 sqs spans + ([#9824](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9824)) +- Add process spans to aws2 sqs instrumentation + ([#9778](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9778)) +- Add `service.name` to MDC + ([#9647](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9647)) +- Capture enduser attributes in Spring Security + ([#9777](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9777)) +- Capture message id in aws1 sqs instrumentation + ([#9841](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9841)) +- Implement capturing message headers for aws2 sqs spans + ([#9842](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9842)) +- Move kafka metrics to separate instrumentation module + ([#9862](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9862)) +- Capture logback logger context properties + ([#9553](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9553)) +- Stable JVM semconv implementation: classes + ([#9821](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9821)) +- Stable JVM semconv implementation: threads + ([#9839](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9839)) +- Stable JVM semconv implementation: GC + ([#9890](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9890)) +- Bridge incubator metrics apis + ([#9884](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9884)) +- Ability to instrument logs before OTel injection into OTel appenders + ([#9798](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9798)) +- Suppress instrumentation based on suppress Context key + ([#9739](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9739)) +- Stable JVM semconv implementation: the rest + ([#9896](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9896)) + +### 🛠️ Bug fixes + +- Fix armeria server instrumentation for http2 + ([#9723](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9723)) +- Guard against null list from aws SQS lib + ([#9710](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9710)) +- Fix parsing port from mariadb jdbc url + ([#9863](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9863)) + +### 🧰 Tooling + +- Improve disableShadowRelocate + ([#9715](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9715)) +- Allow injection of helper bytecode as resources + ([#9752](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9752)) +- Rewrite @Advice.Enter for indy advice + ([#9887](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9887)) ## Version 1.31.0 (2023-10-12) diff --git a/README.md b/README.md index 5fc5c9a6877a..27c0818d8e7f 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ If you are looking for documentation on using those. ## Getting Started Download -the [latest version](https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar). +the [latest version](https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v1.32.1/opentelemetry-javaagent.jar). This package includes the instrumentation agent as well as instrumentations for all supported libraries and all available data exporters. diff --git a/benchmark-overhead-jmh/build.gradle.kts b/benchmark-overhead-jmh/build.gradle.kts index d1ce65dd8a0e..76027cef4c71 100644 --- a/benchmark-overhead-jmh/build.gradle.kts +++ b/benchmark-overhead-jmh/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } dependencies { - jmhImplementation("org.springframework.boot:spring-boot-starter-web:3.1.5") + jmhImplementation("org.springframework.boot:spring-boot-starter-web:3.2.3") } tasks { diff --git a/benchmark-overhead/Dockerfile-petclinic-base b/benchmark-overhead/Dockerfile-petclinic-base index a8dffbed01ec..28c2bf980071 100644 --- a/benchmark-overhead/Dockerfile-petclinic-base +++ b/benchmark-overhead/Dockerfile-petclinic-base @@ -13,7 +13,7 @@ RUN git checkout 8aa4d49 RUN ./mvnw package -Dmaven.test.skip=true RUN cp target/spring-petclinic-rest*.jar /app/spring-petclinic-rest.jar -FROM bellsoft/liberica-openjdk-alpine:21.0.1 +FROM bellsoft/liberica-openjdk-alpine:21.0.2 COPY --from=app-build /app/spring-petclinic-rest.jar /app/spring-petclinic-rest.jar WORKDIR /app EXPOSE 9966 diff --git a/benchmark-overhead/build.gradle.kts b/benchmark-overhead/build.gradle.kts index 7eaa9959137d..a761e83f1739 100644 --- a/benchmark-overhead/build.gradle.kts +++ b/benchmark-overhead/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("java") - id("com.diffplug.spotless") version "6.22.0" + id("com.diffplug.spotless") version "6.25.0" } spotless { @@ -16,16 +16,16 @@ repositories { } dependencies { - implementation(enforcedPlatform("org.junit:junit-bom:5.10.1")) + implementation(enforcedPlatform("org.junit:junit-bom:5.10.2")) - testImplementation("org.testcontainers:testcontainers:1.19.2") - testImplementation("org.testcontainers:postgresql:1.19.2") + testImplementation("org.testcontainers:testcontainers:1.19.6") + testImplementation("org.testcontainers:postgresql:1.19.6") testImplementation("org.junit.jupiter:junit-jupiter-api") testImplementation("org.junit.jupiter:junit-jupiter-params") testImplementation("com.squareup.okhttp3:okhttp:4.12.0") testImplementation("org.jooq:joox:2.0.0") - testImplementation("com.jayway.jsonpath:json-path:2.8.0") - testImplementation("org.slf4j:slf4j-simple:2.0.9") + testImplementation("com.jayway.jsonpath:json-path:2.9.0") + testImplementation("org.slf4j:slf4j-simple:2.0.12") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") } diff --git a/benchmark-overhead/gradle/wrapper/gradle-wrapper.jar b/benchmark-overhead/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b7..d64cd4917707 100644 Binary files a/benchmark-overhead/gradle/wrapper/gradle-wrapper.jar and b/benchmark-overhead/gradle/wrapper/gradle-wrapper.jar differ diff --git a/benchmark-overhead/gradle/wrapper/gradle-wrapper.properties b/benchmark-overhead/gradle/wrapper/gradle-wrapper.properties index 46671acb6e14..4baf5a11d45a 100644 --- a/benchmark-overhead/gradle/wrapper/gradle-wrapper.properties +++ b/benchmark-overhead/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/benchmark-overhead/gradlew.bat b/benchmark-overhead/gradlew.bat index 93e3f59f135d..25da30dbdeee 100644 --- a/benchmark-overhead/gradlew.bat +++ b/benchmark-overhead/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/conventions/build.gradle.kts b/conventions/build.gradle.kts index 72ba4f25ef79..2ffe59fb4c1b 100644 --- a/conventions/build.gradle.kts +++ b/conventions/build.gradle.kts @@ -1,7 +1,7 @@ plugins { `kotlin-dsl` // When updating, update below in dependencies too - id("com.diffplug.spotless") version "6.22.0" + id("com.diffplug.spotless") version "6.25.0" } spotless { @@ -54,24 +54,24 @@ dependencies { implementation("org.apache.maven:maven-aether-provider:3.3.9") // When updating, update above in plugins too - implementation("com.diffplug.spotless:spotless-plugin-gradle:6.22.0") - implementation("com.google.guava:guava:32.1.3-jre") + implementation("com.diffplug.spotless:spotless-plugin-gradle:6.25.0") + implementation("com.google.guava:guava:33.0.0-jre") implementation("gradle.plugin.com.google.protobuf:protobuf-gradle-plugin:0.8.18") implementation("com.github.johnrengelman:shadow:8.1.1") implementation("org.apache.httpcomponents:httpclient:4.5.14") - implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.15.1") - implementation("org.owasp:dependency-check-gradle:8.4.3") + implementation("com.gradle.enterprise:com.gradle.enterprise.gradle.plugin:3.16.2") + implementation("org.owasp:dependency-check-gradle:9.0.9") implementation("ru.vyarus:gradle-animalsniffer-plugin:1.7.1") // When updating, also update dependencyManagement/build.gradle.kts - implementation("net.bytebuddy:byte-buddy-gradle-plugin:1.14.9") + implementation("net.bytebuddy:byte-buddy-gradle-plugin:1.14.12") implementation("gradle.plugin.io.morethan.jmhreport:gradle-jmh-report:0.9.0") implementation("me.champeau.jmh:jmh-gradle-plugin:0.7.2") implementation("net.ltgt.gradle:gradle-errorprone-plugin:3.1.0") - implementation("net.ltgt.gradle:gradle-nullaway-plugin:1.6.0") + implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.0.0") implementation("me.champeau.gradle:japicmp-gradle-plugin:0.4.2") - testImplementation(enforcedPlatform("org.junit:junit-bom:5.10.1")) + testImplementation(enforcedPlatform("org.junit:junit-bom:5.10.2")) testImplementation("org.junit.jupiter:junit-jupiter-api") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") - testImplementation("org.assertj:assertj-core:3.24.2") + testImplementation("org.assertj:assertj-core:3.25.3") } diff --git a/conventions/src/main/kotlin/otel.japicmp-conventions.gradle.kts b/conventions/src/main/kotlin/otel.japicmp-conventions.gradle.kts index e3fd6ed5d559..b1e371719d53 100644 --- a/conventions/src/main/kotlin/otel.japicmp-conventions.gradle.kts +++ b/conventions/src/main/kotlin/otel.japicmp-conventions.gradle.kts @@ -47,6 +47,10 @@ fun findArtifact(version: String): File { } } +fun getMajorVersion(version: String): Int { + return version.substringBefore('.').toInt() +} + // generate the api diff report for any module that is stable if (project.findProperty("otel.stable") == "true") { afterEvaluate { @@ -66,6 +70,14 @@ if (project.findProperty("otel.stable") == "true") { // the japicmp "old" version is either the user-specified one, or the latest release. val apiBaseVersion: String? by project val baselineVersion = apiBaseVersion ?: latestReleasedVersion + if (apiBaseVersion == null && apiNewVersion == null) { + val baseMajor = getMajorVersion(baselineVersion) + val projectMajor = getMajorVersion(project.version as String) + // disable japicmp when project major version is behind major version of latest release, + // if that is the case we are building a patch for the previous release + enabled = projectMajor >= baseMajor + } + oldClasspath.from( try { files(findArtifact(baselineVersion)) diff --git a/conventions/src/main/kotlin/otel.java-conventions.gradle.kts b/conventions/src/main/kotlin/otel.java-conventions.gradle.kts index bbf30365c6dd..05beac472b52 100644 --- a/conventions/src/main/kotlin/otel.java-conventions.gradle.kts +++ b/conventions/src/main/kotlin/otel.java-conventions.gradle.kts @@ -122,7 +122,7 @@ abstract class NettyAlignmentRule : ComponentMetadataRule { with(ctx.details) { if (id.group == "io.netty" && id.name != "netty") { if (id.version.startsWith("4.1.")) { - belongsTo("io.netty:netty-bom:4.1.100.Final", false) + belongsTo("io.netty:netty-bom:4.1.107.Final", false) } else if (id.version.startsWith("4.0.")) { belongsTo("io.netty:netty-bom:4.0.56.Final", false) } @@ -139,8 +139,8 @@ dependencies { compileOnly("com.google.code.findbugs:jsr305") compileOnly("com.google.errorprone:error_prone_annotations") - codenarc("org.codenarc:CodeNarc:3.3.0") - codenarc(platform("org.codehaus.groovy:groovy-bom:3.0.19")) + codenarc("org.codenarc:CodeNarc:3.4.0") + codenarc(platform("org.codehaus.groovy:groovy-bom:3.0.20")) modules { // checkstyle uses the very old google-collections which causes Java 9 module conflict with @@ -407,7 +407,7 @@ codenarc { checkstyle { configFile = rootProject.file("buildscripts/checkstyle.xml") // this version should match the version of google_checks.xml used as basis for above configuration - toolVersion = "10.12.5" + toolVersion = "10.13.0" maxWarnings = 0 } diff --git a/custom-checks/src/main/java/com/google/errorprone/bugpatterns/checkreturnvalue/CanIgnoreReturnValueSuggesterFactory.java b/custom-checks/src/main/java/com/google/errorprone/bugpatterns/checkreturnvalue/CanIgnoreReturnValueSuggesterFactory.java new file mode 100644 index 000000000000..d157d5fe924a --- /dev/null +++ b/custom-checks/src/main/java/com/google/errorprone/bugpatterns/checkreturnvalue/CanIgnoreReturnValueSuggesterFactory.java @@ -0,0 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.google.errorprone.bugpatterns.checkreturnvalue; + +import com.google.errorprone.ErrorProneFlags; + +public final class CanIgnoreReturnValueSuggesterFactory { + + // calls package private constructor of CanIgnoreReturnValueSuggester + public static CanIgnoreReturnValueSuggester createCanIgnoreReturnValueSuggester( + ErrorProneFlags errorProneFlags) { + return new CanIgnoreReturnValueSuggester(errorProneFlags); + } + + private CanIgnoreReturnValueSuggesterFactory() {} +} diff --git a/custom-checks/src/main/java/io/opentelemetry/javaagent/customchecks/OtelCanIgnoreReturnValueSuggester.java b/custom-checks/src/main/java/io/opentelemetry/javaagent/customchecks/OtelCanIgnoreReturnValueSuggester.java index a41cbc549871..559c6200bc19 100644 --- a/custom-checks/src/main/java/io/opentelemetry/javaagent/customchecks/OtelCanIgnoreReturnValueSuggester.java +++ b/custom-checks/src/main/java/io/opentelemetry/javaagent/customchecks/OtelCanIgnoreReturnValueSuggester.java @@ -13,6 +13,7 @@ import com.google.errorprone.VisitorState; import com.google.errorprone.bugpatterns.BugChecker; import com.google.errorprone.bugpatterns.checkreturnvalue.CanIgnoreReturnValueSuggester; +import com.google.errorprone.bugpatterns.checkreturnvalue.CanIgnoreReturnValueSuggesterFactory; import com.google.errorprone.matchers.Description; import com.google.inject.Inject; import com.sun.source.tree.ClassTree; @@ -33,7 +34,8 @@ public class OtelCanIgnoreReturnValueSuggester extends BugChecker @Inject OtelCanIgnoreReturnValueSuggester(ErrorProneFlags errorProneFlags) { - delegate = new CanIgnoreReturnValueSuggester(errorProneFlags); + delegate = + CanIgnoreReturnValueSuggesterFactory.createCanIgnoreReturnValueSuggester(errorProneFlags); } public OtelCanIgnoreReturnValueSuggester() { diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index f54edbbcc5fd..c4f8716698d2 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -8,11 +8,11 @@ val dependencyVersions = hashMapOf() rootProject.extra["versions"] = dependencyVersions // this line is managed by .github/scripts/update-sdk-version.sh -val otelSdkVersion = "1.32.0" +val otelSdkVersion = "1.34.1" val otelSdkAlphaVersion = otelSdkVersion.replaceFirst("(-SNAPSHOT)?$".toRegex(), "-alpha$1") // Need both BOM and groovy jars -val groovyVersion = "4.0.15" +val groovyVersion = "4.0.18" // We don't force libraries we instrument to new versions since we compile and test against specific // old baseline versions but we do try to force those libraries' transitive dependencies to new @@ -26,25 +26,25 @@ val groovyVersion = "4.0.15" // configurations.testRuntimeClasspath.resolutionStrategy.force "com.google.guava:guava:19.0" val DEPENDENCY_BOMS = listOf( - "com.fasterxml.jackson:jackson-bom:2.15.3", - "com.squareup.okio:okio-bom:3.6.0", // see https://github.com/open-telemetry/opentelemetry-java/issues/5637 - "com.google.guava:guava-bom:32.1.3-jre", + "com.fasterxml.jackson:jackson-bom:2.16.1", + "com.squareup.okio:okio-bom:3.8.0", // see https://github.com/open-telemetry/opentelemetry-java/issues/5637 + "com.google.guava:guava-bom:33.0.0-jre", "org.apache.groovy:groovy-bom:${groovyVersion}", "io.opentelemetry:opentelemetry-bom:${otelSdkVersion}", "io.opentelemetry:opentelemetry-bom-alpha:${otelSdkAlphaVersion}", - "org.junit:junit-bom:5.10.1", - "org.testcontainers:testcontainers-bom:1.19.2", - "org.spockframework:spock-bom:2.4-M1-groovy-4.0" + "org.junit:junit-bom:5.10.2", + "org.testcontainers:testcontainers-bom:1.19.6", + "org.spockframework:spock-bom:2.4-M2-groovy-4.0" ) val autoServiceVersion = "1.1.1" val autoValueVersion = "1.10.4" -val errorProneVersion = "2.23.0" -val byteBuddyVersion = "1.14.9" +val errorProneVersion = "2.25.0" +val byteBuddyVersion = "1.14.12" val asmVersion = "9.6" val jmhVersion = "1.37" val mockitoVersion = "4.11.0" -val slf4jVersion = "2.0.9" +val slf4jVersion = "2.0.12" val CORE_DEPENDENCIES = listOf( "io.opentelemetry.semconv:opentelemetry-semconv:1.21.0-alpha", @@ -79,26 +79,26 @@ val CORE_DEPENDENCIES = listOf( // There are dependencies included here that appear to have no usages, but are maintained at // this top level to help consistently satisfy large numbers of transitive dependencies. val DEPENDENCIES = listOf( - "io.r2dbc:r2dbc-proxy:1.1.2.RELEASE", - "ch.qos.logback:logback-classic:1.3.8", // 1.4+ requires Java 11+ + "io.r2dbc:r2dbc-proxy:1.1.4.RELEASE", + "ch.qos.logback:logback-classic:1.3.14", // 1.4+ requires Java 11+ "com.github.stefanbirkner:system-lambda:1.2.1", "com.github.stefanbirkner:system-rules:1.19.0", "uk.org.webcompere:system-stubs-jupiter:2.0.3", - "com.uber.nullaway:nullaway:0.10.16", + "com.uber.nullaway:nullaway:0.10.23", "commons-beanutils:commons-beanutils:1.9.4", "commons-cli:commons-cli:1.6.0", - "commons-codec:commons-codec:1.16.0", + "commons-codec:commons-codec:1.16.1", "commons-collections:commons-collections:3.2.2", "commons-digester:commons-digester:2.1", "commons-fileupload:commons-fileupload:1.5", - "commons-io:commons-io:2.15.0", + "commons-io:commons-io:2.15.1", "commons-lang:commons-lang:2.6", - "commons-logging:commons-logging:1.2", - "commons-validator:commons-validator:1.7", + "commons-logging:commons-logging:1.3.0", + "commons-validator:commons-validator:1.8.0", "io.netty:netty:3.10.6.Final", "io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:1.28.0-alpha", "io.opentelemetry.proto:opentelemetry-proto:1.0.0-alpha", - "org.assertj:assertj-core:3.24.2", + "org.assertj:assertj-core:3.25.3", "org.awaitility:awaitility:4.2.0", "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", @@ -108,7 +108,7 @@ val DEPENDENCIES = listOf( "org.junit-pioneer:junit-pioneer:1.9.1", "org.objenesis:objenesis:3.3", // Note that this is only referenced as "org.springframework.boot" in build files, not the artifact name. - "org.springframework.boot:spring-boot-dependencies:2.7.17", + "org.springframework.boot:spring-boot-dependencies:2.7.18", "javax.validation:validation-api:2.0.1.Final", "org.snakeyaml:snakeyaml-engine:2.7" ) diff --git a/examples/distro/build.gradle b/examples/distro/build.gradle index d37449efc702..e1f9b3bd1f43 100644 --- a/examples/distro/build.gradle +++ b/examples/distro/build.gradle @@ -12,9 +12,9 @@ buildscript { } } dependencies { - classpath "com.diffplug.spotless:spotless-plugin-gradle:6.22.0" + classpath "com.diffplug.spotless:spotless-plugin-gradle:6.25.0" classpath "gradle.plugin.com.github.johnrengelman:shadow:8.0.0" - classpath "io.opentelemetry.instrumentation:gradle-plugins:1.32.0-alpha-SNAPSHOT" + classpath "io.opentelemetry.instrumentation:gradle-plugins:1.32.1-alpha" } } @@ -27,14 +27,14 @@ subprojects { ext { versions = [ // this line is managed by .github/scripts/update-sdk-version.sh - opentelemetrySdk : "1.32.0", + opentelemetrySdk : "1.34.1", // these lines are managed by .github/scripts/update-version.sh - opentelemetryJavaagent : "1.32.0-SNAPSHOT", - opentelemetryJavaagentAlpha: "1.32.0-alpha-SNAPSHOT", + opentelemetryJavaagent : "1.32.1", + opentelemetryJavaagentAlpha: "1.32.1-alpha", autoservice : "1.1.1", - junit : "5.10.1" + junit : "5.10.2" ] deps = [ @@ -68,7 +68,7 @@ subprojects { implementation(platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:${versions.opentelemetryJavaagent}")) implementation(platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:${versions.opentelemetryJavaagentAlpha}")) - testImplementation("org.mockito:mockito-core:5.7.0") + testImplementation("org.mockito:mockito-core:5.10.0") testImplementation(enforcedPlatform("org.junit:junit-bom:${versions.junit}")) testImplementation("org.junit.jupiter:junit-jupiter-api:${versions.junit}") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${versions.junit}") diff --git a/examples/distro/gradle/instrumentation.gradle b/examples/distro/gradle/instrumentation.gradle index 11c939f5bea2..2284733fea99 100644 --- a/examples/distro/gradle/instrumentation.gradle +++ b/examples/distro/gradle/instrumentation.gradle @@ -25,7 +25,7 @@ dependencies { // test dependencies testImplementation("io.opentelemetry.javaagent:opentelemetry-testing-common") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") - testImplementation("org.assertj:assertj-core:3.24.2") + testImplementation("org.assertj:assertj-core:3.25.3") add("codegen", "io.opentelemetry.javaagent:opentelemetry-javaagent-tooling:${versions.opentelemetryJavaagentAlpha}") add("muzzleBootstrap", "io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations-support:${versions.opentelemetryJavaagentAlpha}") diff --git a/examples/distro/gradle/wrapper/gradle-wrapper.jar b/examples/distro/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b7..d64cd4917707 100644 Binary files a/examples/distro/gradle/wrapper/gradle-wrapper.jar and b/examples/distro/gradle/wrapper/gradle-wrapper.jar differ diff --git a/examples/distro/gradle/wrapper/gradle-wrapper.properties b/examples/distro/gradle/wrapper/gradle-wrapper.properties index 46671acb6e14..4baf5a11d45a 100644 --- a/examples/distro/gradle/wrapper/gradle-wrapper.properties +++ b/examples/distro/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/examples/distro/gradlew.bat b/examples/distro/gradlew.bat index 93e3f59f135d..25da30dbdeee 100644 --- a/examples/distro/gradlew.bat +++ b/examples/distro/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/examples/distro/smoke-tests/build.gradle b/examples/distro/smoke-tests/build.gradle index 38977302f0c0..fc6a38c3b45f 100644 --- a/examples/distro/smoke-tests/build.gradle +++ b/examples/distro/smoke-tests/build.gradle @@ -3,14 +3,14 @@ plugins { } dependencies { - testImplementation("org.testcontainers:testcontainers:1.19.2") - testImplementation("com.fasterxml.jackson.core:jackson-databind:2.15.3") - testImplementation("com.google.protobuf:protobuf-java-util:3.25.1") + testImplementation("org.testcontainers:testcontainers:1.19.6") + testImplementation("com.fasterxml.jackson.core:jackson-databind:2.16.1") + testImplementation("com.google.protobuf:protobuf-java-util:3.25.3") testImplementation("com.squareup.okhttp3:okhttp:4.12.0") testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.0.0-alpha") testImplementation("io.opentelemetry:opentelemetry-api") - testImplementation("ch.qos.logback:logback-classic:1.4.11") + testImplementation("ch.qos.logback:logback-classic:1.5.0") } tasks.test { diff --git a/examples/extension/build.gradle b/examples/extension/build.gradle index 63c4ad256e93..21193e82f573 100644 --- a/examples/extension/build.gradle +++ b/examples/extension/build.gradle @@ -11,10 +11,10 @@ plugins { See https://imperceptiblethoughts.com/shadow/ for more details about Shadow plugin. */ id "com.github.johnrengelman.shadow" version "8.1.1" - id "com.diffplug.spotless" version "6.22.0" + id "com.diffplug.spotless" version "6.25.0" - id "io.opentelemetry.instrumentation.muzzle-generation" version "1.32.0-alpha-SNAPSHOT" - id "io.opentelemetry.instrumentation.muzzle-check" version "1.32.0-alpha-SNAPSHOT" + id "io.opentelemetry.instrumentation.muzzle-generation" version "1.32.1-alpha" + id "io.opentelemetry.instrumentation.muzzle-check" version "1.32.1-alpha" } group 'io.opentelemetry.example' @@ -23,13 +23,13 @@ version '1.0' ext { versions = [ // this line is managed by .github/scripts/update-sdk-version.sh - opentelemetrySdk : "1.32.0", + opentelemetrySdk : "1.34.1", // these lines are managed by .github/scripts/update-version.sh - opentelemetryJavaagent : "1.32.0-SNAPSHOT", - opentelemetryJavaagentAlpha: "1.32.0-alpha-SNAPSHOT", + opentelemetryJavaagent : "1.32.1", + opentelemetryJavaagentAlpha: "1.32.1-alpha", - junit : "5.10.1" + junit : "5.10.2" ] deps = [ @@ -96,19 +96,19 @@ dependencies { Only dependencies added to `implementation` configuration will be picked up by Shadow plugin and added to the resulting jar for our extension's distribution. */ - implementation 'org.apache.commons:commons-lang3:3.13.0' + implementation 'org.apache.commons:commons-lang3:3.14.0' //All dependencies below are only for tests - testImplementation("org.testcontainers:testcontainers:1.19.2") - testImplementation("com.fasterxml.jackson.core:jackson-databind:2.15.3") - testImplementation("com.google.protobuf:protobuf-java-util:3.25.1") + testImplementation("org.testcontainers:testcontainers:1.19.6") + testImplementation("com.fasterxml.jackson.core:jackson-databind:2.16.1") + testImplementation("com.google.protobuf:protobuf-java-util:3.25.3") testImplementation("com.squareup.okhttp3:okhttp:4.12.0") testImplementation("io.opentelemetry:opentelemetry-api") testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.0.0-alpha") testImplementation("org.junit.jupiter:junit-jupiter-api:${versions.junit}") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${versions.junit}") - testRuntimeOnly("ch.qos.logback:logback-classic:1.4.11") + testRuntimeOnly("ch.qos.logback:logback-classic:1.5.0") //Otel Java instrumentation that we use and extend during integration tests otel("io.opentelemetry.javaagent:opentelemetry-javaagent:${versions.opentelemetryJavaagent}") diff --git a/examples/extension/gradle/wrapper/gradle-wrapper.jar b/examples/extension/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b7..d64cd4917707 100644 Binary files a/examples/extension/gradle/wrapper/gradle-wrapper.jar and b/examples/extension/gradle/wrapper/gradle-wrapper.jar differ diff --git a/examples/extension/gradle/wrapper/gradle-wrapper.properties b/examples/extension/gradle/wrapper/gradle-wrapper.properties index 46671acb6e14..4baf5a11d45a 100644 --- a/examples/extension/gradle/wrapper/gradle-wrapper.properties +++ b/examples/extension/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/examples/extension/gradlew.bat b/examples/extension/gradlew.bat index 93e3f59f135d..25da30dbdeee 100644 --- a/examples/extension/gradlew.bat +++ b/examples/extension/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/gradle-plugins/build.gradle.kts b/gradle-plugins/build.gradle.kts index 304805464f5b..a98367ce157d 100644 --- a/gradle-plugins/build.gradle.kts +++ b/gradle-plugins/build.gradle.kts @@ -24,11 +24,11 @@ configurations.named("compileOnly") { extendsFrom(bbGradlePlugin) } -val byteBuddyVersion = "1.14.9" +val byteBuddyVersion = "1.14.12" val aetherVersion = "1.1.0" dependencies { - implementation("com.google.guava:guava:32.1.3-jre") + implementation("com.google.guava:guava:33.0.0-jre") // we need to use byte buddy variant that does not shade asm implementation("net.bytebuddy:byte-buddy-gradle-plugin:${byteBuddyVersion}") { exclude(group = "net.bytebuddy", module = "byte-buddy") @@ -41,9 +41,9 @@ dependencies { implementation("gradle.plugin.com.github.johnrengelman:shadow:8.0.0") - testImplementation("org.assertj:assertj-core:3.24.2") + testImplementation("org.assertj:assertj-core:3.25.3") - testImplementation(enforcedPlatform("org.junit:junit-bom:5.10.1")) + testImplementation(enforcedPlatform("org.junit:junit-bom:5.10.2")) testImplementation("org.junit.jupiter:junit-jupiter-api") testImplementation("org.junit.jupiter:junit-jupiter-params") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") diff --git a/gradle-plugins/gradle/wrapper/gradle-wrapper.jar b/gradle-plugins/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b7..d64cd4917707 100644 Binary files a/gradle-plugins/gradle/wrapper/gradle-wrapper.jar and b/gradle-plugins/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle-plugins/gradle/wrapper/gradle-wrapper.properties b/gradle-plugins/gradle/wrapper/gradle-wrapper.properties index 46671acb6e14..4baf5a11d45a 100644 --- a/gradle-plugins/gradle/wrapper/gradle-wrapper.properties +++ b/gradle-plugins/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradle-plugins/gradlew.bat b/gradle-plugins/gradlew.bat index 93e3f59f135d..25da30dbdeee 100644 --- a/gradle-plugins/gradlew.bat +++ b/gradle-plugins/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/gradle-plugins/settings.gradle.kts b/gradle-plugins/settings.gradle.kts index a28df395ff7d..46959d2ec5d2 100644 --- a/gradle-plugins/settings.gradle.kts +++ b/gradle-plugins/settings.gradle.kts @@ -6,5 +6,5 @@ pluginManagement { } plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0" + id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" } diff --git a/gradle-plugins/src/main/kotlin/io/opentelemetry/javaagent/muzzle/AcceptableVersions.kt b/gradle-plugins/src/main/kotlin/io/opentelemetry/javaagent/muzzle/AcceptableVersions.kt index fa43a08e7405..6271152efb47 100644 --- a/gradle-plugins/src/main/kotlin/io/opentelemetry/javaagent/muzzle/AcceptableVersions.kt +++ b/gradle-plugins/src/main/kotlin/io/opentelemetry/javaagent/muzzle/AcceptableVersions.kt @@ -33,6 +33,7 @@ class AcceptableVersions(private val skipVersions: Collection) : || versionString.contains("public_draft") || versionString.contains("snapshot") || versionString.contains("test") + || versionString.startsWith("0.0.0-") || GIT_SHA_PATTERN.matches(versionString) || DATETIME_PATTERN.matches(versionString) return !draftVersion diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135c49b7..d64cd4917707 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 46671acb6e14..4baf5a11d45a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionSha256Sum=9631d53cf3e74bfa726893aee1f8994fee4e060c401335946dba2156f440f24c +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f135d..25da30dbdeee 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerRoute.java b/instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerRoute.java index 2d1dab9ca1d7..094bc2948a36 100644 --- a/instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerRoute.java +++ b/instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerRoute.java @@ -10,7 +10,6 @@ import io.opentelemetry.instrumentation.api.instrumenter.ContextCustomizer; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan; import io.opentelemetry.instrumentation.api.internal.HttpRouteState; import javax.annotation.Nullable; @@ -95,16 +94,17 @@ public static void update( HttpServerRouteBiGetter httpRouteGetter, T arg1, U arg2) { - Span serverSpan = LocalRootSpan.fromContextOrNull(context); + HttpRouteState httpRouteState = HttpRouteState.fromContextOrNull(context); + if (httpRouteState == null) { + return; + } + Span serverSpan = httpRouteState.getSpan(); // even if the server span is not sampled, we have to continue - we need to compute the // http.route properly so that it can be captured by the server metrics if (serverSpan == null) { return; } - HttpRouteState httpRouteState = HttpRouteState.fromContextOrNull(context); - if (httpRouteState == null) { - return; - } + // special case for servlet filters, even when we have a route from previous filter see whether // the new route is better and if so use it instead boolean onlyIfBetterRoute = diff --git a/instrumentation-api-semconv/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerRouteTest.java b/instrumentation-api-semconv/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerRouteTest.java index 4df036ad27cb..b9d634827f78 100644 --- a/instrumentation-api-semconv/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerRouteTest.java +++ b/instrumentation-api-semconv/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerRouteTest.java @@ -12,6 +12,7 @@ import static org.mockito.Mockito.when; import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; @@ -39,7 +40,7 @@ void setUp() { HttpServerRoute.builder(getter) .setKnownMethods(new HashSet<>(singletonList("GET"))) .build()) - .buildInstrumenter(); + .buildInstrumenter(s -> SpanKind.SERVER); } @Test @@ -61,6 +62,27 @@ void noLocalRootSpan() { span -> assertThat(span).hasName("parent"), span -> assertThat(span).hasName("test")); } + @Test + void nonServerRootSpan() { + Instrumenter testInstrumenter = + Instrumenter.builder(testing.getOpenTelemetry(), "test", s -> s) + .addContextCustomizer( + HttpServerRoute.builder(getter) + .setKnownMethods(new HashSet<>(singletonList("GET"))) + .build()) + .buildInstrumenter(s -> SpanKind.INTERNAL); + + Context context = testInstrumenter.start(Context.root(), "test"); + assertNull(HttpServerRoute.get(context)); + + HttpServerRoute.update(context, HttpServerRouteSource.SERVER, "/get/:id"); + + testInstrumenter.end(context, "test", null, null); + + assertNull(HttpServerRoute.get(context)); + assertThat(testing.getSpans()).satisfiesExactly(span -> assertThat(span).hasName("test")); + } + @Test void shouldSetRoute() { when(getter.getHttpRequestMethod("test")).thenReturn("GET"); diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/Instrumenter.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/Instrumenter.java index 97f523bea61f..0d4ed4eedda4 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/Instrumenter.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/Instrumenter.java @@ -11,6 +11,7 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.internal.HttpRouteState; import io.opentelemetry.instrumentation.api.internal.InstrumenterAccess; import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil; import io.opentelemetry.instrumentation.api.internal.SupportabilityMetrics; @@ -203,6 +204,9 @@ private Context doStart(Context parentContext, REQUEST request, @Nullable Instan if (localRoot) { context = LocalRootSpan.store(context, span); + if (spanKind == SpanKind.SERVER) { + HttpRouteState.updateSpan(context, span); + } } return spanSuppressor.storeInContext(context, spanKind, span); diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/HttpRouteState.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/HttpRouteState.java index 0eda2755da92..afd023467c16 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/HttpRouteState.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/HttpRouteState.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.api.internal; +import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.context.ContextKey; import io.opentelemetry.context.ImplicitContextKeyed; @@ -24,20 +25,36 @@ public static HttpRouteState fromContextOrNull(Context context) { return context.get(KEY); } + public static void updateSpan(Context context, Span span) { + HttpRouteState state = fromContextOrNull(context); + if (state != null) { + state.span = span; + } + } + + // this method is used reflectively from InstrumentationApiContextBridging public static HttpRouteState create( @Nullable String method, @Nullable String route, int updatedBySourceOrder) { - return new HttpRouteState(method, route, updatedBySourceOrder); + return create(method, route, updatedBySourceOrder, null); + } + + // this method is used reflectively from InstrumentationApiContextBridging + public static HttpRouteState create( + @Nullable String method, @Nullable String route, int updatedBySourceOrder, Span span) { + return new HttpRouteState(method, route, updatedBySourceOrder, span); } @Nullable private final String method; @Nullable private volatile String route; private volatile int updatedBySourceOrder; + @Nullable private volatile Span span; private HttpRouteState( - @Nullable String method, @Nullable String route, int updatedBySourceOrder) { + @Nullable String method, @Nullable String route, int updatedBySourceOrder, Span span) { this.method = method; this.updatedBySourceOrder = updatedBySourceOrder; this.route = route; + this.span = span; } @Override @@ -59,6 +76,11 @@ public String getRoute() { return route; } + @Nullable + public Span getSpan() { + return span; + } + public void update( @SuppressWarnings("unused") Context context, // context is used by the javaagent bridge instrumentation diff --git a/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/build.gradle.kts b/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/build.gradle.kts index f594bab91e72..db08d0675a96 100644 --- a/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/build.gradle.kts +++ b/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/build.gradle.kts @@ -15,6 +15,10 @@ dependencies { } tasks { + withType().configureEach { + systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) + } + val testStableSemconv by registering(Test::class) { jvmArgs("-Dotel.semconv-stability.opt-in=http") } diff --git a/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/RequestWithHost.java b/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/RequestWithHost.java index 6fd5767e83a8..e18de7e6d035 100644 --- a/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/RequestWithHost.java +++ b/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/RequestWithHost.java @@ -19,9 +19,13 @@ public class RequestWithHost extends HttpRequestWrapper implements ClassicHttpRe public RequestWithHost(HttpHost httpHost, ClassicHttpRequest httpRequest) { super(httpRequest); - - this.scheme = httpHost.getSchemeName(); - this.authority = new URIAuthority(httpHost.getHostName(), httpHost.getPort()); + if (httpHost != null) { + this.scheme = httpHost.getSchemeName(); + this.authority = new URIAuthority(httpHost.getHostName(), httpHost.getPort()); + } else { + this.scheme = httpRequest.getScheme(); + this.authority = httpRequest.getAuthority(); + } } @Override diff --git a/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/ApacheHttpClientTest.java b/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/ApacheHttpClientTest.java index cea57cc51900..e76b1ae75821 100644 --- a/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/ApacheHttpClientTest.java +++ b/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/ApacheHttpClientTest.java @@ -20,6 +20,7 @@ import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.io.HttpClientResponseHandler; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; @@ -90,6 +91,26 @@ void executeRequestWithCallback(ClassicHttpRequest request, URI uri, HttpClientR } } + @Nested + class ApacheClientNullHttpHostRequestTest extends AbstractTest { + @Override + ClassicHttpRequest createRequest(String method, URI uri) { + // also testing with an absolute path below + return new BasicClassicHttpRequest(method, HttpHost.create(uri), fullPathFromUri(uri)); + } + + @Override + ClassicHttpResponse doExecuteRequest(ClassicHttpRequest request, URI uri) throws Exception { + return getClient(uri).execute(null, request); + } + + @Override + void executeRequestWithCallback(ClassicHttpRequest request, URI uri, HttpClientResult result) + throws Exception { + getClient(uri).execute(null, request, new ResponseHandler(result)); + } + } + @Nested class ApacheClientHostAbsoluteUriRequestTest extends AbstractTest { @Override @@ -202,6 +223,11 @@ protected void configure(HttpClientTestOptions.Builder optionsBuilder) { super.configure(optionsBuilder); // apparently apache http client does not report the 302 status code? optionsBuilder.setResponseCodeOnRedirectError(null); + + if (Boolean.getBoolean("testLatestDeps")) { + optionsBuilder.disableTestHttps(); + optionsBuilder.disableTestRemoteConnection(); + } } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts index 87b5a3ee9062..fa90530579e1 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts @@ -47,6 +47,14 @@ dependencies { testLibrary("com.amazonaws:aws-java-sdk-kinesis:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-dynamodb:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-sns:1.11.106") + testLibrary("com.amazonaws:aws-java-sdk-sqs:1.11.106") + testLibrary("com.amazonaws:aws-java-sdk-secretsmanager:1.11.309") + testLibrary("com.amazonaws:aws-java-sdk-stepfunctions:1.11.230") + testLibrary("com.amazonaws:aws-java-sdk-lambda:1.11.678") + testLibrary("com.amazonaws:aws-java-sdk-bedrock:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagent:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagentruntime:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockruntime:1.12.744") testImplementation(project(":instrumentation:aws-sdk:aws-sdk-1.11:testing")) @@ -150,3 +158,16 @@ tasks { systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) } } + +if (!(findProperty("testLatestDeps") as Boolean)) { + configurations.testRuntimeClasspath { + resolutionStrategy { + eachDependency { + // early versions of aws sdk are not compatible with jackson 2.16.0 + if (requested.group.startsWith("com.fasterxml.jackson")) { + useVersion("2.15.3") + } + } + } + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java index d5ba3d2c5add..d5c571932c34 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java @@ -20,7 +20,7 @@ public AwsSdkInstrumentationModule() { @Override public boolean isHelperClass(String className) { - return className.startsWith("io.opentelemetry.contrib.awsxray."); + return className.startsWith("io.opentelemetry.contrib.awsxray.") || className.startsWith("com.fasterxml.jackson"); } @Override diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/S3TracingTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/S3TracingTest.groovy index 987a50ed9576..889c856a7c51 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/S3TracingTest.groovy +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/S3TracingTest.groovy @@ -444,6 +444,7 @@ class S3TracingTest extends AgentInstrumentationSpecification { "net.peer.port" { it == null || Number } "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long } "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long } + "aws.sns.topic.arn" "$topicArn" } } } @@ -467,6 +468,7 @@ class S3TracingTest extends AgentInstrumentationSpecification { "net.peer.port" { it == null || Number } "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long } "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long } + "aws.sns.topic.arn" "$topicArn" } } } @@ -514,6 +516,7 @@ class S3TracingTest extends AgentInstrumentationSpecification { "net.peer.port" { it == null || Number } "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" { it == null || it instanceof Long } "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" { it == null || it instanceof Long } + "aws.sns.topic.arn" "$topicArn" } } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/SnsTracingTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/SnsTracingTest.groovy index 97749cf0857f..a0b83ca870d5 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/SnsTracingTest.groovy +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/SnsTracingTest.groovy @@ -131,6 +131,7 @@ class SnsTracingTest extends AgentInstrumentationSpecification { "$SemanticAttributes.NET_PROTOCOL_VERSION" "1.1" "net.peer.port" { it == null || Number } "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long + "aws.sns.topic.arn" "$topicArn" } } } @@ -154,6 +155,7 @@ class SnsTracingTest extends AgentInstrumentationSpecification { "$SemanticAttributes.NET_PROTOCOL_VERSION" "1.1" "net.peer.port" { it == null || Number } "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long + "aws.sns.topic.arn" "$topicArn" } } } @@ -176,6 +178,7 @@ class SnsTracingTest extends AgentInstrumentationSpecification { "$SemanticAttributes.NET_PROTOCOL_VERSION" "1.1" "net.peer.port" { it == null || Number } "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long + "aws.sns.topic.arn" "$topicArn" } } span(1) { diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/build.gradle.kts index f12de2b7f8b7..37056341532a 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/build.gradle.kts @@ -18,6 +18,13 @@ dependencies { testLibrary("com.amazonaws:aws-java-sdk-dynamodb:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-sns:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-sqs:1.11.106") + testLibrary("com.amazonaws:aws-java-sdk-secretsmanager:1.11.309") + testLibrary("com.amazonaws:aws-java-sdk-stepfunctions:1.11.230") + testLibrary("com.amazonaws:aws-java-sdk-lambda:1.11.678") + testLibrary("com.amazonaws:aws-java-sdk-bedrock:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagent:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagentruntime:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockruntime:1.12.744") // last version that does not use json protocol latestDepTestLibrary("com.amazonaws:aws-java-sdk-sqs:1.12.583") @@ -47,3 +54,16 @@ tasks { dependsOn(testReceiveSpansDisabled) } } + +if (!(findProperty("testLatestDeps") as Boolean)) { + configurations.testRuntimeClasspath { + resolutionStrategy { + eachDependency { + // early versions of aws sdk are not compatible with jackson 2.16.0 + if (requested.group.startsWith("com.fasterxml.jackson")) { + useVersion("2.15.3") + } + } + } + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts index cf76b0521767..dec4935b55f6 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts @@ -17,7 +17,28 @@ dependencies { testLibrary("com.amazonaws:aws-java-sdk-kinesis:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-dynamodb:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-sns:1.11.106") + testLibrary("com.amazonaws:aws-java-sdk-sqs:1.11.106") + testLibrary("com.amazonaws:aws-java-sdk-secretsmanager:1.11.309") + testLibrary("com.amazonaws:aws-java-sdk-stepfunctions:1.11.230") + testLibrary("com.amazonaws:aws-java-sdk-lambda:1.11.678") + testLibrary("com.amazonaws:aws-java-sdk-bedrock:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagent:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockagentruntime:1.12.744") + testLibrary("com.amazonaws:aws-java-sdk-bedrockruntime:1.12.744") // last version that does not use json protocol latestDepTestLibrary("com.amazonaws:aws-java-sdk-sqs:1.12.583") } + +if (!(findProperty("testLatestDeps") as Boolean)) { + configurations.testRuntimeClasspath { + resolutionStrategy { + eachDependency { + // early versions of aws sdk are not compatible with jackson 2.16.0 + if (requested.group.startsWith("com.fasterxml.jackson")) { + useVersion("2.15.3") + } + } + } + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsBedrockResourceType.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsBedrockResourceType.java new file mode 100644 index 000000000000..e890cb3c0f46 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsBedrockResourceType.java @@ -0,0 +1,133 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v1_11; + +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_AGENT_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_DATA_SOURCE_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_KNOWLEDGE_BASE_ID; + +import io.opentelemetry.api.common.AttributeKey; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +enum AwsBedrockResourceType { + AGENT_TYPE(AWS_AGENT_ID, RequestAccess::getAgentId), + DATA_SOURCE_TYPE(AWS_DATA_SOURCE_ID, RequestAccess::getDataSourceId), + KNOWLEDGE_BASE_TYPE(AWS_KNOWLEDGE_BASE_ID, RequestAccess::getKnowledgeBaseId); + + @SuppressWarnings("ImmutableEnumChecker") + private final AttributeKey keyAttribute; + + @SuppressWarnings("ImmutableEnumChecker") + private final Function attributeValueAccessor; + + AwsBedrockResourceType( + AttributeKey keyAttribute, Function attributeValueAccessor) { + this.keyAttribute = keyAttribute; + this.attributeValueAccessor = attributeValueAccessor; + } + + public AttributeKey getKeyAttribute() { + return keyAttribute; + } + + public Function getAttributeValueAccessor() { + return attributeValueAccessor; + } + + public static AwsBedrockResourceType getRequestType(String requestClass) { + return AwsBedrockResourceTypeMap.BEDROCK_REQUEST_MAP.get(requestClass); + } + + public static AwsBedrockResourceType getResponseType(String responseClass) { + return AwsBedrockResourceTypeMap.BEDROCK_RESPONSE_MAP.get(responseClass); + } + + private static class AwsBedrockResourceTypeMap { + private static final Map BEDROCK_REQUEST_MAP = new HashMap<>(); + private static final Map BEDROCK_RESPONSE_MAP = new HashMap<>(); + + // Bedrock request/response mapping + // We only support operations that are related to the resource and where the context contains + // the AgentID/DataSourceID/KnowledgeBaseID. + // AgentID + private static final List agentRequestClasses = + Arrays.asList( + "CreateAgentActionGroupRequest", + "CreateAgentAliasRequest", + "DeleteAgentActionGroupRequest", + "DeleteAgentAliasRequest", + "DeleteAgentRequest", + "DeleteAgentVersionRequest", + "GetAgentActionGroupRequest", + "GetAgentAliasRequest", + "GetAgentRequest", + "GetAgentVersionRequest", + "ListAgentActionGroupsRequest", + "ListAgentAliasesRequest", + "ListAgentKnowledgeBasesRequest", + "ListAgentVersionsRequest", + "PrepareAgentRequest", + "UpdateAgentActionGroupRequest", + "UpdateAgentAliasRequest", + "UpdateAgentRequest"); + private static final List agentResponseClasses = + Arrays.asList( + "DeleteAgentAliasResult", + "DeleteAgentResult", + "DeleteAgentVersionResult", + "PrepareAgentResult"); + // DataSourceID + private static final List dataSourceRequestClasses = + Arrays.asList("DeleteDataSourceRequest", "GetDataSourceRequest", "UpdateDataSourceRequest"); + private static final List dataSourceResponseClasses = + Arrays.asList("DeleteDataSourceResult"); + // KnowledgeBaseID + private static final List knowledgeBaseRequestClasses = + Arrays.asList( + "AssociateAgentKnowledgeBaseRequest", + "CreateDataSourceRequest", + "DeleteKnowledgeBaseRequest", + "DisassociateAgentKnowledgeBaseRequest", + "GetAgentKnowledgeBaseRequest", + "GetKnowledgeBaseRequest", + "ListDataSourcesRequest", + "UpdateAgentKnowledgeBaseRequest"); + private static final List knowledgeBaseResponseClasses = + Arrays.asList("DeleteKnowledgeBaseResult"); + + private AwsBedrockResourceTypeMap() {} + + static { + // Populate the BEDROCK_REQUEST_MAP + for (String agentRequestClass : agentRequestClasses) { + BEDROCK_REQUEST_MAP.put(agentRequestClass, AwsBedrockResourceType.AGENT_TYPE); + } + for (String dataSourceRequestClass : dataSourceRequestClasses) { + BEDROCK_REQUEST_MAP.put(dataSourceRequestClass, AwsBedrockResourceType.DATA_SOURCE_TYPE); + } + for (String knowledgeBaseRequestClass : knowledgeBaseRequestClasses) { + BEDROCK_REQUEST_MAP.put( + knowledgeBaseRequestClass, AwsBedrockResourceType.KNOWLEDGE_BASE_TYPE); + } + + // Populate the BEDROCK_RESPONSE_MAP + for (String agentResponseClass : agentResponseClasses) { + BEDROCK_REQUEST_MAP.put(agentResponseClass, AwsBedrockResourceType.AGENT_TYPE); + } + for (String dataSourceResponseClass : dataSourceResponseClasses) { + BEDROCK_REQUEST_MAP.put(dataSourceResponseClass, AwsBedrockResourceType.DATA_SOURCE_TYPE); + } + for (String knowledgeBaseResponseClass : knowledgeBaseResponseClasses) { + BEDROCK_REQUEST_MAP.put( + knowledgeBaseResponseClass, AwsBedrockResourceType.KNOWLEDGE_BASE_TYPE); + } + } + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsExperimentalAttributes.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsExperimentalAttributes.java index 3e8fddec5c15..8f86a67b3918 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsExperimentalAttributes.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsExperimentalAttributes.java @@ -18,6 +18,49 @@ final class AwsExperimentalAttributes { static final AttributeKey AWS_STREAM_NAME = stringKey("aws.stream.name"); static final AttributeKey AWS_TABLE_NAME = stringKey("aws.table.name"); static final AttributeKey AWS_REQUEST_ID = stringKey("aws.requestId"); + static final AttributeKey AWS_AGENT_ID = stringKey("aws.bedrock.agent.id"); + static final AttributeKey AWS_KNOWLEDGE_BASE_ID = + stringKey("aws.bedrock.knowledge_base.id"); + static final AttributeKey AWS_DATA_SOURCE_ID = stringKey("aws.bedrock.data_source.id"); + static final AttributeKey AWS_GUARDRAIL_ID = stringKey("aws.bedrock.guardrail.id"); + static final AttributeKey AWS_GUARDRAIL_ARN = stringKey("aws.bedrock.guardrail.arn"); + + // TODO: Merge in gen_ai attributes in opentelemetry-semconv-incubating once upgrade to v1.26.0 + static final AttributeKey AWS_BEDROCK_RUNTIME_MODEL_ID = + stringKey("gen_ai.request.model"); + static final AttributeKey AWS_BEDROCK_SYSTEM = stringKey("gen_ai.system"); + + static final AttributeKey GEN_AI_REQUEST_MAX_TOKENS = + stringKey("gen_ai.request.max_tokens"); + + static final AttributeKey GEN_AI_REQUEST_TEMPERATURE = + stringKey("gen_ai.request.temperature"); + + static final AttributeKey GEN_AI_REQUEST_TOP_P = stringKey("gen_ai.request.top_p"); + + static final AttributeKey GEN_AI_RESPONSE_FINISH_REASONS = + stringKey("gen_ai.response.finish_reasons"); + + static final AttributeKey GEN_AI_USAGE_INPUT_TOKENS = + stringKey("gen_ai.usage.input_tokens"); + + static final AttributeKey GEN_AI_USAGE_OUTPUT_TOKENS = + stringKey("gen_ai.usage.output_tokens"); + + static final AttributeKey AWS_STATE_MACHINE_ARN = + stringKey("aws.stepfunctions.state_machine.arn"); + + static final AttributeKey AWS_STEP_FUNCTIONS_ACTIVITY_ARN = + stringKey("aws.stepfunctions.activity.arn"); + + static final AttributeKey AWS_SNS_TOPIC_ARN = stringKey("aws.sns.topic.arn"); + + static final AttributeKey AWS_SECRET_ARN = stringKey("aws.secretsmanager.secret.arn"); + + static final AttributeKey AWS_LAMBDA_NAME = stringKey("aws.lambda.function.name"); + + static final AttributeKey AWS_LAMBDA_RESOURCE_ID = + stringKey("aws.lambda.resource_mapping.id"); private AwsExperimentalAttributes() {} } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkExperimentalAttributesExtractor.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkExperimentalAttributesExtractor.java index 245f09a5d8f5..aef793698044 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkExperimentalAttributesExtractor.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AwsSdkExperimentalAttributesExtractor.java @@ -6,13 +6,31 @@ package io.opentelemetry.instrumentation.awssdk.v1_11; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_AGENT; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_AGENT_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_BEDROCK_RUNTIME_MODEL_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_BEDROCK_SYSTEM; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_BUCKET_NAME; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_ENDPOINT; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_GUARDRAIL_ARN; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_GUARDRAIL_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_KNOWLEDGE_BASE_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_LAMBDA_NAME; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_LAMBDA_RESOURCE_ID; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_QUEUE_NAME; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_QUEUE_URL; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_REQUEST_ID; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_SECRET_ARN; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_SNS_TOPIC_ARN; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_STATE_MACHINE_ARN; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_STEP_FUNCTIONS_ACTIVITY_ARN; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_STREAM_NAME; import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.AWS_TABLE_NAME; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.GEN_AI_REQUEST_MAX_TOKENS; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.GEN_AI_REQUEST_TEMPERATURE; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.GEN_AI_REQUEST_TOP_P; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.GEN_AI_RESPONSE_FINISH_REASONS; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.GEN_AI_USAGE_INPUT_TOKENS; +import static io.opentelemetry.instrumentation.awssdk.v1_11.AwsExperimentalAttributes.GEN_AI_USAGE_OUTPUT_TOKENS; import com.amazonaws.AmazonWebServiceResponse; import com.amazonaws.Request; @@ -21,12 +39,17 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import java.util.Objects; import java.util.function.Function; import javax.annotation.Nullable; class AwsSdkExperimentalAttributesExtractor implements AttributesExtractor, Response> { private static final String COMPONENT_NAME = "java-aws-sdk"; + private static final String BEDROCK_SERVICE = "AmazonBedrock"; + private static final String BEDROCK_AGENT_SERVICE = "AWSBedrockAgent"; + private static final String BEDROCK_AGENT_RUNTIME_SERVICE = "AWSBedrockAgentRuntime"; + private static final String BEDROCK_RUNTIME_SERVICE = "AmazonBedrockRuntime"; @Override public void onStart(AttributesBuilder attributes, Context parentContext, Request request) { @@ -34,21 +57,30 @@ public void onStart(AttributesBuilder attributes, Context parentContext, Request attributes.put(AWS_ENDPOINT, request.getEndpoint().toString()); Object originalRequest = request.getOriginalRequest(); - setRequestAttribute(attributes, AWS_BUCKET_NAME, originalRequest, RequestAccess::getBucketName); - setRequestAttribute(attributes, AWS_QUEUE_URL, originalRequest, RequestAccess::getQueueUrl); - setRequestAttribute(attributes, AWS_QUEUE_NAME, originalRequest, RequestAccess::getQueueName); - setRequestAttribute(attributes, AWS_STREAM_NAME, originalRequest, RequestAccess::getStreamName); - setRequestAttribute(attributes, AWS_TABLE_NAME, originalRequest, RequestAccess::getTableName); - } + String requestClassName = originalRequest.getClass().getSimpleName(); + setAttribute(attributes, AWS_BUCKET_NAME, originalRequest, RequestAccess::getBucketName); + setAttribute(attributes, AWS_QUEUE_URL, originalRequest, RequestAccess::getQueueUrl); + setAttribute(attributes, AWS_QUEUE_NAME, originalRequest, RequestAccess::getQueueName); + setAttribute(attributes, AWS_STREAM_NAME, originalRequest, RequestAccess::getStreamName); + setAttribute(attributes, AWS_TABLE_NAME, originalRequest, RequestAccess::getTableName); + setAttribute( + attributes, AWS_STATE_MACHINE_ARN, originalRequest, RequestAccess::getStateMachineArn); + setAttribute( + attributes, + AWS_STEP_FUNCTIONS_ACTIVITY_ARN, + originalRequest, + RequestAccess::getStepFunctionsActivityArn); + setAttribute(attributes, AWS_SNS_TOPIC_ARN, originalRequest, RequestAccess::getSnsTopicArn); + setAttribute(attributes, AWS_SECRET_ARN, originalRequest, RequestAccess::getSecretArn); + setAttribute(attributes, AWS_LAMBDA_NAME, originalRequest, RequestAccess::getLambdaName); + setAttribute( + attributes, AWS_LAMBDA_RESOURCE_ID, originalRequest, RequestAccess::getLambdaResourceId); - private static void setRequestAttribute( - AttributesBuilder attributes, - AttributeKey key, - Object request, - Function getter) { - String value = getter.apply(request); - if (value != null) { - attributes.put(key, value); + // Get serviceName defined in the AWS Java SDK V1 Request class. + String serviceName = request.getServiceName(); + // Extract request attributes only for Bedrock services. + if (isBedrockService(serviceName)) { + bedrockOnStart(attributes, originalRequest, requestClassName, serviceName); } } @@ -59,12 +91,136 @@ public void onEnd( Request request, @Nullable Response response, @Nullable Throwable error) { - if (response != null && response.getAwsResponse() instanceof AmazonWebServiceResponse) { - AmazonWebServiceResponse awsResp = (AmazonWebServiceResponse) response.getAwsResponse(); - String requestId = awsResp.getRequestId(); - if (requestId != null) { - attributes.put(AWS_REQUEST_ID, requestId); + if (response != null) { + Object awsResp = response.getAwsResponse(); + setAttribute(attributes, AWS_STATE_MACHINE_ARN, awsResp, RequestAccess::getStateMachineArn); + setAttribute( + attributes, + AWS_STEP_FUNCTIONS_ACTIVITY_ARN, + awsResp, + RequestAccess::getStepFunctionsActivityArn); + setAttribute(attributes, AWS_SNS_TOPIC_ARN, awsResp, RequestAccess::getSnsTopicArn); + setAttribute(attributes, AWS_SECRET_ARN, awsResp, RequestAccess::getSecretArn); + if (awsResp instanceof AmazonWebServiceResponse) { + AmazonWebServiceResponse awsWebServiceResponse = (AmazonWebServiceResponse) awsResp; + String requestId = awsWebServiceResponse.getRequestId(); + if (requestId != null) { + attributes.put(AWS_REQUEST_ID, requestId); + } } + // Get serviceName defined in the AWS Java SDK V1 Request class. + String serviceName = request.getServiceName(); + // Extract response attributes for Bedrock services + if (awsResp != null && isBedrockService(serviceName)) { + bedrockOnEnd(attributes, awsResp, serviceName); + } + } + } + + private static void bedrockOnStart( + AttributesBuilder attributes, + Object originalRequest, + String requestClassName, + String serviceName) { + switch (serviceName) { + case BEDROCK_SERVICE: + setAttribute(attributes, AWS_GUARDRAIL_ID, originalRequest, RequestAccess::getGuardrailId); + break; + case BEDROCK_AGENT_SERVICE: + AwsBedrockResourceType resourceType = + AwsBedrockResourceType.getRequestType(requestClassName); + if (resourceType != null) { + setAttribute( + attributes, + resourceType.getKeyAttribute(), + originalRequest, + resourceType.getAttributeValueAccessor()); + } + break; + case BEDROCK_AGENT_RUNTIME_SERVICE: + setAttribute(attributes, AWS_AGENT_ID, originalRequest, RequestAccess::getAgentId); + setAttribute( + attributes, AWS_KNOWLEDGE_BASE_ID, originalRequest, RequestAccess::getKnowledgeBaseId); + break; + case BEDROCK_RUNTIME_SERVICE: + if (!Objects.equals(requestClassName, "InvokeModelRequest")) { + break; + } + attributes.put(AWS_BEDROCK_SYSTEM, "aws_bedrock"); + Function getter = RequestAccess::getModelId; + String modelId = getter.apply(originalRequest); + attributes.put(AWS_BEDROCK_RUNTIME_MODEL_ID, modelId); + + setAttribute( + attributes, GEN_AI_REQUEST_MAX_TOKENS, originalRequest, RequestAccess::getMaxTokens); + setAttribute( + attributes, GEN_AI_REQUEST_TEMPERATURE, originalRequest, RequestAccess::getTemperature); + setAttribute(attributes, GEN_AI_REQUEST_TOP_P, originalRequest, RequestAccess::getTopP); + setAttribute( + attributes, GEN_AI_USAGE_INPUT_TOKENS, originalRequest, RequestAccess::getInputTokens); + break; + default: + break; + } + } + + private static void bedrockOnEnd( + AttributesBuilder attributes, Object awsResp, String serviceName) { + switch (serviceName) { + case BEDROCK_SERVICE: + setAttribute(attributes, AWS_GUARDRAIL_ID, awsResp, RequestAccess::getGuardrailId); + setAttribute(attributes, AWS_GUARDRAIL_ARN, awsResp, RequestAccess::getGuardrailArn); + break; + case BEDROCK_AGENT_SERVICE: + String responseClassName = awsResp.getClass().getSimpleName(); + AwsBedrockResourceType resourceType = + AwsBedrockResourceType.getResponseType(responseClassName); + if (resourceType != null) { + setAttribute( + attributes, + resourceType.getKeyAttribute(), + awsResp, + resourceType.getAttributeValueAccessor()); + } + break; + case BEDROCK_AGENT_RUNTIME_SERVICE: + setAttribute(attributes, AWS_AGENT_ID, awsResp, RequestAccess::getAgentId); + setAttribute(attributes, AWS_KNOWLEDGE_BASE_ID, awsResp, RequestAccess::getKnowledgeBaseId); + break; + case BEDROCK_RUNTIME_SERVICE: + if (!Objects.equals(awsResp.getClass().getSimpleName(), "InvokeModelResult")) { + break; + } + + setAttribute(attributes, GEN_AI_USAGE_INPUT_TOKENS, awsResp, RequestAccess::getInputTokens); + setAttribute( + attributes, GEN_AI_USAGE_OUTPUT_TOKENS, awsResp, RequestAccess::getOutputTokens); + setAttribute( + attributes, GEN_AI_RESPONSE_FINISH_REASONS, awsResp, RequestAccess::getFinishReasons); + break; + default: + break; + } + } + + private static boolean isBedrockService(String serviceName) { + // Check if the serviceName belongs to Bedrock Services defined in AWS Java SDK V1. + // For example AmazonBedrock + return serviceName.equals(BEDROCK_SERVICE) + || serviceName.equals(BEDROCK_AGENT_SERVICE) + || serviceName.equals(BEDROCK_AGENT_RUNTIME_SERVICE) + || serviceName.equals(BEDROCK_RUNTIME_SERVICE); + } + + private static void setAttribute( + AttributesBuilder attributes, + AttributeKey key, + Object request, + Function getter) { + String value = getter.apply(request); + if (value != null) { + attributes.put(key, value); } } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/RequestAccess.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/RequestAccess.java index bb2ae9266c5c..512d5345cc63 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/RequestAccess.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/RequestAccess.java @@ -5,9 +5,17 @@ package io.opentelemetry.instrumentation.awssdk.v1_11; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Objects; +import java.util.stream.Stream; import javax.annotation.Nullable; final class RequestAccess { @@ -20,36 +28,365 @@ protected RequestAccess computeValue(Class type) { } }; + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Nullable + private static JsonNode parseTargetBody(ByteBuffer buffer) { + try { + byte[] bytes; + // Create duplicate to avoid mutating the original buffer position + ByteBuffer duplicate = buffer.duplicate(); + if (buffer.hasArray()) { + bytes = + Arrays.copyOfRange( + duplicate.array(), + duplicate.arrayOffset(), + duplicate.arrayOffset() + duplicate.remaining()); + } else { + bytes = new byte[buffer.remaining()]; + buffer.get(bytes); + } + return objectMapper.readTree(bytes); + } catch (IOException e) { + return null; + } + } + + @Nullable + private static JsonNode getJsonBody(Object target) { + if (target == null) { + return null; + } + + RequestAccess access = REQUEST_ACCESSORS.get(target.getClass()); + ByteBuffer bodyBuffer = invokeOrNullGeneric(access.getBody, target, ByteBuffer.class); + if (bodyBuffer == null) { + return null; + } + + return parseTargetBody(bodyBuffer); + } + + @Nullable + private static String findFirstMatchingPath(JsonNode jsonBody, String... paths) { + if (jsonBody == null) { + return null; + } + + return Stream.of(paths) + .map( + path -> { + JsonNode node = jsonBody.at(path); + if (node != null && !node.isMissingNode()) { + return node.asText(); + } + return null; + }) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + + @Nullable + private static String approximateTokenCount(JsonNode jsonBody, String... textPaths) { + if (jsonBody == null) { + return null; + } + + return Stream.of(textPaths) + .map( + path -> { + JsonNode node = jsonBody.at(path); + if (node != null && !node.isMissingNode()) { + int tokenEstimate = (int) Math.ceil(node.asText().length() / 6.0); + return Integer.toString(tokenEstimate); + } + return null; + }) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/textGenerationConfig/maxTokenCount" + // Anthropic Claude -> "/max_tokens" + // Cohere Command -> "/max_tokens" + // Cohere Command R -> "/max_tokens" + // AI21 Jamba -> "/max_tokens" + // Meta Llama -> "/max_gen_len" + // Mistral AI -> "/max_tokens" + @Nullable + static String getMaxTokens(Object target) { + return findFirstMatchingPath( + getJsonBody(target), "/textGenerationConfig/maxTokenCount", "/max_tokens", "/max_gen_len"); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/textGenerationConfig/temperature" + // Anthropic Claude -> "/temperature" + // Cohere Command -> "/temperature" + // Cohere Command R -> "/temperature" + // AI21 Jamba -> "/temperature" + // Meta Llama -> "/temperature" + // Mistral AI -> "/temperature" + @Nullable + static String getTemperature(Object target) { + return findFirstMatchingPath( + getJsonBody(target), "/textGenerationConfig/temperature", "/temperature"); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/textGenerationConfig/topP" + // Anthropic Claude -> "/top_p" + // Cohere Command -> "/p" + // Cohere Command R -> "/p" + // AI21 Jamba -> "/top_p" + // Meta Llama -> "/top_p" + // Mistral AI -> "/top_p" + @Nullable + static String getTopP(Object target) { + return findFirstMatchingPath(getJsonBody(target), "/textGenerationConfig/topP", "/top_p", "/p"); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/inputTextTokenCount" + // Anthropic Claude -> "/usage/input_tokens" + // Cohere Command -> "/prompt" + // Cohere Command R -> "/message" + // AI21 Jamba -> "/usage/prompt_tokens" + // Meta Llama -> "/prompt_token_count" + // Mistral AI -> "/prompt" + @Nullable + static String getInputTokens(Object target) { + JsonNode jsonBody = getJsonBody(target); + if (jsonBody == null) { + return null; + } + + // Try direct tokens counts first + String directCount = + findFirstMatchingPath( + jsonBody, + "/inputTextTokenCount", + "/usage/input_tokens", + "/usage/prompt_tokens", + "/prompt_token_count"); + + if (directCount != null) { + return directCount; + } + + // Fall back to token approximation + return approximateTokenCount(jsonBody, "/prompt", "/message"); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/results/0/tokenCount" + // Anthropic Claude -> "/usage/output_tokens" + // Cohere Command -> "/generations/0/text" + // Cohere Command R -> "/text" + // AI21 Jamba -> "/usage/completion_tokens" + // Meta Llama -> "/generation_token_count" + // Mistral AI -> "/outputs/0/text" + @Nullable + static String getOutputTokens(Object target) { + JsonNode jsonBody = getJsonBody(target); + if (jsonBody == null) { + return null; + } + + // Try direct token counts first + String directCount = + findFirstMatchingPath( + jsonBody, + "/results/0/tokenCount", + "/usage/output_tokens", + "/usage/completion_tokens", + "/generation_token_count"); + + if (directCount != null) { + return directCount; + } + + return approximateTokenCount(jsonBody, "/outputs/0/text", "/text"); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/results/0/completionReason" + // Anthropic Claude -> "/stop_reason" + // Cohere Command -> "/generations/0/finish_reason" + // Cohere Command R -> "/finish_reason" + // AI21 Jamba -> "/choices/0/finish_reason" + // Meta Llama -> "/stop_reason" + // Mistral AI -> "/outputs/0/stop_reason" + @Nullable + static String getFinishReasons(Object target) { + String finishReason = + findFirstMatchingPath( + getJsonBody(target), + "/results/0/completionReason", + "/stop_reason", + "/generations/0/finish_reason", + "/choices/0/finish_reason", + "/outputs/0/stop_reason", + "/finish_reason"); + + return finishReason != null ? "[" + finishReason + "]" : null; + } + + @Nullable + static String getLambdaName(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getLambdaName, request); + } + + @Nullable + static String getLambdaResourceId(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getLambdaResourceId, request); + } + + @Nullable + static String getSecretArn(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getSecretArn, request); + } + + @Nullable + static String getSnsTopicArn(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getSnsTopicArn, request); + } + + @Nullable + static String getStepFunctionsActivityArn(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getStepFunctionsActivityArn, request); + } + + @Nullable + static String getStateMachineArn(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getStateMachineArn, request); + } + @Nullable static String getBucketName(Object request) { + if (request == null) { + return null; + } RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); return invokeOrNull(access.getBucketName, request); } @Nullable static String getQueueUrl(Object request) { + if (request == null) { + return null; + } RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); return invokeOrNull(access.getQueueUrl, request); } @Nullable static String getQueueName(Object request) { + if (request == null) { + return null; + } RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); return invokeOrNull(access.getQueueName, request); } @Nullable static String getStreamName(Object request) { + if (request == null) { + return null; + } RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); return invokeOrNull(access.getStreamName, request); } @Nullable static String getTableName(Object request) { + if (request == null) { + return null; + } RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); return invokeOrNull(access.getTableName, request); } + @Nullable + static String getAgentId(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getAgentId, request); + } + + @Nullable + static String getKnowledgeBaseId(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getKnowledgeBaseId, request); + } + + @Nullable + static String getDataSourceId(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getDataSourceId, request); + } + + @Nullable + static String getGuardrailId(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getGuardrailId, request); + } + + @Nullable + static String getGuardrailArn(Object request) { + if (request == null) { + return null; + } + return findNestedAccessorOrNull(request, "getGuardrailArn"); + } + + @Nullable + static String getModelId(Object request) { + if (request == null) { + return null; + } + RequestAccess access = REQUEST_ACCESSORS.get(request.getClass()); + return invokeOrNull(access.getModelId, request); + } + @Nullable private static String invokeOrNull(@Nullable MethodHandle method, Object obj) { if (method == null) { @@ -62,27 +399,82 @@ private static String invokeOrNull(@Nullable MethodHandle method, Object obj) { } } + @Nullable + private static T invokeOrNullGeneric( + @Nullable MethodHandle method, Object obj, Class returnType) { + if (method == null) { + return null; + } + try { + return returnType.cast(method.invoke(obj)); + } catch (Throwable e) { + return null; + } + } + @Nullable private final MethodHandle getBucketName; @Nullable private final MethodHandle getQueueUrl; @Nullable private final MethodHandle getQueueName; @Nullable private final MethodHandle getStreamName; @Nullable private final MethodHandle getTableName; + @Nullable private final MethodHandle getAgentId; + @Nullable private final MethodHandle getKnowledgeBaseId; + @Nullable private final MethodHandle getDataSourceId; + @Nullable private final MethodHandle getGuardrailId; + @Nullable private final MethodHandle getModelId; + @Nullable private final MethodHandle getBody; + @Nullable private final MethodHandle getStateMachineArn; + @Nullable private final MethodHandle getStepFunctionsActivityArn; + @Nullable private final MethodHandle getSnsTopicArn; + @Nullable private final MethodHandle getSecretArn; + @Nullable private final MethodHandle getLambdaName; + @Nullable private final MethodHandle getLambdaResourceId; private RequestAccess(Class clz) { - getBucketName = findAccessorOrNull(clz, "getBucketName"); - getQueueUrl = findAccessorOrNull(clz, "getQueueUrl"); - getQueueName = findAccessorOrNull(clz, "getQueueName"); - getStreamName = findAccessorOrNull(clz, "getStreamName"); - getTableName = findAccessorOrNull(clz, "getTableName"); + getBucketName = findAccessorOrNull(clz, "getBucketName", String.class); + getQueueUrl = findAccessorOrNull(clz, "getQueueUrl", String.class); + getQueueName = findAccessorOrNull(clz, "getQueueName", String.class); + getStreamName = findAccessorOrNull(clz, "getStreamName", String.class); + getTableName = findAccessorOrNull(clz, "getTableName", String.class); + getAgentId = findAccessorOrNull(clz, "getAgentId", String.class); + getKnowledgeBaseId = findAccessorOrNull(clz, "getKnowledgeBaseId", String.class); + getDataSourceId = findAccessorOrNull(clz, "getDataSourceId", String.class); + getGuardrailId = findAccessorOrNull(clz, "getGuardrailId", String.class); + getModelId = findAccessorOrNull(clz, "getModelId", String.class); + getBody = findAccessorOrNull(clz, "getBody", ByteBuffer.class); + getStateMachineArn = findAccessorOrNull(clz, "getStateMachineArn", String.class); + getStepFunctionsActivityArn = findAccessorOrNull(clz, "getActivityArn", String.class); + getSnsTopicArn = findAccessorOrNull(clz, "getTopicArn", String.class); + getSecretArn = findAccessorOrNull(clz, "getARN", String.class); + getLambdaName = findAccessorOrNull(clz, "getFunctionName", String.class); + getLambdaResourceId = findAccessorOrNull(clz, "getUUID", String.class); } @Nullable - private static MethodHandle findAccessorOrNull(Class clz, String methodName) { + private static MethodHandle findAccessorOrNull( + Class clz, String methodName, Class returnType) { try { return MethodHandles.publicLookup() - .findVirtual(clz, methodName, MethodType.methodType(String.class)); + .findVirtual(clz, methodName, MethodType.methodType(returnType)); } catch (Throwable t) { return null; } } + + @Nullable + private static String findNestedAccessorOrNull(Object obj, String... methodNames) { + Object current = obj; + for (String methodName : methodNames) { + if (current == null) { + return null; + } + try { + Method method = current.getClass().getMethod(methodName); + current = method.invoke(current); + } catch (Exception e) { + return null; + } + } + return (current instanceof String) ? (String) current : null; + } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java index a3e2d0e770c8..41c772692d05 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java @@ -137,7 +137,7 @@ static String getMessageAttribute(Request request, String name) { } static String getMessageId(Response response) { - if (response.getAwsResponse() instanceof SendMessageResult) { + if (response != null && response.getAwsResponse() instanceof SendMessageResult) { return ((SendMessageResult) response.getAwsResponse()).getMessageId(); } return null; diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingList.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingList.java index 769a52d8954d..a0977017aaf6 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingList.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingList.java @@ -13,6 +13,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import java.util.Iterator; import java.util.List; +import java.util.function.Consumer; class TracingList extends SdkInternalList { private static final long serialVersionUID = 1L; @@ -57,6 +58,13 @@ public Iterator iterator() { return it; } + @Override + public void forEach(Consumer action) { + for (Message message : this) { + action.accept(message); + } + } + private static boolean inAwsClient() { for (Class caller : CallerClass.INSTANCE.getClassContext()) { if (AmazonSQSClient.class == caller) { diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts index 548631e9f187..51483839a748 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts @@ -14,6 +14,14 @@ dependencies { compileOnly("com.amazonaws:aws-java-sdk-dynamodb:1.11.106") compileOnly("com.amazonaws:aws-java-sdk-sns:1.11.106") compileOnly("com.amazonaws:aws-java-sdk-sqs:1.11.106") + compileOnly("com.amazonaws:aws-java-sdk-secretsmanager:1.11.309") + compileOnly("com.amazonaws:aws-java-sdk-stepfunctions:1.11.230") + compileOnly("com.amazonaws:aws-java-sdk-lambda:1.11.678") + + compileOnly("com.amazonaws:aws-java-sdk-bedrock:1.12.744") + compileOnly("com.amazonaws:aws-java-sdk-bedrockagent:1.12.744") + compileOnly("com.amazonaws:aws-java-sdk-bedrockagentruntime:1.12.744") + compileOnly("com.amazonaws:aws-java-sdk-bedrockruntime:1.12.744") // needed for SQS - using emq directly as localstack references emq v0.15.7 ie WITHOUT AWS trace header propagation implementation("org.elasticmq:elasticmq-rest-sqs_2.12:1.0.0") diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy index 95e6ed8985d1..990fc177bc1d 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy +++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy @@ -27,6 +27,24 @@ import com.amazonaws.services.rds.AmazonRDSClientBuilder import com.amazonaws.services.rds.model.DeleteOptionGroupRequest import com.amazonaws.services.s3.AmazonS3Client import com.amazonaws.services.s3.AmazonS3ClientBuilder +import com.amazonaws.services.bedrockagent.AWSBedrockAgentClientBuilder +import com.amazonaws.services.bedrockagent.model.GetAgentRequest +import com.amazonaws.services.bedrockagent.model.GetKnowledgeBaseRequest +import com.amazonaws.services.bedrockagent.model.GetDataSourceRequest +import com.amazonaws.services.bedrock.AmazonBedrockClientBuilder +import com.amazonaws.services.bedrock.model.GetGuardrailRequest +import com.amazonaws.services.bedrockruntime.AmazonBedrockRuntimeClientBuilder +import com.amazonaws.services.bedrockruntime.model.InvokeModelRequest +import com.amazonaws.services.stepfunctions.AWSStepFunctionsClientBuilder +import com.amazonaws.services.stepfunctions.model.DescribeStateMachineRequest +import com.amazonaws.services.stepfunctions.model.DescribeActivityRequest +import com.amazonaws.services.sns.AmazonSNSClientBuilder +import com.amazonaws.services.sns.model.PublishRequest +import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder +import com.amazonaws.services.secretsmanager.model.CreateSecretRequest +import com.amazonaws.services.lambda.AWSLambdaClientBuilder +import com.amazonaws.services.lambda.model.GetEventSourceMappingRequest +import com.amazonaws.services.lambda.model.GetFunctionRequest import io.opentelemetry.api.trace.Span import io.opentelemetry.instrumentation.test.InstrumentationSpecification import io.opentelemetry.semconv.SemanticAttributes @@ -38,6 +56,7 @@ import spock.lang.Shared import spock.lang.Unroll import java.time.Duration +import java.nio.charset.StandardCharsets import static io.opentelemetry.api.trace.SpanKind.CLIENT import static io.opentelemetry.api.trace.SpanKind.PRODUCER @@ -156,6 +175,296 @@ abstract class AbstractAws1ClientTest extends InstrumentationSpecification { """ + "Bedrock" | "GetGuardrail" | "GET" | "/" | + AmazonBedrockClientBuilder.standard() | { c -> c.getGuardrail(new GetGuardrailRequest().withGuardrailIdentifier("guardrailId")) } | ["aws.bedrock.guardrail.id":"guardrailId", "aws.bedrock.guardrail.arn": "guardrailArn"] | """ + { + "blockedInputMessaging": "string", + "blockedOutputsMessaging": "string", + "contentPolicy": {}, + "createdAt": "2024-06-12T18:31:45Z", + "description": "string", + "guardrailArn": "guardrailArn", + "guardrailId": "guardrailId", + "kmsKeyArn": "string", + "name": "string", + "sensitiveInformationPolicy": {}, + "status": "READY", + "topicPolicy": { + "topics": [ + { + "definition": "string", + "examples": [ "string" ], + "name": "string", + "type": "string" + } + ] + }, + "updatedAt": "2024-06-12T18:31:48Z", + "version": "DRAFT", + "wordPolicy": {} + } + """ + "AWSBedrockAgent" | "GetAgent" | "GET" | "/" | AWSBedrockAgentClientBuilder.standard() | { c -> c.getAgent(new GetAgentRequest().withAgentId("agentId")) } | ["aws.bedrock.agent.id": "agentId"] | "" + "AWSBedrockAgent" | "GetKnowledgeBase" | "GET" | "/" | AWSBedrockAgentClientBuilder.standard() | { c -> c.getKnowledgeBase(new GetKnowledgeBaseRequest().withKnowledgeBaseId("knowledgeBaseId")) } | ["aws.bedrock.knowledge_base.id": "knowledgeBaseId"] | "" + "AWSBedrockAgent" | "GetDataSource" | "GET" | "/" | AWSBedrockAgentClientBuilder.standard() | { c -> c.getDataSource(new GetDataSourceRequest().withDataSourceId("datasourceId").withKnowledgeBaseId("knowledgeBaseId")) } | ["aws.bedrock.data_source.id": "datasourceId"] | "" + "BedrockRuntime" | "InvokeModel" | "POST" | "/" | + AmazonBedrockRuntimeClientBuilder.standard() | + { c -> + c.invokeModel( + new InvokeModelRequest() + .withModelId("ai21.jamba-1-5-mini-v1:0") + .withBody(StandardCharsets.UTF_8.encode(''' + { + "messages": [{ + "role": "user", + "message": "Which LLM are you?" + }], + "max_tokens": 1000, + "top_p": 0.8, + "temperature": 0.7 + } + ''')) + ) + } | + [ + "gen_ai.request.model": "ai21.jamba-1-5-mini-v1:0", + "gen_ai.system": "aws_bedrock", + "gen_ai.request.max_tokens": "1000", + "gen_ai.request.temperature": "0.7", + "gen_ai.request.top_p": "0.8", + "gen_ai.response.finish_reasons": "[stop]", + "gen_ai.usage.input_tokens": "5", + "gen_ai.usage.output_tokens": "42" + ] | + ''' + { + "choices": [{ + "finish_reason": "stop" + }], + "usage": { + "prompt_tokens": 5, + "completion_tokens": 42 + } + } + ''' + "BedrockRuntime" | "InvokeModel" | "POST" | "/" | + AmazonBedrockRuntimeClientBuilder.standard() | + { c -> + c.invokeModel( + new InvokeModelRequest() + .withModelId("amazon.titan-text-premier-v1:0") + .withBody(StandardCharsets.UTF_8.encode(''' + { + "inputText": "Hello, world!", + "textGenerationConfig": { + "temperature": 0.7, + "topP": 0.9, + "maxTokenCount": 100, + "stopSequences": ["END"] + } + } + ''')) + ) + } | + [ + "gen_ai.request.model": "amazon.titan-text-premier-v1:0", + "gen_ai.system": "aws_bedrock", + "gen_ai.request.max_tokens": "100", + "gen_ai.request.temperature": "0.7", + "gen_ai.request.top_p": "0.9", + "gen_ai.response.finish_reasons": "[stop]", + "gen_ai.usage.input_tokens": "5", + "gen_ai.usage.output_tokens": "42" + ] | + ''' + { + "inputTextTokenCount": 5, + "results": [ + { + "tokenCount": 42, + "outputText": "Hi! I'm Titan, an AI assistant. How can I help you today?", + "completionReason": "stop" + } + ] + } + ''' + "BedrockRuntime" | "InvokeModel" | "POST" | "/" | + AmazonBedrockRuntimeClientBuilder.standard() | + { c -> + c.invokeModel( + new InvokeModelRequest() + .withModelId("anthropic.claude-3-5-sonnet-20241022-v2:0") + .withBody(StandardCharsets.UTF_8.encode(''' + { + "anthropic_version": "bedrock-2023-05-31", + "messages": [{ + "role": "user", + "content": "Hello, world" + }], + "max_tokens": 100, + "temperature": 0.7, + "top_p": 0.9 + } + ''')) + ) + } | + [ + "gen_ai.request.model": "anthropic.claude-3-5-sonnet-20241022-v2:0", + "gen_ai.system": "aws_bedrock", + "gen_ai.request.max_tokens": "100", + "gen_ai.request.temperature": "0.7", + "gen_ai.request.top_p": "0.9", + "gen_ai.response.finish_reasons": "[end_turn]", + "gen_ai.usage.input_tokens": "2095", + "gen_ai.usage.output_tokens": "503" + ] | + ''' + { + "stop_reason": "end_turn", + "usage": { + "input_tokens": 2095, + "output_tokens": 503 + } + } + ''' + "BedrockRuntime" | "InvokeModel" | "POST" | "/" | + AmazonBedrockRuntimeClientBuilder.standard() | + { c -> + c.invokeModel( + new InvokeModelRequest() + .withModelId("meta.llama3-70b-instruct-v1:0") + .withBody(StandardCharsets.UTF_8.encode(''' + { + "prompt": "<|begin_of_text|><|start_header_id|>user<|end_header_id|>\\\\nDescribe the purpose of a 'hello world' program in one line. <|eot_id|>\\\\n<|start_header_id|>assistant<|end_header_id|>\\\\n", + "max_gen_len": 128, + "temperature": 0.1, + "top_p": 0.9 + } + ''')) + ) + } | + [ + "gen_ai.request.model": "meta.llama3-70b-instruct-v1:0", + "gen_ai.system": "aws_bedrock", + "gen_ai.request.max_tokens": "128", + "gen_ai.request.temperature": "0.1", + "gen_ai.request.top_p": "0.9", + "gen_ai.response.finish_reasons": "[stop]", + "gen_ai.usage.input_tokens": "2095", + "gen_ai.usage.output_tokens": "503" + ] | + ''' + { + "prompt_token_count": 2095, + "generation_token_count": 503, + "stop_reason": "stop" + } + ''' + "BedrockRuntime" | "InvokeModel" | "POST" | "/" | + AmazonBedrockRuntimeClientBuilder.standard() | + { c -> + c.invokeModel( + new InvokeModelRequest() + .withModelId("cohere.command-r-v1:0") + .withBody(StandardCharsets.UTF_8.encode(''' + { + "message": "Convince me to write a LISP interpreter in one line.", + "temperature": 0.8, + "max_tokens": 4096, + "p": 0.45 + } + ''')) + ) + } | + [ + "gen_ai.request.model": "cohere.command-r-v1:0", + "gen_ai.system": "aws_bedrock", + "gen_ai.request.max_tokens": "4096", + "gen_ai.request.temperature": "0.8", + "gen_ai.request.top_p": "0.45", + "gen_ai.response.finish_reasons": "[COMPLETE]", + "gen_ai.usage.input_tokens": "9", + "gen_ai.usage.output_tokens": "2" + ] | + ''' + { + "text": "test-output", + "finish_reason": "COMPLETE" + } + ''' + "BedrockRuntime" | "InvokeModel" | "POST" | "/" | + AmazonBedrockRuntimeClientBuilder.standard() | + { c -> + c.invokeModel( + new InvokeModelRequest() + .withModelId("mistral.mistral-large-2402-v1:0") + .withBody(StandardCharsets.UTF_8.encode(''' + { + "prompt": "[INST] Describe the difference between a compiler and interpreter in one line. [/INST]\\\\n", + "max_tokens": 4096, + "temperature": 0.75, + "top_p": 0.25 + } + ''')) + ) + } | + [ + "gen_ai.request.model": "mistral.mistral-large-2402-v1:0", + "gen_ai.system": "aws_bedrock", + "gen_ai.request.max_tokens": "4096", + "gen_ai.request.temperature": "0.75", + "gen_ai.request.top_p": "0.25", + "gen_ai.response.finish_reasons": "[stop]", + "gen_ai.usage.input_tokens": "16", + "gen_ai.usage.output_tokens": "2" + ] | + ''' + { + "outputs": [{ + "text": "test-output", + "stop_reason": "stop" + }] + } + ''' + "AWSStepFunctions" | "DescribeStateMachine" | "POST" | "/" | AWSStepFunctionsClientBuilder.standard() + | { c -> c.describeStateMachine(new DescribeStateMachineRequest().withStateMachineArn("stateMachineArn")) } + | ["aws.stepfunctions.state_machine.arn": "stateMachineArn"] + | "" + "AWSStepFunctions" | "DescribeActivity" | "POST" | "/" | AWSStepFunctionsClientBuilder.standard() + | { c -> c.describeActivity(new DescribeActivityRequest().withActivityArn("activityArn")) } + | ["aws.stepfunctions.activity.arn": "activityArn"] + | "" + "SNS" | "Publish" | "POST" | "/" | AmazonSNSClientBuilder.standard() + | { c -> c.publish(new PublishRequest().withMessage("message").withTopicArn("topicArn")) } + | ["aws.sns.topic.arn": "topicArn"] + | """ + + + 567910cd-659e-55d4-8ccb-5aaf14679dc0 + + + d74b8436-ae13-5ab4-a9ff-ce54dfea72a0 + + + """ + "AWSSecretsManager" | "CreateSecret" | "POST" | "/" | AWSSecretsManagerClientBuilder.standard() + | { c -> c.createSecret(new CreateSecretRequest().withName("secretName").withSecretString("secretValue")) } + | ["aws.secretsmanager.secret.arn": "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3"] + | """ + { + "ARN": "arn:aws:secretsmanager:us-west-2:123456789012:secret:MyTestDatabaseSecret-a1b2c3", + "Name":"MyTestDatabaseSecret", + "VersionId": "EXAMPLE1-90ab-cdef-fedc-ba987SECRET1" + } + """ + "AWSLambda" | "GetEventSourceMapping" | "GET" | "/" | AWSLambdaClientBuilder.standard() + | { c -> c.getEventSourceMapping(new GetEventSourceMappingRequest().withUUID("uuid")) } + | ["aws.lambda.resource_mapping.id": "uuid"] + | "" + "AWSLambda" | "GetFunction" | "GET" | "/" | AWSLambdaClientBuilder.standard() + | { c-> c.getFunction(new GetFunctionRequest().withFunctionName("functionName")) } + | ["aws.lambda.function.name": "functionName"] + | "" } def "send #operation request to closed port"() { diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsTracingTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsTracingTest.groovy index eff15ed53f11..eea2cf660eb4 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsTracingTest.groovy +++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSqsTracingTest.groovy @@ -67,8 +67,15 @@ abstract class AbstractSqsTracingTest extends InstrumentationSpecification { receiveMessageRequest.withMessageAttributeNames("test-message-header") } def receiveMessageResult = client.receiveMessage(receiveMessageRequest) - receiveMessageResult.messages.each {message -> - runWithSpan("process child") {} + // test different ways of iterating the messages list + if (testCaptureHeaders) { + receiveMessageResult.messages.each { message -> + runWithSpan("process child") {} + } + } else { + receiveMessageResult.messages.forEach { message -> + runWithSpan("process child") {} + } } then: diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/build.gradle.kts index 8f442b268b88..24c14dec4e50 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/build.gradle.kts @@ -84,6 +84,9 @@ dependencies { testLibrary("software.amazon.awssdk:sqs:2.2.0") testLibrary("software.amazon.awssdk:sns:2.2.0") testLibrary("software.amazon.awssdk:ses:2.2.0") + testLibrary("software.amazon.awssdk:sfn:2.2.0") + testLibrary("software.amazon.awssdk:secretsmanager:2.2.0") + testLibrary("software.amazon.awssdk:lambda:2.2.0") // last version that does not use json protocol latestDepTestLibrary("software.amazon.awssdk:sqs:2.21.17") diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AbstractAwsSdkInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AbstractAwsSdkInstrumentationModule.java index 5dc5f2ab9d4f..8f3b0e5a1080 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AbstractAwsSdkInstrumentationModule.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/AbstractAwsSdkInstrumentationModule.java @@ -24,7 +24,7 @@ protected AbstractAwsSdkInstrumentationModule(String additionalInstrumentationNa @Override public boolean isHelperClass(String className) { - return className.startsWith("io.opentelemetry.contrib.awsxray."); + return className.startsWith("io.opentelemetry.contrib.awsxray.") || className.startsWith("com.fasterxml.jackson"); } @Override diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/build.gradle.kts index e73abc7bc35f..d387a7472c18 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/build.gradle.kts @@ -21,6 +21,9 @@ dependencies { testLibrary("software.amazon.awssdk:s3:2.2.0") testLibrary("software.amazon.awssdk:sqs:2.2.0") testLibrary("software.amazon.awssdk:sns:2.2.0") + testLibrary("software.amazon.awssdk:sfn:2.2.0") + testLibrary("software.amazon.awssdk:secretsmanager:2.2.0") + testLibrary("software.amazon.awssdk:lambda:2.2.0") // last version that does not use json protocol latestDepTestLibrary("software.amazon.awssdk:sqs:2.21.17") diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts index 081d542e76ab..4f71a06a571c 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts @@ -19,6 +19,9 @@ dependencies { testLibrary("software.amazon.awssdk:rds:2.2.0") testLibrary("software.amazon.awssdk:s3:2.2.0") testLibrary("software.amazon.awssdk:ses:2.2.0") + testLibrary("software.amazon.awssdk:sfn:2.2.0") + testLibrary("software.amazon.awssdk:secretsmanager:2.2.0") + testLibrary("software.amazon.awssdk:lambda:2.2.0") // last version that does not use json protocol latestDepTestLibrary("software.amazon.awssdk:sqs:2.21.17") diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsExperimentalAttributes.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsExperimentalAttributes.java new file mode 100644 index 000000000000..9e9f9cf59f33 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsExperimentalAttributes.java @@ -0,0 +1,73 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; + +import io.opentelemetry.api.common.AttributeKey; + +final class AwsExperimentalAttributes { + static final AttributeKey AWS_BUCKET_NAME = stringKey("aws.bucket.name"); + static final AttributeKey AWS_QUEUE_URL = stringKey("aws.queue.url"); + 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"); + static final AttributeKey AWS_GUARDRAIL_ID = stringKey("aws.bedrock.guardrail.id"); + static final AttributeKey AWS_GUARDRAIL_ARN = stringKey("aws.bedrock.guardrail.arn"); + static final AttributeKey AWS_AGENT_ID = stringKey("aws.bedrock.agent.id"); + static final AttributeKey AWS_DATA_SOURCE_ID = stringKey("aws.bedrock.data_source.id"); + static final AttributeKey AWS_KNOWLEDGE_BASE_ID = + stringKey("aws.bedrock.knowledge_base.id"); + + // TODO: Merge in gen_ai attributes in opentelemetry-semconv-incubating once upgrade to v1.26.0 + static final AttributeKey GEN_AI_MODEL = stringKey("gen_ai.request.model"); + static final AttributeKey GEN_AI_SYSTEM = stringKey("gen_ai.system"); + + static final AttributeKey GEN_AI_REQUEST_MAX_TOKENS = + stringKey("gen_ai.request.max_tokens"); + + static final AttributeKey GEN_AI_REQUEST_TEMPERATURE = + stringKey("gen_ai.request.temperature"); + + static final AttributeKey GEN_AI_REQUEST_TOP_P = stringKey("gen_ai.request.top_p"); + + static final AttributeKey GEN_AI_RESPONSE_FINISH_REASONS = + stringKey("gen_ai.response.finish_reasons"); + + static final AttributeKey GEN_AI_USAGE_INPUT_TOKENS = + stringKey("gen_ai.usage.input_tokens"); + + static final AttributeKey GEN_AI_USAGE_OUTPUT_TOKENS = + stringKey("gen_ai.usage.output_tokens"); + + static final AttributeKey AWS_STATE_MACHINE_ARN = + stringKey("aws.stepfunctions.state_machine.arn"); + + static final AttributeKey AWS_STEP_FUNCTIONS_ACTIVITY_ARN = + stringKey("aws.stepfunctions.activity.arn"); + + static final AttributeKey AWS_SNS_TOPIC_ARN = stringKey("aws.sns.topic.arn"); + + static final AttributeKey AWS_SECRET_ARN = stringKey("aws.secretsmanager.secret.arn"); + + static final AttributeKey AWS_LAMBDA_NAME = stringKey("aws.lambda.function.name"); + + static final AttributeKey AWS_LAMBDA_ARN = stringKey("aws.lambda.function.arn"); + + static final AttributeKey AWS_LAMBDA_RESOURCE_ID = + stringKey("aws.lambda.resource_mapping.id"); + + static boolean isGenAiAttribute(String attributeKey) { + return attributeKey.equals(GEN_AI_REQUEST_MAX_TOKENS.getKey()) + || attributeKey.equals(GEN_AI_REQUEST_TEMPERATURE.getKey()) + || attributeKey.equals(GEN_AI_REQUEST_TOP_P.getKey()) + || attributeKey.equals(GEN_AI_RESPONSE_FINISH_REASONS.getKey()) + || attributeKey.equals(GEN_AI_USAGE_INPUT_TOKENS.getKey()) + || attributeKey.equals(GEN_AI_USAGE_OUTPUT_TOKENS.getKey()); + } + + private AwsExperimentalAttributes() {} +} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsSdkRequest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsSdkRequest.java index 54253d0f7bcb..5326400f7efd 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsSdkRequest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsSdkRequest.java @@ -5,10 +5,20 @@ package io.opentelemetry.instrumentation.awssdk.v2_2; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCK; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKAGENTOPERATION; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKAGENTRUNTIMEOPERATION; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKDATASOURCEOPERATION; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKKNOWLEDGEBASEOPERATION; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKRUNTIME; import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.DYNAMODB; import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.KINESIS; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.LAMBDA; import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.S3; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.SECRETSMANAGER; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.SNS; import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.SQS; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.STEPFUNCTION; import static io.opentelemetry.instrumentation.awssdk.v2_2.FieldMapping.request; import static io.opentelemetry.instrumentation.awssdk.v2_2.FieldMapping.response; @@ -32,6 +42,49 @@ enum AwsSdkRequest { S3Request(S3, "S3Request"), SqsRequest(SQS, "SqsRequest"), KinesisRequest(KINESIS, "KinesisRequest"), + BedrockRequest(BEDROCK, "BedrockRequest"), + BedrockAgentRuntimeRequest(BEDROCKAGENTRUNTIMEOPERATION, "BedrockAgentRuntimeRequest"), + BedrockRuntimeRequest(BEDROCKRUNTIME, "BedrockRuntimeRequest"), + // BedrockAgent API based requests. We only support operations that are related to + // Agent/DataSources/KnowledgeBases + // resources and the request/response context contains the resource ID. + BedrockCreateAgentActionGroupRequest(BEDROCKAGENTOPERATION, "CreateAgentActionGroupRequest"), + BedrockCreateAgentAliasRequest(BEDROCKAGENTOPERATION, "CreateAgentAliasRequest"), + BedrockDeleteAgentActionGroupRequest(BEDROCKAGENTOPERATION, "DeleteAgentActionGroupRequest"), + BedrockDeleteAgentAliasRequest(BEDROCKAGENTOPERATION, "DeleteAgentAliasRequest"), + BedrockDeleteAgentVersionRequest(BEDROCKAGENTOPERATION, "DeleteAgentVersionRequest"), + BedrockGetAgentActionGroupRequest(BEDROCKAGENTOPERATION, "GetAgentActionGroupRequest"), + BedrockGetAgentAliasRequest(BEDROCKAGENTOPERATION, "GetAgentAliasRequest"), + BedrockGetAgentRequest(BEDROCKAGENTOPERATION, "GetAgentRequest"), + BedrockGetAgentVersionRequest(BEDROCKAGENTOPERATION, "GetAgentVersionRequest"), + BedrockListAgentActionGroupsRequest(BEDROCKAGENTOPERATION, "ListAgentActionGroupsRequest"), + BedrockListAgentAliasesRequest(BEDROCKAGENTOPERATION, "ListAgentAliasesRequest"), + BedrockListAgentKnowledgeBasesRequest(BEDROCKAGENTOPERATION, "ListAgentKnowledgeBasesRequest"), + BedrocListAgentVersionsRequest(BEDROCKAGENTOPERATION, "ListAgentVersionsRequest"), + BedrockPrepareAgentRequest(BEDROCKAGENTOPERATION, "PrepareAgentRequest"), + BedrockUpdateAgentActionGroupRequest(BEDROCKAGENTOPERATION, "UpdateAgentActionGroupRequest"), + BedrockUpdateAgentAliasRequest(BEDROCKAGENTOPERATION, "UpdateAgentAliasRequest"), + BedrockUpdateAgentRequest(BEDROCKAGENTOPERATION, "UpdateAgentRequest"), + BedrockBedrockAgentRequest(BEDROCKAGENTOPERATION, "BedrockAgentRequest"), + BedrockDeleteDataSourceRequest(BEDROCKDATASOURCEOPERATION, "DeleteDataSourceRequest"), + BedrockGetDataSourceRequest(BEDROCKDATASOURCEOPERATION, "GetDataSourceRequest"), + BedrockUpdateDataSourceRequest(BEDROCKDATASOURCEOPERATION, "UpdateDataSourceRequest"), + BedrocAssociateAgentKnowledgeBaseRequest( + BEDROCKKNOWLEDGEBASEOPERATION, "AssociateAgentKnowledgeBaseRequest"), + BedrockCreateDataSourceRequest(BEDROCKKNOWLEDGEBASEOPERATION, "CreateDataSourceRequest"), + BedrockDeleteKnowledgeBaseRequest(BEDROCKKNOWLEDGEBASEOPERATION, "DeleteKnowledgeBaseRequest"), + BedrockDisassociateAgentKnowledgeBaseRequest( + BEDROCKKNOWLEDGEBASEOPERATION, "DisassociateAgentKnowledgeBaseRequest"), + BedrockGetAgentKnowledgeBaseRequest( + BEDROCKKNOWLEDGEBASEOPERATION, "GetAgentKnowledgeBaseRequest"), + BedrockGetKnowledgeBaseRequest(BEDROCKKNOWLEDGEBASEOPERATION, "GetKnowledgeBaseRequest"), + BedrockListDataSourcesRequest(BEDROCKKNOWLEDGEBASEOPERATION, "ListDataSourcesRequest"), + BedrockUpdateAgentKnowledgeBaseRequest( + BEDROCKKNOWLEDGEBASEOPERATION, "UpdateAgentKnowledgeBaseRequest"), + SfnRequest(STEPFUNCTION, "SfnRequest"), + SnsRequest(SNS, "SnsRequest"), + SecretsManagerRequest(SECRETSMANAGER, "SecretsManagerRequest"), + LambdaRequest(LAMBDA, "LambdaRequest"), // specific requests BatchGetItem( DYNAMODB, diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsSdkRequestType.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsSdkRequestType.java index 9062f2aa1738..4cd468e095ff 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsSdkRequestType.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AwsSdkRequestType.java @@ -5,17 +5,76 @@ package io.opentelemetry.instrumentation.awssdk.v2_2; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_AGENT_ID; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_BUCKET_NAME; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_DATA_SOURCE_ID; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_GUARDRAIL_ARN; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_GUARDRAIL_ID; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_KNOWLEDGE_BASE_ID; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_LAMBDA_ARN; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_LAMBDA_NAME; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_LAMBDA_RESOURCE_ID; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_QUEUE_NAME; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_QUEUE_URL; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_SECRET_ARN; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_SNS_TOPIC_ARN; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_STATE_MACHINE_ARN; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_STEP_FUNCTIONS_ACTIVITY_ARN; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_STREAM_NAME; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.AWS_TABLE_NAME; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_MODEL; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_REQUEST_MAX_TOKENS; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_REQUEST_TEMPERATURE; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_REQUEST_TOP_P; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_RESPONSE_FINISH_REASONS; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_USAGE_INPUT_TOKENS; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_USAGE_OUTPUT_TOKENS; import static io.opentelemetry.instrumentation.awssdk.v2_2.FieldMapping.request; +import static io.opentelemetry.instrumentation.awssdk.v2_2.FieldMapping.response; import java.util.Collections; import java.util.List; import java.util.Map; enum AwsSdkRequestType { - S3(request("aws.bucket.name", "Bucket")), - SQS(request("aws.queue.url", "QueueUrl"), request("aws.queue.name", "QueueName")), - KINESIS(request("aws.stream.name", "StreamName")), - DYNAMODB(request("aws.table.name", "TableName")); + S3(request(AWS_BUCKET_NAME.getKey(), "Bucket")), + SQS(request(AWS_QUEUE_URL.getKey(), "QueueUrl"), request(AWS_QUEUE_NAME.getKey(), "QueueName")), + KINESIS(request(AWS_STREAM_NAME.getKey(), "StreamName")), + DYNAMODB(request(AWS_TABLE_NAME.getKey(), "TableName")), + BEDROCK( + request(AWS_GUARDRAIL_ID.getKey(), "guardrailIdentifier"), + response(AWS_GUARDRAIL_ARN.getKey(), "guardrailArn")), + BEDROCKAGENTOPERATION( + request(AWS_AGENT_ID.getKey(), "agentId"), response(AWS_AGENT_ID.getKey(), "agentId")), + BEDROCKAGENTRUNTIMEOPERATION( + request(AWS_AGENT_ID.getKey(), "agentId"), + response(AWS_AGENT_ID.getKey(), "agentId"), + request(AWS_KNOWLEDGE_BASE_ID.getKey(), "knowledgeBaseId"), + response(AWS_KNOWLEDGE_BASE_ID.getKey(), "knowledgeBaseId")), + BEDROCKDATASOURCEOPERATION( + request(AWS_DATA_SOURCE_ID.getKey(), "dataSourceId"), + response(AWS_DATA_SOURCE_ID.getKey(), "dataSourceId")), + BEDROCKKNOWLEDGEBASEOPERATION( + request(AWS_KNOWLEDGE_BASE_ID.getKey(), "knowledgeBaseId"), + response(AWS_KNOWLEDGE_BASE_ID.getKey(), "knowledgeBaseId")), + BEDROCKRUNTIME( + request(GEN_AI_MODEL.getKey(), "modelId"), + request(GEN_AI_REQUEST_MAX_TOKENS.getKey(), "body"), + request(GEN_AI_REQUEST_TEMPERATURE.getKey(), "body"), + request(GEN_AI_REQUEST_TOP_P.getKey(), "body"), + request(GEN_AI_USAGE_INPUT_TOKENS.getKey(), "body"), + response(GEN_AI_RESPONSE_FINISH_REASONS.getKey(), "body"), + response(GEN_AI_USAGE_INPUT_TOKENS.getKey(), "body"), + response(GEN_AI_USAGE_OUTPUT_TOKENS.getKey(), "body")), + STEPFUNCTION( + request(AWS_STATE_MACHINE_ARN.getKey(), "stateMachineArn"), + request(AWS_STEP_FUNCTIONS_ACTIVITY_ARN.getKey(), "activityArn")), + SNS(request(AWS_SNS_TOPIC_ARN.getKey(), "TopicArn")), + SECRETSMANAGER(response(AWS_SECRET_ARN.getKey(), "ARN")), + LAMBDA( + request(AWS_LAMBDA_NAME.getKey(), "FunctionName"), + request(AWS_LAMBDA_RESOURCE_ID.getKey(), "UUID"), + response(AWS_LAMBDA_ARN.getKey(), "Configuration.FunctionArn")); // Wrapping in unmodifiableMap @SuppressWarnings("ImmutableEnumChecker") diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/FieldMapper.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/FieldMapper.java index 569d0eb5ae18..8f2d463237a8 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/FieldMapper.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/FieldMapper.java @@ -65,8 +65,13 @@ private void mapToAttributes( for (int i = 1; i < path.size() && target != null; i++) { target = next(target, path.get(i)); } + String value; if (target != null) { - String value = serializer.serialize(target); + if (AwsExperimentalAttributes.isGenAiAttribute(fieldMapping.getAttribute())) { + value = serializer.serialize(fieldMapping.getAttribute(), target); + } else { + value = serializer.serialize(target); + } if (!StringUtils.isEmpty(value)) { span.setAttribute(fieldMapping.getAttribute(), value); } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/Serializer.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/Serializer.java index 979ecb08e87d..fb846cae6a48 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/Serializer.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/Serializer.java @@ -5,13 +5,19 @@ package io.opentelemetry.instrumentation.awssdk.v2_2; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nullable; +import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.core.SdkPojo; import software.amazon.awssdk.http.ContentStreamProvider; import software.amazon.awssdk.http.SdkHttpFullRequest; @@ -21,6 +27,8 @@ class Serializer { + private static final ObjectMapper objectMapper = new ObjectMapper(); + @Nullable String serialize(Object target) { @@ -41,6 +49,41 @@ String serialize(Object target) { return target.toString(); } + @Nullable + String serialize(String attributeName, Object target) { + try { + JsonNode jsonBody; + if (target instanceof SdkBytes) { + String jsonString = ((SdkBytes) target).asUtf8String(); + jsonBody = objectMapper.readTree(jsonString); + } else { + if (target != null) { + return target.toString(); + } + return null; + } + + switch (attributeName) { + case "gen_ai.request.max_tokens": + return getMaxTokens(jsonBody); + case "gen_ai.request.temperature": + return getTemperature(jsonBody); + case "gen_ai.request.top_p": + return getTopP(jsonBody); + case "gen_ai.response.finish_reasons": + return getFinishReasons(jsonBody); + case "gen_ai.usage.input_tokens": + return getInputTokens(jsonBody); + case "gen_ai.usage.output_tokens": + return getOutputTokens(jsonBody); + default: + return null; + } + } catch (JsonProcessingException e) { + return null; + } + } + @Nullable private static String serialize(SdkPojo sdkPojo) { ProtocolMarshaller marshaller = @@ -65,4 +108,162 @@ private String serialize(Collection collection) { String serialized = collection.stream().map(this::serialize).collect(Collectors.joining(",")); return (StringUtils.isEmpty(serialized) ? null : "[" + serialized + "]"); } + + @Nullable + private static String findFirstMatchingPath(JsonNode jsonBody, String... paths) { + if (jsonBody == null) { + return null; + } + + return Stream.of(paths) + .map( + path -> { + JsonNode node = jsonBody.at(path); + if (node != null && !node.isMissingNode()) { + return node.asText(); + } + return null; + }) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + + @Nullable + private static String approximateTokenCount(JsonNode jsonBody, String... textPaths) { + if (jsonBody == null) { + return null; + } + + return Stream.of(textPaths) + .map( + path -> { + JsonNode node = jsonBody.at(path); + if (node != null && !node.isMissingNode()) { + int tokenEstimate = (int) Math.ceil(node.asText().length() / 6.0); + return Integer.toString(tokenEstimate); + } + return null; + }) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/textGenerationConfig/maxTokenCount" + // Anthropic Claude -> "/max_tokens" + // Cohere Command -> "/max_tokens" + // Cohere Command R -> "/max_tokens" + // AI21 Jamba -> "/max_tokens" + // Meta Llama -> "/max_gen_len" + // Mistral AI -> "/max_tokens" + @Nullable + private static String getMaxTokens(JsonNode jsonBody) { + return findFirstMatchingPath( + jsonBody, "/textGenerationConfig/maxTokenCount", "/max_tokens", "/max_gen_len"); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/textGenerationConfig/temperature" + // Anthropic Claude -> "/temperature" + // Cohere Command -> "/temperature" + // Cohere Command R -> "/temperature" + // AI21 Jamba -> "/temperature" + // Meta Llama -> "/temperature" + // Mistral AI -> "/temperature" + @Nullable + private static String getTemperature(JsonNode jsonBody) { + return findFirstMatchingPath(jsonBody, "/textGenerationConfig/temperature", "/temperature"); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/textGenerationConfig/topP" + // Anthropic Claude -> "/top_p" + // Cohere Command -> "/p" + // Cohere Command R -> "/p" + // AI21 Jamba -> "/top_p" + // Meta Llama -> "/top_p" + // Mistral AI -> "/top_p" + @Nullable + private static String getTopP(JsonNode jsonBody) { + return findFirstMatchingPath(jsonBody, "/textGenerationConfig/topP", "/top_p", "/p"); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/results/0/completionReason" + // Anthropic Claude -> "/stop_reason" + // Cohere Command -> "/generations/0/finish_reason" + // Cohere Command R -> "/finish_reason" + // AI21 Jamba -> "/choices/0/finish_reason" + // Meta Llama -> "/stop_reason" + // Mistral AI -> "/outputs/0/stop_reason" + @Nullable + private static String getFinishReasons(JsonNode jsonBody) { + String finishReason = + findFirstMatchingPath( + jsonBody, + "/results/0/completionReason", + "/stop_reason", + "/generations/0/finish_reason", + "/choices/0/finish_reason", + "/outputs/0/stop_reason", + "/finish_reason"); + + return finishReason != null ? "[" + finishReason + "]" : null; + } + + // Model -> Path Mapping: + // Amazon Titan -> "/inputTextTokenCount" + // Anthropic Claude -> "/usage/input_tokens" + // Cohere Command -> "/prompt" + // Cohere Command R -> "/message" + // AI21 Jamba -> "/usage/prompt_tokens" + // Meta Llama -> "/prompt_token_count" + // Mistral AI -> "/prompt" + @Nullable + private static String getInputTokens(JsonNode jsonBody) { + // Try direct tokens counts first + String directCount = + findFirstMatchingPath( + jsonBody, + "/inputTextTokenCount", + "/usage/input_tokens", + "/usage/prompt_tokens", + "/prompt_token_count"); + + if (directCount != null) { + return directCount; + } + + // Fall back to token approximation + return approximateTokenCount(jsonBody, "/prompt", "/message"); + } + + // Model -> Path Mapping: + // Amazon Titan -> "/results/0/tokenCount" + // Anthropic Claude -> "/usage/output_tokens" + // Cohere Command -> "/generations/0/text" + // Cohere Command R -> "/text" + // AI21 Jamba -> "/usage/completion_tokens" + // Meta Llama -> "/generation_token_count" + // Mistral AI -> "/outputs/0/text" + @Nullable + private static String getOutputTokens(JsonNode jsonBody) { + // Try direct token counts first + String directCount = + findFirstMatchingPath( + jsonBody, + "/results/0/tokenCount", + "/usage/output_tokens", + "/usage/completion_tokens", + "/generation_token_count"); + + if (directCount != null) { + return directCount; + } + + // Fall back to token approximation + return approximateTokenCount(jsonBody, "/outputs/0/text", "/text"); + } } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingExecutionInterceptor.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingExecutionInterceptor.java index f717b1efc44c..352b02093ef9 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingExecutionInterceptor.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingExecutionInterceptor.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.awssdk.v2_2; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsExperimentalAttributes.GEN_AI_SYSTEM; +import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.BEDROCKRUNTIME; import static io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkRequestType.DYNAMODB; import io.opentelemetry.api.common.AttributeKey; @@ -42,6 +44,7 @@ /** AWS request execution interceptor. */ final class TracingExecutionInterceptor implements ExecutionInterceptor { + private static final String GEN_AI_SYSTEM_BEDROCK = "aws_bedrock"; // the class name is part of the attribute name, so that it will be shaded when used in javaagent // instrumentation, and won't conflict with usage outside javaagent instrumentation @@ -317,6 +320,10 @@ private void populateRequestAttributes( span.setAttribute(SemanticAttributes.DB_OPERATION, operation); } } + + if (awsSdkRequest.type() == BEDROCKRUNTIME) { + span.setAttribute(GEN_AI_SYSTEM, GEN_AI_SYSTEM_BEDROCK); + } } @Override diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingList.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingList.java index 71994688908c..46491f501bb8 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingList.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/TracingList.java @@ -10,6 +10,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.function.Consumer; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.services.sqs.model.Message; @@ -59,4 +60,11 @@ public Iterator iterator() { return it; } + + @Override + public void forEach(Consumer action) { + for (Message message : this) { + action.accept(message); + } + } } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/testing/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-2.2/testing/build.gradle.kts index 2a7f14d14b72..584b8dda6c07 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/testing/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-2.2/testing/build.gradle.kts @@ -19,6 +19,9 @@ dependencies { compileOnly("software.amazon.awssdk:sqs:2.2.0") compileOnly("software.amazon.awssdk:sns:2.2.0") compileOnly("software.amazon.awssdk:ses:2.2.0") + compileOnly("software.amazon.awssdk:sfn:2.2.0") + compileOnly("software.amazon.awssdk:lambda:2.2.0") + compileOnly("software.amazon.awssdk:secretsmanager:2.2.0") // needed for SQS - using emq directly as localstack references emq v0.15.7 ie WITHOUT AWS trace header propagation implementation("org.elasticmq:elasticmq-rest-sqs_2.12:1.0.0") diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2ClientTest.groovy index 53390c8d8524..692cd005ebe5 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2ClientTest.groovy +++ b/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2ClientTest.groovy @@ -33,8 +33,19 @@ import software.amazon.awssdk.services.sqs.SqsAsyncClient import software.amazon.awssdk.services.sqs.SqsClient import software.amazon.awssdk.services.sqs.model.CreateQueueRequest import software.amazon.awssdk.services.sqs.model.SendMessageRequest +import software.amazon.awssdk.services.sfn.SfnClient +import software.amazon.awssdk.services.sfn.model.DescribeStateMachineRequest +import software.amazon.awssdk.services.sfn.model.DescribeActivityRequest +import software.amazon.awssdk.services.lambda.LambdaClient +import software.amazon.awssdk.services.lambda.model.GetFunctionRequest +import software.amazon.awssdk.services.lambda.model.GetEventSourceMappingRequest +import software.amazon.awssdk.services.sns.SnsClient +import software.amazon.awssdk.services.sns.model.PublishRequest +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest import spock.lang.Unroll + import java.time.Duration import java.util.concurrent.Future @@ -120,7 +131,31 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest { "$SemanticAttributes.MESSAGING_SYSTEM" "AmazonSQS" } else if (service == "Kinesis") { "aws.stream.name" "somestream" + } else if (service == "Bedrock" && operation == "GetGuardrail") { + "aws.bedrock.guardrail.id" "guardrailId" + } else if (service == "BedrockAgent" && operation == "GetAgent") { + "aws.bedrock.agent.id" "agentId" + } else if (service == "BedrockAgent" && operation == "GetKnowledgeBase") { + "aws.bedrock.knowledge_base.id" "knowledgeBaseId" + } else if (service == "BedrockAgent" && operation == "GetDataSource") { + "aws.bedrock.data_source.id" "datasourceId" + } else if (service == "BedrockRuntime" && operation == "InvokeModel") { + "gen_ai.request.model" "meta.llama2-13b-chat-v1" + "gen_ai.system" "aws_bedrock" + } else if (service == "Sfn" && operation == "DescribeStateMachine") { + "aws.stepfunctions.state_machine.arn" "stateMachineArn" + } else if (service == "Sfn" && operation == "DescribeActivity") { + "aws.stepfunctions.activity.arn" "activityArn" + } else if (service == "Lambda" && operation == "GetFunction") { + "aws.lambda.function.name" "functionName" + } else if (service == "Lambda" && operation == "GetEventSourceMapping") { + "aws.lambda.resource_mapping.id" "sourceEventId" + } else if (service == "Sns") { + "aws.sns.topic.arn" "topicArn" + } else if (service == "SecretsManager") { + "aws.secretsmanager.secret.arn" "someSecretArn" } + } } } @@ -162,6 +197,41 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest { 0ac9cda2-bbf4-11d3-f92b-31fa5e8dbc99 """ + "Sfn" | "DescribeStateMachine" | "POST" | "UNKNOWN" | SfnClient.builder() + | { c -> c.describeStateMachine(DescribeStateMachineRequest.builder().stateMachineArn("stateMachineArn").build()) } + | "" + "Sfn" | "DescribeActivity" | "POST" | "UNKNOWN" | SfnClient.builder() + | { c -> c.describeActivity(DescribeActivityRequest.builder().activityArn("activityArn").build()) } + | "" + "Lambda" | "GetFunction" | "GET" | "UNKNOWN" | LambdaClient.builder() + | { c -> c.getFunction(GetFunctionRequest.builder().functionName("functionName").build()) } + | "" + "Lambda" | "GetEventSourceMapping" | "GET" |"UNKNOWN" | LambdaClient.builder() + | { c -> c.getEventSourceMapping(GetEventSourceMappingRequest.builder().uuid("sourceEventId").build()) } + | "" + "Sns" | "Publish" | "POST" | "d74b8436-ae13-5ab4-a9ff-ce54dfea72a0" | SnsClient.builder() + | { c -> c.publish(PublishRequest.builder().topicArn("topicArn").message("message").build()) } + | """ + + + 567910cd-659e-55d4-8ccb-5aaf14679dc0 + + + d74b8436-ae13-5ab4-a9ff-ce54dfea72a0 + + + """ + "SecretsManager" | "GetSecretValue" | "POST" | "UNKNOWN" | SecretsManagerClient.builder() + | { c -> c.getSecretValue(GetSecretValueRequest.builder().secretId("someSecret1").build()) } + | """ + { + "ARN":"someSecretArn", + "CreatedDate":1.523477145713E9, + "Name":"MyTestDatabaseSecret", + "SecretString":"{\\n \\"username\\":\\"david\\",\\n \\"password\\":\\"EXAMPLE-PASSWORD\\"\\n}\\n", + "VersionId":"EXAMPLE1-90ab-cdef-fedc-ba987SECRET1" + } + """ } def "send #operation async request with builder #builder.class.getName() mocked response"() { diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2SqsTracingTest.groovy b/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2SqsTracingTest.groovy index 7cf38cc44b98..6f851dbcf983 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2SqsTracingTest.groovy +++ b/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2SqsTracingTest.groovy @@ -307,7 +307,8 @@ abstract class AbstractAws2SqsTracingTest extends InstrumentationSpecification { then: resp.messages.size() == 1 - resp.messages.each {message -> runWithSpan("process child") {}} + // using forEach instead of each here to test different ways of iterating messages list + resp.messages.forEach {message -> runWithSpan("process child") {}} assertSqsTraces(false, true) } diff --git a/instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/AzureHttpClientInstrumentation.java b/instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/AzureHttpClientInstrumentation.java index 5a27c5ba13e3..2e1a68f2affe 100644 --- a/instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/AzureHttpClientInstrumentation.java +++ b/instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/AzureHttpClientInstrumentation.java @@ -6,12 +6,15 @@ package io.opentelemetry.javaagent.instrumentation.azurecore.v1_36; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface; +import static io.opentelemetry.javaagent.instrumentation.azurecore.v1_36.SuppressNestedClientHelper.disallowNestedClientSpanMono; +import static io.opentelemetry.javaagent.instrumentation.azurecore.v1_36.SuppressNestedClientHelper.disallowNestedClientSpanSync; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; import com.azure.core.http.HttpResponse; +import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; @@ -33,15 +36,37 @@ public void transform(TypeTransformer transformer) { .and(isPublic()) .and(named("send")) .and(returns(named("reactor.core.publisher.Mono"))), - this.getClass().getName() + "$SuppressNestedClientAdvice"); + this.getClass().getName() + "$SuppressNestedClientMonoAdvice"); + transformer.applyAdviceToMethod( + isMethod() + .and(isPublic()) + .and(named("sendSync")) + .and(returns(named("com.azure.core.http.HttpResponse"))), + this.getClass().getName() + "$SuppressNestedClientSyncAdvice"); + } + + @SuppressWarnings("unused") + public static class SuppressNestedClientMonoAdvice { + @Advice.OnMethodExit(suppress = Throwable.class) + public static void asyncSendExit(@Advice.Return(readOnly = false) Mono mono) { + mono = disallowNestedClientSpanMono(mono); + } } @SuppressWarnings("unused") - public static class SuppressNestedClientAdvice { + public static class SuppressNestedClientSyncAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void syncSendEnter(@Advice.Local("otelScope") Scope scope) { + scope = disallowNestedClientSpanSync(); + } @Advice.OnMethodExit(suppress = Throwable.class) - public static void methodExit(@Advice.Return(readOnly = false) Mono mono) { - mono = new SuppressNestedClientMono<>(mono); + public static void syncSendExit( + @Advice.Return HttpResponse response, @Advice.Local("otelScope") Scope scope) { + if (scope != null) { + scope.close(); + } } } } diff --git a/instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/SuppressNestedClientMono.java b/instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/SuppressNestedClientHelper.java similarity index 59% rename from instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/SuppressNestedClientMono.java rename to instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/SuppressNestedClientHelper.java index f899ba48b5bf..ce3bb12e4211 100644 --- a/instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/SuppressNestedClientMono.java +++ b/instrumentation/azure-core/azure-core-1.36/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/azurecore/v1_36/SuppressNestedClientHelper.java @@ -14,24 +14,30 @@ import reactor.core.CoreSubscriber; import reactor.core.publisher.Mono; -public class SuppressNestedClientMono extends Mono { +public class SuppressNestedClientHelper { - private final Mono delegate; - - public SuppressNestedClientMono(Mono delegate) { - this.delegate = delegate; - } - - @Override - public void subscribe(CoreSubscriber actual) { + public static Scope disallowNestedClientSpanSync() { Context parentContext = currentContext(); if (doesNotHaveClientSpan(parentContext)) { - try (Scope ignored = disallowNestedClientSpan(parentContext).makeCurrent()) { - delegate.subscribe(actual); - } - } else { - delegate.subscribe(actual); + return disallowNestedClientSpan(parentContext).makeCurrent(); } + return null; + } + + public static Mono disallowNestedClientSpanMono(Mono delegate) { + return new Mono() { + @Override + public void subscribe(CoreSubscriber coreSubscriber) { + Context parentContext = currentContext(); + if (doesNotHaveClientSpan(parentContext)) { + try (Scope ignored = disallowNestedClientSpan(parentContext).makeCurrent()) { + delegate.subscribe(coreSubscriber); + } + } else { + delegate.subscribe(coreSubscriber); + } + } + }; } private static boolean doesNotHaveClientSpan(Context parentContext) { @@ -44,4 +50,6 @@ private static Context disallowNestedClientSpan(Context parentContext) { return SpanKey.HTTP_CLIENT.storeInContext( SpanKey.KIND_CLIENT.storeInContext(parentContext, span), span); } + + private SuppressNestedClientHelper() {} } diff --git a/instrumentation/azure-core/azure-core-1.36/library-instrumentation-shaded/build.gradle.kts b/instrumentation/azure-core/azure-core-1.36/library-instrumentation-shaded/build.gradle.kts index ed5e44af39b2..940331b69140 100644 --- a/instrumentation/azure-core/azure-core-1.36/library-instrumentation-shaded/build.gradle.kts +++ b/instrumentation/azure-core/azure-core-1.36/library-instrumentation-shaded/build.gradle.kts @@ -7,7 +7,7 @@ plugins { group = "io.opentelemetry.javaagent.instrumentation" dependencies { - implementation("com.azure:azure-core-tracing-opentelemetry:1.0.0-beta.32") + implementation("com.azure:azure-core-tracing-opentelemetry:1.0.0-beta.42") } tasks { diff --git a/instrumentation/azure-core/azure-core-1.36/library-instrumentation-shaded/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracingOptions.java b/instrumentation/azure-core/azure-core-1.36/library-instrumentation-shaded/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracingOptions.java new file mode 100644 index 000000000000..99338d6958ea --- /dev/null +++ b/instrumentation/azure-core/azure-core-1.36/library-instrumentation-shaded/src/main/java/com/azure/core/tracing/opentelemetry/OpenTelemetryTracingOptions.java @@ -0,0 +1,16 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.azure.core.tracing.opentelemetry; + +import com.azure.core.util.TracingOptions; + +/** + * Replace {@link OpenTelemetryTracingOptions} from com.azure:azure-core-tracing-opentelemetry with + * a stub. Auto instrumentation does not use {@link OpenTelemetryTracingOptions}. This is needed + * because {@link OpenTelemetryTracingOptions} calls super constructor in {@link TracingOptions} + * that does exist in com.azure:azure-core:1.36.0 which triggers muzzle failure. + */ +public class OpenTelemetryTracingOptions extends TracingOptions {} diff --git a/instrumentation/dropwizard/dropwizard-testing/build.gradle.kts b/instrumentation/dropwizard/dropwizard-testing/build.gradle.kts index aef551a103c2..601f5e8e6205 100644 --- a/instrumentation/dropwizard/dropwizard-testing/build.gradle.kts +++ b/instrumentation/dropwizard/dropwizard-testing/build.gradle.kts @@ -21,5 +21,9 @@ configurations.testRuntimeClasspath { // requires old logback (and therefore also old slf4j) force("ch.qos.logback:logback-classic:1.2.11") force("org.slf4j:slf4j-api:1.7.36") + + // dropwizard testing is not compatible with jackson 2.16.0 + force("com.fasterxml.jackson.core:jackson-databind:2.15.3") + force("com.fasterxml.jackson.module:jackson-module-afterburner:2.15.3") } } diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/build.gradle.kts b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/build.gradle.kts index 934d51f6805c..4ac2c79ffb65 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/build.gradle.kts +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/build.gradle.kts @@ -59,6 +59,8 @@ dependencies { } tasks.withType().configureEach { + systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) + // TODO run tests both with and without experimental span attributes jvmArgs("-Dotel.instrumentation.elasticsearch.experimental-span-attributes=true") diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy index 62b279220373..45978451d0c9 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringRepositoryTest.groovy @@ -7,8 +7,10 @@ package springdata import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification import io.opentelemetry.semconv.SemanticAttributes +import org.junit.jupiter.api.Assumptions import org.springframework.context.annotation.AnnotationConfigApplicationContext import spock.lang.Shared +import spock.util.environment.Jvm import java.lang.reflect.InvocationHandler import java.lang.reflect.Method @@ -48,7 +50,7 @@ class Elasticsearch53SpringRepositoryTest extends AgentInstrumentationSpecificat } void close() { - applicationContext.close() + applicationContext?.close() } @Override @@ -58,6 +60,9 @@ class Elasticsearch53SpringRepositoryTest extends AgentInstrumentationSpecificat } def setup() { + // when running on jdk 21 this test occasionally fails with timeout + Assumptions.assumeTrue(Boolean.getBoolean("testLatestDeps") || !Jvm.getCurrent().isJava21Compatible()) + repo.refresh() clearExportedData() runWithSpan("delete") { diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy index 3f9ae07bea05..faf1dd312404 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/groovy/springdata/Elasticsearch53SpringTemplateTest.groovy @@ -18,12 +18,14 @@ import org.elasticsearch.node.Node import org.elasticsearch.search.aggregations.bucket.nested.InternalNested import org.elasticsearch.search.aggregations.bucket.terms.Terms import org.elasticsearch.transport.Netty3Plugin +import org.junit.jupiter.api.Assumptions import org.springframework.data.elasticsearch.core.ElasticsearchTemplate import org.springframework.data.elasticsearch.core.ResultsExtractor import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder import org.springframework.data.elasticsearch.core.query.NativeSearchQuery import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder import spock.lang.Shared +import spock.util.environment.Jvm import java.util.concurrent.atomic.AtomicLong @@ -45,7 +47,6 @@ class Elasticsearch53SpringTemplateTest extends AgentInstrumentationSpecificatio ElasticsearchTemplate template def setupSpec() { - esWorkingDir = File.createTempDir("test-es-working-dir-", "") esWorkingDir.deleteOnExit() println "ES work dir: $esWorkingDir" @@ -81,6 +82,11 @@ class Elasticsearch53SpringTemplateTest extends AgentInstrumentationSpecificatio } } + def setup() { + // when running on jdk 21 this test occasionally fails with timeout + Assumptions.assumeTrue(Boolean.getBoolean("testLatestDeps") || !Jvm.getCurrent().isJava21Compatible()) + } + def "test elasticsearch error"() { when: template.refresh(indexName) diff --git a/instrumentation/grails-3.0/javaagent/build.gradle.kts b/instrumentation/grails-3.0/javaagent/build.gradle.kts index c741ff5d6952..5076048d31fe 100644 --- a/instrumentation/grails-3.0/javaagent/build.gradle.kts +++ b/instrumentation/grails-3.0/javaagent/build.gradle.kts @@ -13,7 +13,7 @@ muzzle { // which (also obviously) does not exist skip("3.1.15", "3.3.6") // these versions pass if you add the grails maven repository (https://repo.grails.org/artifactory/core) - skip("3.2.0", "3.3.0", "3.3.1", "3.3.2", "3.3.3", "3.3.10", "3.3.13", "3.3.14", "3.3.15", "3.3.16", "4.0.0", "4.0.1", "4.0.5", "4.0.6", "4.0.7", "4.0.8", "4.0.9", "4.0.10", "4.0.11", "4.0.12", "4.0.13") + skip("3.2.0", "3.3.0", "3.3.1", "3.3.2", "3.3.3", "3.3.10", "3.3.13", "3.3.14", "3.3.15", "3.3.16", "3.3.17", "3.3.18", "4.0.0", "4.0.1", "4.0.5", "4.0.6", "4.0.7", "4.0.8", "4.0.9", "4.0.10", "4.0.11", "4.0.12", "4.0.13") assertInverse.set(true) } } diff --git a/instrumentation/grpc-1.6/javaagent/build.gradle.kts b/instrumentation/grpc-1.6/javaagent/build.gradle.kts index a25ad45d2101..e9ed7bdff45e 100644 --- a/instrumentation/grpc-1.6/javaagent/build.gradle.kts +++ b/instrumentation/grpc-1.6/javaagent/build.gradle.kts @@ -44,3 +44,16 @@ tasks { } } } + +if (!(findProperty("testLatestDeps") as Boolean)) { + configurations.testRuntimeClasspath { + resolutionStrategy { + eachDependency { + // early versions of grpc are not compatible with netty 4.1.101.Final + if (requested.group == "io.netty") { + useVersion("4.1.100.Final") + } + } + } + } +} diff --git a/instrumentation/grpc-1.6/library/build.gradle.kts b/instrumentation/grpc-1.6/library/build.gradle.kts index 807f6950a246..18f55a3a3318 100644 --- a/instrumentation/grpc-1.6/library/build.gradle.kts +++ b/instrumentation/grpc-1.6/library/build.gradle.kts @@ -21,3 +21,16 @@ tasks { systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) } } + +if (!(findProperty("testLatestDeps") as Boolean)) { + configurations.testRuntimeClasspath { + resolutionStrategy { + eachDependency { + // early versions of grpc are not compatible with netty 4.1.101.Final + if (requested.group == "io.netty") { + useVersion("4.1.100.Final") + } + } + } + } +} diff --git a/instrumentation/grpc-1.6/testing/src/main/java/io/opentelemetry/instrumentation/grpc/v1_6/AbstractGrpcTest.java b/instrumentation/grpc-1.6/testing/src/main/java/io/opentelemetry/instrumentation/grpc/v1_6/AbstractGrpcTest.java index 0db883dfd939..da01df6d9aee 100644 --- a/instrumentation/grpc-1.6/testing/src/main/java/io/opentelemetry/instrumentation/grpc/v1_6/AbstractGrpcTest.java +++ b/instrumentation/grpc-1.6/testing/src/main/java/io/opentelemetry/instrumentation/grpc/v1_6/AbstractGrpcTest.java @@ -755,7 +755,10 @@ public void sayHello( t -> { // gRPC doesn't appear to propagate server exceptions that are thrown, not onError. assertThat(t.getStatus().getCode()).isEqualTo(Status.UNKNOWN.getCode()); - assertThat(t.getStatus().getDescription()).isNull(); + assertThat(t.getStatus().getDescription()) + .satisfiesAnyOf( + a -> assertThat(a).isNull(), + a -> assertThat(a).isEqualTo("Application error processing RPC")); }); testing() diff --git a/instrumentation/jmx-metrics/javaagent/src/main/java/io/opentelemetry/instrumentation/javaagent/jmx/JmxMetricInsightInstaller.java b/instrumentation/jmx-metrics/javaagent/src/main/java/io/opentelemetry/instrumentation/javaagent/jmx/JmxMetricInsightInstaller.java index 69b3c09c90d7..74a6f75ffb4f 100644 --- a/instrumentation/jmx-metrics/javaagent/src/main/java/io/opentelemetry/instrumentation/javaagent/jmx/JmxMetricInsightInstaller.java +++ b/instrumentation/jmx-metrics/javaagent/src/main/java/io/opentelemetry/instrumentation/javaagent/jmx/JmxMetricInsightInstaller.java @@ -20,6 +20,7 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; +import java.time.Duration; import java.util.List; /** An {@link AgentListener} that enables JMX metrics during agent startup. */ @@ -32,22 +33,22 @@ public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) { if (config.getBoolean("otel.jmx.enabled", true)) { JmxMetricInsight service = - JmxMetricInsight.createService(GlobalOpenTelemetry.get(), beanDiscoveryDelay(config)); + JmxMetricInsight.createService( + GlobalOpenTelemetry.get(), beanDiscoveryDelay(config).toMillis()); MetricConfiguration conf = buildMetricConfiguration(config); service.start(conf); } } - private static long beanDiscoveryDelay(ConfigProperties configProperties) { - Long discoveryDelay = configProperties.getLong("otel.jmx.discovery.delay"); + private static Duration beanDiscoveryDelay(ConfigProperties configProperties) { + Duration discoveryDelay = configProperties.getDuration("otel.jmx.discovery.delay"); if (discoveryDelay != null) { return discoveryDelay; } // If discovery delay has not been configured, have a peek at the metric export interval. // It makes sense for both of these values to be similar. - long exportInterval = configProperties.getLong("otel.metric.export.interval", 60000); - return exportInterval; + return configProperties.getDuration("otel.metric.export.interval", Duration.ofMinutes(1)); } private static String resourceFor(String platform) { diff --git a/instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/engine/BeanFinder.java b/instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/engine/BeanFinder.java index 8b0fd636bed3..b9856f1dc98c 100644 --- a/instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/engine/BeanFinder.java +++ b/instrumentation/jmx-metrics/library/src/main/java/io/opentelemetry/instrumentation/jmx/engine/BeanFinder.java @@ -25,7 +25,13 @@ class BeanFinder { private final MetricRegistrar registrar; private MetricConfiguration conf; - private final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor(); + private final ScheduledExecutorService exec = + Executors.newSingleThreadScheduledExecutor( + runnable -> { + Thread result = new Thread(runnable, "jmx_bean_finder"); + result.setDaemon(true); + return result; + }); private final long discoveryDelay; private final long maxDelay; private long delay = 1000; // number of milliseconds until first attempt to discover MBeans @@ -39,12 +45,18 @@ class BeanFinder { void discoverBeans(MetricConfiguration conf) { this.conf = conf; - if (!conf.isEmpty()) { - // Issue 9336: Corner case: PlatformMBeanServer will remain unitialized until a direct - // reference to it is made. This call makes sure that the PlatformMBeanServer will be in - // the set of MBeanServers reported by MBeanServerFactory. - ManagementFactory.getPlatformMBeanServer(); - } + exec.schedule( + () -> { + // Issue 9336: Corner case: PlatformMBeanServer will remain unitialized until a direct + // reference to it is made. This call makes sure that the PlatformMBeanServer will be in + // the set of MBeanServers reported by MBeanServerFactory. + // Issue 11143: This call initializes java.util.logging.LogManager. We should not call it + // before application has had a chance to configure custom log manager. This is needed for + // wildfly. + ManagementFactory.getPlatformMBeanServer(); + }, + discoveryDelay, + TimeUnit.MILLISECONDS); exec.schedule( new Runnable() { diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/io/opentelemetry/instrumentation/kafka/internal/AbstractOpenTelemetryMetricsReporterTest.java b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/io/opentelemetry/instrumentation/kafka/internal/AbstractOpenTelemetryMetricsReporterTest.java index 9b46663e96b3..9f937b8fc0bf 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/io/opentelemetry/instrumentation/kafka/internal/AbstractOpenTelemetryMetricsReporterTest.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/io/opentelemetry/instrumentation/kafka/internal/AbstractOpenTelemetryMetricsReporterTest.java @@ -18,6 +18,8 @@ import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.sdk.metrics.data.MetricData; import io.opentelemetry.sdk.metrics.data.PointData; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.Instant; @@ -33,13 +35,12 @@ import org.apache.kafka.clients.CommonClientConfigs; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.clients.consumer.KafkaConsumerAccess; import org.apache.kafka.clients.producer.KafkaProducer; -import org.apache.kafka.clients.producer.KafkaProducerAccess; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.MetricName; import org.apache.kafka.common.metrics.KafkaMetric; +import org.apache.kafka.common.metrics.Metrics; import org.apache.kafka.common.metrics.MetricsReporter; import org.apache.kafka.common.serialization.ByteArrayDeserializer; import org.apache.kafka.common.serialization.ByteArraySerializer; @@ -139,14 +140,36 @@ protected Map consumerConfig() { @Test void noDuplicateMetricsReporter() { - List producerMetricsReporters = - KafkaProducerAccess.getMetricsReporters(producer); + List producerMetricsReporters = getMetricsReporters(producer); assertThat(countOpenTelemetryMetricsReporters(producerMetricsReporters)).isEqualTo(1); - List consumerMetricsReporters = - KafkaConsumerAccess.getMetricsReporters(consumer); + List consumerMetricsReporters = getMetricsReporters(consumer); assertThat(countOpenTelemetryMetricsReporters(consumerMetricsReporters)).isEqualTo(1); } + private static List getMetricsReporters(Object producerOrConsumer) { + return getMetricsRegistry(producerOrConsumer).reporters(); + } + + private static Metrics getMetricsRegistry(Object producerOrConsumer) { + Class clazz = producerOrConsumer.getClass(); + try { + Field field = clazz.getDeclaredField("metrics"); + field.setAccessible(true); + return (Metrics) field.get(producerOrConsumer); + } catch (Exception ignored) { + // Ignore + } + try { + Method method = clazz.getDeclaredMethod("metricsRegistry"); + method.setAccessible(true); + return (Metrics) method.invoke(producerOrConsumer); + } catch (Exception ignored) { + // Ignore + } + throw new IllegalStateException( + "Failed to get metrics registry from " + producerOrConsumer.getClass().getName()); + } + private static long countOpenTelemetryMetricsReporters(List metricsReporters) { return metricsReporters.stream() .filter(reporter -> reporter.getClass().getName().endsWith("OpenTelemetryMetricsReporter")) @@ -176,8 +199,6 @@ void observeMetrics() { "kafka.consumer.join_total", "kafka.consumer.last_heartbeat_seconds_ago", "kafka.consumer.last_rebalance_seconds_ago", - "kafka.consumer.partition_assigned_latency_avg", - "kafka.consumer.partition_assigned_latency_max", "kafka.consumer.rebalance_latency_avg", "kafka.consumer.rebalance_latency_max", "kafka.consumer.rebalance_latency_total", diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumerAccess.java b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumerAccess.java deleted file mode 100644 index 2b698af5dd54..000000000000 --- a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/org/apache/kafka/clients/consumer/KafkaConsumerAccess.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.apache.kafka.clients.consumer; - -import java.util.List; -import org.apache.kafka.common.metrics.MetricsReporter; - -public class KafkaConsumerAccess { - - private KafkaConsumerAccess() {} - - public static List getMetricsReporters(KafkaConsumer consumer) { - return consumer.metrics.reporters(); - } -} diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/org/apache/kafka/clients/producer/KafkaProducerAccess.java b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/org/apache/kafka/clients/producer/KafkaProducerAccess.java deleted file mode 100644 index 6121524f6f92..000000000000 --- a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/org/apache/kafka/clients/producer/KafkaProducerAccess.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.apache.kafka.clients.producer; - -import java.util.List; -import org.apache.kafka.common.metrics.MetricsReporter; - -public class KafkaProducerAccess { - - private KafkaProducerAccess() {} - - public static List getMetricsReporters(KafkaProducer producer) { - return producer.metrics.reporters(); - } -} diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/build.gradle.kts b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/build.gradle.kts index a24c3dbf5b38..2d20bdf26dd0 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/build.gradle.kts +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/build.gradle.kts @@ -19,6 +19,7 @@ dependencies { tasks { withType().configureEach { usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service) + systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) } val testReceiveSpansDisabled by registering(Test::class) { diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/test/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/internal/OpenTelemetryMetricsReporterTest.java b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/test/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/internal/OpenTelemetryMetricsReporterTest.java index 11a48d71d2dc..acce809e39f1 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/test/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/internal/OpenTelemetryMetricsReporterTest.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-2.6/library/src/test/java/io/opentelemetry/instrumentation/kafkaclients/v2_6/internal/OpenTelemetryMetricsReporterTest.java @@ -24,6 +24,7 @@ import java.util.Map; import org.apache.kafka.clients.consumer.KafkaConsumer; import org.apache.kafka.clients.producer.KafkaProducer; +import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -44,6 +45,8 @@ protected InstrumentationExtension testing() { @Test void badConfig() { + Assumptions.assumeFalse(Boolean.getBoolean("testLatestDeps")); + // Bad producer config assertThatThrownBy( () -> { diff --git a/instrumentation/kubernetes-client-7.0/javaagent/build.gradle.kts b/instrumentation/kubernetes-client-7.0/javaagent/build.gradle.kts index 67cf51b7e269..d3d085e6dfbe 100644 --- a/instrumentation/kubernetes-client-7.0/javaagent/build.gradle.kts +++ b/instrumentation/kubernetes-client-7.0/javaagent/build.gradle.kts @@ -14,9 +14,29 @@ muzzle { dependencies { library("io.kubernetes:client-java-api:7.0.0") - implementation(project(":instrumentation:okhttp:okhttp-3.0:javaagent")) - testInstrumentation(project(":instrumentation:okhttp:okhttp-3.0:javaagent")) + + latestDepTestLibrary("io.kubernetes:client-java-api:19.+") +} + +testing { + suites { + val version20Test by registering(JvmTestSuite::class) { + dependencies { + if (findProperty("testLatestDeps") as Boolean) { + implementation("io.kubernetes:client-java-api:+") + } else { + implementation("io.kubernetes:client-java-api:20.0.0") + } + } + } + } +} + +tasks { + check { + dependsOn(testing.suites) + } } tasks.withType().configureEach { diff --git a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java index 7b95f6a95893..1800e32aaca4 100644 --- a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java +++ b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/ApiClientInstrumentation.java @@ -35,7 +35,7 @@ public ElementMatcher typeMatcher() { @Override public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod( - isPublic().and(named("buildRequest")).and(takesArguments(10)), + isPublic().and(named("buildRequest")).and(takesArguments(10).or(takesArguments(11))), this.getClass().getName() + "$BuildRequestAdvice"); transformer.applyAdviceToMethod( isPublic() diff --git a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesRequestDigest.java b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesRequestDigest.java index e53504ff1a58..a3365c342224 100644 --- a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesRequestDigest.java +++ b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesRequestDigest.java @@ -89,7 +89,7 @@ public KubernetesVerb getVerb() { @Override public String toString() { if (isNonResourceRequest) { - return verb.value() + ' ' + urlPath; + return (verb != null ? verb.value() + ' ' : "") + urlPath; } String groupVersion; diff --git a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesResource.java b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesResource.java index 57b10b3db5f2..31413a790c08 100644 --- a/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesResource.java +++ b/instrumentation/kubernetes-client-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesResource.java @@ -12,7 +12,7 @@ class KubernetesResource { public static final Pattern CORE_RESOURCE_URL_PATH_PATTERN = Pattern.compile( - "^/api/v1(/namespaces/(?[\\w-]+))?/(?[\\w-]+)(/(?[\\w-]+))?(/(?[\\w-]+))?"); + "^/api/v1(/namespaces/(?[\\w-]+))?/(?[\\w-]+)(/(?[\\w-]+))?(/(?[\\w-]+))?(/.*)?"); public static final Pattern REGULAR_RESOURCE_URL_PATH_PATTERN = Pattern.compile( diff --git a/instrumentation/kubernetes-client-7.0/javaagent/src/version20Test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientVer20Test.java b/instrumentation/kubernetes-client-7.0/javaagent/src/version20Test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientVer20Test.java new file mode 100644 index 000000000000..dc9c44c1fa16 --- /dev/null +++ b/instrumentation/kubernetes-client-7.0/javaagent/src/version20Test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientVer20Test.java @@ -0,0 +1,289 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.kubernetesclient; + +import static io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil.orderByRootSpanName; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static org.assertj.core.api.Assertions.assertThat; + +import io.kubernetes.client.openapi.ApiCallback; +import io.kubernetes.client.openapi.ApiClient; +import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.apis.CoreV1Api; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.semconv.SemanticAttributes; +import io.opentelemetry.testing.internal.armeria.common.HttpResponse; +import io.opentelemetry.testing.internal.armeria.common.HttpStatus; +import io.opentelemetry.testing.internal.armeria.common.MediaType; +import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.MockWebServerExtension; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; +import org.assertj.core.api.AbstractAssert; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +@SuppressWarnings("deprecation") // until old http semconv are dropped in 2.0 +class KubernetesClientVer20Test { + + private static final String TEST_USER_AGENT = "test-user-agent"; + + @RegisterExtension + private static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private final MockWebServerExtension mockWebServer = new MockWebServerExtension(); + + private CoreV1Api coreV1Api; + + @BeforeEach + void beforeEach() { + mockWebServer.start(); + ApiClient apiClient = new ApiClient(); + apiClient.setUserAgent(TEST_USER_AGENT); + apiClient.setBasePath(mockWebServer.httpUri().toString()); + coreV1Api = new CoreV1Api(apiClient); + } + + @AfterEach + void afterEach() { + mockWebServer.stop(); + } + + @Test + void synchronousCall() throws ApiException { + mockWebServer.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, "42")); + String response = + testing.runWithSpan( + "parent", + () -> + coreV1Api + .connectGetNamespacedPodProxyWithPath("name", "namespace", "path") + .execute()); + + assertThat(response).isEqualTo("42"); + assertThat(mockWebServer.takeRequest().request().headers().get("traceparent")).isNotBlank(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName("get pods/proxy") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo( + SemanticAttributes.HTTP_URL, + mockWebServer.httpUri() + + "/api/v1/namespaces/namespace/pods/name/proxy/path"), + equalTo(SemanticAttributes.HTTP_METHOD, "GET"), + equalTo(SemanticAttributes.HTTP_STATUS_CODE, 200), + equalTo(SemanticAttributes.NET_PEER_NAME, "127.0.0.1"), + equalTo(SemanticAttributes.NET_PEER_PORT, mockWebServer.httpPort()), + satisfies( + SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH, + AbstractAssert::isNotNull), + equalTo( + AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"), + equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name")))); + } + + @Test + void handleErrorsInSyncCall() { + mockWebServer.enqueue( + HttpResponse.of(HttpStatus.valueOf(451), MediaType.PLAIN_TEXT_UTF_8, "42")); + ApiException exception = null; + try { + testing.runWithSpan( + "parent", + () -> { + coreV1Api.connectGetNamespacedPodProxyWithPath("name", "namespace", "path").execute(); + }); + } catch (ApiException e) { + exception = e; + } + ApiException apiException = exception; + assertThat(apiException).isNotNull(); + assertThat(mockWebServer.takeRequest().request().headers().get("traceparent")).isNotBlank(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("parent") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(apiException), + span -> + span.hasName("get pods/proxy") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasStatus(StatusData.error()) + .hasException(apiException) + .hasAttributesSatisfyingExactly( + equalTo( + SemanticAttributes.HTTP_URL, + mockWebServer.httpUri() + + "/api/v1/namespaces/namespace/pods/name/proxy/path"), + equalTo(SemanticAttributes.HTTP_METHOD, "GET"), + equalTo(SemanticAttributes.HTTP_STATUS_CODE, 451), + equalTo(SemanticAttributes.NET_PEER_NAME, "127.0.0.1"), + equalTo(SemanticAttributes.NET_PEER_PORT, mockWebServer.httpPort()), + satisfies( + SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH, + AbstractAssert::isNotNull), + equalTo( + AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"), + equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name")))); + } + + @Test + void asynchronousCall() throws ApiException, InterruptedException { + mockWebServer.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, "42")); + + AtomicReference responseBodyReference = new AtomicReference<>(); + CountDownLatch countDownLatch = new CountDownLatch(1); + + testing.runWithSpan( + "parent", + () -> { + coreV1Api + .connectGetNamespacedPodProxyWithPath("name", "namespace", "path") + .executeAsync( + new ApiCallbackTemplate() { + @Override + public void onSuccess( + String result, int statusCode, Map> responseHeaders) { + responseBodyReference.set(result); + countDownLatch.countDown(); + testing.runWithSpan("callback", () -> {}); + } + }); + }); + + countDownLatch.await(); + + assertThat(responseBodyReference.get()).isEqualTo("42"); + assertThat(mockWebServer.takeRequest().request().headers().get("traceparent")).isNotBlank(); + + testing.waitAndAssertSortedTraces( + orderByRootSpanName("parent", "get pods/proxy", "callback"), + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName("get pods/proxy") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo( + SemanticAttributes.HTTP_URL, + mockWebServer.httpUri() + + "/api/v1/namespaces/namespace/pods/name/proxy/path"), + equalTo(SemanticAttributes.HTTP_METHOD, "GET"), + equalTo(SemanticAttributes.HTTP_STATUS_CODE, 200), + equalTo(SemanticAttributes.NET_PEER_NAME, "127.0.0.1"), + equalTo(SemanticAttributes.NET_PEER_PORT, mockWebServer.httpPort()), + satisfies( + SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH, + AbstractAssert::isNotNull), + equalTo( + AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"), + equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name")), + span -> + span.hasName("callback") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + @Test + void handleErrorsInAsynchronousCall() throws ApiException, InterruptedException { + + mockWebServer.enqueue( + HttpResponse.of(HttpStatus.valueOf(451), MediaType.PLAIN_TEXT_UTF_8, "42")); + + AtomicReference exceptionReference = new AtomicReference<>(); + CountDownLatch countDownLatch = new CountDownLatch(1); + + testing.runWithSpan( + "parent", + () -> { + coreV1Api + .connectGetNamespacedPodProxyWithPath("name", "namespace", "path") + .executeAsync( + new ApiCallbackTemplate() { + @Override + public void onFailure( + ApiException e, int statusCode, Map> responseHeaders) { + exceptionReference.set(e); + countDownLatch.countDown(); + testing.runWithSpan("callback", () -> {}); + } + }); + }); + + countDownLatch.await(); + + assertThat(exceptionReference.get()).isNotNull(); + assertThat(mockWebServer.takeRequest().request().headers().get("traceparent")).isNotBlank(); + + testing.waitAndAssertSortedTraces( + orderByRootSpanName("parent", "get pods/proxy", "callback"), + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasName("get pods/proxy") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasStatus(StatusData.error()) + .hasException(exceptionReference.get()) + .hasAttributesSatisfyingExactly( + equalTo( + SemanticAttributes.HTTP_URL, + mockWebServer.httpUri() + + "/api/v1/namespaces/namespace/pods/name/proxy/path"), + equalTo(SemanticAttributes.HTTP_METHOD, "GET"), + equalTo(SemanticAttributes.HTTP_STATUS_CODE, 451), + equalTo(SemanticAttributes.NET_PEER_NAME, "127.0.0.1"), + equalTo(SemanticAttributes.NET_PEER_PORT, mockWebServer.httpPort()), + satisfies( + SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH, + AbstractAssert::isNotNull), + equalTo( + AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"), + equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name")), + span -> + span.hasName("callback") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } + + private static class ApiCallbackTemplate implements ApiCallback { + @Override + public void onFailure( + ApiException e, int statusCode, Map> responseHeaders) {} + + @Override + public void onSuccess( + String result, int statusCode, Map> responseHeaders) {} + + @Override + public void onUploadProgress(long bytesWritten, long contentLength, boolean done) {} + + @Override + public void onDownloadProgress(long bytesRead, long contentLength, boolean done) {} + } +} diff --git a/instrumentation/log4j/log4j-appender-2.17/javaagent/build.gradle.kts b/instrumentation/log4j/log4j-appender-2.17/javaagent/build.gradle.kts index 022c1c049eb9..6bee5f29b074 100644 --- a/instrumentation/log4j/log4j-appender-2.17/javaagent/build.gradle.kts +++ b/instrumentation/log4j/log4j-appender-2.17/javaagent/build.gradle.kts @@ -22,9 +22,10 @@ dependencies { testImplementation("org.awaitility:awaitility") - // this dependency is needed for the slf4j->log4j test if (testLatestDeps) { - testImplementation("org.apache.logging.log4j:log4j-slf4j2-impl:2.19.0") + // this dependency is needed for the slf4j->log4j test + testImplementation("org.apache.logging.log4j:log4j-slf4j2-impl:2.+") + testCompileOnly("biz.aQute.bnd:biz.aQute.bnd.annotation:7.0.0") } else { // log4j 2.17 doesn't have an slf4j2 bridge testImplementation("org.apache.logging.log4j:log4j-slf4j-impl:2.17.0") diff --git a/instrumentation/log4j/log4j-appender-2.17/library/build.gradle.kts b/instrumentation/log4j/log4j-appender-2.17/library/build.gradle.kts index 6a48ee260f96..4296c4f3da75 100644 --- a/instrumentation/log4j/log4j-appender-2.17/library/build.gradle.kts +++ b/instrumentation/log4j/log4j-appender-2.17/library/build.gradle.kts @@ -6,4 +6,8 @@ dependencies { library("org.apache.logging.log4j:log4j-core:2.17.0") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") + + if (findProperty("testLatestDeps") as Boolean) { + testCompileOnly("biz.aQute.bnd:biz.aQute.bnd.annotation:7.0.0") + } } diff --git a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/FutureListenerWrappers.java b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/FutureListenerWrappers.java index 3f0d3f764e3d..b1a7e6eb24c4 100644 --- a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/FutureListenerWrappers.java +++ b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/FutureListenerWrappers.java @@ -43,7 +43,7 @@ protected Boolean computeValue(Class type) { }; public static boolean shouldWrap(GenericFutureListener> listener) { - return shouldWrap.get(listener.getClass()); + return listener != null && shouldWrap.get(listener.getClass()); } @SuppressWarnings("unchecked") diff --git a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/NettyFutureInstrumentation.java b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/NettyFutureInstrumentation.java index 2948fd77b656..49a0b86756bf 100644 --- a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/NettyFutureInstrumentation.java +++ b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4/common/NettyFutureInstrumentation.java @@ -82,6 +82,8 @@ public static void wrapListener( for (int i = 0; i < listeners.length; ++i) { if (FutureListenerWrappers.shouldWrap(listeners[i])) { wrappedListeners[i] = FutureListenerWrappers.wrap(context, listeners[i]); + } else { + wrappedListeners[i] = listeners[i]; } } listeners = wrappedListeners; diff --git a/instrumentation/netty/netty-4.1/library/src/main/java/io/opentelemetry/instrumentation/netty/v4_1/internal/server/HttpServerRequestTracingHandler.java b/instrumentation/netty/netty-4.1/library/src/main/java/io/opentelemetry/instrumentation/netty/v4_1/internal/server/HttpServerRequestTracingHandler.java index 69f90c7e8815..14618125bd8f 100644 --- a/instrumentation/netty/netty-4.1/library/src/main/java/io/opentelemetry/instrumentation/netty/v4_1/internal/server/HttpServerRequestTracingHandler.java +++ b/instrumentation/netty/netty-4.1/library/src/main/java/io/opentelemetry/instrumentation/netty/v4_1/internal/server/HttpServerRequestTracingHandler.java @@ -73,12 +73,13 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception } @Override - public void channelInactive(ChannelHandlerContext ctx) { + public void channelInactive(ChannelHandlerContext ctx) throws Exception { // connection was closed, close all remaining requests Attribute> contextAttr = ctx.channel().attr(AttributeKeys.SERVER_CONTEXT); Deque serverContexts = contextAttr.get(); if (serverContexts == null) { + super.channelInactive(ctx); return; } @@ -86,6 +87,7 @@ public void channelInactive(ChannelHandlerContext ctx) { while ((serverContext = serverContexts.pollFirst()) != null) { instrumenter.end(serverContext.context(), serverContext.request(), null, null); } + super.channelInactive(ctx); } private static Deque getOrCreate(Channel channel, AttributeKey> key) { diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/InstrumentationApiContextBridging.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/InstrumentationApiContextBridging.java index 2c1e36124395..eed3c4d281df 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/InstrumentationApiContextBridging.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/context/InstrumentationApiContextBridging.java @@ -59,12 +59,14 @@ final class InstrumentationApiContextBridging { private static final MethodHandle AGENT_GET_METHOD; private static final MethodHandle AGENT_GET_ROUTE; private static final MethodHandle AGENT_GET_UPDATED_BY_SOURCE_ORDER; + private static final MethodHandle AGENT_GET_SPAN; private static final Class APPLICATION_HTTP_ROUTE_STATE; private static final MethodHandle APPLICATION_CREATE; private static final MethodHandle APPLICATION_GET_METHOD; private static final MethodHandle APPLICATION_GET_ROUTE; private static final MethodHandle APPLICATION_GET_UPDATED_BY_SOURCE_ORDER; + private static final MethodHandle APPLICATION_GET_SPAN; static { MethodHandles.Lookup lookup = MethodHandles.lookup(); @@ -74,11 +76,13 @@ final class InstrumentationApiContextBridging { MethodHandle agentGetMethod = null; MethodHandle agentGetRoute = null; MethodHandle agentGetUpdatedBySourceOrder = null; + MethodHandle agentGetSpan = null; Class applicationHttpRouteState = null; MethodHandle applicationCreate = null; MethodHandle applicationGetMethod = null; MethodHandle applicationGetRoute = null; MethodHandle applicationGetUpdatedBySourceOrder = null; + MethodHandle applicationGetSpan = null; try { agentHttpRouteState = @@ -87,7 +91,12 @@ final class InstrumentationApiContextBridging { lookup.findStatic( agentHttpRouteState, "create", - MethodType.methodType(agentHttpRouteState, String.class, String.class, int.class)); + MethodType.methodType( + agentHttpRouteState, + String.class, + String.class, + int.class, + io.opentelemetry.api.trace.Span.class)); agentGetMethod = lookup.findVirtual(agentHttpRouteState, "getMethod", MethodType.methodType(String.class)); agentGetRoute = @@ -95,15 +104,30 @@ final class InstrumentationApiContextBridging { agentGetUpdatedBySourceOrder = lookup.findVirtual( agentHttpRouteState, "getUpdatedBySourceOrder", MethodType.methodType(int.class)); + agentGetSpan = + lookup.findVirtual( + agentHttpRouteState, + "getSpan", + MethodType.methodType(io.opentelemetry.api.trace.Span.class)); applicationHttpRouteState = Class.forName("application.io.opentelemetry.instrumentation.api.internal.HttpRouteState"); - applicationCreate = - lookup.findStatic( - applicationHttpRouteState, - "create", - MethodType.methodType( - applicationHttpRouteState, String.class, String.class, int.class)); + try { + applicationCreate = + lookup.findStatic( + applicationHttpRouteState, + "create", + MethodType.methodType( + applicationHttpRouteState, String.class, String.class, int.class, Span.class)); + } catch (NoSuchMethodException exception) { + // older instrumentation-api has only the variant that does not take span + applicationCreate = + lookup.findStatic( + applicationHttpRouteState, + "create", + MethodType.methodType( + applicationHttpRouteState, String.class, String.class, int.class)); + } applicationGetMethod = lookup.findVirtual( applicationHttpRouteState, "getMethod", MethodType.methodType(String.class)); @@ -115,6 +139,13 @@ final class InstrumentationApiContextBridging { applicationHttpRouteState, "getUpdatedBySourceOrder", MethodType.methodType(int.class)); + try { + applicationGetSpan = + lookup.findVirtual( + applicationHttpRouteState, "getSpan", MethodType.methodType(Span.class)); + } catch (NoSuchMethodException ignored) { + // not present in older instrumentation-api + } } catch (Throwable ignored) { // instrumentation-api may be absent on the classpath, or it might be an older version } @@ -124,11 +155,13 @@ final class InstrumentationApiContextBridging { AGENT_GET_METHOD = agentGetMethod; AGENT_GET_ROUTE = agentGetRoute; AGENT_GET_UPDATED_BY_SOURCE_ORDER = agentGetUpdatedBySourceOrder; + AGENT_GET_SPAN = agentGetSpan; APPLICATION_HTTP_ROUTE_STATE = applicationHttpRouteState; APPLICATION_CREATE = applicationCreate; APPLICATION_GET_METHOD = applicationGetMethod; APPLICATION_GET_ROUTE = applicationGetRoute; APPLICATION_GET_UPDATED_BY_SOURCE_ORDER = applicationGetUpdatedBySourceOrder; + APPLICATION_GET_SPAN = applicationGetSpan; } @Nullable @@ -151,12 +184,16 @@ final class InstrumentationApiContextBridging { APPLICATION_CREATE, AGENT_GET_METHOD, AGENT_GET_ROUTE, - AGENT_GET_UPDATED_BY_SOURCE_ORDER), + AGENT_GET_UPDATED_BY_SOURCE_ORDER, + AGENT_GET_SPAN, + o -> o != null ? Bridging.toApplication((io.opentelemetry.api.trace.Span) o) : null), httpRouteStateConvert( AGENT_CREATE, APPLICATION_GET_METHOD, APPLICATION_GET_ROUTE, - APPLICATION_GET_UPDATED_BY_SOURCE_ORDER)); + APPLICATION_GET_UPDATED_BY_SOURCE_ORDER, + APPLICATION_GET_SPAN, + o -> o != null ? Bridging.toAgentOrNull((Span) o) : null)); } catch (Throwable ignored) { return null; } @@ -166,12 +203,18 @@ private static Function httpRouteStateConvert( MethodHandle create, MethodHandle getMethod, MethodHandle getRoute, - MethodHandle getUpdatedBySourceOrder) { + MethodHandle getUpdatedBySourceOrder, + MethodHandle getSpan, + Function convertSpan) { return httpRouteHolder -> { try { String method = (String) getMethod.invoke(httpRouteHolder); String route = (String) getRoute.invoke(httpRouteHolder); int updatedBySourceOrder = (int) getUpdatedBySourceOrder.invoke(httpRouteHolder); + if (create.type().parameterCount() == 4 && getSpan != null) { + Object span = convertSpan.apply(getSpan.invoke(httpRouteHolder)); + return create.invoke(method, route, updatedBySourceOrder, span); + } return create.invoke(method, route, updatedBySourceOrder); } catch (Throwable e) { return null; diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.27/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_27/ApplicationOpenTelemetry127.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.27/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_27/ApplicationOpenTelemetry127.java index 35ab4715541b..bb9663677b3b 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.27/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_27/ApplicationOpenTelemetry127.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.27/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_27/ApplicationOpenTelemetry127.java @@ -63,18 +63,39 @@ public ContextPropagators getPropagators() { } private static ApplicationMeterFactory getMeterFactory() { - try { + // this class is defined in opentelemetry-api-1.32 + ApplicationMeterFactory meterFactory = + getMeterFactory( + "io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator.metrics.ApplicationMeterFactory132Incubator"); + if (meterFactory == null) { + // this class is defined in opentelemetry-api-1.32 + meterFactory = + getMeterFactory( + "io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.metrics.ApplicationMeterFactory132"); + } + if (meterFactory == null) { // this class is defined in opentelemetry-api-1.31 - Class clazz = - Class.forName( + meterFactory = + getMeterFactory( "io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_31.metrics.ApplicationMeterFactory131"); + } + if (meterFactory == null) { + meterFactory = new ApplicationMeterFactory115(); + } + + return meterFactory; + } + + private static ApplicationMeterFactory getMeterFactory(String className) { + try { + Class clazz = Class.forName(className); return (ApplicationMeterFactory) clazz.getConstructor().newInstance(); } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException exception) { - return new ApplicationMeterFactory115(); + return null; } } } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/build.gradle.kts b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/build.gradle.kts index 149aa266e99b..6968e8bb3206 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/build.gradle.kts +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/build.gradle.kts @@ -14,3 +14,12 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-extension-incubator") } + +configurations.configureEach { + if (name == "testRuntimeClasspath" || name == "testCompileClasspath") { + resolutionStrategy { + force("io.opentelemetry:opentelemetry-api:1.31.0") + force("io.opentelemetry:opentelemetry-extension-incubator:1.31.0-alpha") + } + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationDoubleHistogramBuilder131.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationDoubleHistogramBuilder131.java index c26e92381f60..485ac714929b 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationDoubleHistogramBuilder131.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationDoubleHistogramBuilder131.java @@ -9,9 +9,10 @@ import application.io.opentelemetry.api.metrics.LongHistogramBuilder; import application.io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.Bridging; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationDoubleHistogramBuilder; import java.util.List; -final class ApplicationDoubleHistogramBuilder131 extends ApplicationDoubleHistogramBuilder132 +final class ApplicationDoubleHistogramBuilder131 extends ApplicationDoubleHistogramBuilder implements ExtendedDoubleHistogramBuilder { private final io.opentelemetry.api.metrics.DoubleHistogramBuilder agentBuilder; diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationLongHistogramBuilder131.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationLongHistogramBuilder131.java index 9b86334a88cc..d46fc99d08c1 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationLongHistogramBuilder131.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationLongHistogramBuilder131.java @@ -8,9 +8,10 @@ import application.io.opentelemetry.api.common.AttributeKey; import application.io.opentelemetry.extension.incubator.metrics.ExtendedLongHistogramBuilder; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.Bridging; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationLongHistogramBuilder; import java.util.List; -final class ApplicationLongHistogramBuilder131 extends ApplicationLongHistogramBuilder132 +final class ApplicationLongHistogramBuilder131 extends ApplicationLongHistogramBuilder implements ExtendedLongHistogramBuilder { private final io.opentelemetry.api.metrics.LongHistogramBuilder agentBuilder; diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationMeter131.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationMeter131.java index 66d159215c48..688568523fdc 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationMeter131.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationMeter131.java @@ -11,11 +11,11 @@ import application.io.opentelemetry.api.metrics.LongUpDownCounterBuilder; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_15.metrics.ApplicationMeter115; -class ApplicationMeter131 extends ApplicationMeter115 { +public class ApplicationMeter131 extends ApplicationMeter115 { private final io.opentelemetry.api.metrics.Meter agentMeter; - ApplicationMeter131(io.opentelemetry.api.metrics.Meter agentMeter) { + protected ApplicationMeter131(io.opentelemetry.api.metrics.Meter agentMeter) { super(agentMeter); this.agentMeter = agentMeter; } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/build.gradle.kts b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/build.gradle.kts new file mode 100644 index 000000000000..fc59c934fdc9 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/build.gradle.kts @@ -0,0 +1,31 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +dependencies { + compileOnly(project(":opentelemetry-api-shaded-for-instrumenting", configuration = "v1_32")) + compileOnly("io.opentelemetry:opentelemetry-extension-incubator") + + implementation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:javaagent")) + implementation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.4:javaagent")) + implementation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.10:javaagent")) + implementation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.15:javaagent")) + implementation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.27:javaagent")) + implementation(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.31:javaagent")) +} + +testing { + suites { + val incubatorTest by registering(JvmTestSuite::class) { + dependencies { + implementation("io.opentelemetry:opentelemetry-extension-incubator") + } + } + } +} + +tasks { + check { + dependsOn(testing.suites) + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/incubatorTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/MeterTest.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/incubatorTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/MeterTest.java new file mode 100644 index 000000000000..2c8446897eb2 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/incubatorTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/MeterTest.java @@ -0,0 +1,468 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator.metrics; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.DoubleCounter; +import io.opentelemetry.api.metrics.DoubleCounterBuilder; +import io.opentelemetry.api.metrics.DoubleGaugeBuilder; +import io.opentelemetry.api.metrics.DoubleHistogram; +import io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.api.metrics.DoubleUpDownCounter; +import io.opentelemetry.api.metrics.DoubleUpDownCounterBuilder; +import io.opentelemetry.api.metrics.LongCounter; +import io.opentelemetry.api.metrics.LongCounterBuilder; +import io.opentelemetry.api.metrics.LongGaugeBuilder; +import io.opentelemetry.api.metrics.LongHistogram; +import io.opentelemetry.api.metrics.LongHistogramBuilder; +import io.opentelemetry.api.metrics.LongUpDownCounter; +import io.opentelemetry.api.metrics.LongUpDownCounterBuilder; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.ObservableDoubleGauge; +import io.opentelemetry.api.metrics.ObservableLongGauge; +import io.opentelemetry.extension.incubator.metrics.DoubleGauge; +import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleCounterBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleGaugeBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleUpDownCounterBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedLongCounterBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedLongGaugeBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedLongHistogramBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedLongUpDownCounterBuilder; +import io.opentelemetry.extension.incubator.metrics.LongGauge; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; +import org.assertj.core.api.AbstractIterableAssert; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.extension.RegisterExtension; + +class MeterTest { + + @RegisterExtension + static final AgentInstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private String instrumentationName; + private Meter meter; + + @BeforeEach + void setupMeter(TestInfo test) { + instrumentationName = "test-" + test.getDisplayName(); + meter = + testing + .getOpenTelemetry() + .getMeterProvider() + .meterBuilder(instrumentationName) + .setInstrumentationVersion("1.2.3") + .setSchemaUrl("http://schema.org") + .build(); + } + + @Test + void longCounter() { + LongCounterBuilder builder = meter.counterBuilder("test").setDescription("d").setUnit("u"); + assertThat(builder).isInstanceOf(ExtendedLongCounterBuilder.class); + ExtendedLongCounterBuilder extendedBuilder = (ExtendedLongCounterBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + LongCounter instrument = builder.build(); + + instrument.add(5, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + instrument.add(6, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasLongSumSatisfying( + sum -> + sum.isMonotonic() + .hasPointsSatisfying( + point -> + point + .hasValue(11) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + } + + @Test + void doubleCounter() { + DoubleCounterBuilder builder = + meter.counterBuilder("test").ofDoubles().setDescription("d").setUnit("u"); + assertThat(builder).isInstanceOf(ExtendedDoubleCounterBuilder.class); + ExtendedDoubleCounterBuilder extendedBuilder = (ExtendedDoubleCounterBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + DoubleCounter instrument = builder.build(); + + instrument.add(5.5, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + instrument.add(6.6, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasDoubleSumSatisfying( + sum -> + sum.isMonotonic() + .hasPointsSatisfying( + point -> + point + .hasValue(12.1) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + } + + @Test + void longUpDownCounter() { + LongUpDownCounterBuilder builder = + meter.upDownCounterBuilder("test").setDescription("d").setUnit("u"); + assertThat(builder).isInstanceOf(ExtendedLongUpDownCounterBuilder.class); + ExtendedLongUpDownCounterBuilder extendedBuilder = (ExtendedLongUpDownCounterBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + LongUpDownCounter instrument = builder.build(); + + instrument.add(5, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + instrument.add(6, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasLongSumSatisfying( + sum -> + sum.isNotMonotonic() + .hasPointsSatisfying( + point -> + point + .hasValue(11) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + } + + @Test + void doubleUpDownCounter() { + DoubleUpDownCounterBuilder builder = + meter.upDownCounterBuilder("test").ofDoubles().setDescription("d").setUnit("u"); + assertThat(builder).isInstanceOf(ExtendedDoubleUpDownCounterBuilder.class); + ExtendedDoubleUpDownCounterBuilder extendedBuilder = + (ExtendedDoubleUpDownCounterBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + DoubleUpDownCounter instrument = builder.build(); + + instrument.add(5.5, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + instrument.add(6.6, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasDoubleSumSatisfying( + sum -> + sum.isNotMonotonic() + .hasPointsSatisfying( + point -> + point + .hasValue(12.1) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + } + + @Test + void longHistogram() { + LongHistogramBuilder builder = + meter.histogramBuilder("test").ofLongs().setDescription("d").setUnit("u"); + builder.setExplicitBucketBoundariesAdvice(singletonList(10L)); + assertThat(builder).isInstanceOf(ExtendedLongHistogramBuilder.class); + ExtendedLongHistogramBuilder extendedBuilder = (ExtendedLongHistogramBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + LongHistogram instrument = builder.build(); + + instrument.record(5, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + instrument.record(6, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> + point + .hasSum(11.0) + .hasBucketBoundaries(10.0) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + } + + @Test + void doubleHistogram() { + DoubleHistogramBuilder builder = + meter.histogramBuilder("test").setDescription("d").setUnit("u"); + builder.setExplicitBucketBoundariesAdvice(singletonList(10.0)); + assertThat(builder).isInstanceOf(ExtendedDoubleHistogramBuilder.class); + ExtendedDoubleHistogramBuilder extendedBuilder = (ExtendedDoubleHistogramBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + DoubleHistogram instrument = builder.build(); + + instrument.record(5.5, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + instrument.record(6.6, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> + point + .hasSum(12.1) + .hasBucketBoundaries(10.0) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + } + + @Test + void longGauge() throws InterruptedException { + LongGaugeBuilder builder = + meter.gaugeBuilder("test").ofLongs().setDescription("d").setUnit("u"); + assertThat(builder).isInstanceOf(ExtendedLongGaugeBuilder.class); + ExtendedLongGaugeBuilder extendedBuilder = (ExtendedLongGaugeBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + ObservableLongGauge observableGauge = + builder.buildWithCallback( + result -> + result.record(123, Attributes.of(stringKey("test"), "test", stringKey("q"), "r"))); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasLongGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(123) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + + observableGauge.close(); + + // sleep exporter interval + Thread.sleep(100); + testing.clearData(); + Thread.sleep(100); + + testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty); + } + + @Test + void syncLongGauge() throws InterruptedException { + LongGaugeBuilder builder = + meter.gaugeBuilder("test").ofLongs().setDescription("d").setUnit("u"); + assertThat(builder).isInstanceOf(ExtendedLongGaugeBuilder.class); + ExtendedLongGaugeBuilder extendedBuilder = (ExtendedLongGaugeBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + LongGauge longGauge = extendedBuilder.build(); + longGauge.set(321); + longGauge.set(123, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasLongGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> point.hasValue(321).hasAttributes(Attributes.empty()), + point -> + point + .hasValue(123) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + + // sleep exporter interval + Thread.sleep(100); + testing.clearData(); + Thread.sleep(100); + + testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty); + } + + @Test + void doubleGauge() throws InterruptedException { + DoubleGaugeBuilder builder = meter.gaugeBuilder("test").setDescription("d").setUnit("u"); + assertThat(builder).isInstanceOf(ExtendedDoubleGaugeBuilder.class); + ExtendedDoubleGaugeBuilder extendedBuilder = (ExtendedDoubleGaugeBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + ObservableDoubleGauge observableGauge = + builder.buildWithCallback( + result -> + result.record(1.23, Attributes.of(stringKey("test"), "test", stringKey("q"), "r"))); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> + point + .hasValue(1.23) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + + observableGauge.close(); + + // sleep exporter interval + Thread.sleep(100); + testing.clearData(); + Thread.sleep(100); + + testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty); + } + + @Test + void syncDoubleGauge() throws InterruptedException { + DoubleGaugeBuilder builder = meter.gaugeBuilder("test").setDescription("d").setUnit("u"); + assertThat(builder).isInstanceOf(ExtendedDoubleGaugeBuilder.class); + ExtendedDoubleGaugeBuilder extendedBuilder = (ExtendedDoubleGaugeBuilder) builder; + extendedBuilder.setAttributesAdvice(singletonList(stringKey("test"))); + + DoubleGauge doubleGauge = extendedBuilder.build(); + doubleGauge.set(3.21); + doubleGauge.set(1.23, Attributes.of(stringKey("test"), "test", stringKey("q"), "r")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasDoubleGaugeSatisfying( + gauge -> + gauge.hasPointsSatisfying( + point -> point.hasValue(3.21).hasAttributes(Attributes.empty()), + point -> + point + .hasValue(1.23) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + + // sleep exporter interval + Thread.sleep(100); + testing.clearData(); + Thread.sleep(100); + + testing.waitAndAssertMetrics(instrumentationName, "test", AbstractIterableAssert::isEmpty); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/OpenTelemetryApiInstrumentationModule.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/OpenTelemetryApiInstrumentationModule.java new file mode 100644 index 000000000000..893718fc8e6f --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/OpenTelemetryApiInstrumentationModule.java @@ -0,0 +1,42 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32; + +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; +import static java.util.Collections.singletonList; +import static net.bytebuddy.matcher.ElementMatchers.not; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import java.util.List; +import net.bytebuddy.matcher.ElementMatcher; + +@AutoService(InstrumentationModule.class) +public class OpenTelemetryApiInstrumentationModule extends InstrumentationModule { + public OpenTelemetryApiInstrumentationModule() { + super("opentelemetry-api", "opentelemetry-api-1.32"); + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + // skip instrumentation when opentelemetry-extension-incubator is present, instrumentation is + // handled by OpenTelemetryApiIncubatorInstrumentationModule + return not( + hasClassesNamed( + "application.io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder")); + } + + @Override + public boolean isIndyModule() { + return false; + } + + @Override + public List typeInstrumentations() { + return singletonList(new OpenTelemetryInstrumentation()); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/OpenTelemetryInstrumentation.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/OpenTelemetryInstrumentation.java new file mode 100644 index 000000000000..147c18b51b33 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/OpenTelemetryInstrumentation.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.none; + +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.metrics.ApplicationMeterFactory132; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class OpenTelemetryInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("application.io.opentelemetry.api.GlobalOpenTelemetry"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + none(), OpenTelemetryInstrumentation.class.getName() + "$InitAdvice"); + } + + @SuppressWarnings({"ReturnValueIgnored", "unused"}) + public static class InitAdvice { + @Advice.OnMethodEnter + public static void init() { + // the sole purpose of this advice is to ensure that ApplicationMeterFactory132 is recognized + // as helper class and injected into class loader + ApplicationMeterFactory132.class.getName(); + } + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/OpenTelemetryApiIncubatorInstrumentationModule.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/OpenTelemetryApiIncubatorInstrumentationModule.java new file mode 100644 index 000000000000..dc20c2596ea6 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/OpenTelemetryApiIncubatorInstrumentationModule.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator; + +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; +import static java.util.Collections.singletonList; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import java.util.List; +import net.bytebuddy.matcher.ElementMatcher; + +@AutoService(InstrumentationModule.class) +public class OpenTelemetryApiIncubatorInstrumentationModule extends InstrumentationModule { + public OpenTelemetryApiIncubatorInstrumentationModule() { + super("opentelemetry-api", "opentelemetry-api-1.32", "opentelemetry-api-incubator-1.32"); + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + // skip instrumentation when opentelemetry-extension-incubator is not present, instrumentation + // is handled by OpenTelemetryApiInstrumentationModule + return hasClassesNamed( + "application.io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder"); + } + + @Override + public boolean isIndyModule() { + return false; + } + + @Override + public List typeInstrumentations() { + return singletonList(new OpenTelemetryIncubatorInstrumentation()); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/OpenTelemetryIncubatorInstrumentation.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/OpenTelemetryIncubatorInstrumentation.java new file mode 100644 index 000000000000..76c1469c3a0d --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/OpenTelemetryIncubatorInstrumentation.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.none; + +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator.metrics.ApplicationMeterFactory132Incubator; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class OpenTelemetryIncubatorInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("application.io.opentelemetry.api.GlobalOpenTelemetry"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + none(), OpenTelemetryIncubatorInstrumentation.class.getName() + "$InitAdvice"); + } + + @SuppressWarnings({"ReturnValueIgnored", "unused"}) + public static class InitAdvice { + @Advice.OnMethodEnter + public static void init() { + // the sole purpose of this advice is to ensure that ApplicationMeterFactory132Incubator + // is recognized as helper class and injected into class loader + ApplicationMeterFactory132Incubator.class.getName(); + } + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationDoubleHistogramBuilder132Incubator.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationDoubleHistogramBuilder132Incubator.java new file mode 100644 index 000000000000..c4d6ee6df52f --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationDoubleHistogramBuilder132Incubator.java @@ -0,0 +1,44 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator.metrics; + +import application.io.opentelemetry.api.common.AttributeKey; +import application.io.opentelemetry.api.metrics.LongHistogramBuilder; +import application.io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.Bridging; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationDoubleHistogramBuilder; +import java.util.List; + +class ApplicationDoubleHistogramBuilder132Incubator extends ApplicationDoubleHistogramBuilder + implements ExtendedDoubleHistogramBuilder { + + private final io.opentelemetry.api.metrics.DoubleHistogramBuilder agentBuilder; + + ApplicationDoubleHistogramBuilder132Incubator( + io.opentelemetry.api.metrics.DoubleHistogramBuilder agentBuilder) { + super(agentBuilder); + this.agentBuilder = agentBuilder; + } + + @Override + public LongHistogramBuilder ofLongs() { + return new ApplicationLongHistogramBuilder132Incubator(agentBuilder.ofLongs()); + } + + @Override + public ExtendedDoubleHistogramBuilder setExplicitBucketBoundariesAdvice( + List bucketBoundaries) { + agentBuilder.setExplicitBucketBoundariesAdvice(bucketBoundaries); + return this; + } + + @Override + public ExtendedDoubleHistogramBuilder setAttributesAdvice(List> attributes) { + ((io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder) agentBuilder) + .setAttributesAdvice(Bridging.toAgent(attributes)); + return this; + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationLongHistogramBuilder132Incubator.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationLongHistogramBuilder132Incubator.java new file mode 100644 index 000000000000..4f6882cf6670 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationLongHistogramBuilder132Incubator.java @@ -0,0 +1,38 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator.metrics; + +import application.io.opentelemetry.api.common.AttributeKey; +import application.io.opentelemetry.extension.incubator.metrics.ExtendedLongHistogramBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.Bridging; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationLongHistogramBuilder; +import java.util.List; + +class ApplicationLongHistogramBuilder132Incubator extends ApplicationLongHistogramBuilder + implements ExtendedLongHistogramBuilder { + + private final io.opentelemetry.api.metrics.LongHistogramBuilder agentBuilder; + + ApplicationLongHistogramBuilder132Incubator( + io.opentelemetry.api.metrics.LongHistogramBuilder agentBuilder) { + super(agentBuilder); + this.agentBuilder = agentBuilder; + } + + @Override + public ExtendedLongHistogramBuilder setExplicitBucketBoundariesAdvice( + List bucketBoundaries) { + agentBuilder.setExplicitBucketBoundariesAdvice(bucketBoundaries); + return this; + } + + @Override + public ExtendedLongHistogramBuilder setAttributesAdvice(List> attributes) { + ((io.opentelemetry.extension.incubator.metrics.ExtendedLongHistogramBuilder) agentBuilder) + .setAttributesAdvice(Bridging.toAgent(attributes)); + return this; + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationMeter132Incubator.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationMeter132Incubator.java new file mode 100644 index 000000000000..5af68b1815f4 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationMeter132Incubator.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator.metrics; + +import application.io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_31.metrics.ApplicationMeter131; + +class ApplicationMeter132Incubator extends ApplicationMeter131 { + + private final io.opentelemetry.api.metrics.Meter agentMeter; + + ApplicationMeter132Incubator(io.opentelemetry.api.metrics.Meter agentMeter) { + super(agentMeter); + this.agentMeter = agentMeter; + } + + @Override + public DoubleHistogramBuilder histogramBuilder(String name) { + return new ApplicationDoubleHistogramBuilder132Incubator(agentMeter.histogramBuilder(name)); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationMeterFactory132Incubator.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationMeterFactory132Incubator.java new file mode 100644 index 000000000000..75ac0773c7a4 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/ApplicationMeterFactory132Incubator.java @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator.metrics; + +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationMeter; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationMeterFactory; + +// this class is used from opentelemetry-api-1.27 via reflection +public final class ApplicationMeterFactory132Incubator implements ApplicationMeterFactory { + @Override + public ApplicationMeter newMeter(Meter agentMeter) { + return new ApplicationMeter132Incubator(agentMeter); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationDoubleHistogramBuilder132.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationDoubleHistogramBuilder132.java similarity index 79% rename from instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationDoubleHistogramBuilder132.java rename to instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationDoubleHistogramBuilder132.java index 58a1e4c6e3c8..8b116a7b01fb 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationDoubleHistogramBuilder132.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationDoubleHistogramBuilder132.java @@ -3,9 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_31.metrics; +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.metrics; import application.io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import application.io.opentelemetry.api.metrics.LongHistogramBuilder; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationDoubleHistogramBuilder; import java.util.List; @@ -19,7 +20,12 @@ class ApplicationDoubleHistogramBuilder132 extends ApplicationDoubleHistogramBui this.agentBuilder = agentBuilder; } - // return type is different from what 1.31 uses + @Override + public LongHistogramBuilder ofLongs() { + return new ApplicationLongHistogramBuilder132(agentBuilder.ofLongs()); + } + + @Override public DoubleHistogramBuilder setExplicitBucketBoundariesAdvice(List bucketBoundaries) { agentBuilder.setExplicitBucketBoundariesAdvice(bucketBoundaries); return this; diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationLongHistogramBuilder132.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationLongHistogramBuilder132.java similarity index 92% rename from instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationLongHistogramBuilder132.java rename to instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationLongHistogramBuilder132.java index ebeb9f4a72b7..fa494e250ef9 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/ApplicationLongHistogramBuilder132.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationLongHistogramBuilder132.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_31.metrics; +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.metrics; import application.io.opentelemetry.api.metrics.LongHistogramBuilder; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationLongHistogramBuilder; @@ -19,7 +19,7 @@ class ApplicationLongHistogramBuilder132 extends ApplicationLongHistogramBuilder this.agentBuilder = agentBuilder; } - // return type is different from what 1.31 uses + @Override public LongHistogramBuilder setExplicitBucketBoundariesAdvice(List bucketBoundaries) { agentBuilder.setExplicitBucketBoundariesAdvice(bucketBoundaries); return this; diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationMeter132.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationMeter132.java new file mode 100644 index 000000000000..ec880d3959f9 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationMeter132.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.metrics; + +import application.io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_15.metrics.ApplicationMeter115; + +class ApplicationMeter132 extends ApplicationMeter115 { + + private final io.opentelemetry.api.metrics.Meter agentMeter; + + ApplicationMeter132(io.opentelemetry.api.metrics.Meter agentMeter) { + super(agentMeter); + this.agentMeter = agentMeter; + } + + @Override + public DoubleHistogramBuilder histogramBuilder(String name) { + return new ApplicationDoubleHistogramBuilder132(agentMeter.histogramBuilder(name)); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationMeterFactory132.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationMeterFactory132.java new file mode 100644 index 000000000000..4adde3791bba --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/ApplicationMeterFactory132.java @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.metrics; + +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationMeter; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationMeterFactory; + +// this class is used from opentelemetry-api-1.27 via reflection +public final class ApplicationMeterFactory132 implements ApplicationMeterFactory { + @Override + public ApplicationMeter newMeter(Meter agentMeter) { + return new ApplicationMeter132(agentMeter); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/MeterTest.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/MeterTest.java new file mode 100644 index 000000000000..982e47d4e651 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/metrics/MeterTest.java @@ -0,0 +1,116 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.metrics; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static java.util.Collections.singletonList; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.DoubleHistogram; +import io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.api.metrics.LongHistogram; +import io.opentelemetry.api.metrics.LongHistogramBuilder; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.extension.RegisterExtension; + +class MeterTest { + + @RegisterExtension + static final AgentInstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private String instrumentationName; + private Meter meter; + + @BeforeEach + void setupMeter(TestInfo test) { + instrumentationName = "test-" + test.getDisplayName(); + meter = + testing + .getOpenTelemetry() + .getMeterProvider() + .meterBuilder(instrumentationName) + .setInstrumentationVersion("1.2.3") + .setSchemaUrl("http://schema.org") + .build(); + } + + @Test + void longHistogram() { + LongHistogramBuilder builder = + meter.histogramBuilder("test").ofLongs().setDescription("d").setUnit("u"); + builder.setExplicitBucketBoundariesAdvice(singletonList(10L)); + + LongHistogram instrument = builder.build(); + + instrument.record(5, Attributes.of(stringKey("test"), "test")); + instrument.record(6, Attributes.of(stringKey("test"), "test")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> + point + .hasSum(11.0) + .hasBucketBoundaries(10.0) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + } + + @Test + void doubleHistogram() { + DoubleHistogramBuilder builder = + meter.histogramBuilder("test").setDescription("d").setUnit("u"); + builder.setExplicitBucketBoundariesAdvice(singletonList(10.0)); + + DoubleHistogram instrument = builder.build(); + + instrument.record(5.5, Attributes.of(stringKey("test"), "test")); + instrument.record(6.6, Attributes.of(stringKey("test"), "test")); + + testing.waitAndAssertMetrics( + instrumentationName, + "test", + metrics -> + metrics.anySatisfy( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasDescription("d") + .hasUnit("u") + .hasInstrumentationScope( + InstrumentationScopeInfo.builder(instrumentationName) + .setVersion("1.2.3") + .build()) + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> + point + .hasSum(12.1) + .hasBucketBoundaries(10.0) + .hasAttributesSatisfying( + equalTo(stringKey("test"), "test")))))); + } +} diff --git a/instrumentation/opentelemetry-extension-annotations-1.0/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java b/instrumentation/opentelemetry-extension-annotations-1.0/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java index 09f6a864c953..910ad39bb178 100644 --- a/instrumentation/opentelemetry-extension-annotations-1.0/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java +++ b/instrumentation/opentelemetry-extension-annotations-1.0/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java @@ -6,7 +6,6 @@ package io.opentelemetry.test.annotation; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import io.opentelemetry.api.common.AttributeKey; @@ -158,7 +157,7 @@ void excludedMethod() throws Exception { new TracedWithSpan().ignored(); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); } @Test @@ -253,7 +252,7 @@ void completingCompletionStage() throws Exception { new TracedWithSpan().completionStage(future); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); future.complete("Done"); @@ -286,7 +285,7 @@ void exceptionallyCompletingCompletionStage() throws Exception { new TracedWithSpan().completionStage(future); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); future.completeExceptionally(new IllegalArgumentException("Boom")); @@ -405,7 +404,7 @@ void completingCompletableFuture() throws Exception { new TracedWithSpan().completableFuture(future); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); future.complete("Done"); @@ -438,7 +437,7 @@ void exceptionallyCompletingCompletableFuture() throws Exception { new TracedWithSpan().completableFuture(future); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); future.completeExceptionally(new IllegalArgumentException("Boom")); diff --git a/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/test/java/io/opentelemetry/test/annotation/AddingSpanAttributesInstrumentationTest.java b/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/test/java/io/opentelemetry/test/annotation/AddingSpanAttributesInstrumentationTest.java index 0d22c766a157..8e524c343490 100644 --- a/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/test/java/io/opentelemetry/test/annotation/AddingSpanAttributesInstrumentationTest.java +++ b/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/test/java/io/opentelemetry/test/annotation/AddingSpanAttributesInstrumentationTest.java @@ -101,7 +101,7 @@ void noExistingSpan() throws Exception { new ExtractAttributesUsingAddingSpanAttributes().withSpanAttributes("foo", "bar", null, "baz"); - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); } @Test diff --git a/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java b/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java index e3dae869ba10..d8fd78699ae5 100644 --- a/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java +++ b/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/test/java/io/opentelemetry/test/annotation/WithSpanInstrumentationTest.java @@ -158,7 +158,7 @@ void excludedMethod() throws Exception { new TracedWithSpan().ignored(); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); } @Test @@ -253,7 +253,7 @@ void completingCompletionStage() throws Exception { new TracedWithSpan().completionStage(future); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); future.complete("Done"); @@ -286,7 +286,7 @@ void exceptionallyCompletingCompletionStage() throws Exception { new TracedWithSpan().completionStage(future); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); future.completeExceptionally(new IllegalArgumentException("Boom")); @@ -405,7 +405,7 @@ void completingCompletableFuture() throws Exception { new TracedWithSpan().completableFuture(future); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); future.complete("Done"); @@ -438,7 +438,7 @@ void exceptionallyCompletingCompletableFuture() throws Exception { new TracedWithSpan().completableFuture(future); Thread.sleep(500); // sleep a bit just to make sure no span is captured - assertThat(testing.waitForTraces(0)); + assertThat(testing.waitForTraces(0)).isEmpty(); future.completeExceptionally(new IllegalArgumentException("Boom")); diff --git a/instrumentation/opentelemetry-instrumentation-api/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationapi/HttpRouteStateInstrumentation.java b/instrumentation/opentelemetry-instrumentation-api/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationapi/HttpRouteStateInstrumentation.java index e1438dc085ff..52f93afba7c5 100644 --- a/instrumentation/opentelemetry-instrumentation-api/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationapi/HttpRouteStateInstrumentation.java +++ b/instrumentation/opentelemetry-instrumentation-api/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationapi/HttpRouteStateInstrumentation.java @@ -8,10 +8,12 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import application.io.opentelemetry.api.trace.Span; import application.io.opentelemetry.context.Context; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.context.AgentContextStorage; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.trace.Bridging; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -31,6 +33,11 @@ public void transform(TypeTransformer transformer) { .and(takesArgument(1, int.class)) .and(takesArgument(2, String.class)), this.getClass().getName() + "$UpdateAdvice"); + transformer.applyAdviceToMethod( + named("updateSpan") + .and(takesArgument(0, named("application.io.opentelemetry.context.Context"))) + .and(takesArgument(1, named("application.io.opentelemetry.api.trace.Span"))), + this.getClass().getName() + "$UpdateSpanAdvice"); } @SuppressWarnings("unused") @@ -54,4 +61,17 @@ public static void onEnter( agentRouteState.update(agentContext, updatedBySourceOrder, route); } } + + @SuppressWarnings("unused") + public static class UpdateSpanAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter( + @Advice.Argument(0) Context applicationContext, @Advice.Argument(1) Span applicationSpan) { + + io.opentelemetry.context.Context agentContext = + AgentContextStorage.getAgentContext(applicationContext); + io.opentelemetry.instrumentation.api.internal.HttpRouteState.updateSpan( + agentContext, Bridging.toAgentOrNull(applicationSpan)); + } + } } diff --git a/instrumentation/ratpack/ratpack-1.4/javaagent/build.gradle.kts b/instrumentation/ratpack/ratpack-1.4/javaagent/build.gradle.kts index fdf659017336..8ff9e2107ae6 100644 --- a/instrumentation/ratpack/ratpack-1.4/javaagent/build.gradle.kts +++ b/instrumentation/ratpack/ratpack-1.4/javaagent/build.gradle.kts @@ -55,6 +55,10 @@ tasks { jvmArgs("-Dotel.semconv-stability.opt-in=http") } + withType().configureEach { + systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) + } + check { dependsOn(testStableSemconv) } diff --git a/instrumentation/ratpack/ratpack-1.4/testing/src/main/java/io/opentelemetry/instrumentation/ratpack/client/AbstractRatpackHttpClientTest.java b/instrumentation/ratpack/ratpack-1.4/testing/src/main/java/io/opentelemetry/instrumentation/ratpack/client/AbstractRatpackHttpClientTest.java index cb8e575b9709..bde6ead5f357 100644 --- a/instrumentation/ratpack/ratpack-1.4/testing/src/main/java/io/opentelemetry/instrumentation/ratpack/client/AbstractRatpackHttpClientTest.java +++ b/instrumentation/ratpack/ratpack-1.4/testing/src/main/java/io/opentelemetry/instrumentation/ratpack/client/AbstractRatpackHttpClientTest.java @@ -133,7 +133,10 @@ protected void configure(HttpClientTestOptions.Builder optionsBuilder) { optionsBuilder.setClientSpanErrorMapper( (uri, exception) -> { if (uri.toString().equals("https://192.0.2.1/")) { - return new ConnectTimeoutException("connection timed out: /192.0.2.1:443"); + return new ConnectTimeoutException( + "connection timed out" + + (Boolean.getBoolean("testLatestDeps") ? " after 2000 ms" : "") + + ": /192.0.2.1:443"); } else if (OS.WINDOWS.isCurrentOs() && uri.toString().equals("http://localhost:61/")) { return new ConnectTimeoutException("connection timed out: localhost/127.0.0.1:61"); } else if (uri.getPath().equals("/read-timeout")) { diff --git a/instrumentation/rediscala-1.8/javaagent/build.gradle.kts b/instrumentation/rediscala-1.8/javaagent/build.gradle.kts index bd73085bfe16..8442cb3dbf1b 100644 --- a/instrumentation/rediscala-1.8/javaagent/build.gradle.kts +++ b/instrumentation/rediscala-1.8/javaagent/build.gradle.kts @@ -44,12 +44,19 @@ muzzle { versions.set("[1.9.0,)") assertInverse.set(true) } + + pass { + group.set("io.github.rediscala") + module.set("rediscala_2.13") + versions.set("[1.10.0,)") + assertInverse.set(true) + } } dependencies { library("com.github.etaty:rediscala_2.11:1.8.0") - latestDepTestLibrary("com.github.etaty:rediscala_2.13:+") + latestDepTestLibrary("io.github.rediscala:rediscala_2.13:+") } tasks { diff --git a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RequestInstrumentation.java b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RequestInstrumentation.java index 018cd0cf855e..0daf60166a41 100644 --- a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RequestInstrumentation.java +++ b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RequestInstrumentation.java @@ -23,7 +23,11 @@ import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +import redis.ActorRequest; +import redis.BufferedRequest; import redis.RedisCommand; +import redis.Request; +import redis.RoundRobinPoolRequest; import scala.concurrent.ExecutionContext; import scala.concurrent.Future; @@ -74,11 +78,11 @@ public static void onEnter( @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void onExit( + @Advice.This Object action, @Advice.Argument(0) RedisCommand cmd, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope, @Advice.Thrown Throwable throwable, - @Advice.FieldValue("executionContext") ExecutionContext ctx, @Advice.Return(readOnly = false) Future responseFuture) { if (scope == null) { @@ -86,6 +90,17 @@ public static void onExit( } scope.close(); + ExecutionContext ctx = null; + if (action instanceof ActorRequest) { + ctx = ((ActorRequest) action).executionContext(); + } else if (action instanceof Request) { + ctx = ((Request) action).executionContext(); + } else if (action instanceof BufferedRequest) { + ctx = ((BufferedRequest) action).executionContext(); + } else if (action instanceof RoundRobinPoolRequest) { + ctx = ((RoundRobinPoolRequest) action).executionContext(); + } + if (throwable != null) { instrumenter().end(context, cmd, null, throwable); } else { diff --git a/instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy b/instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy index 7e8048ddd8fb..6e4e9b98e0c6 100644 --- a/instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy +++ b/instrumentation/rediscala-1.8/javaagent/src/test/groovy/RediscalaClientTest.groovy @@ -3,7 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import akka.actor.ActorSystem import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification import io.opentelemetry.semconv.SemanticAttributes import org.testcontainers.containers.GenericContainer @@ -26,7 +25,7 @@ class RediscalaClientTest extends AgentInstrumentationSpecification { int port @Shared - ActorSystem system + def system @Shared RedisClient redisClient @@ -34,15 +33,36 @@ class RediscalaClientTest extends AgentInstrumentationSpecification { def setupSpec() { redisServer.start() port = redisServer.getMappedPort(6379) - system = ActorSystem.create() - redisClient = new RedisClient("localhost", - port, - Option.apply(null), - Option.apply(null), - "RedisClient", - Option.apply(null), - system, - new RedisDispatcher("rediscala.rediscala-client-worker-dispatcher")) + // latest has separate artifacts for akka an pekko, currently latestDepTestLibrary picks the + // pekko one + try { + def clazz = Class.forName("akka.actor.ActorSystem") + system = clazz.getMethod("create").invoke(null) + } catch (ClassNotFoundException exception) { + def clazz = Class.forName("org.apache.pekko.actor.ActorSystem") + system = clazz.getMethod("create").invoke(null) + } + // latest RedisClient constructor takes username as argument + if (RedisClient.metaClass.getMetaMethod("username") != null) { + redisClient = new RedisClient("localhost", + port, + Option.apply(null), + Option.apply(null), + Option.apply(null), + "RedisClient", + Option.apply(null), + system, + new RedisDispatcher("rediscala.rediscala-client-worker-dispatcher")) + } else { + redisClient = new RedisClient("localhost", + port, + Option.apply(null), + Option.apply(null), + "RedisClient", + Option.apply(null), + system, + new RedisDispatcher("rediscala.rediscala-client-worker-dispatcher")) + } } def cleanupSpec() { diff --git a/instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-2.0/javaagent/build.gradle.kts b/instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-2.0/javaagent/build.gradle.kts index b6e0f261e88a..df17718e19ff 100644 --- a/instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-2.0/javaagent/build.gradle.kts +++ b/instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-2.0/javaagent/build.gradle.kts @@ -21,6 +21,9 @@ dependencies { testImplementation(project(":instrumentation:spring:spring-cloud-gateway:spring-cloud-gateway-common:testing")) testLibrary("org.springframework.boot:spring-boot-starter-test:2.0.0.RELEASE") + + latestDepTestLibrary("org.springframework.cloud:spring-cloud-starter-gateway:2.1.+") + latestDepTestLibrary("org.springframework.boot:spring-boot-starter-test:2.1.+") } tasks.withType().configureEach { @@ -33,19 +36,9 @@ tasks.withType().configureEach { systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) } -val latestDepTest = findProperty("testLatestDeps") as Boolean - -if (latestDepTest) { - // spring 6 requires java 17 - otelJava { - minJavaVersionSupported.set(JavaVersion.VERSION_17) - } -} else { - // spring 5 requires old logback (and therefore also old slf4j) - configurations.testRuntimeClasspath { - resolutionStrategy { - force("ch.qos.logback:logback-classic:1.2.11") - force("org.slf4j:slf4j-api:1.7.36") - } +configurations.testRuntimeClasspath { + resolutionStrategy { + force("ch.qos.logback:logback-classic:1.2.11") + force("org.slf4j:slf4j-api:1.7.36") } } diff --git a/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/ConsumerConfig.java b/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/ConsumerConfig.java index f24070bc1bda..4c97068197f7 100644 --- a/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/ConsumerConfig.java +++ b/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/ConsumerConfig.java @@ -5,6 +5,7 @@ package io.opentelemetry.testing; +import java.lang.reflect.Method; import org.apache.kafka.clients.admin.NewTopic; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.SpringBootConfiguration; @@ -15,6 +16,8 @@ import org.springframework.kafka.config.TopicBuilder; import org.springframework.kafka.core.ConsumerFactory; import org.springframework.kafka.listener.ConcurrentMessageListenerContainer; +import org.springframework.util.backoff.BackOff; +import org.springframework.util.backoff.FixedBackOff; @SpringBootConfiguration @EnableAutoConfiguration @@ -50,7 +53,13 @@ public ConcurrentKafkaListenerContainerFactory batchFactory( ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); // do not retry failed records - factory.setBatchErrorHandler(new DoNothingBatchErrorHandler()); + try { + Class.forName("org.springframework.kafka.listener.BatchErrorHandler"); + ErrorHandlerSetter.setBatchErrorHandler(factory); + } catch (ClassNotFoundException ignored) { + // org.springframework.kafka.listener.BatchErrorHandler is missing in latest + setCommonErrorHandler(factory); + } factory.setConsumerFactory(consumerFactory); factory.setBatchListener(true); factory.setAutoStartup(true); @@ -68,11 +77,34 @@ public ConcurrentKafkaListenerContainerFactory singleFactory( ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); // do not retry failed records - factory.setErrorHandler(new DoNothingErrorHandler()); + try { + Class.forName("org.springframework.kafka.listener.ErrorHandler"); + ErrorHandlerSetter.setErrorHandler(factory); + } catch (ClassNotFoundException ignored) { + // org.springframework.kafka.listener.ErrorHandler is missing in latest + setCommonErrorHandler(factory); + } factory.setConsumerFactory(consumerFactory); factory.setBatchListener(false); factory.setAutoStartup(true); customizerProvider.ifAvailable(factory::setContainerCustomizer); return factory; } + + private static void setCommonErrorHandler( + ConcurrentKafkaListenerContainerFactory factory) { + try { + Class handlerClass = + Class.forName("org.springframework.kafka.listener.CommonErrorHandler"); + Class defaultHandlerClass = + Class.forName("org.springframework.kafka.listener.DefaultErrorHandler"); + BackOff backOff = new FixedBackOff(0, 0); + Object handler = + defaultHandlerClass.getDeclaredConstructor(BackOff.class).newInstance(backOff); + Method method = factory.getClass().getMethod("setCommonErrorHandler", handlerClass); + method.invoke(factory, handler); + } catch (Exception exception) { + // ignored + } + } } diff --git a/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/ErrorHandlerSetter.java b/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/ErrorHandlerSetter.java new file mode 100644 index 000000000000..4d2c97c42a36 --- /dev/null +++ b/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/ErrorHandlerSetter.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.testing; + +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; + +// Base classes for error handlers are missing in the latest version. Setter methods were extracted +// in ConsumerConfig to avoid verifier attempting to load these classes. +class ErrorHandlerSetter { + + private ErrorHandlerSetter() {} + + static void setBatchErrorHandler( + ConcurrentKafkaListenerContainerFactory factory) { + factory.setBatchErrorHandler(new DoNothingBatchErrorHandler()); + } + + static void setErrorHandler(ConcurrentKafkaListenerContainerFactory factory) { + factory.setErrorHandler(new DoNothingErrorHandler()); + } +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/SpringWebfluxTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/SpringWebfluxTest.java index 2cf40ededd1c..57c56683eb21 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/SpringWebfluxTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/SpringWebfluxTest.java @@ -36,6 +36,7 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.testing.assertj.EventDataAssert; import io.opentelemetry.sdk.testing.assertj.TraceAssert; import io.opentelemetry.sdk.trace.data.StatusData; import io.opentelemetry.testing.internal.armeria.client.WebClient; @@ -484,28 +485,33 @@ void get404Test() { .hasKind(SpanKind.INTERNAL) .hasParent(trace.getSpan(0)) .hasStatus(StatusData.error()) - .hasEventsSatisfyingExactly( - event -> - event - .hasName(EXCEPTION_EVENT_NAME) - .hasAttributesSatisfyingExactly( - equalTo( - EXCEPTION_TYPE, - "org.springframework.web.server.ResponseStatusException"), - satisfies( - EXCEPTION_MESSAGE, - val -> - val.containsAnyOf( - "Response status 404", "404 NOT_FOUND")), - satisfies( - EXCEPTION_STACKTRACE, - val -> val.isInstanceOf(String.class)))) + .hasEventsSatisfyingExactly(SpringWebfluxTest::resource404Exception) .hasAttributesSatisfyingExactly( equalTo( stringKey("spring-webflux.handler.type"), "org.springframework.web.reactive.resource.ResourceWebHandler")))); } + private static void resource404Exception(EventDataAssert event) { + if (Boolean.getBoolean("testLatestDeps")) { + event + .hasName(EXCEPTION_EVENT_NAME) + .hasAttributesSatisfyingExactly( + equalTo( + EXCEPTION_TYPE, + "org.springframework.web.reactive.resource.NoResourceFoundException"), + satisfies(EXCEPTION_MESSAGE, val -> val.isInstanceOf(String.class)), + satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))); + } else { + event + .hasName(EXCEPTION_EVENT_NAME) + .hasAttributesSatisfyingExactly( + equalTo(EXCEPTION_TYPE, "org.springframework.web.server.ResponseStatusException"), + equalTo(EXCEPTION_MESSAGE, "Response status 404"), + satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class))); + } + } + @Test void basicPostTest() { String echoString = "TEST"; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ControllerSpringWebFluxServerTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ControllerSpringWebFluxServerTest.java similarity index 91% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ControllerSpringWebFluxServerTest.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ControllerSpringWebFluxServerTest.java index 54bbe7360b1a..c3ac74a4af9f 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ControllerSpringWebFluxServerTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ControllerSpringWebFluxServerTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION; import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND; @@ -52,8 +52,9 @@ protected SpanDataAssert assertHandlerSpan( .hasAttributesSatisfyingExactly( equalTo( EXCEPTION_TYPE, - "org.springframework.web.server.ResponseStatusException"), - equalTo(EXCEPTION_MESSAGE, "404 NOT_FOUND"), + "org.springframework.web.reactive.resource.NoResourceFoundException"), + equalTo( + EXCEPTION_MESSAGE, "404 NOT_FOUND \"No static resource notFound.\""), satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class)))); } else { span.hasEventsSatisfyingExactly( diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/DelayedControllerSpringWebFluxServerTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/DelayedControllerSpringWebFluxServerTest.java similarity index 95% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/DelayedControllerSpringWebFluxServerTest.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/DelayedControllerSpringWebFluxServerTest.java index 4237b4455fb5..1ef1302dca70 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/DelayedControllerSpringWebFluxServerTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/DelayedControllerSpringWebFluxServerTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint; import java.time.Duration; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/DelayedHandlerSpringWebFluxServerTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/DelayedHandlerSpringWebFluxServerTest.java similarity index 95% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/DelayedHandlerSpringWebFluxServerTest.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/DelayedHandlerSpringWebFluxServerTest.java index b889416e8c33..d513e13d18a0 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/DelayedHandlerSpringWebFluxServerTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/DelayedHandlerSpringWebFluxServerTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint; import java.time.Duration; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/HandlerSpringWebFluxServerTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/HandlerSpringWebFluxServerTest.java similarity index 91% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/HandlerSpringWebFluxServerTest.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/HandlerSpringWebFluxServerTest.java index 6f1837ebfe25..d33cb788e9c7 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/HandlerSpringWebFluxServerTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/HandlerSpringWebFluxServerTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION; import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND; @@ -50,8 +50,9 @@ protected SpanDataAssert assertHandlerSpan( .hasAttributesSatisfyingExactly( equalTo( EXCEPTION_TYPE, - "org.springframework.web.server.ResponseStatusException"), - equalTo(EXCEPTION_MESSAGE, "404 NOT_FOUND"), + "org.springframework.web.reactive.resource.NoResourceFoundException"), + equalTo( + EXCEPTION_MESSAGE, "404 NOT_FOUND \"No static resource notFound.\""), satisfies(EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class)))); } else { span.hasEventsSatisfyingExactly( diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ImmediateControllerSpringWebFluxServerTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ImmediateControllerSpringWebFluxServerTest.java similarity index 95% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ImmediateControllerSpringWebFluxServerTest.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ImmediateControllerSpringWebFluxServerTest.java index 8327904044a2..ccdecadb5478 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ImmediateControllerSpringWebFluxServerTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ImmediateControllerSpringWebFluxServerTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint; import java.util.function.Supplier; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ImmediateHandlerSpringWebFluxServerTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ImmediateHandlerSpringWebFluxServerTest.java similarity index 96% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ImmediateHandlerSpringWebFluxServerTest.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ImmediateHandlerSpringWebFluxServerTest.java index 94d515e62e18..6e0dbc0e95fe 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ImmediateHandlerSpringWebFluxServerTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ImmediateHandlerSpringWebFluxServerTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeTrue; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ServerTestController.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ServerTestController.java similarity index 95% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ServerTestController.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ServerTestController.java index d8ab437ae9d5..812c976457c1 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ServerTestController.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ServerTestController.java @@ -3,9 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; -import static server.base.SpringWebFluxServerTest.NESTED_PATH; +import static io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base.SpringWebFluxServerTest.NESTED_PATH; import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint; import java.net.URI; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ServerTestRouteFactory.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ServerTestRouteFactory.java similarity index 95% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ServerTestRouteFactory.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ServerTestRouteFactory.java index b1742c4cfff4..7d91a7aa48b4 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/ServerTestRouteFactory.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/ServerTestRouteFactory.java @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; +import static io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base.SpringWebFluxServerTest.NESTED_PATH; import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RequestPredicates.path; import static org.springframework.web.reactive.function.server.RouterFunctions.nest; import static org.springframework.web.reactive.function.server.RouterFunctions.route; -import static server.base.SpringWebFluxServerTest.NESTED_PATH; import io.opentelemetry.api.trace.Span; import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/SpringWebFluxServerTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/SpringWebFluxServerTest.java similarity index 97% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/SpringWebFluxServerTest.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/SpringWebFluxServerTest.java index 9efe2589b978..c1403355d593 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/SpringWebFluxServerTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/SpringWebFluxServerTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION; import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.NOT_FOUND; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/package-info.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/package-info.java similarity index 62% rename from instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/package-info.java rename to instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/package-info.java index 679f71c0a4af..f915cf01d493 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/base/package-info.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/server/base/package-info.java @@ -2,4 +2,4 @@ * The classes in this package are specific to tests that extend {@link * io.opentelemetry.instrumentation.test.base.HttpServerTest}. */ -package server.base; +package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.server.base; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/SpringWebFluxTestApplication.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/SpringWebFluxTestApplication.java index 401388e2345a..0151501226ed 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/SpringWebFluxTestApplication.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/test/java/server/SpringWebFluxTestApplication.java @@ -17,7 +17,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.FilterType; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.BodyInserters; @@ -27,9 +26,7 @@ import reactor.core.publisher.Mono; @SpringBootApplication -@ComponentScan( - basePackages = {"server"}, - excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "server.base.*")) +@ComponentScan(basePackages = {"server"}) public class SpringWebFluxTestApplication { private static final Tracer tracer = GlobalOpenTelemetry.getTracer("test"); diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/TestWebfluxSpringBootApp.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/TestWebfluxSpringBootApp.java index 5437f2e481f6..717bba794b1d 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/TestWebfluxSpringBootApp.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/TestWebfluxSpringBootApp.java @@ -71,8 +71,8 @@ Flux success() { @RequestMapping("/query") @ResponseBody - String query_param(@RequestParam("some") String param) { - return controller(QUERY_PARAM, () -> "some=" + param); + Mono query_param(@RequestParam("some") String param) { + return Mono.just(controller(QUERY_PARAM, () -> "some=" + param)); } @RequestMapping("/redirect") @@ -102,20 +102,21 @@ Flux> exception() throws Exception { } @RequestMapping("/captureHeaders") - ResponseEntity capture_headers( + Mono> capture_headers( @RequestHeader("X-Test-Request") String testRequestHeader) { - return controller( - CAPTURE_HEADERS, - () -> - ResponseEntity.ok() - .header("X-Test-Response", testRequestHeader) - .body(CAPTURE_HEADERS.getBody())); + return Mono.just( + controller( + CAPTURE_HEADERS, + () -> + ResponseEntity.ok() + .header("X-Test-Response", testRequestHeader) + .body(CAPTURE_HEADERS.getBody()))); } @RequestMapping("/path/{id}/param") @ResponseBody - String path_param(@PathVariable("id") int id) { - return controller(PATH_PARAM, () -> String.valueOf(id)); + Mono path_param(@PathVariable("id") int id) { + return Mono.just(controller(PATH_PARAM, () -> String.valueOf(id))); } @RequestMapping("/child") diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/build.gradle.kts b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/build.gradle.kts index 9c4425b96814..f196226a3986 100644 --- a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/build.gradle.kts +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/build.gradle.kts @@ -50,4 +50,6 @@ tasks.withType().configureEach { // required on jdk17 jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") jvmArgs("-XX:+IgnoreUnrecognizedVMOptions") + + systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) } diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/ServletFilterTest.groovy b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/ServletFilterTest.groovy index 644a6a44d21c..42d94ca6ba6a 100644 --- a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/ServletFilterTest.groovy +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/ServletFilterTest.groovy @@ -4,6 +4,13 @@ */ import filter.AbstractServletFilterTest +import io.opentelemetry.api.trace.SpanKind +import io.opentelemetry.api.trace.StatusCode +import io.opentelemetry.instrumentation.test.asserts.TraceAssert +import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint +import io.opentelemetry.sdk.trace.data.SpanData + +import static io.opentelemetry.api.trace.SpanKind.INTERNAL class ServletFilterTest extends AbstractServletFilterTest { @@ -14,4 +21,32 @@ class ServletFilterTest extends AbstractServletFilterTest { Class filterConfigClass() { ServletFilterConfig } + + @Override + void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint) { + if (Boolean.getBoolean("testLatestDeps") && endpoint == ServerEndpoint.NOT_FOUND) { + trace.span(index) { + name "ResourceHttpRequestHandler.handleRequest" + kind INTERNAL + childOf((SpanData) parent) + status StatusCode.ERROR + errorEventWithAnyMessage Class.forName("org.springframework.web.servlet.resource.NoResourceFoundException") + } + } else { + super.handlerSpan(trace, index, parent, method, endpoint) + } + } + + @Override + void responseSpan(TraceAssert trace, int index, Object parent, String method, ServerEndpoint endpoint) { + if (Boolean.getBoolean("testLatestDeps") && endpoint == ServerEndpoint.NOT_FOUND) { + trace.span(index) { + name ~/\.sendError$/ + kind SpanKind.INTERNAL + // not verifying the parent span, in the latest version the responseSpan is the child of the SERVER span, not the handler span + } + } else { + super.responseSpan(trace, index, parent, method, endpoint) + } + } } diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/SpringBootBasedTest.groovy b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/SpringBootBasedTest.groovy index 9b647b549687..a37e190e5194 100644 --- a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/SpringBootBasedTest.groovy +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/javaagent/src/test/groovy/SpringBootBasedTest.groovy @@ -4,10 +4,31 @@ */ import boot.AbstractSpringBootBasedTest +import io.opentelemetry.api.trace.StatusCode +import io.opentelemetry.instrumentation.test.asserts.TraceAssert +import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint +import io.opentelemetry.sdk.trace.data.SpanData + +import static io.opentelemetry.api.trace.SpanKind.INTERNAL class SpringBootBasedTest extends AbstractSpringBootBasedTest { Class securityConfigClass() { SecurityConfig } + + @Override + void handlerSpan(TraceAssert trace, int index, Object parent, String method = "GET", ServerEndpoint endpoint) { + if (Boolean.getBoolean("testLatestDeps") && endpoint == ServerEndpoint.NOT_FOUND) { + trace.span(index) { + name "ResourceHttpRequestHandler.handleRequest" + kind INTERNAL + childOf((SpanData) parent) + status StatusCode.ERROR + errorEventWithAnyMessage Class.forName("org.springframework.web.servlet.resource.NoResourceFoundException") + } + } else { + super.handlerSpan(trace, index, parent, method, endpoint) + } + } } diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/CommonLibraryIgnoredTypesConfigurer.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/CommonLibraryIgnoredTypesConfigurer.java new file mode 100644 index 000000000000..1bcacdf2b816 --- /dev/null +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/CommonLibraryIgnoredTypesConfigurer.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.ignore; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesBuilder; +import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesConfigurer; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; + +/** + * Unlike the {@link AdditionalLibraryIgnoredTypesConfigurer}, this one is applied to all tests. It + * should only contain classes that are included in the most commonly used libraries in test (e.g. + * Spring Boot). + */ +@AutoService(IgnoredTypesConfigurer.class) +public class CommonLibraryIgnoredTypesConfigurer implements IgnoredTypesConfigurer { + + @Override + public void configure(IgnoredTypesBuilder builder, ConfigProperties config) { + builder.ignoreClass("org.springframework.boot.autoconfigure.ssl.FileWatcher$WatcherThread"); + } +} diff --git a/licenses/byte-buddy-dep-1.14.9.jar/META-INF/LICENSE b/licenses/byte-buddy-dep-1.14.12.jar/META-INF/LICENSE similarity index 100% rename from licenses/byte-buddy-dep-1.14.9.jar/META-INF/LICENSE rename to licenses/byte-buddy-dep-1.14.12.jar/META-INF/LICENSE diff --git a/licenses/byte-buddy-dep-1.14.9.jar/META-INF/NOTICE b/licenses/byte-buddy-dep-1.14.12.jar/META-INF/NOTICE similarity index 100% rename from licenses/byte-buddy-dep-1.14.9.jar/META-INF/NOTICE rename to licenses/byte-buddy-dep-1.14.12.jar/META-INF/NOTICE diff --git a/licenses/jackson-annotations-2.15.3.jar/META-INF/LICENSE b/licenses/jackson-annotations-2.16.1.jar/META-INF/LICENSE similarity index 100% rename from licenses/jackson-annotations-2.15.3.jar/META-INF/LICENSE rename to licenses/jackson-annotations-2.16.1.jar/META-INF/LICENSE diff --git a/licenses/jackson-annotations-2.15.3.jar/META-INF/NOTICE b/licenses/jackson-annotations-2.16.1.jar/META-INF/NOTICE similarity index 100% rename from licenses/jackson-annotations-2.15.3.jar/META-INF/NOTICE rename to licenses/jackson-annotations-2.16.1.jar/META-INF/NOTICE diff --git a/licenses/jackson-core-2.15.3.jar/META-INF/LICENSE b/licenses/jackson-core-2.16.1.jar/META-INF/LICENSE similarity index 100% rename from licenses/jackson-core-2.15.3.jar/META-INF/LICENSE rename to licenses/jackson-core-2.16.1.jar/META-INF/LICENSE diff --git a/licenses/jackson-core-2.15.3.jar/META-INF/NOTICE b/licenses/jackson-core-2.16.1.jar/META-INF/NOTICE similarity index 100% rename from licenses/jackson-core-2.15.3.jar/META-INF/NOTICE rename to licenses/jackson-core-2.16.1.jar/META-INF/NOTICE diff --git a/licenses/jackson-databind-2.15.3.jar/META-INF/LICENSE b/licenses/jackson-databind-2.16.1.jar/META-INF/LICENSE similarity index 100% rename from licenses/jackson-databind-2.15.3.jar/META-INF/LICENSE rename to licenses/jackson-databind-2.16.1.jar/META-INF/LICENSE diff --git a/licenses/jackson-databind-2.15.3.jar/META-INF/NOTICE b/licenses/jackson-databind-2.16.1.jar/META-INF/NOTICE similarity index 100% rename from licenses/jackson-databind-2.15.3.jar/META-INF/NOTICE rename to licenses/jackson-databind-2.16.1.jar/META-INF/NOTICE diff --git a/licenses/jackson-dataformat-yaml-2.15.3.jar/META-INF/LICENSE b/licenses/jackson-dataformat-yaml-2.16.1.jar/META-INF/LICENSE similarity index 100% rename from licenses/jackson-dataformat-yaml-2.15.3.jar/META-INF/LICENSE rename to licenses/jackson-dataformat-yaml-2.16.1.jar/META-INF/LICENSE diff --git a/licenses/jackson-dataformat-yaml-2.15.3.jar/META-INF/NOTICE b/licenses/jackson-dataformat-yaml-2.16.1.jar/META-INF/NOTICE similarity index 100% rename from licenses/jackson-dataformat-yaml-2.15.3.jar/META-INF/NOTICE rename to licenses/jackson-dataformat-yaml-2.16.1.jar/META-INF/NOTICE diff --git a/licenses/jackson-jr-objects-2.15.3.jar/META-INF/LICENSE b/licenses/jackson-jr-objects-2.16.1.jar/META-INF/LICENSE similarity index 100% rename from licenses/jackson-jr-objects-2.15.3.jar/META-INF/LICENSE rename to licenses/jackson-jr-objects-2.16.1.jar/META-INF/LICENSE diff --git a/licenses/jackson-jr-objects-2.15.3.jar/META-INF/NOTICE b/licenses/jackson-jr-objects-2.16.1.jar/META-INF/NOTICE similarity index 100% rename from licenses/jackson-jr-objects-2.15.3.jar/META-INF/NOTICE rename to licenses/jackson-jr-objects-2.16.1.jar/META-INF/NOTICE diff --git a/licenses/licenses.md b/licenses/licenses.md index 52756f1bce21..e11ea3c4cd62 100644 --- a/licenses/licenses.md +++ b/licenses/licenses.md @@ -1,7 +1,7 @@ # javaagent ## Dependency License Report -_2023-11-13 19:19:44 PST_ +_2024-02-16 16:47:01 EET_ ## Apache License, Version 2.0 **1** **Group:** `com.blogspot.mydailyjava` **Name:** `weak-lock-free` **Version:** `0.18` @@ -9,40 +9,40 @@ _2023-11-13 19:19:44 PST_ > - **POM Project URL**: [https://github.com/raphw/weak-lock-free](https://github.com/raphw/weak-lock-free) > - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) -**2** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-annotations` **Version:** `2.15.3` +**2** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-annotations` **Version:** `2.16.1` > - **Project URL**: [https://github.com/FasterXML/jackson](https://github.com/FasterXML/jackson) > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -> - **Embedded license files**: [jackson-annotations-2.15.3.jar/META-INF/LICENSE](jackson-annotations-2.15.3.jar/META-INF/LICENSE) - - [jackson-annotations-2.15.3.jar/META-INF/NOTICE](jackson-annotations-2.15.3.jar/META-INF/NOTICE) +> - **Embedded license files**: [jackson-annotations-2.16.1.jar/META-INF/LICENSE](jackson-annotations-2.16.1.jar/META-INF/LICENSE) + - [jackson-annotations-2.16.1.jar/META-INF/NOTICE](jackson-annotations-2.16.1.jar/META-INF/NOTICE) -**3** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-core` **Version:** `2.15.3` +**3** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-core` **Version:** `2.16.1` > - **Project URL**: [https://github.com/FasterXML/jackson-core](https://github.com/FasterXML/jackson-core) > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -> - **Embedded license files**: [jackson-core-2.15.3.jar/META-INF/LICENSE](jackson-core-2.15.3.jar/META-INF/LICENSE) - - [jackson-core-2.15.3.jar/META-INF/NOTICE](jackson-core-2.15.3.jar/META-INF/NOTICE) +> - **Embedded license files**: [jackson-core-2.16.1.jar/META-INF/LICENSE](jackson-core-2.16.1.jar/META-INF/LICENSE) + - [jackson-core-2.16.1.jar/META-INF/NOTICE](jackson-core-2.16.1.jar/META-INF/NOTICE) -**4** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-databind` **Version:** `2.15.3` +**4** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-databind` **Version:** `2.16.1` > - **Project URL**: [https://github.com/FasterXML/jackson](https://github.com/FasterXML/jackson) > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -> - **Embedded license files**: [jackson-databind-2.15.3.jar/META-INF/LICENSE](jackson-databind-2.15.3.jar/META-INF/LICENSE) - - [jackson-databind-2.15.3.jar/META-INF/NOTICE](jackson-databind-2.15.3.jar/META-INF/NOTICE) +> - **Embedded license files**: [jackson-databind-2.16.1.jar/META-INF/LICENSE](jackson-databind-2.16.1.jar/META-INF/LICENSE) + - [jackson-databind-2.16.1.jar/META-INF/NOTICE](jackson-databind-2.16.1.jar/META-INF/NOTICE) -**5** **Group:** `com.fasterxml.jackson.dataformat` **Name:** `jackson-dataformat-yaml` **Version:** `2.15.3` +**5** **Group:** `com.fasterxml.jackson.dataformat` **Name:** `jackson-dataformat-yaml` **Version:** `2.16.1` > - **Project URL**: [https://github.com/FasterXML/jackson-dataformats-text](https://github.com/FasterXML/jackson-dataformats-text) > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -> - **Embedded license files**: [jackson-dataformat-yaml-2.15.3.jar/META-INF/LICENSE](jackson-dataformat-yaml-2.15.3.jar/META-INF/LICENSE) - - [jackson-dataformat-yaml-2.15.3.jar/META-INF/NOTICE](jackson-dataformat-yaml-2.15.3.jar/META-INF/NOTICE) +> - **Embedded license files**: [jackson-dataformat-yaml-2.16.1.jar/META-INF/LICENSE](jackson-dataformat-yaml-2.16.1.jar/META-INF/LICENSE) + - [jackson-dataformat-yaml-2.16.1.jar/META-INF/NOTICE](jackson-dataformat-yaml-2.16.1.jar/META-INF/NOTICE) -**6** **Group:** `com.fasterxml.jackson.jr` **Name:** `jackson-jr-objects` **Version:** `2.15.3` +**6** **Group:** `com.fasterxml.jackson.jr` **Name:** `jackson-jr-objects` **Version:** `2.16.1` > - **Project URL**: [https://github.com/FasterXML/jackson-jr](https://github.com/FasterXML/jackson-jr) > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -> - **Embedded license files**: [jackson-jr-objects-2.15.3.jar/META-INF/LICENSE](jackson-jr-objects-2.15.3.jar/META-INF/LICENSE) - - [jackson-jr-objects-2.15.3.jar/META-INF/NOTICE](jackson-jr-objects-2.15.3.jar/META-INF/NOTICE) +> - **Embedded license files**: [jackson-jr-objects-2.16.1.jar/META-INF/LICENSE](jackson-jr-objects-2.16.1.jar/META-INF/LICENSE) + - [jackson-jr-objects-2.16.1.jar/META-INF/NOTICE](jackson-jr-objects-2.16.1.jar/META-INF/NOTICE) **7** **Group:** `com.googlecode.concurrentlinkedhashmap` **Name:** `concurrentlinkedhashmap-lru` **Version:** `1.4.2` > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) @@ -54,103 +54,103 @@ _2023-11-13 19:19:44 PST_ > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **Embedded license files**: [okhttp-4.12.0.jar/okhttp3/internal/publicsuffix/NOTICE](okhttp-4.12.0.jar/okhttp3/internal/publicsuffix/NOTICE) -**9** **Group:** `com.squareup.okio` **Name:** `okio-jvm` **Version:** `3.6.0` +**9** **Group:** `com.squareup.okio` **Name:** `okio-jvm` **Version:** `3.8.0` > - **POM Project URL**: [https://github.com/square/okio/](https://github.com/square/okio/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**10** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api` **Version:** `1.32.0` +**10** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) -**11** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api-events` **Version:** `1.32.0-alpha` +**11** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api-events` **Version:** `1.34.1-alpha` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) -**12** **Group:** `io.opentelemetry` **Name:** `opentelemetry-context` **Version:** `1.32.0` +**12** **Group:** `io.opentelemetry` **Name:** `opentelemetry-context` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) -**13** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-common` **Version:** `1.32.0` +**13** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-common` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**14** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-jaeger` **Version:** `1.32.0` +**14** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-jaeger` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**15** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-logging` **Version:** `1.32.0` +**15** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-logging` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**16** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-logging-otlp` **Version:** `1.32.0` +**16** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-logging-otlp` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**17** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-otlp` **Version:** `1.32.0` +**17** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-otlp` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**18** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-otlp-common` **Version:** `1.32.0` +**18** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-otlp-common` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**19** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-prometheus` **Version:** `1.32.0-alpha` +**19** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-prometheus` **Version:** `1.34.1-alpha` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**20** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-sender-okhttp` **Version:** `1.32.0` +**20** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-sender-okhttp` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**21** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-zipkin` **Version:** `1.32.0` +**21** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-zipkin` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**22** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-incubator` **Version:** `1.32.0-alpha` +**22** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-incubator` **Version:** `1.34.1-alpha` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) -**23** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-kotlin` **Version:** `1.32.0` +**23** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-kotlin` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**24** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-trace-propagators` **Version:** `1.32.0` +**24** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-trace-propagators` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**25** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk` **Version:** `1.32.0` +**25** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**26** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-common` **Version:** `1.32.0` +**26** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-common` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**27** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure` **Version:** `1.32.0` +**27** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**28** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure-spi` **Version:** `1.32.0` +**28** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure-spi` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**29** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-incubator` **Version:** `1.32.0-alpha` +**29** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-incubator` **Version:** `1.34.1-alpha` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**30** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-jaeger-remote-sampler` **Version:** `1.32.0` +**30** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-jaeger-remote-sampler` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**31** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-logs` **Version:** `1.32.0` +**31** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-logs` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**32** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-metrics` **Version:** `1.32.0` +**32** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-metrics` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**33** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-trace` **Version:** `1.32.0` +**33** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-trace` **Version:** `1.34.1` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java](https://github.com/open-telemetry/opentelemetry-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) @@ -162,133 +162,156 @@ _2023-11-13 19:19:44 PST_ > - **POM Project URL**: [https://github.com/open-telemetry/semantic-conventions-java](https://github.com/open-telemetry/semantic-conventions-java) > - **POM License**: Apache License, Version 2.0 - [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) -**36** **Group:** `io.zipkin.reporter2` **Name:** `zipkin-reporter` **Version:** `2.16.3` +**36** **Group:** `io.prometheus` **Name:** `prometheus-metrics-config` **Version:** `1.1.0` +> - **Manifest License**: Apache License, Version 2.0 (Not Packaged) +> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) + +**37** **Group:** `io.prometheus` **Name:** `prometheus-metrics-exporter-common` **Version:** `1.1.0` +> - **Manifest License**: Apache License, Version 2.0 (Not Packaged) +> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) + +**38** **Group:** `io.prometheus` **Name:** `prometheus-metrics-exporter-httpserver` **Version:** `1.1.0` +> - **Manifest License**: Apache License, Version 2.0 (Not Packaged) +> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) + +**39** **Group:** `io.prometheus` **Name:** `prometheus-metrics-exposition-formats` **Version:** `1.1.0` +> - **Manifest License**: Apache License, Version 2.0 (Not Packaged) +> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) + +**40** **Group:** `io.prometheus` **Name:** `prometheus-metrics-model` **Version:** `1.1.0` +> - **Manifest License**: Apache License, Version 2.0 (Not Packaged) +> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) + +**41** **Group:** `io.prometheus` **Name:** `prometheus-metrics-shaded-protobuf` **Version:** `1.1.0` +> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) + +**42** **Group:** `io.zipkin.reporter2` **Name:** `zipkin-reporter` **Version:** `2.17.1` > - **Manifest Project URL**: [https://zipkin.io/](https://zipkin.io/) > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -> - **Embedded license files**: [zipkin-reporter-2.16.3.jar/META-INF/LICENSE](zipkin-reporter-2.16.3.jar/META-INF/LICENSE) +> - **Embedded license files**: [zipkin-reporter-2.17.1.jar/META-INF/LICENSE](zipkin-reporter-2.17.1.jar/META-INF/LICENSE) -**37** **Group:** `io.zipkin.reporter2` **Name:** `zipkin-sender-okhttp3` **Version:** `2.16.3` +**43** **Group:** `io.zipkin.reporter2` **Name:** `zipkin-sender-okhttp3` **Version:** `2.17.1` > - **Manifest Project URL**: [https://zipkin.io/](https://zipkin.io/) > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -> - **Embedded license files**: [zipkin-sender-okhttp3-2.16.3.jar/META-INF/LICENSE](zipkin-sender-okhttp3-2.16.3.jar/META-INF/LICENSE) +> - **Embedded license files**: [zipkin-sender-okhttp3-2.17.1.jar/META-INF/LICENSE](zipkin-sender-okhttp3-2.17.1.jar/META-INF/LICENSE) -**38** **Group:** `io.zipkin.zipkin2` **Name:** `zipkin` **Version:** `2.23.2` +**44** **Group:** `io.zipkin.zipkin2` **Name:** `zipkin` **Version:** `2.25.2` > - **Manifest Project URL**: [http://zipkin.io/](http://zipkin.io/) > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -> - **Embedded license files**: [zipkin-2.23.2.jar/META-INF/LICENSE](zipkin-2.23.2.jar/META-INF/LICENSE) +> - **Embedded license files**: [zipkin-2.25.2.jar/META-INF/LICENSE](zipkin-2.25.2.jar/META-INF/LICENSE) -**39** **Group:** `net.bytebuddy` **Name:** `byte-buddy-dep` **Version:** `1.14.9` +**45** **Group:** `net.bytebuddy` **Name:** `byte-buddy-dep` **Version:** `1.14.12` > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -> - **Embedded license files**: [byte-buddy-dep-1.14.9.jar/META-INF/LICENSE](byte-buddy-dep-1.14.9.jar/META-INF/LICENSE) - - [byte-buddy-dep-1.14.9.jar/META-INF/NOTICE](byte-buddy-dep-1.14.9.jar/META-INF/NOTICE) +> - **Embedded license files**: [byte-buddy-dep-1.14.12.jar/META-INF/LICENSE](byte-buddy-dep-1.14.12.jar/META-INF/LICENSE) + - [byte-buddy-dep-1.14.12.jar/META-INF/NOTICE](byte-buddy-dep-1.14.12.jar/META-INF/NOTICE) -**40** **Group:** `org.jetbrains` **Name:** `annotations` **Version:** `13.0` +**46** **Group:** `org.jetbrains` **Name:** `annotations` **Version:** `13.0` > - **POM Project URL**: [http://www.jetbrains.org](http://www.jetbrains.org) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**41** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib` **Version:** `1.9.20` +**47** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib` **Version:** `1.9.22` > - **POM Project URL**: [https://kotlinlang.org/](https://kotlinlang.org/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**42** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib-jdk7` **Version:** `1.9.20` +**48** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib-jdk7` **Version:** `1.9.22` > - **POM Project URL**: [https://kotlinlang.org/](https://kotlinlang.org/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**43** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib-jdk8` **Version:** `1.9.20` +**49** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib-jdk8` **Version:** `1.9.22` > - **POM Project URL**: [https://kotlinlang.org/](https://kotlinlang.org/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**44** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.6` +**50** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) -**45** **Group:** `org.ow2.asm` **Name:** `asm-analysis` **Version:** `9.6` +**51** **Group:** `org.ow2.asm` **Name:** `asm-analysis` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) -**46** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.6` +**52** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) -**47** **Group:** `org.ow2.asm` **Name:** `asm-tree` **Version:** `9.6` +**53** **Group:** `org.ow2.asm` **Name:** `asm-tree` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) -**48** **Group:** `org.ow2.asm` **Name:** `asm-util` **Version:** `9.6` +**54** **Group:** `org.ow2.asm` **Name:** `asm-util` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) -**49** **Group:** `org.snakeyaml` **Name:** `snakeyaml-engine` **Version:** `2.7` +**55** **Group:** `org.snakeyaml` **Name:** `snakeyaml-engine` **Version:** `2.7` > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM Project URL**: [https://bitbucket.org/snakeyaml/snakeyaml-engine](https://bitbucket.org/snakeyaml/snakeyaml-engine) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**50** **Group:** `org.yaml` **Name:** `snakeyaml` **Version:** `2.1` +**56** **Group:** `org.yaml` **Name:** `snakeyaml` **Version:** `2.2` > - **Manifest License**: Apache License, Version 2.0 (Not Packaged) > - **POM Project URL**: [https://bitbucket.org/snakeyaml/snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) ## MIT License -**51** **Group:** `org.slf4j` **Name:** `slf4j-api` **Version:** `2.0.9` +**57** **Group:** `org.slf4j` **Name:** `slf4j-api` **Version:** `2.0.12` > - **Project URL**: [http://www.slf4j.org](http://www.slf4j.org) > - **POM License**: MIT License - [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT) -> - **Embedded license files**: [slf4j-api-2.0.9.jar/META-INF/LICENSE.txt](slf4j-api-2.0.9.jar/META-INF/LICENSE.txt) +> - **Embedded license files**: [slf4j-api-2.0.12.jar/META-INF/LICENSE.txt](slf4j-api-2.0.12.jar/META-INF/LICENSE.txt) -**52** **Group:** `org.slf4j` **Name:** `slf4j-simple` **Version:** `2.0.9` +**58** **Group:** `org.slf4j` **Name:** `slf4j-simple` **Version:** `2.0.12` > - **Project URL**: [http://www.slf4j.org](http://www.slf4j.org) > - **POM License**: MIT License - [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT) -> - **Embedded license files**: [slf4j-simple-2.0.9.jar/META-INF/LICENSE.txt](slf4j-simple-2.0.9.jar/META-INF/LICENSE.txt) +> - **Embedded license files**: [slf4j-simple-2.0.12.jar/META-INF/LICENSE.txt](slf4j-simple-2.0.12.jar/META-INF/LICENSE.txt) ## The 3-Clause BSD License -**53** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.6` +**59** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) -**54** **Group:** `org.ow2.asm` **Name:** `asm-analysis` **Version:** `9.6` +**60** **Group:** `org.ow2.asm` **Name:** `asm-analysis` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) -**55** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.6` +**61** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) -**56** **Group:** `org.ow2.asm` **Name:** `asm-tree` **Version:** `9.6` +**62** **Group:** `org.ow2.asm` **Name:** `asm-tree` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) > - **POM License**: The 3-Clause BSD License - [https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) -**57** **Group:** `org.ow2.asm` **Name:** `asm-util` **Version:** `9.6` +**63** **Group:** `org.ow2.asm` **Name:** `asm-util` **Version:** `9.6` > - **Manifest Project URL**: [http://asm.ow2.org](http://asm.ow2.org) > - **Manifest License**: The 3-Clause BSD License (Not Packaged) > - **POM Project URL**: [http://asm.ow2.io/](http://asm.ow2.io/) @@ -297,6 +320,4 @@ _2023-11-13 19:19:44 PST_ ## Unknown -**58** **Group:** `com.squareup.okio` **Name:** `okio` **Version:** `3.6.0` - -**59** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib-common` **Version:** `1.9.20` +**64** **Group:** `com.squareup.okio` **Name:** `okio` **Version:** `3.8.0` diff --git a/licenses/slf4j-api-2.0.9.jar/META-INF/LICENSE.txt b/licenses/slf4j-api-2.0.12.jar/META-INF/LICENSE.txt similarity index 100% rename from licenses/slf4j-api-2.0.9.jar/META-INF/LICENSE.txt rename to licenses/slf4j-api-2.0.12.jar/META-INF/LICENSE.txt diff --git a/licenses/slf4j-simple-2.0.9.jar/META-INF/LICENSE.txt b/licenses/slf4j-simple-2.0.12.jar/META-INF/LICENSE.txt similarity index 100% rename from licenses/slf4j-simple-2.0.9.jar/META-INF/LICENSE.txt rename to licenses/slf4j-simple-2.0.12.jar/META-INF/LICENSE.txt diff --git a/licenses/zipkin-2.23.2.jar/META-INF/LICENSE b/licenses/zipkin-2.25.2.jar/META-INF/LICENSE similarity index 100% rename from licenses/zipkin-2.23.2.jar/META-INF/LICENSE rename to licenses/zipkin-2.25.2.jar/META-INF/LICENSE diff --git a/licenses/zipkin-reporter-2.16.3.jar/META-INF/LICENSE b/licenses/zipkin-reporter-2.17.1.jar/META-INF/LICENSE similarity index 100% rename from licenses/zipkin-reporter-2.16.3.jar/META-INF/LICENSE rename to licenses/zipkin-reporter-2.17.1.jar/META-INF/LICENSE diff --git a/licenses/zipkin-sender-okhttp3-2.16.3.jar/META-INF/LICENSE b/licenses/zipkin-sender-okhttp3-2.17.1.jar/META-INF/LICENSE similarity index 100% rename from licenses/zipkin-sender-okhttp3-2.16.3.jar/META-INF/LICENSE rename to licenses/zipkin-sender-okhttp3-2.17.1.jar/META-INF/LICENSE diff --git a/opentelemetry-api-shaded-for-instrumenting/build.gradle.kts b/opentelemetry-api-shaded-for-instrumenting/build.gradle.kts index b1d2785296af..8075e3ebd2d5 100644 --- a/opentelemetry-api-shaded-for-instrumenting/build.gradle.kts +++ b/opentelemetry-api-shaded-for-instrumenting/build.gradle.kts @@ -38,6 +38,13 @@ val v1_31Deps by configurations.creating { exclude("io.opentelemetry", "opentelemetry-bom") exclude("io.opentelemetry", "opentelemetry-bom-alpha") } +val v1_32Deps by configurations.creating { + isCanBeResolved = true + isCanBeConsumed = false + // exclude the bom added by dependencyManagement + exclude("io.opentelemetry", "opentelemetry-bom") + exclude("io.opentelemetry", "opentelemetry-bom-alpha") +} // configuration for publishing the shadowed artifact val v1_10 by configurations.creating { @@ -56,6 +63,10 @@ val v1_31 by configurations.creating { isCanBeConsumed = true isCanBeResolved = false } +val v1_32 by configurations.creating { + isCanBeConsumed = true + isCanBeResolved = false +} dependencies { latestDeps("io.opentelemetry:opentelemetry-api") @@ -81,6 +92,11 @@ dependencies { strictly("1.31.0") } } + v1_32Deps("io.opentelemetry:$it") { + version { + strictly("1.32.0") + } + } } listOf("opentelemetry-extension-incubator").forEach { @@ -89,6 +105,11 @@ dependencies { strictly("1.31.0-alpha") } } + v1_32Deps("io.opentelemetry:$it") { + version { + strictly("1.32.0-alpha") + } + } } } @@ -120,11 +141,16 @@ tasks { configurations = listOf(v1_31Deps) archiveClassifier.set("v1_31") } + val v1_32Shadow by registering(ShadowJar::class) { + configurations = listOf(v1_32Deps) + archiveClassifier.set("v1_32") + } artifacts { add(v1_10.name, v1_10Shadow) add(v1_15.name, v1_15Shadow) add(v1_27.name, v1_27Shadow) add(v1_31.name, v1_31Shadow) + add(v1_32.name, v1_32Shadow) } } diff --git a/settings.gradle.kts b/settings.gradle.kts index ac4b9bb3d2fc..c2c5435be329 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,26 +1,26 @@ pluginManagement { plugins { id("com.github.jk1.dependency-license-report") version "2.5" - id("com.google.cloud.tools.jib") version "3.4.0" + id("com.google.cloud.tools.jib") version "3.4.1" id("com.gradle.plugin-publish") version "1.2.1" id("io.github.gradle-nexus.publish-plugin") version "1.3.0" - id("org.jetbrains.kotlin.jvm") version "1.9.20" + id("org.jetbrains.kotlin.jvm") version "1.9.22" id("org.xbib.gradle.plugin.jflex") version "3.0.2" id("org.unbroken-dome.xjc") version "2.0.0" - id("org.graalvm.buildtools.native") version "0.9.28" + id("org.graalvm.buildtools.native") version "0.10.1" } } plugins { - id("com.gradle.enterprise") version "3.15.1" - id("com.gradle.common-custom-user-data-gradle-plugin") version "1.12" - id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0" + id("com.gradle.enterprise") version "3.16.2" + id("com.gradle.common-custom-user-data-gradle-plugin") version "1.12.2" + id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" // this can't live in pluginManagement currently due to // https://github.com/bmuschko/gradle-docker-plugin/issues/1123 // in particular, these commands are failing (reproducible locally): // ./gradlew :smoke-tests:images:servlet:buildLinuxTestImages pushMatrix -PsmokeTestServer=jetty // ./gradlew :smoke-tests:images:servlet:buildWindowsTestImages pushMatrix -PsmokeTestServer=jetty - id("com.bmuschko.docker-remote-api") version "9.3.7" apply false + id("com.bmuschko.docker-remote-api") version "9.4.0" apply false } dependencyResolutionManagement { @@ -402,6 +402,7 @@ include(":instrumentation:opentelemetry-api:opentelemetry-api-1.10:javaagent") include(":instrumentation:opentelemetry-api:opentelemetry-api-1.15:javaagent") include(":instrumentation:opentelemetry-api:opentelemetry-api-1.27:javaagent") include(":instrumentation:opentelemetry-api:opentelemetry-api-1.31:javaagent") +include(":instrumentation:opentelemetry-api:opentelemetry-api-1.32:javaagent") include(":instrumentation:opentelemetry-extension-annotations-1.0:javaagent") include(":instrumentation:opentelemetry-extension-kotlin-1.0:javaagent") include(":instrumentation:opentelemetry-instrumentation-annotations-1.16:javaagent") diff --git a/smoke-tests-otel-starter/build.gradle.kts b/smoke-tests-otel-starter/build.gradle.kts index 470a0657c581..8d9419ec083d 100644 --- a/smoke-tests-otel-starter/build.gradle.kts +++ b/smoke-tests-otel-starter/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("otel.java-conventions") - id("org.springframework.boot") version "3.1.5" + id("org.springframework.boot") version "3.2.3" id("org.graalvm.buildtools.native") } diff --git a/smoke-tests/build.gradle.kts b/smoke-tests/build.gradle.kts index 4c334c70dfc2..e6930f5c0c4b 100644 --- a/smoke-tests/build.gradle.kts +++ b/smoke-tests/build.gradle.kts @@ -15,7 +15,7 @@ otelJava { maxJavaVersionForTests.set(JavaVersion.VERSION_11) } -val dockerJavaVersion = "3.3.4" +val dockerJavaVersion = "3.3.5" dependencies { testCompileOnly("com.google.auto.value:auto-value-annotations") testAnnotationProcessor("com.google.auto.value:auto-value") @@ -23,13 +23,13 @@ dependencies { api("org.spockframework:spock-core") api(project(":testing-common")) - implementation(platform("io.grpc:grpc-bom:1.59.0")) + implementation(platform("io.grpc:grpc-bom:1.62.2")) implementation("org.slf4j:slf4j-api") implementation("io.opentelemetry:opentelemetry-api") implementation("io.opentelemetry.proto:opentelemetry-proto") implementation("org.testcontainers:testcontainers") implementation("com.fasterxml.jackson.core:jackson-databind") - implementation("com.google.protobuf:protobuf-java-util:3.25.1") + implementation("com.google.protobuf:protobuf-java-util:3.25.3") implementation("io.grpc:grpc-netty-shaded") implementation("io.grpc:grpc-protobuf") implementation("io.grpc:grpc-stub") diff --git a/smoke-tests/images/fake-backend/build.gradle.kts b/smoke-tests/images/fake-backend/build.gradle.kts index ab01a6f3fb12..4cf90385e282 100644 --- a/smoke-tests/images/fake-backend/build.gradle.kts +++ b/smoke-tests/images/fake-backend/build.gradle.kts @@ -12,7 +12,7 @@ plugins { } dependencies { - implementation("com.linecorp.armeria:armeria-grpc:1.26.3") + implementation("com.linecorp.armeria:armeria-grpc:1.27.2") implementation("io.opentelemetry.proto:opentelemetry-proto") runtimeOnly("org.slf4j:slf4j-simple") } diff --git a/smoke-tests/images/grpc/build.gradle.kts b/smoke-tests/images/grpc/build.gradle.kts index 5d080f717cef..cda358303737 100644 --- a/smoke-tests/images/grpc/build.gradle.kts +++ b/smoke-tests/images/grpc/build.gradle.kts @@ -8,10 +8,10 @@ plugins { } dependencies { - implementation(platform("io.grpc:grpc-bom:1.59.0")) + implementation(platform("io.grpc:grpc-bom:1.62.2")) implementation(platform("io.opentelemetry:opentelemetry-bom:1.0.0")) implementation(platform("io.opentelemetry:opentelemetry-bom-alpha:1.0.0-alpha")) - implementation(platform("org.apache.logging.log4j:log4j-bom:2.21.1")) + implementation(platform("org.apache.logging.log4j:log4j-bom:2.23.0")) implementation("io.grpc:grpc-netty-shaded") implementation("io.grpc:grpc-protobuf") diff --git a/smoke-tests/images/quarkus/build.gradle.kts b/smoke-tests/images/quarkus/build.gradle.kts index 01e16b9cf22c..cbe556f734e5 100644 --- a/smoke-tests/images/quarkus/build.gradle.kts +++ b/smoke-tests/images/quarkus/build.gradle.kts @@ -12,11 +12,11 @@ plugins { id("otel.java-conventions") id("com.google.cloud.tools.jib") - id("io.quarkus") version "3.5.2" + id("io.quarkus") version "3.8.0" } dependencies { - implementation(enforcedPlatform("io.quarkus:quarkus-bom:3.5.2")) + implementation(enforcedPlatform("io.quarkus:quarkus-bom:3.8.0")) implementation("io.quarkus:quarkus-resteasy") } diff --git a/smoke-tests/images/spring-boot/build.gradle.kts b/smoke-tests/images/spring-boot/build.gradle.kts index 5c3791dbb56f..67d9540dc4f9 100644 --- a/smoke-tests/images/spring-boot/build.gradle.kts +++ b/smoke-tests/images/spring-boot/build.gradle.kts @@ -5,12 +5,12 @@ plugins { id("otel.java-conventions") id("com.google.cloud.tools.jib") - id("org.springframework.boot") version "2.7.17" + id("org.springframework.boot") version "2.7.18" } dependencies { implementation(platform("io.opentelemetry:opentelemetry-bom:1.0.0")) - implementation(platform("org.springframework.boot:spring-boot-dependencies:2.7.17")) + implementation(platform("org.springframework.boot:spring-boot-dependencies:2.7.18")) implementation("io.opentelemetry:opentelemetry-api") implementation(project(":instrumentation-annotations")) @@ -20,7 +20,7 @@ dependencies { configurations.runtimeClasspath { resolutionStrategy { // requires old logback (and therefore also old slf4j) - force("ch.qos.logback:logback-classic:1.2.11") + force("ch.qos.logback:logback-classic:1.2.13") force("org.slf4j:slf4j-api:1.7.36") } } diff --git a/smoke-tests/src/test/java/io/opentelemetry/smoketest/windows/WindowsTestContainerManager.java b/smoke-tests/src/test/java/io/opentelemetry/smoketest/windows/WindowsTestContainerManager.java index 0026380032d2..cdb4f41f2647 100644 --- a/smoke-tests/src/test/java/io/opentelemetry/smoketest/windows/WindowsTestContainerManager.java +++ b/smoke-tests/src/test/java/io/opentelemetry/smoketest/windows/WindowsTestContainerManager.java @@ -341,6 +341,8 @@ private static Waiter createTargetWaiter(TargetWaitStrategy strategy) { // https://github.com/google/error-prone/issues/3090 @SuppressWarnings("MethodCanBeStatic") private interface Waiter { + // errorprone 2.24.0 flags logHandler as unused + @SuppressWarnings("UnusedVariable") default void configureLogger(ContainerLogHandler logHandler) {} void waitFor(Container container); diff --git a/testing/armeria-shaded-for-testing/build.gradle.kts b/testing/armeria-shaded-for-testing/build.gradle.kts index 103553d928a8..e0ba5ce7eb45 100644 --- a/testing/armeria-shaded-for-testing/build.gradle.kts +++ b/testing/armeria-shaded-for-testing/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } dependencies { - implementation("com.linecorp.armeria:armeria-junit5:1.26.3") + implementation("com.linecorp.armeria:armeria-junit5:1.27.2") } tasks { diff --git a/version.gradle.kts b/version.gradle.kts index 043387ffcc40..c38a2e00f334 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -1,5 +1,5 @@ -val stableVersion = "1.32.0-SNAPSHOT" -val alphaVersion = "1.32.0-alpha-SNAPSHOT" +val stableVersion = "1.32.1-adot2" +val alphaVersion = "1.32.1-adot2-alpha" allprojects { if (findProperty("otel.stable") != "true") {