diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7971d1daf5b2..e1c0e8066f1a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,6 +1,6 @@ # # Learn about membership in OpenTelemetry community: -# https://github.com/open-telemetry/community/blob/main/community-membership.md +# https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md # # # Learn about CODEOWNERS file format: diff --git a/.github/graal-native-docker-compose.yaml b/.github/graal-native-docker-compose.yaml index 5f7634b72ec4..bdcf87f31317 100644 --- a/.github/graal-native-docker-compose.yaml +++ b/.github/graal-native-docker-compose.yaml @@ -14,14 +14,18 @@ services: kafka: image: confluentinc/cp-kafka:6.2.10 + ports: + - 9094:9094 depends_on: - zookeeper - ports: - - "29092:29092" environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 - KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092 - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT - KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT + KAFKA_LISTENERS: INTERNAL://0.0.0.0:9092,OUTSIDE://0.0.0.0:9094 + KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:9092,OUTSIDE://localhost:9094 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT + KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_DEFAULT_REPLICATION_FACTOR: 1 + KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 + KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 diff --git a/.github/renovate.json5 b/.github/renovate.json5 index c47982066dbc..c93741ed8db4 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -11,11 +11,19 @@ // https://github.com/renovatebot/renovate/discussions/8399#discussioncomment-305798 "separateMinorPatch": true, "packageRules": [ + { + // this is to reduce the number of renovate PRs by consolidating them into a weekly batch + "matchManagers": ["github-actions"], + "extends": ["schedule:weekly"], + "groupName": "github actions", + "separateMinorPatch": false // overrides separateMinorPatch specified above + }, { "matchPackageNames": [ "io.opentelemetry.contrib:opentelemetry-aws-resources", "io.opentelemetry.contrib:opentelemetry-aws-xray-propagator", "io.opentelemetry.contrib:opentelemetry-gcp-resources", + "io.opentelemetry.contrib:opentelemetry-baggage-processor", "io.opentelemetry.proto:opentelemetry-proto", "io.opentelemetry.semconv:opentelemetry-semconv" ], diff --git a/.github/workflows/auto-update-otel-sdk.yml b/.github/workflows/auto-update-otel-sdk.yml index 7c7773a46ac1..7fdd8c5994af 100644 --- a/.github/workflows/auto-update-otel-sdk.yml +++ b/.github/workflows/auto-update-otel-sdk.yml @@ -66,13 +66,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 - name: Update license report run: ./gradlew generateLicenseReport diff --git a/.github/workflows/build-common.yml b/.github/workflows/build-common.yml index 8a5f1311e784..79efebc87490 100644 --- a/.github/workflows/build-common.yml +++ b/.github/workflows/build-common.yml @@ -32,13 +32,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: ${{ inputs.cache-read-only }} # gradle enterprise is used for the build cache @@ -54,7 +54,7 @@ jobs: steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: gradle/actions/wrapper-validation@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + - uses: gradle/actions/wrapper-validation@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 license-check: runs-on: ubuntu-latest @@ -65,13 +65,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: ${{ inputs.cache-read-only }} # gradle enterprise is used for the build cache @@ -88,12 +88,11 @@ jobs: run: | # add any untracked folders that may have been added by generateLicenseReport git add licenses - # there's always going to one line difference due to the timestamp included in the report - if [[ $(git diff --cached --shortstat licenses) == " 1 file changed, 1 insertion(+), 1 deletion(-)" ]] + if [[ $(git diff --cached --shortstat licenses) == "" ]] then echo "Licenses are up-to-date." else - echo "Licenses are not up-to-date, please run './gradlew generateLicenseReport' locally and commit." + echo "Licenses are not up-to-date, please run './gradlew generateLicenseReport --no-build-cache' locally and commit." echo echo "$(git diff --cached --stat licenses)" echo @@ -135,7 +134,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version @@ -145,7 +144,7 @@ jobs: sed -i "s/org.gradle.jvmargs=/org.gradle.jvmargs=-Xmx3g /" gradle.properties - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: ${{ inputs.cache-read-only }} # gradle enterprise is used for the build cache @@ -172,7 +171,7 @@ jobs: fi - name: Upload agent jar - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: opentelemetry-javaagent.jar path: javaagent/build/libs/opentelemetry-javaagent-*-SNAPSHOT.jar @@ -183,7 +182,7 @@ jobs: mkdir sboms cp javaagent/build/spdx/*.spdx.json sboms - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 name: Upload SBOMs with: name: opentelemetry-java-instrumentation-SBOM.zip @@ -221,21 +220,21 @@ jobs: - id: setup-test-java name: Set up JDK ${{ matrix.test-java-version }}-${{ matrix.vm }} for running tests - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 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@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version # vaadin 14 tests fail with node 18 - name: Set up Node - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: node-version: 16 @@ -250,7 +249,7 @@ jobs: run: .github/scripts/deadlock-detector.sh - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: # only push cache for one matrix option since github action cache space is limited cache-read-only: ${{ inputs.cache-read-only || matrix.test-java-version != 11 || matrix.vm != 'hotspot' }} @@ -292,7 +291,7 @@ jobs: - name: Upload deadlock detector artifacts if any if: failure() - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: deadlock-detector-test-${{ matrix.test-java-version }}-${{ matrix.vm }}-${{ matrix.test-partition }} path: /tmp/deadlock-detector-* @@ -300,7 +299,7 @@ jobs: - name: Upload jvm crash dump files if any if: failure() - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: javacore-test-${{ matrix.test-java-version }}-${{ matrix.test-partition }} path: | @@ -343,13 +342,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Set up Gradle cache - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 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' }} @@ -369,7 +368,7 @@ jobs: - name: Upload jvm crash dump files if any if: failure() - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: javacore-smoke-test-${{ matrix.smoke-test-suite }}-${{ matrix.os }} # we expect crash dumps either in root director or in smoke-tests @@ -396,13 +395,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: ${{ inputs.cache-read-only }} @@ -419,13 +418,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Set up Gradle cache - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: ${{ inputs.cache-read-only }} diff --git a/.github/workflows/build-pull-request.yml b/.github/workflows/build-pull-request.yml index 402beccc91f1..4008f6e2d316 100644 --- a/.github/workflows/build-pull-request.yml +++ b/.github/workflows/build-pull-request.yml @@ -2,6 +2,11 @@ name: Build pull request on: pull_request: + types: + - labeled + - opened + - synchronize + - reopened concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 23dd91e96469..214f30cb4ef6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -67,13 +67,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: # gradle enterprise is used for the build cache gradle-home-cache-excludes: caches/build-cache-1 diff --git a/.github/workflows/codeql-daily.yml b/.github/workflows/codeql-daily.yml index b597a361bc7a..658038dc362d 100644 --- a/.github/workflows/codeql-daily.yml +++ b/.github/workflows/codeql-daily.yml @@ -24,13 +24,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up Java 17 - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Initialize CodeQL - uses: github/codeql-action/init@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9 + uses: github/codeql-action/init@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0 with: languages: java # using "latest" helps to keep up with the latest Kotlin support @@ -38,14 +38,14 @@ jobs: tools: latest - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 - name: Build # skipping build cache is needed so that all modules will be analyzed run: ./gradlew assemble -x javadoc --no-build-cache --no-daemon - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9 + uses: github/codeql-action/analyze@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0 workflow-notification: needs: diff --git a/.github/workflows/overhead-benchmark-daily.yml b/.github/workflows/overhead-benchmark-daily.yml index ed072cc7c7c5..cc62b80ed000 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: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 - name: Run tests working-directory: benchmark-overhead diff --git a/.github/workflows/owasp-dependency-check-daily.yml b/.github/workflows/owasp-dependency-check-daily.yml index 8071a1d78035..2d44702e2024 100644 --- a/.github/workflows/owasp-dependency-check-daily.yml +++ b/.github/workflows/owasp-dependency-check-daily.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@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version @@ -28,7 +28,7 @@ jobs: run: | sed -i "s/org.gradle.jvmargs=/org.gradle.jvmargs=-Xmx3g /" gradle.properties - - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + - uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 - run: ./gradlew :javaagent:dependencyCheckAnalyze env: @@ -36,7 +36,7 @@ jobs: - name: Upload report if: always() - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: path: javaagent/build/reports diff --git a/.github/workflows/pr-smoke-test-early-jdk8-images.yml b/.github/workflows/pr-smoke-test-early-jdk8-images.yml new file mode 100644 index 000000000000..e29c168590f2 --- /dev/null +++ b/.github/workflows/pr-smoke-test-early-jdk8-images.yml @@ -0,0 +1,35 @@ +name: PR build early jdk8 images for smoke tests + +on: + pull_request: + paths: + - "smoke-tests/images/early-jdk8/**" + - ".github/workflows/pr-smoke-test-early-jdk8-images.yml" + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + + - name: Free disk space + run: .github/scripts/gha-free-disk-space.sh + + - name: Set up JDK for running Gradle + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 + with: + distribution: temurin + java-version-file: .java-version + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + with: + cache-read-only: true + # gradle enterprise is used for the build cache + gradle-home-cache-excludes: caches/build-cache-1 + + - name: Build Docker image + run: ./gradlew :smoke-tests:images:early-jdk8:imageBuild diff --git a/.github/workflows/pr-smoke-test-fake-backend-images.yml b/.github/workflows/pr-smoke-test-fake-backend-images.yml index d0892b77fe40..75bb09623157 100644 --- a/.github/workflows/pr-smoke-test-fake-backend-images.yml +++ b/.github/workflows/pr-smoke-test-fake-backend-images.yml @@ -19,13 +19,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: true # gradle enterprise is used for the build cache @@ -46,13 +46,13 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: 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 50880664b23d..52662d3943b4 100644 --- a/.github/workflows/pr-smoke-test-servlet-images.yml +++ b/.github/workflows/pr-smoke-test-servlet-images.yml @@ -43,7 +43,7 @@ jobs: java-version-file: .java-version - name: Set up Gradle cache - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: true diff --git a/.github/workflows/publish-petclinic-benchmark-image.yml b/.github/workflows/publish-petclinic-benchmark-image.yml index b3c93ba5f769..9646756ff7db 100644 --- a/.github/workflows/publish-petclinic-benchmark-image.yml +++ b/.github/workflows/publish-petclinic-benchmark-image.yml @@ -29,7 +29,7 @@ jobs: run: echo "TS=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV - name: Push to GitHub packages - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: push: true file: benchmark-overhead/Dockerfile-petclinic-base diff --git a/.github/workflows/publish-smoke-test-early-jdk8-images.yml b/.github/workflows/publish-smoke-test-early-jdk8-images.yml new file mode 100644 index 000000000000..8ba8425e28ec --- /dev/null +++ b/.github/workflows/publish-smoke-test-early-jdk8-images.yml @@ -0,0 +1,49 @@ +name: Publish early jdk8 images for smoke tests + +on: + push: + paths: + - "smoke-tests/images/early-jdk8/**" + - ".github/workflows/pr-smoke-test-early-jdk8-images.yml" + branches: + - main + workflow_dispatch: + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Free disk space + run: .github/scripts/gha-free-disk-space.sh + + - name: Set up JDK for running Gradle + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version-file: .java-version + + - name: Login to GitHub package registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set tag + run: echo "TAG=$(date '+%Y%m%d').$GITHUB_RUN_ID" >> $GITHUB_ENV + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 + + - name: Build Docker image + run: ./gradlew :smoke-tests:images:early-jdk8:dockerPush -PextraTag=${{ env.TAG }} + + workflow-notification: + needs: + - publish + if: always() + uses: ./.github/workflows/reusable-workflow-notification.yml + with: + success: ${{ needs.publish.result == 'success' }} diff --git a/.github/workflows/publish-smoke-test-fake-backend-images.yml b/.github/workflows/publish-smoke-test-fake-backend-images.yml index 991986922670..ffd8a242ad8a 100644 --- a/.github/workflows/publish-smoke-test-fake-backend-images.yml +++ b/.github/workflows/publish-smoke-test-fake-backend-images.yml @@ -35,7 +35,7 @@ jobs: run: echo "TAG=$(date '+%Y%m%d').$GITHUB_RUN_ID" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 - name: Build Docker image run: ./gradlew :smoke-tests:images:fake-backend:jib -Djib.httpTimeout=120000 -Djib.console=plain -PextraTag=${{ env.TAG }} @@ -68,7 +68,7 @@ jobs: run: echo "TAG=$(date '+%Y%m%d').$GITHUB_RUN_ID" >> $GITHUB_ENV - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 - name: Build Docker image run: ./gradlew :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 e38a4574e151..98b12af63d50 100644 --- a/.github/workflows/publish-smoke-test-servlet-images.yml +++ b/.github/workflows/publish-smoke-test-servlet-images.yml @@ -54,20 +54,20 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Login to GitHub package registry - uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Gradle cache - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 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 e0b42505f189..e86cd2ebe4f0 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@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + - uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 - name: Build and publish artifacts env: @@ -114,7 +114,7 @@ jobs: cp javaagent/build/spdx/*.spdx.json sboms zip opentelemetry-java-instrumentation-SBOM.zip sboms/* - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 name: Upload SBOMs with: name: opentelemetry-java-instrumentation-SBOM diff --git a/.github/workflows/reusable-muzzle.yml b/.github/workflows/reusable-muzzle.yml index 581ff55e004d..7ea42f3deaf2 100644 --- a/.github/workflows/reusable-muzzle.yml +++ b/.github/workflows/reusable-muzzle.yml @@ -28,13 +28,13 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: ${{ inputs.cache-read-only }} diff --git a/.github/workflows/reusable-native-tests.yml b/.github/workflows/reusable-native-tests.yml index e9e8e278e265..09ea5ce2312c 100644 --- a/.github/workflows/reusable-native-tests.yml +++ b/.github/workflows/reusable-native-tests.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - id: read-java run: echo "version=$(cat .java-version)" >> "$GITHUB_OUTPUT" - - uses: graalvm/setup-graalvm@2f25c0caae5b220866f732832d5e3e29ff493338 # v1.2.1.1 + - uses: graalvm/setup-graalvm@22cc13fe88ef133134b3798e128fb208df55e1f5 # v1.2.3.1 with: version: "latest" java-version: "${{ steps.read-java.outputs.version }}" diff --git a/.github/workflows/reusable-smoke-test-images.yml b/.github/workflows/reusable-smoke-test-images.yml index db97848fd712..73eeb4aa53a1 100644 --- a/.github/workflows/reusable-smoke-test-images.yml +++ b/.github/workflows/reusable-smoke-test-images.yml @@ -44,14 +44,14 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version - name: Login to GitHub package registry if: inputs.publish - uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0 + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -61,7 +61,7 @@ jobs: run: echo "TAG=$(date '+%Y%m%d').$GITHUB_RUN_ID" >> $GITHUB_ENV - name: Set up Gradle cache - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 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 c1c529a37d2b..2b2727ba8ea1 100644 --- a/.github/workflows/reusable-test-indy.yml +++ b/.github/workflows/reusable-test-indy.yml @@ -19,7 +19,6 @@ permissions: jobs: test-indy: name: testIndy${{ matrix.test-partition }} - if: ${{ contains(github.event.pull_request.labels.*.name, 'test indy') }} runs-on: ubuntu-latest strategy: matrix: @@ -36,7 +35,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version @@ -47,7 +46,7 @@ jobs: # vaadin 14 tests fail with node 18 - name: Set up Node - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 with: node-version: 16 @@ -59,7 +58,7 @@ jobs: key: ${{ runner.os }}-test-latest-cache-pnpm-modules - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: ${{ inputs.cache-read-only }} # gradle enterprise is used for the build cache diff --git a/.github/workflows/reusable-test-latest-deps.yml b/.github/workflows/reusable-test-latest-deps.yml index 654b50c68979..15f59f58c94c 100644 --- a/.github/workflows/reusable-test-latest-deps.yml +++ b/.github/workflows/reusable-test-latest-deps.yml @@ -35,7 +35,7 @@ jobs: run: .github/scripts/gha-free-disk-space.sh - name: Set up JDK for running Gradle - uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1 + uses: actions/setup-java@6a0805fcefea3d4657a47ac4c165951e33482018 # v4.2.2 with: distribution: temurin java-version-file: .java-version @@ -55,7 +55,7 @@ jobs: run: .github/scripts/deadlock-detector.sh - name: Setup Gradle - uses: gradle/actions/setup-gradle@db19848a5fa7950289d3668fb053140cf3028d43 # v3.3.2 + uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0 with: cache-read-only: ${{ inputs.cache-read-only }} # gradle enterprise is used for the build cache @@ -90,7 +90,7 @@ jobs: - name: Upload deadlock detector artifacts if any if: failure() - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: deadlock-detector-test-latest-${{ matrix.test-java-version }}-${{ matrix.vm }}-${{ matrix.test-partition }} path: /tmp/deadlock-detector-* @@ -98,7 +98,7 @@ jobs: - name: Upload jvm crash dump files if any if: failure() - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: javacore-test-latest-${{ matrix.test-java-version }}-${{ matrix.test-partition }} path: | diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 0cea8cc256f5..9644ee8d786d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -34,7 +34,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3 + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 with: results_file: results.sarif results_format: sarif @@ -56,7 +56,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: SARIF file path: results.sarif @@ -64,6 +64,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9 + uses: github/codeql-action/upload-sarif@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0 with: sarif_file: results.sarif diff --git a/CHANGELOG.md b/CHANGELOG.md index 173e3067b91c..442a8540ecde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,125 @@ ## Unreleased +## Version 1.33.5 (2024-07-25) + +### 📈 Enhancements + +- Backport: Update the OpenTelemetry SDK version to 1.40.0 + ([#11879](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11879)) + +## Version 2.6.0 (2024-07-17) + +The Spring Boot Starter (`opentelemetry-spring-boot-starter`) is now stable. + +### Migration notes + +- The `opentelemetry-spring-boot` and `opentelemetry-spring-boot-3` artifacts have been merged + into a single artifact named `opentelemetry-spring-boot-autoconfigure` + which supports both Spring Boot 2 and Spring Boot 3 +- Two experimental HTTP metrics have been renamed: + - `http.server.request.size` → `http.server.request.body.size`, + - `http.server.response.size` → `http.server.response.body.size` + +### 🌟 New javaagent instrumentation + +- Javalin + ([#11587](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11587)) +- ClickHouse + ([#11660](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11660)) + +### 📈 Enhancements + +- Support HTTP client instrumentation configuration in Spring starter + ([#11620](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11620)) +- Influxdb client: don't fill `db.statement` for create/drop database and write operations + ([#11557](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11557)) +- Support `otel.instrumentation.common.default-enabled` in the Spring starter + ([#11746](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11746)) +- Support Jetty HTTP client 12 + ([#11519](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11519)) +- Add Pulsar `messaging.producer.duration` metric + ([#11591](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11591)) +- Improve instrumentation suppression behavior + ([#11640](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11640)) +- Propagate OpenTelemetry context through custom AWS client context for Lambda direct calls + ([#11675](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11675)) +- Spring Native support for `@WithSpan` + ([#11757](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11757)) +- Support HTTP server instrumentation config properties in the Spring starter + ([#11667](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11667)) + +### 🛠️ Bug fixes + +- Fix `http.server.active_requests` metric with async requests + ([#11638](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11638)) + +## Version 1.33.4 (2024-06-19) + +### 📈 Enhancements + +- Backport: Undertow, run response customizer on all ServerConnection implementations + ([#11548](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11548)) +- Backport: Improve security manager support + ([#11606](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11606)) +- Backport: Update the OpenTelemetry SDK version to 1.39.0 + ([#11603](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11603)) + +### 🛠️ Bug fixes + +- Backport: Avoid NullPointerException when JMS destination is not available + ([#11577](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11577)) +- Backport: Fix Spring Kafka instrumentation closing the trace too early + ([#11592](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11592)) +- Backport: Fix gRPC instrumentation adding duplicates to metadata instead of overwriting + ([#11604](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11604)) +- Backport: Fix request header capture corrupting tomcat request + ([#11607](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11607)) + +## Version 2.5.0 (2024-06-17) + +### 📈 Enhancements + +- Add support for Informix connection string parsing in JDBC instrumentation + ([#11542](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11542)) +- Generate an SBOM for the javaagent artifact + ([#11075](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11075)) +- Extract sql operation even when the sanitizer is disabled + ([#11472](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11472)) +- Improve security manager support + ([#11466](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11466)) +- Generate Log4j2Plugin.dat for OpenTelemetryAppender + ([#11503](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11503)) +- Stop kotlin coroutine dispatcher from propagating context + ([#11500](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11500)) +- Handle Vert.x sub routes + ([#11535](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11535)) +- Undertow: run response customizer on all ServerConnection implementations + ([#11539](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11539)) +- Allow configuring MDC key names for trace_id, span_id, trace_flags + ([#11329](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11329)) +- Apply async end strategy to all kotlin coroutine flows + ([#11583](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11583)) + +### 🛠️ Bug fixes + +- Fix container.id issue in some crio scenarios + ([#11382](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11382)) +- Fix Finagle http client context propagation + ([#11400](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11400)) +- Fix sporadically failing finagle test + ([#11441](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11441)) +- Fix request header capture corrupting tomcat request + ([#11469](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11469)) +- Fix Ktor server instrumentation when Ktor client library is not present + ([#11454](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11454)) +- Fix gRPC instrumentation adding duplicates to metadata instead of overwriting + ([#11308](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11308)) +- Avoid NullPointerException when JMS destination is not available + ([#11570](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11570)) +- Fix Spring Kafka instrumentation closing the trace too early + ([#11471](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/11471)) + ## Version 1.33.3 (2024-05-21) ### 📈 Enhancements diff --git a/README.md b/README.md index 9de93acfe745..3abe2c6d7aab 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ configured to send data to at `http://localhost:4317`. Configuration parameters are passed as Java system properties (`-D` flags) or -as environment variables. See [the configuration documentation][config] +as environment variables. See [the configuration documentation][config-agent] for the full list of configuration items. For example: ``` @@ -93,11 +93,14 @@ java -javaagent:path/to/opentelemetry-javaagent.jar \ ## Configuring the Agent -The agent is [highly configurable][config]! Many aspects of the agent's behavior can be +The agent is highly configurable! Many aspects of the agent's behavior can be configured for your needs, such as exporter choice, exporter config (like where data is sent), trace context propagation headers, and much more. -[Click here to see the detailed list of configuration environment variables and system properties][config]. +For a detailed list of agent configuration options, see the [agent configuration docs][config-agent]. + +For a detailed list of additional SDK configuration environment variables and system properties, +see the [SDK configuration docs][config-sdk]. *Note: Config parameter names are very likely to change over time, so please check back here when trying out a new version! @@ -151,6 +154,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md). Triagers ([@open-telemetry/java-instrumentation-triagers](https://github.com/orgs/open-telemetry/teams/java-instrumentation-triagers)): +- [Jay DeLuca](https://github.com/jaydeluca) - [Jonas Kunz](https://github.com/JonasKunz), Elastic - [Steve Rao](https://github.com/steverao), Alibaba - [Sylvain Juge](https://github.com/SylvainJuge), Elastic @@ -175,7 +179,7 @@ Emeritus maintainers: - [Tyler Benson](https://github.com/tylerbenson) Learn more about roles in -the [community repository](https://github.com/open-telemetry/community/blob/main/community-membership.md). +the [community repository](https://github.com/open-telemetry/community/blob/main/guides/contributor/membership.md). Thanks to all the people who already contributed! @@ -183,7 +187,9 @@ Thanks to all the people who already contributed! -[config]: https://opentelemetry.io/docs/instrumentation/java/automatic/agent-config/ +[config-agent]: https://opentelemetry.io/docs/zero-code/java/agent/configuration/ + +[config-sdk]: https://opentelemetry.io/docs/languages/java/configuration/ [manual]: https://opentelemetry.io/docs/instrumentation/java/manual/ diff --git a/benchmark-overhead-jmh/build.gradle.kts b/benchmark-overhead-jmh/build.gradle.kts index 6ea672d76543..6e713e3db381 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.3.0") + jmhImplementation("org.springframework.boot:spring-boot-starter-web:3.3.2") } tasks { diff --git a/benchmark-overhead/Dockerfile-petclinic-base b/benchmark-overhead/Dockerfile-petclinic-base index 8b5820293e5a..154833d54187 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.3 +FROM bellsoft/liberica-openjdk-alpine:21.0.4 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 0a455d979963..9793e9c5cbf8 100644 --- a/benchmark-overhead/build.gradle.kts +++ b/benchmark-overhead/build.gradle.kts @@ -16,16 +16,16 @@ repositories { } dependencies { - implementation(enforcedPlatform("org.junit:junit-bom:5.10.2")) + implementation(enforcedPlatform("org.junit:junit-bom:5.10.3")) - testImplementation("org.testcontainers:testcontainers:1.19.8") - testImplementation("org.testcontainers:postgresql:1.19.8") + testImplementation("org.testcontainers:testcontainers:1.20.1") + testImplementation("org.testcontainers:postgresql:1.20.1") 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.1") testImplementation("com.jayway.jsonpath:json-path:2.9.0") - testImplementation("org.slf4j:slf4j-simple:2.0.13") + testImplementation("org.slf4j:slf4j-simple:2.0.16") 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 e6441136f3d4..2c3521197d7c 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 8a1f6b97f473..68e8816d71c9 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=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/benchmark-overhead/gradlew b/benchmark-overhead/gradlew index b740cf13397a..f5feea6d6b11 100755 --- a/benchmark-overhead/gradlew +++ b/benchmark-overhead/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/benchmark-overhead/gradlew.bat b/benchmark-overhead/gradlew.bat index 25da30dbdeee..9d21a21834d5 100644 --- a/benchmark-overhead/gradlew.bat +++ b/benchmark-overhead/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/benchmark-overhead/src/test/java/io/opentelemetry/OverheadTests.java b/benchmark-overhead/src/test/java/io/opentelemetry/OverheadTests.java index b69a6d708294..86756a230f39 100644 --- a/benchmark-overhead/src/test/java/io/opentelemetry/OverheadTests.java +++ b/benchmark-overhead/src/test/java/io/opentelemetry/OverheadTests.java @@ -110,7 +110,7 @@ void runAppOnce(TestConfig config, Agent agent) throws Exception { } private void startRecording(Agent agent, GenericContainer petclinic) throws Exception { - Path outFile = namingConventions.container.jfrFile(agent); + String outFile = namingConventions.container.jfrFile(agent); String[] command = { "jcmd", "1", @@ -123,16 +123,27 @@ private void startRecording(Agent agent, GenericContainer petclinic) throws E petclinic.execInContainer(command); } - private void doWarmupPhase(TestConfig testConfig, GenericContainer petclinic) throws IOException, InterruptedException { - System.out.println("Performing startup warming phase for " + testConfig.getWarmupSeconds() + " seconds..."); + private void doWarmupPhase(TestConfig testConfig, GenericContainer petclinic) + throws IOException, InterruptedException { + System.out.println( + "Performing startup warming phase for " + testConfig.getWarmupSeconds() + " seconds..."); // excluding the JFR recording from the warmup causes strange inconsistencies in the results System.out.println("Starting disposable JFR warmup recording..."); - String[] startCommand = {"jcmd", "1", "JFR.start", "settings=/app/overhead.jfc", "dumponexit=true", "name=warmup", "filename=warmup.jfr"}; + String[] startCommand = { + "jcmd", + "1", + "JFR.start", + "settings=/app/overhead.jfc", + "dumponexit=true", + "name=warmup", + "filename=warmup.jfr" + }; petclinic.execInContainer(startCommand); - long deadline = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(testConfig.getWarmupSeconds()); - while(System.currentTimeMillis() < deadline) { + long deadline = + System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(testConfig.getWarmupSeconds()); + while (System.currentTimeMillis() < deadline) { GenericContainer k6 = new GenericContainer<>(DockerImageName.parse("loadimpact/k6")) .withNetwork(NETWORK) @@ -151,7 +162,7 @@ private void doWarmupPhase(TestConfig testConfig, GenericContainer petclinic) private void writeStartupTimeFile(Agent agent, long start) throws IOException { long delta = System.currentTimeMillis() - start; - Path startupPath = namingConventions.local.startupDurationFile(agent); + Path startupPath = Path.of(namingConventions.local.startupDurationFile(agent)); Files.writeString(startupPath, String.valueOf(delta)); } } diff --git a/benchmark-overhead/src/test/java/io/opentelemetry/containers/K6Container.java b/benchmark-overhead/src/test/java/io/opentelemetry/containers/K6Container.java index ff022970dbb3..7f6994d1a5d7 100644 --- a/benchmark-overhead/src/test/java/io/opentelemetry/containers/K6Container.java +++ b/benchmark-overhead/src/test/java/io/opentelemetry/containers/K6Container.java @@ -8,7 +8,6 @@ import io.opentelemetry.agents.Agent; import io.opentelemetry.config.TestConfig; import io.opentelemetry.util.NamingConventions; -import java.nio.file.Path; import java.time.Duration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,7 +34,7 @@ public K6Container( } public GenericContainer build() { - Path k6OutputFile = namingConventions.container.k6Results(agent); + String k6OutputFile = namingConventions.container.k6Results(agent); return new GenericContainer<>(DockerImageName.parse("loadimpact/k6")) .withNetwork(network) .withNetworkAliases("k6") @@ -52,7 +51,7 @@ public GenericContainer build() { "--rps", String.valueOf(config.getMaxRequestRate()), "--summary-export", - k6OutputFile.toString(), + k6OutputFile, "/app/basic.js") .withStartupCheckStrategy( new OneShotStartupCheckStrategy().withTimeout(Duration.ofMinutes(15))); diff --git a/benchmark-overhead/src/test/java/io/opentelemetry/results/ResultsCollector.java b/benchmark-overhead/src/test/java/io/opentelemetry/results/ResultsCollector.java index c2012cdf41b9..d7b47bb7fbc9 100644 --- a/benchmark-overhead/src/test/java/io/opentelemetry/results/ResultsCollector.java +++ b/benchmark-overhead/src/test/java/io/opentelemetry/results/ResultsCollector.java @@ -54,14 +54,14 @@ private AppPerfResults readAgentResults(Agent agent, TestConfig config) { private AppPerfResults.Builder addStartupTime(AppPerfResults.Builder builder, Agent agent) throws IOException { - Path file = namingConvention.startupDurationFile(agent); + Path file = Path.of(namingConvention.startupDurationFile(agent)); long startupDuration = Long.parseLong(new String(Files.readAllBytes(file)).trim()); return builder.startupDurationMs(startupDuration); } private AppPerfResults.Builder addK6Results(AppPerfResults.Builder builder, Agent agent) throws IOException { - Path k6File = namingConvention.k6Results(agent); + Path k6File = Path.of(namingConvention.k6Results(agent)); String json = new String(Files.readAllBytes(k6File)); double iterationAvg = read(json, "$.metrics.iteration_duration.avg"); double iterationP95 = read(json, "$.metrics.iteration_duration['p(95)']"); @@ -82,7 +82,7 @@ private static double read(String json, String jsonPath) { private AppPerfResults.Builder addJfrResults(AppPerfResults.Builder builder, Agent agent) throws IOException { - Path jfrFile = namingConvention.jfrFile(agent); + Path jfrFile = Path.of(namingConvention.jfrFile(agent)); return builder .totalGCTime(readTotalGCTime(jfrFile)) .totalAllocated(readTotalAllocated(jfrFile)) diff --git a/benchmark-overhead/src/test/java/io/opentelemetry/util/ContainerNamingConvention.java b/benchmark-overhead/src/test/java/io/opentelemetry/util/ContainerNamingConvention.java new file mode 100644 index 000000000000..8866ea28e92c --- /dev/null +++ b/benchmark-overhead/src/test/java/io/opentelemetry/util/ContainerNamingConvention.java @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.util; + +import io.opentelemetry.agents.Agent; + +public class ContainerNamingConvention implements NamingConvention { + private final String dir; + + public ContainerNamingConvention(String dir) { + this.dir = dir; + } + + public String k6Results(Agent agent) { + + return String.join("/", dir, "k6_out_" + agent.getName() + ".json"); + } + + public String jfrFile(Agent agent) { + return String.join("/", dir, "petclinic-" + agent.getName() + ".jfr"); + } + + public String startupDurationFile(Agent agent) { + return String.join("/", dir, "startup-time-" + agent.getName() + ".txt"); + } + + public String root() { + return dir; + } +} diff --git a/benchmark-overhead/src/test/java/io/opentelemetry/util/LocalNamingConvention.java b/benchmark-overhead/src/test/java/io/opentelemetry/util/LocalNamingConvention.java new file mode 100644 index 000000000000..4c4305e849a3 --- /dev/null +++ b/benchmark-overhead/src/test/java/io/opentelemetry/util/LocalNamingConvention.java @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.util; + +import io.opentelemetry.agents.Agent; +import java.nio.file.Paths; + +public class LocalNamingConvention implements NamingConvention { + private final String dir; + + public LocalNamingConvention(String dir) { + this.dir = dir; + } + + public String k6Results(Agent agent) { + return Paths.get(dir, "k6_out_" + agent.getName() + ".json").toString(); + } + + public String jfrFile(Agent agent) { + return Paths.get(dir, "petclinic-" + agent.getName() + ".jfr").toString(); + } + + public String startupDurationFile(Agent agent) { + return Paths.get(dir, "startup-time-" + agent.getName() + ".txt").toString(); + } + + public String root() { + return dir; + } +} diff --git a/benchmark-overhead/src/test/java/io/opentelemetry/util/NamingConvention.java b/benchmark-overhead/src/test/java/io/opentelemetry/util/NamingConvention.java index 96a45eceeef3..afbdd653e9a5 100644 --- a/benchmark-overhead/src/test/java/io/opentelemetry/util/NamingConvention.java +++ b/benchmark-overhead/src/test/java/io/opentelemetry/util/NamingConvention.java @@ -6,51 +6,34 @@ package io.opentelemetry.util; import io.opentelemetry.agents.Agent; -import java.nio.file.Path; -import java.nio.file.Paths; /** * This utility class provides the standard file naming conventions, primarily for files that are * shared between containers and the test runner. It consolidates the naming logic into one place to * ensure consistency, reduce duplication, and decrease errors. */ -public class NamingConvention { - - private final String dir; - - public NamingConvention(String dir) { - this.dir = dir; - } - +public interface NamingConvention { /** - * Returns a path to the location of the k6 results json file. + * Returns a path string to the location of the k6 results json file. * * @param agent The agent to get results file path for */ - public Path k6Results(Agent agent) { - return Paths.get(dir, "k6_out_" + agent.getName() + ".json"); - } + String k6Results(Agent agent); /** - * Returns a path to the location of the jfr output file for a given agent run. + * Returns a path string to the location of the jfr output file for a given agent run. * * @param agent The agent to get the jfr file path for. */ - public Path jfrFile(Agent agent) { - return Paths.get(dir, "petclinic-" + agent.getName() + ".jfr"); - } + String jfrFile(Agent agent); /** - * Returns the path to the file that contains the startup duration for a given agent run. + * Returns the path string to the file that contains the startup duration for a given agent run. * * @param agent The agent to get the startup duration for. */ - public Path startupDurationFile(Agent agent) { - return Paths.get(dir, "startup-time-" + agent.getName() + ".txt"); - } + String startupDurationFile(Agent agent); /** Returns the root path that this naming convention was configured with. */ - public String root() { - return dir; - } + String root(); } diff --git a/benchmark-overhead/src/test/java/io/opentelemetry/util/NamingConventions.java b/benchmark-overhead/src/test/java/io/opentelemetry/util/NamingConventions.java index 6caf28dfef31..4aeca8f7a92e 100644 --- a/benchmark-overhead/src/test/java/io/opentelemetry/util/NamingConventions.java +++ b/benchmark-overhead/src/test/java/io/opentelemetry/util/NamingConventions.java @@ -5,18 +5,22 @@ package io.opentelemetry.util; -/** An container to hold both the local and container naming conventions. */ +/** A container to hold both the local and container naming conventions. */ public class NamingConventions { - public final NamingConvention container = new NamingConvention("/results"); - public final NamingConvention local = new NamingConvention("."); + public final NamingConvention container = new ContainerNamingConvention("/results"); + public final NamingConvention local = new LocalNamingConvention("."); - /** @return Root path for the local naming convention (where results are output) */ + /** + * @return Root path for the local naming convention (where results are output) + */ public String localResults() { return local.root(); } - /** @return Root path for the container naming convention (where results are output) */ + /** + * @return Root path for the container naming convention (where results are output) + */ public String containerResults() { return container.root(); } diff --git a/benchmark-overhead/src/test/resources/collector.yaml b/benchmark-overhead/src/test/resources/collector.yaml index 8111a2406edd..99e635ec335c 100644 --- a/benchmark-overhead/src/test/resources/collector.yaml +++ b/benchmark-overhead/src/test/resources/collector.yaml @@ -1,10 +1,14 @@ extensions: health_check: + endpoint: 0.0.0.0:13133 receivers: otlp: protocols: grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 processors: batch: diff --git a/build.gradle.kts b/build.gradle.kts index 202f1cb2d8ad..36f6b373affd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,15 @@ plugins { id("io.github.gradle-nexus.publish-plugin") id("otel.spotless-conventions") + /* workaround for + What went wrong: + Could not determine the dependencies of task ':smoke-tests-otel-starter:spring-boot-3.2:bootJar'. + > Could not create task ':smoke-tests-otel-starter:spring-boot-3.2:collectReachabilityMetadata'. + > Cannot set the value of task ':smoke-tests-otel-starter:spring-boot-3.2:collectReachabilityMetadata' property 'metadataService' of type org.graalvm.buildtools.gradle.internal.GraalVMReachabilityMetadataService using a provider of type org.graalvm.buildtools.gradle.internal.GraalVMReachabilityMetadataService. + + See https://github.com/gradle/gradle/issues/17559#issuecomment-1327991512 + */ + id("org.graalvm.buildtools.native") apply false } apply(from = "version.gradle.kts") @@ -40,56 +49,56 @@ if (project.findProperty("skipTests") as String? == "true") { } } -tasks { - val listTestsInPartition by registering { - group = "Help" - description = "List test tasks in given partition" - - // total of 4 partitions (see modulo 4 below) - var testPartition = (project.findProperty("testPartition") as String?)?.toInt() - if (testPartition == null) { - throw GradleException("Test partition must be specified") - } else if (testPartition < 0 || testPartition >= 4) { - throw GradleException("Invalid test partition") - } +if (gradle.startParameter.taskNames.any { it.equals("listTestsInPartition") }) { + tasks { + val listTestsInPartition by registering { + group = "Help" + description = "List test tasks in given partition" - val partitionTasks = ArrayList() - var testPartitionCounter = 0 - subprojects { - // relying on predictable ordering of subprojects - // (see https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#N14CB4) - // since we are splitting these tasks across different github action jobs - val enabled = testPartitionCounter++ % 4 == testPartition - if (enabled) { - tasks.withType().configureEach { - partitionTasks.add(this) + // total of 4 partitions (see modulo 4 below) + var testPartition = (project.findProperty("testPartition") as String?)?.toInt() + if (testPartition == null) { + throw GradleException("Test partition must be specified") + } else if (testPartition < 0 || testPartition >= 4) { + throw GradleException("Invalid test partition") + } + + val partitionTasks = ArrayList() + var testPartitionCounter = 0 + subprojects { + // relying on predictable ordering of subprojects + // (see https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#N14CB4) + // since we are splitting these tasks across different github action jobs + val enabled = testPartitionCounter++ % 4 == testPartition + if (enabled) { + tasks.withType().configureEach { + partitionTasks.add(this) + } } } - } - doLast { - File("test-tasks.txt").printWriter().use { writer -> - partitionTasks.forEach { task -> - var taskPath = task.project.path + ":" + task.name - // smoke tests are run separately - // :instrumentation:test runs all instrumentation tests - if (taskPath != ":smoke-tests:test" && taskPath != ":instrumentation:test") { - writer.println(taskPath) + doLast { + File("test-tasks.txt").printWriter().use { writer -> + partitionTasks.forEach { task -> + var taskPath = task.project.path + ":" + task.name + // smoke tests are run separately + // :instrumentation:test runs all instrumentation tests + if (taskPath != ":smoke-tests:test" && taskPath != ":instrumentation:test") { + writer.println(taskPath) + } } } } - } - // disable all tasks to stop build - subprojects { - tasks.configureEach { - enabled = false + // disable all tasks to stop build + subprojects { + tasks.configureEach { + enabled = false + } } } } -} -if (gradle.startParameter.taskNames.any { it.equals("listTestsInPartition") }) { // disable all tasks to stop build project.tasks.configureEach { if (this.name != "listTestsInPartition") { diff --git a/conventions/build.gradle.kts b/conventions/build.gradle.kts index dd227da8baa7..1454ffa411b8 100644 --- a/conventions/build.gradle.kts +++ b/conventions/build.gradle.kts @@ -57,22 +57,22 @@ dependencies { implementation("com.diffplug.spotless:spotless-plugin-gradle:6.25.0") implementation("com.google.guava:guava:33.2.1-jre") implementation("gradle.plugin.com.google.protobuf:protobuf-gradle-plugin:0.8.18") - implementation("com.github.johnrengelman:shadow:8.1.1") + implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.0") implementation("org.apache.httpcomponents:httpclient:4.5.14") - implementation("com.gradle.develocity:com.gradle.develocity.gradle.plugin:3.17.5") - implementation("org.owasp:dependency-check-gradle:9.2.0") + implementation("com.gradle.develocity:com.gradle.develocity.gradle.plugin:3.17.6") + implementation("org.owasp:dependency-check-gradle:10.0.3") implementation("ru.vyarus:gradle-animalsniffer-plugin:1.7.1") implementation("org.spdx:spdx-gradle-plugin:0.8.0") // When updating, also update dependencyManagement/build.gradle.kts - implementation("net.bytebuddy:byte-buddy-gradle-plugin:1.14.17") + implementation("net.bytebuddy:byte-buddy-gradle-plugin:1.14.18") implementation("gradle.plugin.io.morethan.jmhreport:gradle-jmh-report:0.9.6") implementation("me.champeau.jmh:jmh-gradle-plugin:0.7.2") - implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.0.0") + implementation("net.ltgt.gradle:gradle-errorprone-plugin:4.0.1") implementation("net.ltgt.gradle:gradle-nullaway-plugin:2.0.0") implementation("me.champeau.gradle:japicmp-gradle-plugin:0.4.3") - testImplementation(enforcedPlatform("org.junit:junit-bom:5.10.2")) + testImplementation(enforcedPlatform("org.junit:junit-bom:5.10.3")) testImplementation("org.junit.jupiter:junit-jupiter-api") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") - testImplementation("org.assertj:assertj-core:3.26.0") + testImplementation("org.assertj:assertj-core:3.26.3") } diff --git a/conventions/src/main/kotlin/io.opentelemetry.instrumentation.javaagent-shadowing.gradle.kts b/conventions/src/main/kotlin/io.opentelemetry.instrumentation.javaagent-shadowing.gradle.kts index cf37eadaf5de..7b4e59d77d1d 100644 --- a/conventions/src/main/kotlin/io.opentelemetry.instrumentation.javaagent-shadowing.gradle.kts +++ b/conventions/src/main/kotlin/io.opentelemetry.instrumentation.javaagent-shadowing.gradle.kts @@ -1,7 +1,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") } // NOTE: any modifications below should also be made in diff --git a/conventions/src/main/kotlin/otel.java-conventions.gradle.kts b/conventions/src/main/kotlin/otel.java-conventions.gradle.kts index 94b35baa54dc..c3b9ea86c8ff 100644 --- a/conventions/src/main/kotlin/otel.java-conventions.gradle.kts +++ b/conventions/src/main/kotlin/otel.java-conventions.gradle.kts @@ -143,7 +143,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.111.Final", false) + belongsTo("io.netty:netty-bom:4.1.112.Final", false) } else if (id.version.startsWith("4.0.")) { belongsTo("io.netty:netty-bom:4.0.56.Final", false) } @@ -160,8 +160,8 @@ dependencies { compileOnly("com.google.code.findbugs:jsr305") compileOnly("com.google.errorprone:error_prone_annotations") - codenarc("org.codenarc:CodeNarc:3.4.0") - codenarc(platform("org.codehaus.groovy:groovy-bom:3.0.21")) + codenarc("org.codenarc:CodeNarc:3.5.0") + codenarc(platform("org.codehaus.groovy:groovy-bom:3.0.22")) modules { // checkstyle uses the very old google-collections which causes Java 9 module conflict with @@ -294,8 +294,12 @@ tasks { withType().configureEach { isPreserveFileTimestamps = false isReproducibleFileOrder = true - dirMode = Integer.parseInt("0755", 8) - fileMode = Integer.parseInt("0644", 8) + dirPermissions { + unix("755") + } + filePermissions { + unix("644") + } } // Convenient when updating errorprone @@ -356,8 +360,10 @@ tasks.withType().configureEach { val trustStore = project(":testing-common").file("src/misc/testing-keystore.p12") // Work around payara not working when this is set for some reason. - // Don't set for camel as we have tests that interact with AWS and need normal trustStore - if (project.name != "jaxrs-2.0-payara-testing" && project.description != "camel-2-20") { + // Don't set for: + // - camel as we have tests that interact with AWS and need normal trustStore + // - vaadin as tests need to be able to download nodejs when not cached in ~/.vaadin/ + if (project.name != "jaxrs-2.0-payara-testing" && !project.path.contains("vaadin") && project.description != "camel-2-20") { jvmArgumentProviders.add(KeystoreArgumentsProvider(trustStore)) } 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 559c6200bc19..55e1d0bfcee0 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 @@ -15,10 +15,10 @@ 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; import com.sun.source.tree.MethodTree; import com.sun.source.util.TreePath; +import javax.inject.Inject; @AutoService(BugChecker.class) @BugPattern( diff --git a/custom-checks/src/main/java/io/opentelemetry/javaagent/customchecks/OtelInternalJavadoc.java b/custom-checks/src/main/java/io/opentelemetry/javaagent/customchecks/OtelInternalJavadoc.java index 950632166bd3..3d6693a9574e 100644 --- a/custom-checks/src/main/java/io/opentelemetry/javaagent/customchecks/OtelInternalJavadoc.java +++ b/custom-checks/src/main/java/io/opentelemetry/javaagent/customchecks/OtelInternalJavadoc.java @@ -42,7 +42,7 @@ public class OtelInternalJavadoc extends BugChecker implements BugChecker.ClassT @Override public Description matchClass(ClassTree tree, VisitorState state) { - if (!isPublic(tree) || !isInternal(state)) { + if (!isPublic(tree) || !isInternal(state) || tree.getSimpleName().toString().endsWith("Test")) { return Description.NO_MATCH; } String javadoc = getJavadoc(state); diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 594a154460a3..a607a6b60c5a 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -8,12 +8,12 @@ val dependencyVersions = hashMapOf() rootProject.extra["versions"] = dependencyVersions // this line is managed by .github/scripts/update-sdk-version.sh -val otelSdkVersion = "1.39.0" -val otelContribVersion = "1.36.0-alpha" +val otelSdkVersion = "1.40.0" +val otelContribVersion = "1.37.0-alpha" val otelSdkAlphaVersion = otelSdkVersion.replaceFirst("(-SNAPSHOT)?$".toRegex(), "-alpha$1") // Need both BOM and groovy jars -val groovyVersion = "4.0.21" +val groovyVersion = "4.0.22" // 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 @@ -27,25 +27,25 @@ val groovyVersion = "4.0.21" // configurations.testRuntimeClasspath.resolutionStrategy.force "com.google.guava:guava:19.0" val DEPENDENCY_BOMS = listOf( - "com.fasterxml.jackson:jackson-bom:2.17.1", + "com.fasterxml.jackson:jackson-bom:2.17.2", "com.squareup.okio:okio-bom:3.9.0", // see https://github.com/open-telemetry/opentelemetry-java/issues/5637 "com.google.guava:guava-bom:33.2.1-jre", "org.apache.groovy:groovy-bom:${groovyVersion}", "io.opentelemetry:opentelemetry-bom:${otelSdkVersion}", "io.opentelemetry:opentelemetry-bom-alpha:${otelSdkAlphaVersion}", - "org.junit:junit-bom:5.10.2", - "org.testcontainers:testcontainers-bom:1.19.8", + "org.junit:junit-bom:5.10.3", + "org.testcontainers:testcontainers-bom:1.20.1", "org.spockframework:spock-bom:2.4-M4-groovy-4.0" ) val autoServiceVersion = "1.1.1" val autoValueVersion = "1.11.0" -val errorProneVersion = "2.28.0" -val byteBuddyVersion = "1.14.17" +val errorProneVersion = "2.30.0" +val byteBuddyVersion = "1.14.18" val asmVersion = "9.7" val jmhVersion = "1.37" val mockitoVersion = "4.11.0" -val slf4jVersion = "2.0.13" +val slf4jVersion = "2.0.16" val semConvVersion = "1.25.0-alpha" val CORE_DEPENDENCIES = listOf( @@ -87,30 +87,31 @@ val DEPENDENCIES = listOf( "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.11.0", + "com.uber.nullaway:nullaway:0.11.1", "commons-beanutils:commons-beanutils:1.9.4", "commons-cli:commons-cli:1.8.0", - "commons-codec:commons-codec:1.17.0", + "commons-codec:commons-codec:1.17.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.16.1", "commons-lang:commons-lang:2.6", - "commons-logging:commons-logging:1.3.2", + "commons-logging:commons-logging:1.3.3", "commons-validator:commons-validator:1.9.0", "io.netty:netty:3.10.6.Final", "io.opentelemetry.contrib:opentelemetry-aws-resources:${otelContribVersion}", "io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:${otelContribVersion}", "io.opentelemetry.contrib:opentelemetry-gcp-resources:${otelContribVersion}", - "io.opentelemetry.proto:opentelemetry-proto:1.3.1-alpha", + "io.opentelemetry.contrib:opentelemetry-baggage-processor:${otelContribVersion}", + "io.opentelemetry.proto:opentelemetry-proto:1.3.2-alpha", "io.opentelemetry:opentelemetry-extension-annotations:1.18.0", // deprecated, no longer part of bom - "org.assertj:assertj-core:3.26.0", - "org.awaitility:awaitility:4.2.1", + "org.assertj:assertj-core:3.26.3", + "org.awaitility:awaitility:4.2.2", "com.google.code.findbugs:annotations:3.0.1u2", "com.google.code.findbugs:jsr305:3.0.2", "org.apache.groovy:groovy:${groovyVersion}", "org.apache.groovy:groovy-json:${groovyVersion}", - "org.codehaus.mojo:animal-sniffer-annotations:1.23", + "org.codehaus.mojo:animal-sniffer-annotations:1.24", "org.junit-pioneer:junit-pioneer:1.9.1", "org.objenesis:objenesis:3.4", "javax.validation:validation-api:2.0.1.Final", diff --git a/docs/agent-features.md b/docs/agent-features.md index 92b494aa6006..9548c58d8047 100644 --- a/docs/agent-features.md +++ b/docs/agent-features.md @@ -4,9 +4,8 @@ This lists out some of the features specific to java agents that OpenTelemetry A provides. - Bundled exporters - - [OTLP](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md) - - Jaeger gRPC - - Logging + - [OTLP](https://opentelemetry.io/docs/specs/otlp/) + - Console - Zipkin - Bundled propagators - [W3C TraceContext / Baggage](https://www.w3.org/TR/trace-context/) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt index f2ce28a1b43b..9711244d9a5a 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-annotations.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-instrumentation-annotations-2.5.0-SNAPSHOT.jar against opentelemetry-instrumentation-annotations-2.4.0.jar +Comparing source compatibility of opentelemetry-instrumentation-annotations-2.7.0-SNAPSHOT.jar against opentelemetry-instrumentation-annotations-2.6.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt index c5bcfad8b5f5..e6f29db1607f 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-instrumentation-api.txt @@ -1,2 +1,2 @@ -Comparing source compatibility of opentelemetry-instrumentation-api-2.5.0-SNAPSHOT.jar against opentelemetry-instrumentation-api-2.4.0.jar +Comparing source compatibility of opentelemetry-instrumentation-api-2.7.0-SNAPSHOT.jar against opentelemetry-instrumentation-api-2.6.0.jar No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-autoconfigure.txt b/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-autoconfigure.txt new file mode 100644 index 000000000000..f0024ddc916a --- /dev/null +++ b/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-autoconfigure.txt @@ -0,0 +1,2 @@ +Comparing source compatibility of opentelemetry-spring-boot-autoconfigure-2.7.0-SNAPSHOT.jar against opentelemetry-spring-boot-autoconfigure-2.6.0.jar +No changes. \ No newline at end of file diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-starter.txt b/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-starter.txt new file mode 100644 index 000000000000..32590bb0c2c9 --- /dev/null +++ b/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-starter.txt @@ -0,0 +1,2 @@ +Comparing source compatibility of opentelemetry-spring-boot-starter-2.7.0-SNAPSHOT.jar against opentelemetry-spring-boot-starter-2.6.0.jar +No changes. \ No newline at end of file diff --git a/docs/supported-libraries.md b/docs/supported-libraries.md index 71e9591454d2..68065b23894f 100644 --- a/docs/supported-libraries.md +++ b/docs/supported-libraries.md @@ -49,13 +49,14 @@ These are the supported libraries and frameworks: | [AWS SDK](https://aws.amazon.com/sdk-for-java/) | 1.11.x and 2.2+ | [opentelemetry-aws-sdk-1.11](../instrumentation/aws-sdk/aws-sdk-1.11/library),
[opentelemetry-aws-sdk-1.11-autoconfigure](../instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure),
[opentelemetry-aws-sdk-2.2](../instrumentation/aws-sdk/aws-sdk-2.2/library),
[opentelemetry-aws-sdk-2.2-autoconfigure](../instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure) | [Messaging Spans], [Database Client Spans], [HTTP Client Spans] | | [Azure Core](https://docs.microsoft.com/en-us/java/api/overview/azure/core-readme) | 1.14+ | N/A | Context propagation | | [Cassandra Driver](https://github.com/datastax/java-driver) | 3.0+ | [opentelemetry-cassandra-4.4](../instrumentation/cassandra/cassandra-4.4/library) | [Database Client Spans] | +| [Clickhouse Client](https://github.com/ClickHouse/clickhouse-java) | 0.5+ | N/A | [Database Client Spans] | | [Couchbase Client](https://github.com/couchbase/couchbase-java-client) | 2.0+ and 3.1+ | N/A | [Database Client Spans] | | [c3p0](https://github.com/swaldman/c3p0) | 0.9.2+ | [opentelemetry-c3p0-0.9](../instrumentation/c3p0-0.9/library) | [Database Pool Metrics] | | [Dropwizard Metrics](https://metrics.dropwizard.io/) | 4.0+ (disabled by default) | N/A | none | | [Dropwizard Views](https://www.dropwizard.io/en/latest/manual/views.html) | 0.7+ | N/A | Controller Spans [3] | | [Eclipse Grizzly](https://javaee.github.io/grizzly/httpserverframework.html) | 2.3+ | N/A | [HTTP Server Spans], [HTTP Server Metrics] | | [Eclipse Jersey](https://eclipse-ee4j.github.io/jersey/) | 2.0+ | N/A | Provides `http.route` [2], Controller Spans [3] | -| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2+ (not including 10+ yet) | [opentelemetry-jetty-httpclient-9.2](../instrumentation/jetty-httpclient/jetty-httpclient-9.2/library) | [HTTP Client Spans], [HTTP Client Metrics] | +| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2 - 9.4.x,
12.0+ | [opentelemetry-jetty-httpclient-9.2](../instrumentation/jetty-httpclient/jetty-httpclient-9.2/library)
[opentelemetry-jetty-httpclient-12.0](../instrumentation/jetty-httpclient/jetty-httpclient-12.0/library) | [HTTP Client Spans], [HTTP Client Metrics] | | [Eclipse Metro](https://projects.eclipse.org/projects/ee4j.metro) | 2.2+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [Eclipse Mojarra](https://projects.eclipse.org/projects/ee4j.mojarra) | 1.2+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [Elasticsearch API Client](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html) | 7.16 - 7.17.19,
8.0 - 8.9.+ [4] | N/A | [Elasticsearch Client Spans] | @@ -80,6 +81,7 @@ These are the supported libraries and frameworks: | [Java Http Client](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/package-summary.html) | Java 11+ | [opentelemetry-java-http-client](../instrumentation/java-http-client/library) | [HTTP Client Spans], [HTTP Client Metrics] | | [java.util.logging](https://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html) | Java 8+ | N/A | none | | [Java Platform](https://docs.oracle.com/javase/8/docs/api/java/lang/management/ManagementFactory.html) | Java 8+ | [opentelemetry-runtime-telemetry-java8](../instrumentation/runtime-telemetry/runtime-telemetry-java8/library),
[opentelemetry-runtime-telemetry-java17](../instrumentation/runtime-telemetry/runtime-telemetry-java17/library),
[opentelemetry-resources](../instrumentation/resources/library) | [JVM Runtime Metrics] | +| [Javalin](https://javalin.io/) | 5.0+ | N/A | Provides `http.route` [2] | | [JAX-RS](https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/package-summary.html) | 0.5+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [JAX-RS Client](https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/client/package-summary.html) | 1.1+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] | | [JAX-WS](https://jakarta.ee/specifications/xml-web-services/2.3/apidocs/javax/xml/ws/package-summary.html) | 2.0+ (not including 3.x yet) | N/A | Provides `http.route` [2], Controller Spans [3] | @@ -114,7 +116,7 @@ These are the supported libraries and frameworks: | [Reactor Netty](https://github.com/reactor/reactor-netty) | 0.9+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] | | [Rediscala](https://github.com/etaty/rediscala) | 1.8+ | N/A | [Database Client Spans] | | [Redisson](https://github.com/redisson/redisson) | 3.0+ | N/A | [Database Client Spans] | -| [RESTEasy](https://resteasy.github.io/) | 3.0+ | N/A | Provides `http.route` [2], Controller Spans [3] | +| [RESTEasy](https://resteasy.dev/) | 3.0+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [Restlet](https://restlet.github.io/) | 1.0+ | [opentelemetry-restlet-1.1](../instrumentation/restlet/restlet-1.1/library),
[opentelemetry-restlet-2.0](../instrumentation/restlet/restlet-2.0/library) | [HTTP Server Spans], [HTTP Server Metrics] | | [RMI](https://docs.oracle.com/en/java/javase/11/docs/api/java.rmi/java/rmi/package-summary.html) | Java 8+ | | [RPC Client Spans], [RPC Server Spans] | | [RxJava](https://github.com/ReactiveX/RxJava) | 1.0+ | [opentelemetry-rxjava-1.0](../instrumentation/rxjava/rxjava-1.0/library),
[opentelemetry-rxjava-2.0](../instrumentation/rxjava/rxjava-2.0/library),
[opentelemetry-rxjava-3.0](../instrumentation/rxjava/rxjava-3.0/library),
[opentelemetry-rxjava-3.1.1](../instrumentation/rxjava/rxjava-3.1.1/library) | Context propagation | diff --git a/examples/distro/agent/build.gradle b/examples/distro/agent/build.gradle index 096b0d0439e5..3045dbaeca8a 100644 --- a/examples/distro/agent/build.gradle +++ b/examples/distro/agent/build.gradle @@ -1,7 +1,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") } apply from: "$rootDir/gradle/shadow.gradle" diff --git a/examples/distro/build.gradle b/examples/distro/build.gradle index dfb5db46e42a..c1539ab6cb71 100644 --- a/examples/distro/build.gradle +++ b/examples/distro/build.gradle @@ -13,8 +13,8 @@ buildscript { } dependencies { classpath "com.diffplug.spotless:spotless-plugin-gradle:6.25.0" - classpath "com.github.johnrengelman:shadow:8.1.1" - classpath "io.opentelemetry.instrumentation:gradle-plugins:2.5.0-alpha-SNAPSHOT" + classpath "com.gradleup.shadow:shadow-gradle-plugin:8.3.0" + classpath "io.opentelemetry.instrumentation:gradle-plugins:2.7.0-alpha-SNAPSHOT" } } @@ -27,14 +27,14 @@ subprojects { ext { versions = [ // this line is managed by .github/scripts/update-sdk-version.sh - opentelemetrySdk : "1.39.0", + opentelemetrySdk : "1.40.0", // these lines are managed by .github/scripts/update-version.sh - opentelemetryJavaagent : "2.5.0-SNAPSHOT", - opentelemetryJavaagentAlpha: "2.5.0-alpha-SNAPSHOT", + opentelemetryJavaagent : "2.7.0-SNAPSHOT", + opentelemetryJavaagentAlpha: "2.7.0-alpha-SNAPSHOT", autoservice : "1.1.1", - junit : "5.10.2" + junit : "5.10.3" ] deps = [ diff --git a/examples/distro/gradle/instrumentation.gradle b/examples/distro/gradle/instrumentation.gradle index ccaa22fc12b3..ad484d8d2821 100644 --- a/examples/distro/gradle/instrumentation.gradle +++ b/examples/distro/gradle/instrumentation.gradle @@ -1,5 +1,5 @@ apply plugin: 'java' -apply plugin: 'com.github.johnrengelman.shadow' +apply plugin: 'com.gradleup.shadow' apply plugin: 'io.opentelemetry.instrumentation.muzzle-generation' apply plugin: 'io.opentelemetry.instrumentation.muzzle-check' @@ -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.26.0") + testImplementation("org.assertj:assertj-core:3.26.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 e6441136f3d4..2c3521197d7c 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 8a1f6b97f473..68e8816d71c9 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=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/examples/distro/gradlew b/examples/distro/gradlew index b740cf13397a..f5feea6d6b11 100755 --- a/examples/distro/gradlew +++ b/examples/distro/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/examples/distro/gradlew.bat b/examples/distro/gradlew.bat index 25da30dbdeee..9d21a21834d5 100644 --- a/examples/distro/gradlew.bat +++ b/examples/distro/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/examples/distro/smoke-tests/build.gradle b/examples/distro/smoke-tests/build.gradle index feb12ef9ea33..2db60894f48c 100644 --- a/examples/distro/smoke-tests/build.gradle +++ b/examples/distro/smoke-tests/build.gradle @@ -3,11 +3,11 @@ plugins { } dependencies { - testImplementation("org.testcontainers:testcontainers:1.19.8") - testImplementation("com.fasterxml.jackson.core:jackson-databind:2.17.1") - testImplementation("com.google.protobuf:protobuf-java-util:3.25.3") + testImplementation("org.testcontainers:testcontainers:1.20.1") + testImplementation("com.fasterxml.jackson.core:jackson-databind:2.17.2") + testImplementation("com.google.protobuf:protobuf-java-util:3.25.4") testImplementation("com.squareup.okhttp3:okhttp:4.12.0") - testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.3.1-alpha") + testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.3.2-alpha") testImplementation("io.opentelemetry:opentelemetry-api") testImplementation("ch.qos.logback:logback-classic:1.5.6") diff --git a/examples/distro/testing/agent-for-testing/build.gradle b/examples/distro/testing/agent-for-testing/build.gradle index 0879f3985de4..5eec782efd4c 100644 --- a/examples/distro/testing/agent-for-testing/build.gradle +++ b/examples/distro/testing/agent-for-testing/build.gradle @@ -1,7 +1,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") } apply from: "$rootDir/gradle/shadow.gradle" diff --git a/examples/extension/build.gradle b/examples/extension/build.gradle index 372e1a1f5190..625bb443376d 100644 --- a/examples/extension/build.gradle +++ b/examples/extension/build.gradle @@ -10,11 +10,11 @@ plugins { into a single jar. See https://imperceptiblethoughts.com/shadow/ for more details about Shadow plugin. */ - id "com.github.johnrengelman.shadow" version "8.1.1" + id "com.gradleup.shadow" version "8.3.0" id "com.diffplug.spotless" version "6.25.0" - id "io.opentelemetry.instrumentation.muzzle-generation" version "2.5.0-alpha-SNAPSHOT" - id "io.opentelemetry.instrumentation.muzzle-check" version "2.5.0-alpha-SNAPSHOT" + id "io.opentelemetry.instrumentation.muzzle-generation" version "2.7.0-alpha-SNAPSHOT" + id "io.opentelemetry.instrumentation.muzzle-check" version "2.7.0-alpha-SNAPSHOT" } 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.39.0", + opentelemetrySdk : "1.40.0", // these lines are managed by .github/scripts/update-version.sh - opentelemetryJavaagent : "2.5.0-SNAPSHOT", - opentelemetryJavaagentAlpha: "2.5.0-alpha-SNAPSHOT", + opentelemetryJavaagent : "2.7.0-SNAPSHOT", + opentelemetryJavaagentAlpha: "2.7.0-alpha-SNAPSHOT", - junit : "5.10.2" + junit : "5.10.3" ] deps = [ @@ -96,15 +96,15 @@ 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.14.0' + implementation 'org.apache.commons:commons-lang3:3.16.0' //All dependencies below are only for tests - testImplementation("org.testcontainers:testcontainers:1.19.8") - testImplementation("com.fasterxml.jackson.core:jackson-databind:2.17.1") - testImplementation("com.google.protobuf:protobuf-java-util:3.25.3") + testImplementation("org.testcontainers:testcontainers:1.20.1") + testImplementation("com.fasterxml.jackson.core:jackson-databind:2.17.2") + testImplementation("com.google.protobuf:protobuf-java-util:3.25.4") testImplementation("com.squareup.okhttp3:okhttp:4.12.0") testImplementation("io.opentelemetry:opentelemetry-api") - testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.3.1-alpha") + testImplementation("io.opentelemetry.proto:opentelemetry-proto:1.3.2-alpha") testImplementation("org.junit.jupiter:junit-jupiter-api:${versions.junit}") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${versions.junit}") diff --git a/examples/extension/gradle/wrapper/gradle-wrapper.jar b/examples/extension/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4..2c3521197d7c 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 8a1f6b97f473..68e8816d71c9 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=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/examples/extension/gradlew b/examples/extension/gradlew index b740cf13397a..f5feea6d6b11 100755 --- a/examples/extension/gradlew +++ b/examples/extension/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/examples/extension/gradlew.bat b/examples/extension/gradlew.bat index 25da30dbdeee..9d21a21834d5 100644 --- a/examples/extension/gradlew.bat +++ b/examples/extension/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/gradle-plugins/build.gradle.kts b/gradle-plugins/build.gradle.kts index ae63845817b4..01cc58d93509 100644 --- a/gradle-plugins/build.gradle.kts +++ b/gradle-plugins/build.gradle.kts @@ -24,7 +24,7 @@ configurations.named("compileOnly") { extendsFrom(bbGradlePlugin) } -val byteBuddyVersion = "1.14.17" +val byteBuddyVersion = "1.14.18" val aetherVersion = "1.1.0" dependencies { @@ -39,11 +39,11 @@ dependencies { implementation("org.eclipse.aether:aether-transport-http:${aetherVersion}") implementation("org.apache.maven:maven-aether-provider:3.3.9") - implementation("com.github.johnrengelman:shadow:8.1.1") + implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.0") - testImplementation("org.assertj:assertj-core:3.26.0") + testImplementation("org.assertj:assertj-core:3.26.3") - testImplementation(enforcedPlatform("org.junit:junit-bom:5.10.2")) + testImplementation(enforcedPlatform("org.junit:junit-bom:5.10.3")) 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 e6441136f3d4..2c3521197d7c 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 8a1f6b97f473..68e8816d71c9 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=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradle-plugins/gradlew b/gradle-plugins/gradlew index b740cf13397a..f5feea6d6b11 100755 --- a/gradle-plugins/gradlew +++ b/gradle-plugins/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradle-plugins/gradlew.bat b/gradle-plugins/gradlew.bat index 25da30dbdeee..9d21a21834d5 100644 --- a/gradle-plugins/gradlew.bat +++ b/gradle-plugins/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts b/gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts index 1b6cebb97f38..c010f21568fa 100644 --- a/gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts +++ b/gradle-plugins/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts @@ -28,8 +28,7 @@ import java.util.stream.StreamSupport plugins { `java-library` - - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") } // Select a random set of versions to test diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4..2c3521197d7c 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 8a1f6b97f473..68e8816d71c9 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=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index b740cf13397a..f5feea6d6b11 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 25da30dbdeee..9d21a21834d5 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## diff --git a/instrumentation-annotations-support/src/main/java/io/opentelemetry/instrumentation/api/annotation/support/AnnotationReflectionHelper.java b/instrumentation-annotations-support/src/main/java/io/opentelemetry/instrumentation/api/annotation/support/AnnotationReflectionHelper.java index 4695bb3310b6..5bbe2a77a801 100644 --- a/instrumentation-annotations-support/src/main/java/io/opentelemetry/instrumentation/api/annotation/support/AnnotationReflectionHelper.java +++ b/instrumentation-annotations-support/src/main/java/io/opentelemetry/instrumentation/api/annotation/support/AnnotationReflectionHelper.java @@ -14,7 +14,7 @@ import java.util.function.Function; import javax.annotation.Nullable; -/** Helper class for reflecting over annotations at runtime.. */ +/** Helper class for reflecting over annotations at runtime. */ public class AnnotationReflectionHelper { private AnnotationReflectionHelper() {} diff --git a/instrumentation-api-incubator/build.gradle.kts b/instrumentation-api-incubator/build.gradle.kts index 6acb75e5f79d..00d887da1b25 100644 --- a/instrumentation-api-incubator/build.gradle.kts +++ b/instrumentation-api-incubator/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { testImplementation(project(":testing-common")) testImplementation("io.opentelemetry:opentelemetry-sdk") testImplementation("io.opentelemetry:opentelemetry-sdk-testing") + testImplementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating") } tasks { diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/builder/internal/DefaultHttpClientInstrumenterBuilder.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/builder/internal/DefaultHttpClientInstrumenterBuilder.java new file mode 100644 index 000000000000..50f73aa48069 --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/builder/internal/DefaultHttpClientInstrumenterBuilder.java @@ -0,0 +1,216 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.builder.internal; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.context.propagation.TextMapSetter; +import io.opentelemetry.instrumentation.api.incubator.config.internal.CommonConfig; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; +import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceResolver; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +import javax.annotation.Nullable; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class DefaultHttpClientInstrumenterBuilder { + + private final String instrumentationName; + private final OpenTelemetry openTelemetry; + + private final List> additionalExtractors = + new ArrayList<>(); + private final HttpClientAttributesExtractorBuilder + httpAttributesExtractorBuilder; + private final HttpClientAttributesGetter attributesGetter; + private final HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder; + + @Nullable private TextMapSetter headerSetter; + private Function, ? extends SpanNameExtractor> + spanNameExtractorTransformer = Function.identity(); + private boolean emitExperimentalHttpClientMetrics = false; + private Consumer> builderCustomizer = b -> {}; + + public DefaultHttpClientInstrumenterBuilder( + String instrumentationName, + OpenTelemetry openTelemetry, + HttpClientAttributesGetter attributesGetter) { + this.instrumentationName = instrumentationName; + this.openTelemetry = openTelemetry; + httpSpanNameExtractorBuilder = HttpSpanNameExtractor.builder(attributesGetter); + httpAttributesExtractorBuilder = HttpClientAttributesExtractor.builder(attributesGetter); + this.attributesGetter = attributesGetter; + } + + /** + * Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented + * items. The {@link AttributesExtractor} will be executed after all default extractors. + */ + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder addAttributeExtractor( + AttributesExtractor attributesExtractor) { + additionalExtractors.add(attributesExtractor); + return this; + } + + /** + * Configures the HTTP request headers that will be captured as span attributes. + * + * @param requestHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder setCapturedRequestHeaders( + List requestHeaders) { + httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders); + return this; + } + + /** + * Configures the HTTP response headers that will be captured as span attributes. + * + * @param responseHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder setCapturedResponseHeaders( + List responseHeaders) { + httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders); + return this; + } + + /** + * Configures the instrumentation to recognize an alternative set of HTTP request methods. + * + *

By default, this instrumentation defines "known" methods as the ones listed in RFC9110 and the PATCH + * method defined in RFC5789. + * + *

Note: calling this method overrides the default known method sets completely; it does + * not supplement it. + * + * @param knownMethods A set of recognized HTTP request methods. + * @see HttpClientAttributesExtractorBuilder#setKnownMethods(Set) + */ + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder setKnownMethods( + Set knownMethods) { + httpAttributesExtractorBuilder.setKnownMethods(knownMethods); + httpSpanNameExtractorBuilder.setKnownMethods(knownMethods); + return this; + } + + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder setHeaderSetter( + @Nullable TextMapSetter headerSetter) { + this.headerSetter = headerSetter; + return this; + } + + /** + * Configures the instrumentation to emit experimental HTTP client metrics. + * + * @param emitExperimentalHttpClientMetrics {@code true} if the experimental HTTP client metrics + * are to be emitted. + */ + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder + setEmitExperimentalHttpClientMetrics(boolean emitExperimentalHttpClientMetrics) { + this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; + return this; + } + + /** Sets custom {@link SpanNameExtractor} via transform function. */ + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder setSpanNameExtractor( + Function, ? extends SpanNameExtractor> + spanNameExtractorTransformer) { + this.spanNameExtractorTransformer = spanNameExtractorTransformer; + return this; + } + + /** Sets custom {@link PeerServiceResolver}. */ + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder setPeerServiceResolver( + PeerServiceResolver peerServiceResolver) { + return addAttributeExtractor( + HttpClientPeerServiceAttributesExtractor.create(attributesGetter, peerServiceResolver)); + } + + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder setBuilderCustomizer( + Consumer> builderCustomizer) { + this.builderCustomizer = builderCustomizer; + return this; + } + + public Instrumenter build() { + + SpanNameExtractor spanNameExtractor = + spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); + + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, instrumentationName, spanNameExtractor) + .setSpanStatusExtractor(HttpSpanStatusExtractor.create(attributesGetter)) + .addAttributesExtractor(httpAttributesExtractorBuilder.build()) + .addAttributesExtractors(additionalExtractors) + .addOperationMetrics(HttpClientMetrics.get()); + if (emitExperimentalHttpClientMetrics) { + builder + .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(attributesGetter)) + .addOperationMetrics(HttpClientExperimentalMetrics.get()); + } + builderCustomizer.accept(builder); + + if (headerSetter != null) { + return builder.buildClientInstrumenter(headerSetter); + } + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); + } + + public OpenTelemetry getOpenTelemetry() { + return openTelemetry; + } + + @CanIgnoreReturnValue + public DefaultHttpClientInstrumenterBuilder configure(CommonConfig config) { + set(config::getKnownHttpRequestMethods, this::setKnownMethods); + set(config::getClientRequestHeaders, this::setCapturedRequestHeaders); + set(config::getClientResponseHeaders, this::setCapturedResponseHeaders); + set(config::getPeerServiceResolver, this::setPeerServiceResolver); + set( + config::shouldEmitExperimentalHttpClientTelemetry, + this::setEmitExperimentalHttpClientMetrics); + return this; + } + + private static void set(Supplier supplier, Consumer consumer) { + T t = supplier.get(); + if (t != null) { + consumer.accept(t); + } + } +} diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/builder/internal/DefaultHttpServerInstrumenterBuilder.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/builder/internal/DefaultHttpServerInstrumenterBuilder.java new file mode 100644 index 000000000000..b229a7126e48 --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/builder/internal/DefaultHttpServerInstrumenterBuilder.java @@ -0,0 +1,219 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.builder.internal; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.instrumentation.api.incubator.config.internal.CommonConfig; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder; +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesGetter; +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics; +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteBuilder; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +import javax.annotation.Nullable; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class DefaultHttpServerInstrumenterBuilder { + + private final String instrumentationName; + private final OpenTelemetry openTelemetry; + + private final List> additionalExtractors = + new ArrayList<>(); + private Function< + SpanStatusExtractor, + ? extends SpanStatusExtractor> + statusExtractorTransformer = Function.identity(); + private final HttpServerAttributesExtractorBuilder + httpAttributesExtractorBuilder; + private final HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder; + + @Nullable private TextMapGetter headerGetter; + private Function, ? extends SpanNameExtractor> + spanNameExtractorTransformer = Function.identity(); + private final HttpServerRouteBuilder httpServerRouteBuilder; + private final HttpServerAttributesGetter attributesGetter; + private boolean emitExperimentalHttpServerMetrics = false; + + public DefaultHttpServerInstrumenterBuilder( + String instrumentationName, + OpenTelemetry openTelemetry, + HttpServerAttributesGetter attributesGetter) { + this.instrumentationName = instrumentationName; + this.openTelemetry = openTelemetry; + httpAttributesExtractorBuilder = HttpServerAttributesExtractor.builder(attributesGetter); + httpSpanNameExtractorBuilder = HttpSpanNameExtractor.builder(attributesGetter); + httpServerRouteBuilder = HttpServerRoute.builder(attributesGetter); + this.attributesGetter = attributesGetter; + } + + /** + * Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented + * items. + */ + @CanIgnoreReturnValue + public DefaultHttpServerInstrumenterBuilder addAttributesExtractor( + AttributesExtractor attributesExtractor) { + additionalExtractors.add(attributesExtractor); + return this; + } + + @CanIgnoreReturnValue + public DefaultHttpServerInstrumenterBuilder setStatusExtractor( + Function< + SpanStatusExtractor, + ? extends SpanStatusExtractor> + statusExtractor) { + this.statusExtractorTransformer = statusExtractor; + return this; + } + + /** + * Configures the HTTP request headers that will be captured as span attributes. + * + * @param requestHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public DefaultHttpServerInstrumenterBuilder setCapturedRequestHeaders( + List requestHeaders) { + httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders); + return this; + } + + /** + * Configures the HTTP response headers that will be captured as span attributes. + * + * @param responseHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public DefaultHttpServerInstrumenterBuilder setCapturedResponseHeaders( + List responseHeaders) { + httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders); + return this; + } + + /** + * Configures the instrumentation to recognize an alternative set of HTTP request methods. + * + *

By default, this instrumentation defines "known" methods as the ones listed in RFC9110 and the PATCH + * method defined in RFC5789. + * + *

Note: calling this method overrides the default known method sets completely; it does + * not supplement it. + * + * @param knownMethods A set of recognized HTTP request methods. + * @see HttpServerAttributesExtractorBuilder#setKnownMethods(Set) + */ + @CanIgnoreReturnValue + public DefaultHttpServerInstrumenterBuilder setKnownMethods( + Set knownMethods) { + httpAttributesExtractorBuilder.setKnownMethods(knownMethods); + httpSpanNameExtractorBuilder.setKnownMethods(knownMethods); + httpServerRouteBuilder.setKnownMethods(knownMethods); + return this; + } + + @CanIgnoreReturnValue + public DefaultHttpServerInstrumenterBuilder setHeaderGetter( + @Nullable TextMapGetter headerGetter) { + this.headerGetter = headerGetter; + return this; + } + + /** + * Configures the instrumentation to emit experimental HTTP server metrics. + * + * @param emitExperimentalHttpServerMetrics {@code true} if the experimental HTTP server metrics + * are to be emitted. + */ + @CanIgnoreReturnValue + public DefaultHttpServerInstrumenterBuilder + setEmitExperimentalHttpServerMetrics(boolean emitExperimentalHttpServerMetrics) { + this.emitExperimentalHttpServerMetrics = emitExperimentalHttpServerMetrics; + return this; + } + + /** Sets custom {@link SpanNameExtractor} via transform function. */ + @CanIgnoreReturnValue + public DefaultHttpServerInstrumenterBuilder setSpanNameExtractor( + Function, ? extends SpanNameExtractor> + spanNameExtractorTransformer) { + this.spanNameExtractorTransformer = spanNameExtractorTransformer; + return this; + } + + public Instrumenter build() { + InstrumenterBuilder builder = builder(); + + if (headerGetter != null) { + return builder.buildServerInstrumenter(headerGetter); + } + return builder.buildInstrumenter(SpanKindExtractor.alwaysServer()); + } + + private InstrumenterBuilder builder() { + SpanNameExtractor spanNameExtractor = + spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); + + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, instrumentationName, spanNameExtractor) + .setSpanStatusExtractor( + statusExtractorTransformer.apply(HttpSpanStatusExtractor.create(attributesGetter))) + .addAttributesExtractor(httpAttributesExtractorBuilder.build()) + .addAttributesExtractors(additionalExtractors) + .addContextCustomizer(httpServerRouteBuilder.build()) + .addOperationMetrics(HttpServerMetrics.get()); + if (emitExperimentalHttpServerMetrics) { + builder + .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(attributesGetter)) + .addOperationMetrics(HttpServerExperimentalMetrics.get()); + } + + return builder; + } + + @CanIgnoreReturnValue + public DefaultHttpServerInstrumenterBuilder configure(CommonConfig config) { + set(config::getKnownHttpRequestMethods, this::setKnownMethods); + set(config::getServerRequestHeaders, this::setCapturedRequestHeaders); + set(config::getServerResponseHeaders, this::setCapturedResponseHeaders); + set( + config::shouldEmitExperimentalHttpServerTelemetry, + this::setEmitExperimentalHttpServerMetrics); + return this; + } + + private static void set(Supplier supplier, Consumer consumer) { + T t = supplier.get(); + if (t != null) { + consumer.accept(t); + } + } +} diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/CommonConfig.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/CommonConfig.java similarity index 94% rename from javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/CommonConfig.java rename to instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/CommonConfig.java index f6d5a5479001..23875d7e8b5f 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/CommonConfig.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/CommonConfig.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.bootstrap.internal; +package io.opentelemetry.instrumentation.api.incubator.config.internal; import static java.util.Collections.emptyMap; @@ -21,12 +21,6 @@ */ public final class CommonConfig { - private static final CommonConfig instance = new CommonConfig(InstrumentationConfig.get()); - - public static CommonConfig get() { - return instance; - } - private final PeerServiceResolver peerServiceResolver; private final List clientRequestHeaders; private final List clientResponseHeaders; @@ -41,7 +35,7 @@ public static CommonConfig get() { private final String loggingSpanIdKey; private final String loggingTraceFlagsKey; - CommonConfig(InstrumentationConfig config) { + public CommonConfig(InstrumentationConfig config) { peerServiceResolver = PeerServiceResolver.create( config.getMap("otel.instrumentation.common.peer-service-mapping", emptyMap())); diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EnduserConfig.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/EnduserConfig.java similarity index 97% rename from javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EnduserConfig.java rename to instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/EnduserConfig.java index fbde1c90aaa2..b44057c75f90 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EnduserConfig.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/EnduserConfig.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.bootstrap.internal; +package io.opentelemetry.instrumentation.api.incubator.config.internal; import java.util.Objects; diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/InstrumentationConfig.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/InstrumentationConfig.java similarity index 63% rename from javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/InstrumentationConfig.java rename to instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/InstrumentationConfig.java index fc4b7aabc6c2..8ce777b270a7 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/InstrumentationConfig.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/config/internal/InstrumentationConfig.java @@ -3,15 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.bootstrap.internal; +package io.opentelemetry.instrumentation.api.incubator.config.internal; import static java.util.Collections.emptyList; -import static java.util.Objects.requireNonNull; import java.time.Duration; import java.util.List; import java.util.Map; -import java.util.logging.Logger; import javax.annotation.Nullable; /** @@ -28,72 +26,44 @@ *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ -public abstract class InstrumentationConfig { - - private static final Logger logger = Logger.getLogger(InstrumentationConfig.class.getName()); - - private static final InstrumentationConfig DEFAULT = new EmptyInstrumentationConfig(); - - // lazy initialized, so that javaagent can set it - private static volatile InstrumentationConfig instance = DEFAULT; - - /** - * Sets the instrumentation configuration singleton. This method is only supposed to be called - * once, during the agent initialization, just before {@link InstrumentationConfig#get()} is used - * for the first time. - * - *

This method is internal and is hence not for public use. Its API is unstable and can change - * at any time. - */ - public static void internalInitializeConfig(InstrumentationConfig config) { - if (instance != DEFAULT) { - logger.warning("InstrumentationConfig#instance was already set earlier"); - return; - } - instance = requireNonNull(config); - } - - /** Returns the global instrumentation configuration. */ - public static InstrumentationConfig get() { - return instance; - } +public interface InstrumentationConfig { /** * Returns a string-valued configuration property or {@code null} if a property with name {@code * name} has not been configured. */ @Nullable - public abstract String getString(String name); + String getString(String name); /** * Returns a string-valued configuration property or {@code defaultValue} if a property with name * {@code name} has not been configured. */ - public abstract String getString(String name, String defaultValue); + String getString(String name, String defaultValue); /** * Returns a boolean-valued configuration property or {@code defaultValue} if a property with name * {@code name} has not been configured. */ - public abstract boolean getBoolean(String name, boolean defaultValue); + boolean getBoolean(String name, boolean defaultValue); /** * Returns an integer-valued configuration property or {@code defaultValue} if a property with * name {@code name} has not been configured or when parsing has failed. */ - public abstract int getInt(String name, int defaultValue); + int getInt(String name, int defaultValue); /** * Returns a long-valued configuration property or {@code defaultValue} if a property with name * {@code name} has not been configured or when parsing has failed. */ - public abstract long getLong(String name, long defaultValue); + long getLong(String name, long defaultValue); /** * Returns a double-valued configuration property or {@code defaultValue} if a property with name * {@code name} has not been configured or when parsing has failed. */ - public abstract double getDouble(String name, double defaultValue); + double getDouble(String name, double defaultValue); /** * Returns a duration-valued configuration property or {@code defaultValue} if a property with @@ -113,13 +83,13 @@ public static InstrumentationConfig get() { * *

Examples: 10s, 20ms, 5000 */ - public abstract Duration getDuration(String name, Duration defaultValue); + Duration getDuration(String name, Duration defaultValue); /** * This is the same as calling {@code getList(String, List)} with the defaultValue equal to the * emptyList()/ */ - public List getList(String name) { + default List getList(String name) { return getList(name, emptyList()); } @@ -128,7 +98,7 @@ public List getList(String name) { * {@code name} has not been configured. The format of the original value must be comma-separated, * e.g. {@code one,two,three}. The returned list is unmodifiable. */ - public abstract List getList(String name, List defaultValue); + List getList(String name, List defaultValue); /** * Returns a map-valued configuration property or {@code defaultValue} if a property with name @@ -136,5 +106,5 @@ public List getList(String name) { * value must be comma-separated for each key, with an '=' separating the key and value, e.g. * {@code key=value,anotherKey=anotherValue}. The returned map is unmodifiable. */ - public abstract Map getMap(String name, Map defaultValue); + Map getMap(String name, Map defaultValue); } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpClientExperimentalMetrics.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpClientExperimentalMetrics.java index 0beb49456245..dd08cbe493ff 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpClientExperimentalMetrics.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpClientExperimentalMetrics.java @@ -24,9 +24,9 @@ * {@link OperationListener} which keeps track of non-stable * HTTP client metrics: the + * href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpclientrequestbodysize">the * request size and + * href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpclientresponsebodysize"> * the response size. */ public final class HttpClientExperimentalMetrics implements OperationListener { @@ -53,7 +53,7 @@ public static OperationMetrics get() { private HttpClientExperimentalMetrics(Meter meter) { LongHistogramBuilder requestSizeBuilder = meter - .histogramBuilder("http.client.request.size") + .histogramBuilder("http.client.request.body.size") .setUnit("By") .setDescription("Size of HTTP client request bodies.") .ofLongs(); @@ -61,7 +61,7 @@ private HttpClientExperimentalMetrics(Meter meter) { requestSize = requestSizeBuilder.build(); LongHistogramBuilder responseSizeBuilder = meter - .histogramBuilder("http.client.response.size") + .histogramBuilder("http.client.response.body.size") .setUnit("By") .setDescription("Size of HTTP client response bodies.") .ofLongs(); diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpServerExperimentalMetrics.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpServerExperimentalMetrics.java index d6bf144385d5..7c91292f513e 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpServerExperimentalMetrics.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpServerExperimentalMetrics.java @@ -28,9 +28,9 @@ * HTTP server metrics: the * number of in-flight request, the + * href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserverrequestbodysize">the * request size and the + * href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserverresponsebodysize">the * response size. */ public final class HttpServerExperimentalMetrics implements OperationListener { @@ -65,7 +65,7 @@ private HttpServerExperimentalMetrics(Meter meter) { activeRequests = activeRequestsBuilder.build(); LongHistogramBuilder requestSizeBuilder = meter - .histogramBuilder("http.server.request.size") + .histogramBuilder("http.server.request.body.size") .setUnit("By") .setDescription("Size of HTTP server request bodies.") .ofLongs(); @@ -73,7 +73,7 @@ private HttpServerExperimentalMetrics(Meter meter) { requestSize = requestSizeBuilder.build(); LongHistogramBuilder responseSizeBuilder = meter - .histogramBuilder("http.server.response.size") + .histogramBuilder("http.server.response.body.size") .setUnit("By") .setDescription("Size of HTTP server response bodies.") .ofLongs(); diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingMetricsAdvice.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingMetricsAdvice.java new file mode 100644 index 000000000000..8ada61c1683f --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingMetricsAdvice.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.semconv.messaging; + +import static java.util.Arrays.asList; +import static java.util.Collections.unmodifiableList; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogramBuilder; +import io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.semconv.ErrorAttributes; +import io.opentelemetry.semconv.ServerAttributes; +import java.util.List; + +final class MessagingMetricsAdvice { + static final List DURATION_SECONDS_BUCKETS = + unmodifiableList( + asList(0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0)); + + // copied from MessagingIncubatingAttributes + private static final AttributeKey MESSAGING_SYSTEM = + AttributeKey.stringKey("messaging.system"); + private static final AttributeKey MESSAGING_DESTINATION_NAME = + AttributeKey.stringKey("messaging.destination.name"); + private static final AttributeKey MESSAGING_OPERATION = + AttributeKey.stringKey("messaging.operation"); + private static final AttributeKey MESSAGING_BATCH_MESSAGE_COUNT = + AttributeKey.longKey("messaging.batch.message_count"); + + static void applyPublishDurationAdvice(DoubleHistogramBuilder builder) { + if (!(builder instanceof ExtendedDoubleHistogramBuilder)) { + return; + } + ((ExtendedDoubleHistogramBuilder) builder) + .setAttributesAdvice( + asList( + MESSAGING_SYSTEM, + MESSAGING_DESTINATION_NAME, + MESSAGING_OPERATION, + MESSAGING_BATCH_MESSAGE_COUNT, + ErrorAttributes.ERROR_TYPE, + ServerAttributes.SERVER_PORT, + ServerAttributes.SERVER_ADDRESS)); + } + + private MessagingMetricsAdvice() {} +} diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingProducerMetrics.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingProducerMetrics.java new file mode 100644 index 000000000000..44d5b243744a --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingProducerMetrics.java @@ -0,0 +1,85 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.semconv.messaging; + +import static java.util.logging.Level.FINE; + +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.DoubleHistogram; +import io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.ContextKey; +import io.opentelemetry.instrumentation.api.instrumenter.OperationListener; +import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics; +import io.opentelemetry.instrumentation.api.internal.OperationMetricsUtil; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +/** + * {@link OperationListener} which keeps track of Producer + * metrics. + */ +public final class MessagingProducerMetrics implements OperationListener { + private static final double NANOS_PER_S = TimeUnit.SECONDS.toNanos(1); + + private static final ContextKey MESSAGING_PRODUCER_METRICS_STATE = + ContextKey.named("messaging-producer-metrics-state"); + private static final Logger logger = Logger.getLogger(MessagingProducerMetrics.class.getName()); + + private final DoubleHistogram publishDurationHistogram; + + private MessagingProducerMetrics(Meter meter) { + DoubleHistogramBuilder durationBuilder = + meter + .histogramBuilder("messaging.publish.duration") + .setDescription("Measures the duration of publish operation.") + .setExplicitBucketBoundariesAdvice(MessagingMetricsAdvice.DURATION_SECONDS_BUCKETS) + .setUnit("s"); + MessagingMetricsAdvice.applyPublishDurationAdvice(durationBuilder); + publishDurationHistogram = durationBuilder.build(); + } + + public static OperationMetrics get() { + return OperationMetricsUtil.create("messaging produce", MessagingProducerMetrics::new); + } + + @Override + @CanIgnoreReturnValue + public Context onStart(Context context, Attributes startAttributes, long startNanos) { + return context.with( + MESSAGING_PRODUCER_METRICS_STATE, + new AutoValue_MessagingProducerMetrics_State(startAttributes, startNanos)); + } + + @Override + public void onEnd(Context context, Attributes endAttributes, long endNanos) { + MessagingProducerMetrics.State state = context.get(MESSAGING_PRODUCER_METRICS_STATE); + if (state == null) { + logger.log( + FINE, + "No state present when ending context {0}. Cannot record produce publish metrics.", + context); + return; + } + + Attributes attributes = state.startAttributes().toBuilder().putAll(endAttributes).build(); + + publishDurationHistogram.record( + (endNanos - state.startTimeNanos()) / NANOS_PER_S, attributes, context); + } + + @AutoValue + abstract static class State { + + abstract Attributes startAttributes(); + + abstract long startTimeNanos(); + } +} diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpClientExperimentalMetricsTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpClientExperimentalMetricsTest.java index 9d8748ab61c4..b15b58f71df7 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpClientExperimentalMetricsTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpClientExperimentalMetricsTest.java @@ -83,7 +83,7 @@ void collectsMetrics() { .satisfiesExactlyInAnyOrder( metric -> assertThat(metric) - .hasName("http.client.request.size") + .hasName("http.client.request.body.size") .hasUnit("By") .hasDescription("Size of HTTP client request bodies.") .hasHistogramSatisfying( @@ -109,7 +109,7 @@ void collectsMetrics() { .hasSpanId("090a0b0c0d0e0f00")))), metric -> assertThat(metric) - .hasName("http.client.response.size") + .hasName("http.client.response.body.size") .hasUnit("By") .hasDescription("Size of HTTP client response bodies.") .hasHistogramSatisfying( @@ -140,13 +140,13 @@ void collectsMetrics() { .satisfiesExactlyInAnyOrder( metric -> assertThat(metric) - .hasName("http.client.request.size") + .hasName("http.client.request.body.size") .hasHistogramSatisfying( histogram -> histogram.hasPointsSatisfying(point -> point.hasSum(200 /* bytes */))), metric -> assertThat(metric) - .hasName("http.client.response.size") + .hasName("http.client.response.body.size") .hasHistogramSatisfying( histogram -> histogram.hasPointsSatisfying(point -> point.hasSum(400 /* bytes */)))); diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpServerExperimentalMetricsTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpServerExperimentalMetricsTest.java index 95cc458ab13a..13796304b236 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpServerExperimentalMetricsTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpServerExperimentalMetricsTest.java @@ -147,7 +147,7 @@ void collectsMetrics() { .hasSpanId(spanContext1.getSpanId())))), metric -> assertThat(metric) - .hasName("http.server.request.size") + .hasName("http.server.request.body.size") .hasUnit("By") .hasDescription("Size of HTTP server request bodies.") .hasHistogramSatisfying( @@ -172,7 +172,7 @@ void collectsMetrics() { .hasSpanId(spanContext1.getSpanId())))), metric -> assertThat(metric) - .hasName("http.server.response.size") + .hasName("http.server.response.body.size") .hasUnit("By") .hasDescription("Size of HTTP server response bodies.") .hasHistogramSatisfying( @@ -216,7 +216,7 @@ void collectsMetrics() { .hasSpanId(spanContext2.getSpanId())))), metric -> assertThat(metric) - .hasName("http.server.request.size") + .hasName("http.server.request.body.size") .hasHistogramSatisfying( histogram -> histogram.hasPointsSatisfying( @@ -230,7 +230,7 @@ void collectsMetrics() { .hasSpanId(spanContext2.getSpanId())))), metric -> assertThat(metric) - .hasName("http.server.response.size") + .hasName("http.server.response.body.size") .hasHistogramSatisfying( histogram -> histogram.hasPointsSatisfying( diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingProducerMetricsTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingProducerMetricsTest.java new file mode 100644 index 000000000000..491387253ee9 --- /dev/null +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/messaging/MessagingProducerMetricsTest.java @@ -0,0 +1,122 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.semconv.messaging; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.TraceFlags; +import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.instrumenter.OperationListener; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; +import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes; +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.Test; + +class MessagingProducerMetricsTest { + + private static final double[] DURATION_BUCKETS = + MessagingMetricsAdvice.DURATION_SECONDS_BUCKETS.stream().mapToDouble(d -> d).toArray(); + + @Test + void collectsMetrics() { + InMemoryMetricReader metricReader = InMemoryMetricReader.create(); + SdkMeterProvider meterProvider = + SdkMeterProvider.builder().registerMetricReader(metricReader).build(); + + OperationListener listener = MessagingProducerMetrics.get().create(meterProvider.get("test")); + + Attributes requestAttributes = + Attributes.builder() + .put(MessagingIncubatingAttributes.MESSAGING_SYSTEM, "pulsar") + .put( + MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME, + "persistent://public/default/topic") + .put(MessagingIncubatingAttributes.MESSAGING_OPERATION, "publish") + .put(ServerAttributes.SERVER_PORT, 6650) + .put(ServerAttributes.SERVER_ADDRESS, "localhost") + .build(); + + Attributes responseAttributes = + Attributes.builder() + .put(MessagingIncubatingAttributes.MESSAGING_MESSAGE_ID, "1:1:0:0") + .put(MessagingIncubatingAttributes.MESSAGING_BATCH_MESSAGE_COUNT, 2) + .build(); + + Context parent = + Context.root() + .with( + Span.wrap( + SpanContext.create( + "ff01020304050600ff0a0b0c0d0e0f00", + "090a0b0c0d0e0f00", + TraceFlags.getSampled(), + TraceState.getDefault()))); + + Context context1 = listener.onStart(parent, requestAttributes, nanos(100)); + + assertThat(metricReader.collectAllMetrics()).isEmpty(); + + Context context2 = listener.onStart(Context.root(), requestAttributes, nanos(150)); + + assertThat(metricReader.collectAllMetrics()).isEmpty(); + + listener.onEnd(context1, responseAttributes, nanos(250)); + + assertThat(metricReader.collectAllMetrics()) + .satisfiesExactlyInAnyOrder( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasName("messaging.publish.duration") + .hasUnit("s") + .hasDescription("Measures the duration of publish operation.") + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> + point + .hasSum(0.15 /* seconds */) + .hasAttributesSatisfying( + equalTo( + MessagingIncubatingAttributes.MESSAGING_SYSTEM, + "pulsar"), + equalTo( + MessagingIncubatingAttributes + .MESSAGING_DESTINATION_NAME, + "persistent://public/default/topic"), + equalTo(ServerAttributes.SERVER_PORT, 6650), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost")) + .hasExemplarsSatisfying( + exemplar -> + exemplar + .hasTraceId("ff01020304050600ff0a0b0c0d0e0f00") + .hasSpanId("090a0b0c0d0e0f00")) + .hasBucketBoundaries(DURATION_BUCKETS)))); + + listener.onEnd(context2, responseAttributes, nanos(300)); + + assertThat(metricReader.collectAllMetrics()) + .satisfiesExactlyInAnyOrder( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasName("messaging.publish.duration") + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> point.hasSum(0.3 /* seconds */)))); + } + + private static long nanos(int millis) { + return TimeUnit.MILLISECONDS.toNanos(millis); + } +} 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 cee163f4a12e..a51990317067 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.context.ContextKey; import io.opentelemetry.instrumentation.api.internal.HttpRouteState; import io.opentelemetry.instrumentation.api.internal.InstrumenterAccess; import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil; @@ -41,6 +42,9 @@ */ public class Instrumenter { + private static final ContextKey START_OPERATION_LISTENERS = + ContextKey.named("instrumenter-start-operation-listeners"); + /** * Returns a new {@link InstrumenterBuilder}. * @@ -74,6 +78,7 @@ public static InstrumenterBuilder builder private final ContextCustomizer[] contextCustomizers; private final OperationListener[] operationListeners; private final ErrorCauseExtractor errorCauseExtractor; + private final boolean propagateOperationListenersToOnEnd; private final boolean enabled; private final SpanSuppressor spanSuppressor; @@ -89,6 +94,7 @@ public static InstrumenterBuilder builder this.contextCustomizers = builder.contextCustomizers.toArray(new ContextCustomizer[0]); this.operationListeners = builder.buildOperationListeners().toArray(new OperationListener[0]); this.errorCauseExtractor = builder.errorCauseExtractor; + this.propagateOperationListenersToOnEnd = builder.propagateOperationListenersToOnEnd; this.enabled = builder.enabled; this.spanSuppressor = builder.buildSpanSuppressor(); } @@ -198,6 +204,15 @@ private Context doStart(Context parentContext, REQUEST request, @Nullable Instan context = operationListeners[i].onStart(context, attributes, startNanos); } } + if (propagateOperationListenersToOnEnd || context.get(START_OPERATION_LISTENERS) != null) { + // when start and end are not called on the same instrumenter we need to use the operation + // listeners that were used during start in end to correctly handle metrics like + // http.server.active_requests that is recorded both in start and end + // + // need to also add when there is already START_OPERATION_LISTENERS, otherwise this + // instrumenter will call its parent's operation listeners in doEnd + context = context.with(START_OPERATION_LISTENERS, operationListeners); + } if (localRoot) { context = LocalRootSpan.store(context, span); @@ -228,6 +243,10 @@ private void doEnd( } span.setAllAttributes(attributes); + OperationListener[] operationListeners = context.get(START_OPERATION_LISTENERS); + if (operationListeners == null) { + operationListeners = this.operationListeners; + } if (operationListeners.length != 0) { long endNanos = getNanos(endTime); for (int i = operationListeners.length - 1; i >= 0; i--) { diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java index 8c68cd0890d4..6b41ae6c60ab 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java @@ -66,6 +66,7 @@ public final class InstrumenterBuilder { SpanStatusExtractor spanStatusExtractor = SpanStatusExtractor.getDefault(); ErrorCauseExtractor errorCauseExtractor = ErrorCauseExtractor.getDefault(); + boolean propagateOperationListenersToOnEnd = false; boolean enabled = true; InstrumenterBuilder( @@ -370,6 +371,10 @@ private Set getSpanKeysFromAttributesExtractors() { .collect(Collectors.toSet()); } + private void propagateOperationListenersToOnEnd() { + propagateOperationListenersToOnEnd = true; + } + private interface InstrumenterConstructor { Instrumenter create(InstrumenterBuilder builder); @@ -406,6 +411,12 @@ public Instrumenter buildDownstreamInstrumenter( SpanKindExtractor spanKindExtractor) { return builder.buildDownstreamInstrumenter(setter, spanKindExtractor); } + + @Override + public void propagateOperationListenersToOnEnd( + InstrumenterBuilder builder) { + builder.propagateOperationListenersToOnEnd(); + } }); } } diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/InstrumenterBuilderAccess.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/InstrumenterBuilderAccess.java index d8c40af3e47a..2c660577b17c 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/InstrumenterBuilderAccess.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/InstrumenterBuilderAccess.java @@ -26,4 +26,7 @@ Instrumenter buildDownstreamInstrumenter( InstrumenterBuilder builder, TextMapSetter setter, SpanKindExtractor spanKindExtractor); + + void propagateOperationListenersToOnEnd( + InstrumenterBuilder builder); } diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/InstrumenterUtil.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/InstrumenterUtil.java index 24648b4b2fb6..d61a6e8fe367 100644 --- a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/InstrumenterUtil.java +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/InstrumenterUtil.java @@ -67,5 +67,11 @@ public static Instrumenter buildDownstrea builder, setter, spanKindExtractor); } + public static void propagateOperationListenersToOnEnd( + InstrumenterBuilder builder) { + // instrumenterBuilderAccess is guaranteed to be non-null here + instrumenterBuilderAccess.propagateOperationListenersToOnEnd(builder); + } + private InstrumenterUtil() {} } diff --git a/instrumentation/akka/akka-http-10.0/javaagent/build.gradle.kts b/instrumentation/akka/akka-http-10.0/javaagent/build.gradle.kts index 0c4f96c18022..ff1e6c9cccfc 100644 --- a/instrumentation/akka/akka-http-10.0/javaagent/build.gradle.kts +++ b/instrumentation/akka/akka-http-10.0/javaagent/build.gradle.kts @@ -42,6 +42,22 @@ dependencies { latestDepTestLibrary("com.typesafe.akka:akka-stream_2.13:+") } +testing { + suites { + val javaRouteTest by registering(JvmTestSuite::class) { + dependencies { + if (findProperty("testLatestDeps") as Boolean) { + implementation("com.typesafe.akka:akka-http_2.13:+") + implementation("com.typesafe.akka:akka-stream_2.13:+") + } else { + implementation("com.typesafe.akka:akka-http_2.12:10.2.0") + implementation("com.typesafe.akka:akka-stream_2.12:2.6.21") + } + } + } + } +} + tasks { withType().configureEach { // required on jdk17 @@ -52,6 +68,10 @@ tasks { systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) } + + check { + dependsOn(testing.suites) + } } if (findProperty("testLatestDeps") as Boolean) { diff --git a/instrumentation/akka/akka-http-10.0/javaagent/src/javaRouteTest/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerJavaRouteTest.java b/instrumentation/akka/akka-http-10.0/javaagent/src/javaRouteTest/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerJavaRouteTest.java new file mode 100644 index 000000000000..be1357c8d9bf --- /dev/null +++ b/instrumentation/akka/akka-http-10.0/javaagent/src/javaRouteTest/java/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerJavaRouteTest.java @@ -0,0 +1,64 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.akkahttp; + +import static akka.http.javadsl.server.PathMatchers.integerSegment; +import static org.assertj.core.api.Assertions.assertThat; + +import akka.actor.ActorSystem; +import akka.http.javadsl.Http; +import akka.http.javadsl.ServerBinding; +import akka.http.javadsl.server.AllDirectives; +import akka.http.javadsl.server.Route; +import io.opentelemetry.instrumentation.test.utils.PortUtils; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.testing.internal.armeria.client.WebClient; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpRequest; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import io.opentelemetry.testing.internal.armeria.common.HttpMethod; +import java.util.concurrent.CompletionStage; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class AkkaHttpServerJavaRouteTest extends AllDirectives { + @RegisterExtension + private static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private final WebClient client = WebClient.of(); + + @Test + void testRoute() { + ActorSystem system = ActorSystem.create("my-system"); + int port = PortUtils.findOpenPort(); + Http http = Http.get(system); + + Route route = + concat( + pathEndOrSingleSlash(() -> complete("root")), + pathPrefix( + "test", + () -> + concat( + pathSingleSlash(() -> complete("test")), + path(integerSegment(), (i) -> complete("ok"))))); + + CompletionStage binding = http.newServerAt("localhost", port).bind(route); + try { + AggregatedHttpRequest request = + AggregatedHttpRequest.of(HttpMethod.GET, "h1c://localhost:" + port + "/test/1"); + AggregatedHttpResponse response = client.execute(request).aggregate().join(); + + assertThat(response.status().code()).isEqualTo(200); + assertThat(response.contentUtf8()).isEqualTo("ok"); + + testing.waitAndAssertTraces( + trace -> trace.hasSpansSatisfyingExactly(span -> span.hasName("GET /test/*"))); + } finally { + binding.thenCompose(ServerBinding::unbind).thenAccept(unbound -> system.terminate()); + } + } +} diff --git a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/client/AkkaHttpClientSingletons.java b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/client/AkkaHttpClientSingletons.java index feac2dac6281..aa20eeec9f93 100644 --- a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/client/AkkaHttpClientSingletons.java +++ b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/client/AkkaHttpClientSingletons.java @@ -8,17 +8,8 @@ import akka.http.scaladsl.model.HttpRequest; import akka.http.scaladsl.model.HttpResponse; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import io.opentelemetry.javaagent.instrumentation.akkahttp.AkkaHttpUtil; public class AkkaHttpClientSingletons { @@ -28,31 +19,9 @@ public class AkkaHttpClientSingletons { static { SETTER = new HttpHeaderSetter(GlobalOpenTelemetry.getPropagators()); - AkkaHttpClientAttributesGetter httpAttributesGetter = new AkkaHttpClientAttributesGetter(); - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - AkkaHttpUtil.instrumentationName(), - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + AkkaHttpUtil.instrumentationName(), new AkkaHttpClientAttributesGetter()); } public static Instrumenter instrumenter() { diff --git a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/AkkaHttpServerSingletons.java b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/AkkaHttpServerSingletons.java index 71338fca4212..af0a3d61da82 100644 --- a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/AkkaHttpServerSingletons.java +++ b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/AkkaHttpServerSingletons.java @@ -17,7 +17,7 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.instrumentation.akkahttp.AkkaHttpUtil; public final class AkkaHttpServerSingletons { @@ -31,21 +31,21 @@ public final class AkkaHttpServerSingletons { GlobalOpenTelemetry.get(), AkkaHttpUtil.instrumentationName(), HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) .addAttributesExtractor( HttpServerAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addOperationMetrics(HttpServerMetrics.get()) .addContextCustomizer( HttpServerRoute.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()); - if (CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { + if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { builder .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) .addOperationMetrics(HttpServerExperimentalMetrics.get()); diff --git a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/route/AkkaRouteHolder.java b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/route/AkkaRouteHolder.java index 9fa98d8c2add..3f192e5c7d2c 100644 --- a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/route/AkkaRouteHolder.java +++ b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/route/AkkaRouteHolder.java @@ -19,7 +19,7 @@ public class AkkaRouteHolder implements ImplicitContextKeyed { private static final ContextKey KEY = named("opentelemetry-akka-route"); private String route = ""; - private boolean newSegment; + private boolean newSegment = true; private boolean endMatched; private final Deque stack = new ArrayDeque<>(); @@ -70,6 +70,15 @@ public static void restore() { } } + // reset the state to when save was called + public static void reset() { + AkkaRouteHolder holder = Context.current().get(KEY); + if (holder != null) { + holder.route = holder.stack.peek(); + holder.newSegment = true; + } + } + @Override public Context storeInContext(Context context) { return context.with(KEY, this); diff --git a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/route/RouteConcatenationInstrumentation.java b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/route/RouteConcatenationInstrumentation.java index de13aba9fb30..eb13f402bc1e 100644 --- a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/route/RouteConcatenationInstrumentation.java +++ b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/route/RouteConcatenationInstrumentation.java @@ -17,14 +17,26 @@ public class RouteConcatenationInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { return namedOneOf( + // scala 2.11 "akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1", + // scala 2.12 and later "akka.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation"); } @Override public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod( - namedOneOf("apply", "$anonfun$$tilde$1"), this.getClass().getName() + "$ApplyAdvice"); + namedOneOf( + // scala 2.11 + "apply", + // scala 2.12 and later + "$anonfun$$tilde$1"), + this.getClass().getName() + "$ApplyAdvice"); + + // This advice seems to be only needed when defining routes with java dsl. Since java dsl tests + // use scala 2.12 we are going to skip instrumenting this for scala 2.11. + transformer.applyAdviceToMethod( + namedOneOf("$anonfun$$tilde$2"), this.getClass().getName() + "$Apply2Advice"); } @SuppressWarnings("unused") @@ -43,4 +55,13 @@ public static void onExit() { AkkaRouteHolder.restore(); } } + + @SuppressWarnings("unused") + public static class Apply2Advice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter() { + AkkaRouteHolder.reset(); + } + } } diff --git a/instrumentation/akka/akka-http-10.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerRouteTest.scala b/instrumentation/akka/akka-http-10.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerRouteTest.scala new file mode 100644 index 000000000000..3920c6aeb15e --- /dev/null +++ b/instrumentation/akka/akka-http-10.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/akkahttp/AkkaHttpServerRouteTest.scala @@ -0,0 +1,113 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.akkahttp + +import akka.actor.ActorSystem +import akka.http.scaladsl.Http +import akka.http.scaladsl.server.Directives.{ + IntNumber, + complete, + concat, + path, + pathEndOrSingleSlash, + pathPrefix, + pathSingleSlash +} +import akka.http.scaladsl.server.Route +import akka.stream.ActorMaterializer +import io.opentelemetry.instrumentation.test.utils.PortUtils +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension +import io.opentelemetry.sdk.testing.assertj.{SpanDataAssert, TraceAssert} +import io.opentelemetry.testing.internal.armeria.client.WebClient +import io.opentelemetry.testing.internal.armeria.common.{ + AggregatedHttpRequest, + HttpMethod +} +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.{AfterAll, Test, TestInstance} +import org.junit.jupiter.api.extension.RegisterExtension + +import java.net.{URI, URISyntaxException} +import java.util.function.Consumer +import scala.concurrent.duration.DurationInt +import scala.concurrent.Await + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class AkkaHttpServerRouteTest { + @RegisterExtension private val testing: AgentInstrumentationExtension = + AgentInstrumentationExtension.create + private val client: WebClient = WebClient.of() + + implicit val system: ActorSystem = ActorSystem("my-system") + implicit val materializer: ActorMaterializer = ActorMaterializer() + + private def buildAddress(port: Int): URI = try + new URI("http://localhost:" + port + "/") + catch { + case exception: URISyntaxException => + throw new IllegalStateException(exception) + } + + @Test def testSimple(): Unit = { + val route = path("test") { + complete("ok") + } + + test(route, "/test", "GET /test") + } + + @Test def testRoute(): Unit = { + val route = concat( + pathEndOrSingleSlash { + complete("root") + }, + pathPrefix("test") { + concat( + pathSingleSlash { + complete("test") + }, + path(IntNumber) { _ => + complete("ok") + } + ) + } + ) + + test(route, "/test/1", "GET /test/*") + } + + def test(route: Route, path: String, spanName: String): Unit = { + val port = PortUtils.findOpenPort + val address: URI = buildAddress(port) + val binding = + Await.result(Http().bindAndHandle(route, "localhost", port), 10.seconds) + try { + val request = AggregatedHttpRequest.of( + HttpMethod.GET, + address.resolve(path).toString + ) + val response = client.execute(request).aggregate.join + assertThat(response.status.code).isEqualTo(200) + assertThat(response.contentUtf8).isEqualTo("ok") + + testing.waitAndAssertTraces(new Consumer[TraceAssert] { + override def accept(trace: TraceAssert): Unit = + trace.hasSpansSatisfyingExactly(new Consumer[SpanDataAssert] { + override def accept(span: SpanDataAssert): Unit = { + span.hasName(spanName) + } + }) + }) + } finally { + binding.unbind() + } + } + + @AfterAll + def cleanUp(): Unit = { + system.terminate() + } +} diff --git a/instrumentation/apache-dubbo-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachedubbo/v2_7/OpenTelemetryFilter.java b/instrumentation/apache-dubbo-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachedubbo/v2_7/OpenTelemetryFilter.java index 98f7306bfd56..550f469ad9df 100644 --- a/instrumentation/apache-dubbo-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachedubbo/v2_7/OpenTelemetryFilter.java +++ b/instrumentation/apache-dubbo-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachedubbo/v2_7/OpenTelemetryFilter.java @@ -9,7 +9,7 @@ import io.opentelemetry.instrumentation.apachedubbo.v2_7.DubboTelemetry; import io.opentelemetry.instrumentation.apachedubbo.v2_7.internal.DubboClientNetworkAttributesGetter; import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceAttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.rpc.Filter; import org.apache.dubbo.rpc.Invocation; @@ -27,7 +27,7 @@ public OpenTelemetryFilter() { .addAttributesExtractor( PeerServiceAttributesExtractor.create( new DubboClientNetworkAttributesGetter(), - CommonConfig.get().getPeerServiceResolver())) + AgentCommonConfig.get().getPeerServiceResolver())) .build() .newFilter(); } diff --git a/instrumentation/apache-httpasyncclient-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientSingletons.java b/instrumentation/apache-httpasyncclient-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientSingletons.java index cc0605af1092..6a2af90f730e 100644 --- a/instrumentation/apache-httpasyncclient-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientSingletons.java +++ b/instrumentation/apache-httpasyncclient-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientSingletons.java @@ -5,17 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.apachehttpasyncclient; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import org.apache.http.HttpResponse; public final class ApacheHttpAsyncClientSingletons { @@ -24,33 +15,11 @@ public final class ApacheHttpAsyncClientSingletons { private static final Instrumenter INSTRUMENTER; static { - ApacheHttpAsyncClientHttpAttributesGetter httpAttributesGetter = - new ApacheHttpAsyncClientHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, + new ApacheHttpAsyncClientHttpAttributesGetter(), + HttpHeaderSetter.INSTANCE); } public static Instrumenter instrumenter() { diff --git a/instrumentation/apache-httpclient/apache-httpclient-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/ApacheHttpClientSingletons.java b/instrumentation/apache-httpclient/apache-httpclient-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/ApacheHttpClientSingletons.java index d54ca9c2f35b..ef8e120c78c9 100644 --- a/instrumentation/apache-httpclient/apache-httpclient-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/ApacheHttpClientSingletons.java +++ b/instrumentation/apache-httpclient/apache-httpclient-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v2_0/ApacheHttpClientSingletons.java @@ -5,17 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v2_0; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import org.apache.commons.httpclient.HttpMethod; public final class ApacheHttpClientSingletons { @@ -24,33 +15,11 @@ public final class ApacheHttpClientSingletons { private static final Instrumenter INSTRUMENTER; static { - ApacheHttpClientHttpAttributesGetter httpAttributesGetter = - new ApacheHttpClientHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, + new ApacheHttpClientHttpAttributesGetter(), + HttpHeaderSetter.INSTANCE); } public static Instrumenter instrumenter() { diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientSingletons.java b/instrumentation/apache-httpclient/apache-httpclient-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientSingletons.java index 146dd8f08727..a93209c3f42a 100644 --- a/instrumentation/apache-httpclient/apache-httpclient-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientSingletons.java +++ b/instrumentation/apache-httpclient/apache-httpclient-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientSingletons.java @@ -5,17 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import org.apache.http.HttpResponse; public final class ApacheHttpClientSingletons { @@ -24,33 +15,11 @@ public final class ApacheHttpClientSingletons { private static final Instrumenter INSTRUMENTER; static { - ApacheHttpClientHttpAttributesGetter httpAttributesGetter = - new ApacheHttpClientHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, + new ApacheHttpClientHttpAttributesGetter(), + HttpHeaderSetter.INSTANCE); } public static Instrumenter instrumenter() { diff --git a/instrumentation/apache-httpclient/apache-httpclient-4.3/library/src/main/java/io/opentelemetry/instrumentation/apachehttpclient/v4_3/ApacheHttpClientTelemetryBuilder.java b/instrumentation/apache-httpclient/apache-httpclient-4.3/library/src/main/java/io/opentelemetry/instrumentation/apachehttpclient/v4_3/ApacheHttpClientTelemetryBuilder.java index daf0d8c6889e..3526ca01436a 100644 --- a/instrumentation/apache-httpclient/apache-httpclient-4.3/library/src/main/java/io/opentelemetry/instrumentation/apachehttpclient/v4_3/ApacheHttpClientTelemetryBuilder.java +++ b/instrumentation/apache-httpclient/apache-httpclient-4.3/library/src/main/java/io/opentelemetry/instrumentation/apachehttpclient/v4_3/ApacheHttpClientTelemetryBuilder.java @@ -7,20 +7,10 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Function; @@ -30,24 +20,12 @@ public final class ApacheHttpClientTelemetryBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.apache-httpclient-4.3"; - - private final OpenTelemetry openTelemetry; - - private final List> - additionalExtractors = new ArrayList<>(); - private final HttpClientAttributesExtractorBuilder - httpAttributesExtractorBuilder = - HttpClientAttributesExtractor.builder(ApacheHttpClientHttpAttributesGetter.INSTANCE); - private final HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(ApacheHttpClientHttpAttributesGetter.INSTANCE); - private Function< - SpanNameExtractor, - ? extends SpanNameExtractor> - spanNameExtractorTransformer = Function.identity(); - private boolean emitExperimentalHttpClientMetrics = false; + private final DefaultHttpClientInstrumenterBuilder builder; ApacheHttpClientTelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + builder = + new DefaultHttpClientInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, ApacheHttpClientHttpAttributesGetter.INSTANCE); } /** @@ -58,7 +36,7 @@ public final class ApacheHttpClientTelemetryBuilder { public ApacheHttpClientTelemetryBuilder addAttributeExtractor( AttributesExtractor attributesExtractor) { - additionalExtractors.add(attributesExtractor); + builder.addAttributeExtractor(attributesExtractor); return this; } @@ -69,7 +47,7 @@ public ApacheHttpClientTelemetryBuilder addAttributeExtractor( */ @CanIgnoreReturnValue public ApacheHttpClientTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { - httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders); + builder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -80,7 +58,7 @@ public ApacheHttpClientTelemetryBuilder setCapturedRequestHeaders(List r */ @CanIgnoreReturnValue public ApacheHttpClientTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { - httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders); + builder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -99,8 +77,7 @@ public ApacheHttpClientTelemetryBuilder setCapturedResponseHeaders(List */ @CanIgnoreReturnValue public ApacheHttpClientTelemetryBuilder setKnownMethods(Set knownMethods) { - httpAttributesExtractorBuilder.setKnownMethods(knownMethods); - httpSpanNameExtractorBuilder.setKnownMethods(knownMethods); + builder.setKnownMethods(knownMethods); return this; } @@ -113,7 +90,7 @@ public ApacheHttpClientTelemetryBuilder setKnownMethods(Set knownMethods @CanIgnoreReturnValue public ApacheHttpClientTelemetryBuilder setEmitExperimentalHttpClientMetrics( boolean emitExperimentalHttpClientMetrics) { - this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; + builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics); return this; } @@ -124,7 +101,7 @@ public ApacheHttpClientTelemetryBuilder setSpanNameExtractor( SpanNameExtractor, ? extends SpanNameExtractor> spanNameExtractorTransformer) { - this.spanNameExtractorTransformer = spanNameExtractorTransformer; + builder.setSpanNameExtractor(spanNameExtractorTransformer); return this; } @@ -133,29 +110,7 @@ public ApacheHttpClientTelemetryBuilder setSpanNameExtractor( * ApacheHttpClientTelemetryBuilder}. */ public ApacheHttpClientTelemetry build() { - ApacheHttpClientHttpAttributesGetter httpAttributesGetter = - ApacheHttpClientHttpAttributesGetter.INSTANCE; - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(httpAttributesExtractorBuilder.build()) - .addAttributesExtractors(additionalExtractors) - .addOperationMetrics(HttpClientMetrics.get()); - if (emitExperimentalHttpClientMetrics) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - - Instrumenter instrumenter = - builder - // We manually inject because we need to inject internal requests for redirects. - .buildInstrumenter(SpanKindExtractor.alwaysClient()); - - return new ApacheHttpClientTelemetry(instrumenter, openTelemetry.getPropagators()); + return new ApacheHttpClientTelemetry( + builder.build(), builder.getOpenTelemetry().getPropagators()); } } diff --git a/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/ApacheHttpClientSingletons.java b/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/ApacheHttpClientSingletons.java index 8f6ccbdd6a02..e1cc0a667cef 100644 --- a/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/ApacheHttpClientSingletons.java +++ b/instrumentation/apache-httpclient/apache-httpclient-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v5_0/ApacheHttpClientSingletons.java @@ -5,17 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v5_0; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpResponse; @@ -25,33 +16,11 @@ public final class ApacheHttpClientSingletons { private static final Instrumenter INSTRUMENTER; static { - ApacheHttpClientHttpAttributesGetter httpAttributesGetter = - new ApacheHttpClientHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, + new ApacheHttpClientHttpAttributesGetter(), + HttpHeaderSetter.INSTANCE); } public static Instrumenter instrumenter() { diff --git a/instrumentation/apache-httpclient/apache-httpclient-5.2/library/src/main/java/io/opentelemetry/instrumentation/apachehttpclient/v5_2/ApacheHttpClient5TelemetryBuilder.java b/instrumentation/apache-httpclient/apache-httpclient-5.2/library/src/main/java/io/opentelemetry/instrumentation/apachehttpclient/v5_2/ApacheHttpClient5TelemetryBuilder.java index 176555846849..e9a5eb273de0 100644 --- a/instrumentation/apache-httpclient/apache-httpclient-5.2/library/src/main/java/io/opentelemetry/instrumentation/apachehttpclient/v5_2/ApacheHttpClient5TelemetryBuilder.java +++ b/instrumentation/apache-httpclient/apache-httpclient-5.2/library/src/main/java/io/opentelemetry/instrumentation/apachehttpclient/v5_2/ApacheHttpClient5TelemetryBuilder.java @@ -7,20 +7,10 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Function; @@ -30,26 +20,13 @@ public final class ApacheHttpClient5TelemetryBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.apache-httpclient-5.2"; - - private final OpenTelemetry openTelemetry; - - private final List> - additionalExtractors = new ArrayList<>(); - private final HttpClientAttributesExtractorBuilder - httpAttributesExtractorBuilder = - HttpClientAttributesExtractor.builder(ApacheHttpClient5HttpAttributesGetter.INSTANCE); - - private final HttpSpanNameExtractorBuilder - httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(ApacheHttpClient5HttpAttributesGetter.INSTANCE); - private Function< - SpanNameExtractor, - ? extends SpanNameExtractor> - spanNameExtractorTransformer = Function.identity(); - private boolean emitExperimentalHttpClientMetrics = false; + private final DefaultHttpClientInstrumenterBuilder + builder; ApacheHttpClient5TelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + builder = + new DefaultHttpClientInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, ApacheHttpClient5HttpAttributesGetter.INSTANCE); } /** @@ -60,7 +37,7 @@ public final class ApacheHttpClient5TelemetryBuilder { public ApacheHttpClient5TelemetryBuilder addAttributeExtractor( AttributesExtractor attributesExtractor) { - additionalExtractors.add(attributesExtractor); + builder.addAttributeExtractor(attributesExtractor); return this; } @@ -71,7 +48,7 @@ public ApacheHttpClient5TelemetryBuilder addAttributeExtractor( */ @CanIgnoreReturnValue public ApacheHttpClient5TelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { - httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders); + builder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -83,7 +60,7 @@ public ApacheHttpClient5TelemetryBuilder setCapturedRequestHeaders(List @CanIgnoreReturnValue public ApacheHttpClient5TelemetryBuilder setCapturedResponseHeaders( List responseHeaders) { - httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders); + builder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -102,8 +79,7 @@ public ApacheHttpClient5TelemetryBuilder setCapturedResponseHeaders( */ @CanIgnoreReturnValue public ApacheHttpClient5TelemetryBuilder setKnownMethods(Set knownMethods) { - httpAttributesExtractorBuilder.setKnownMethods(knownMethods); - httpSpanNameExtractorBuilder.setKnownMethods(knownMethods); + builder.setKnownMethods(knownMethods); return this; } @@ -116,7 +92,7 @@ public ApacheHttpClient5TelemetryBuilder setKnownMethods(Set knownMethod @CanIgnoreReturnValue public ApacheHttpClient5TelemetryBuilder setEmitExperimentalHttpClientMetrics( boolean emitExperimentalHttpClientMetrics) { - this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; + builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics); return this; } @@ -127,7 +103,7 @@ public ApacheHttpClient5TelemetryBuilder setSpanNameExtractor( SpanNameExtractor, ? extends SpanNameExtractor> spanNameExtractorTransformer) { - this.spanNameExtractorTransformer = spanNameExtractorTransformer; + builder.setSpanNameExtractor(spanNameExtractorTransformer); return this; } @@ -136,29 +112,7 @@ public ApacheHttpClient5TelemetryBuilder setSpanNameExtractor( * ApacheHttpClient5TelemetryBuilder}. */ public ApacheHttpClient5Telemetry build() { - ApacheHttpClient5HttpAttributesGetter httpAttributesGetter = - ApacheHttpClient5HttpAttributesGetter.INSTANCE; - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(httpAttributesExtractorBuilder.build()) - .addAttributesExtractors(additionalExtractors) - .addOperationMetrics(HttpClientMetrics.get()); - if (emitExperimentalHttpClientMetrics) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - - Instrumenter instrumenter = - builder - // We manually inject because we need to inject internal requests for redirects. - .buildInstrumenter(SpanKindExtractor.alwaysClient()); - - return new ApacheHttpClient5Telemetry(instrumenter, openTelemetry.getPropagators()); + return new ApacheHttpClient5Telemetry( + builder.build(), builder.getOpenTelemetry().getPropagators()); } } diff --git a/instrumentation/apache-shenyu-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apacheshenyu/v2_4/MetaDataHelper.java b/instrumentation/apache-shenyu-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apacheshenyu/v2_4/MetaDataHelper.java index 15645b8ea6f7..4414e6eeb628 100644 --- a/instrumentation/apache-shenyu-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apacheshenyu/v2_4/MetaDataHelper.java +++ b/instrumentation/apache-shenyu-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apacheshenyu/v2_4/MetaDataHelper.java @@ -9,7 +9,7 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import org.apache.shenyu.common.dto.MetaData; public final class MetaDataHelper { @@ -58,7 +58,7 @@ public final class MetaDataHelper { static { CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.apache-shenyu.experimental-span-attributes", false); } diff --git a/instrumentation/armeria/armeria-1.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/armeria/v1_3/ArmeriaSingletons.java b/instrumentation/armeria/armeria-1.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/armeria/v1_3/ArmeriaSingletons.java index 99a3b2c6c17f..8f4800ebca34 100644 --- a/instrumentation/armeria/armeria-1.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/armeria/v1_3/ArmeriaSingletons.java +++ b/instrumentation/armeria/armeria-1.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/armeria/v1_3/ArmeriaSingletons.java @@ -11,7 +11,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; import io.opentelemetry.instrumentation.armeria.v1_3.ArmeriaTelemetry; import io.opentelemetry.instrumentation.armeria.v1_3.internal.ArmeriaHttpClientAttributesGetter; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import java.util.function.Function; // Holds singleton references to decorators to match against during suppression. @@ -24,19 +24,19 @@ public final class ArmeriaSingletons { static { ArmeriaTelemetry telemetry = ArmeriaTelemetry.builder(GlobalOpenTelemetry.get()) - .setCapturedClientRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedClientResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setCapturedServerRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedServerResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedClientRequestHeaders(AgentCommonConfig.get().getClientRequestHeaders()) + .setCapturedClientResponseHeaders(AgentCommonConfig.get().getClientResponseHeaders()) + .setCapturedServerRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedServerResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .addClientAttributeExtractor( HttpClientPeerServiceAttributesExtractor.create( ArmeriaHttpClientAttributesGetter.INSTANCE, - CommonConfig.get().getPeerServiceResolver())) + AgentCommonConfig.get().getPeerServiceResolver())) .setEmitExperimentalHttpClientMetrics( - CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) + AgentCommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) .setEmitExperimentalHttpServerMetrics( - CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) + AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) .build(); CLIENT_DECORATOR = telemetry.newClientDecorator(); diff --git a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientSingletons.java b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientSingletons.java index 7963e1d2b3d0..c886631a93cc 100644 --- a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientSingletons.java +++ b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientSingletons.java @@ -7,17 +7,8 @@ import com.ning.http.client.Request; import com.ning.http.client.Response; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; public final class AsyncHttpClientSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.async-http-client-1.9"; @@ -25,33 +16,11 @@ public final class AsyncHttpClientSingletons { private static final Instrumenter INSTRUMENTER; static { - AsyncHttpClientHttpAttributesGetter httpAttributesGetter = - new AsyncHttpClientHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, + new AsyncHttpClientHttpAttributesGetter(), + HttpHeaderSetter.INSTANCE); } public static Instrumenter instrumenter() { diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/build.gradle.kts b/instrumentation/async-http-client/async-http-client-2.0/javaagent/build.gradle.kts index 30b722110c08..9c573a0fd4ec 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/build.gradle.kts +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/build.gradle.kts @@ -18,14 +18,32 @@ dependencies { testInstrumentation(project(":instrumentation:netty:netty-4.1:javaagent")) } -otelJava { - // AHC uses Unsafe and so does not run on later java version - maxJavaVersionForTests.set(JavaVersion.VERSION_1_8) +val latestDepTest = findProperty("testLatestDeps") as Boolean +val testJavaVersion = + gradle.startParameter.projectProperties["testJavaVersion"]?.let(JavaVersion::toVersion) + ?: JavaVersion.current() + +if (!latestDepTest) { + otelJava { + // AHC uses Unsafe and so does not run on later java version + maxJavaVersionForTests.set(JavaVersion.VERSION_1_8) + } +} + +tasks.withType().configureEach { + systemProperty("testLatestDeps", latestDepTest) + // async-http-client 3.0 requires java 11 + // We are not using minJavaVersionSupported for latestDepTest because that way the instrumentation + // gets compiled with java 11 when running latestDepTest. This causes play-mvc-2.4 latest dep tests + // to fail because they require java 8 and instrumentation compiled with java 11 won't apply. + if (latestDepTest && testJavaVersion.isJava8) { + enabled = false + } } // async-http-client 2.0.0 does not work with Netty versions newer than this due to referencing an // internal file. -if (!(findProperty("testLatestDeps") as Boolean)) { +if (!latestDepTest) { configurations.configureEach { if (!name.contains("muzzle")) { resolutionStrategy { diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientSingletons.java b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientSingletons.java index 56e8706a3317..2e140594f0bd 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientSingletons.java +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientSingletons.java @@ -5,17 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import org.asynchttpclient.Response; public final class AsyncHttpClientSingletons { @@ -24,33 +15,11 @@ public final class AsyncHttpClientSingletons { private static final Instrumenter INSTRUMENTER; static { - AsyncHttpClientHttpAttributesGetter httpAttributesGetter = - new AsyncHttpClientHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, + new AsyncHttpClientHttpAttributesGetter(), + HttpHeaderSetter.INSTANCE); } public static Instrumenter instrumenter() { diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientTest.java b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientTest.java index e8b25349aca9..6e968d6b9759 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientTest.java +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientTest.java @@ -10,11 +10,14 @@ import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; +import java.lang.reflect.Method; import java.net.URI; +import java.time.Duration; import java.util.Map; import java.util.concurrent.ExecutionException; import org.asynchttpclient.AsyncCompletionHandler; import org.asynchttpclient.AsyncHttpClient; +import org.asynchttpclient.DefaultAsyncHttpClientConfig; import org.asynchttpclient.Dsl; import org.asynchttpclient.Request; import org.asynchttpclient.RequestBuilder; @@ -31,11 +34,26 @@ class AsyncHttpClientTest extends AbstractHttpClientTest { private static final int CONNECTION_TIMEOUT_MS = (int) CONNECTION_TIMEOUT.toMillis(); // request timeout is needed in addition to connect timeout on async-http-client versions 2.1.0+ - private static final AsyncHttpClient client = - Dsl.asyncHttpClient( - Dsl.config() - .setConnectTimeout(CONNECTION_TIMEOUT_MS) - .setRequestTimeout(CONNECTION_TIMEOUT_MS)); + private static final AsyncHttpClient client = Dsl.asyncHttpClient(configureTimeout(Dsl.config())); + + private static DefaultAsyncHttpClientConfig.Builder configureTimeout( + DefaultAsyncHttpClientConfig.Builder builder) { + setTimeout(builder, "setConnectTimeout", CONNECTION_TIMEOUT_MS); + setTimeout(builder, "setRequestTimeout", CONNECTION_TIMEOUT_MS); + return builder; + } + + private static void setTimeout( + DefaultAsyncHttpClientConfig.Builder builder, String methodName, int timeout) { + boolean testLatestDeps = Boolean.getBoolean("testLatestDeps"); + try { + Method method = + builder.getClass().getMethod(methodName, testLatestDeps ? Duration.class : int.class); + method.invoke(builder, testLatestDeps ? Duration.ofMillis(timeout) : timeout); + } catch (Exception exception) { + throw new IllegalStateException("Failed to set timeout " + methodName, exception); + } + } @Override public Request buildRequest(String method, URI uri, Map headers) { diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/TracingRequestStreamHandler.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/TracingRequestStreamHandler.java index fced56818f52..ae6a42bd6de4 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/TracingRequestStreamHandler.java +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/TracingRequestStreamHandler.java @@ -7,6 +7,7 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.ApiGatewayProxyRequest; import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.AwsLambdaFunctionInstrumenter; @@ -67,49 +68,55 @@ protected TracingRequestStreamHandler( @Override public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - ApiGatewayProxyRequest proxyRequest = ApiGatewayProxyRequest.forStream(input); - AwsLambdaRequest request = - AwsLambdaRequest.create(context, proxyRequest, proxyRequest.getHeaders()); + AwsLambdaRequest request = createRequest(input, context, proxyRequest); io.opentelemetry.context.Context parentContext = instrumenter.extract(request); if (!instrumenter.shouldStart(parentContext, request)) { - doHandleRequest(proxyRequest.freshStream(), output, context); + doHandleRequest(proxyRequest.freshStream(), output, context, request); return; } io.opentelemetry.context.Context otelContext = instrumenter.start(parentContext, request); + Throwable error = null; try (Scope ignored = otelContext.makeCurrent()) { doHandleRequest( proxyRequest.freshStream(), - new OutputStreamWrapper(output, otelContext, request, openTelemetrySdk), - context); + new OutputStreamWrapper(output, otelContext), + context, + request); } catch (Throwable t) { - instrumenter.end(otelContext, request, null, t); - LambdaUtils.forceFlush(openTelemetrySdk, flushTimeoutNanos, TimeUnit.NANOSECONDS); + error = t; throw t; + } finally { + instrumenter.end(otelContext, request, null, error); + LambdaUtils.forceFlush(openTelemetrySdk, flushTimeoutNanos, TimeUnit.NANOSECONDS); } } + protected AwsLambdaRequest createRequest( + InputStream input, Context context, ApiGatewayProxyRequest proxyRequest) throws IOException { + return AwsLambdaRequest.create(context, proxyRequest, proxyRequest.getHeaders()); + } + + protected void doHandleRequest( + InputStream input, OutputStream output, Context context, AwsLambdaRequest request) + throws IOException { + doHandleRequest(input, output, context); + } + protected abstract void doHandleRequest(InputStream input, OutputStream output, Context context) throws IOException; - private class OutputStreamWrapper extends OutputStream { + private static class OutputStreamWrapper extends OutputStream { private final OutputStream delegate; private final io.opentelemetry.context.Context otelContext; - private final AwsLambdaRequest request; - private final OpenTelemetrySdk openTelemetrySdk; private OutputStreamWrapper( - OutputStream delegate, - io.opentelemetry.context.Context otelContext, - AwsLambdaRequest request, - OpenTelemetrySdk openTelemetrySdk) { + OutputStream delegate, io.opentelemetry.context.Context otelContext) { this.delegate = delegate; this.otelContext = otelContext; - this.request = request; - this.openTelemetrySdk = openTelemetrySdk; } @Override @@ -135,8 +142,8 @@ public void flush() throws IOException { @Override public void close() throws IOException { delegate.close(); - instrumenter.end(otelContext, request, null, null); - LambdaUtils.forceFlush(openTelemetrySdk, flushTimeoutNanos, TimeUnit.NANOSECONDS); + Span span = Span.fromContext(otelContext); + span.addEvent("Output stream closed"); } } } diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/TracingRequestStreamWrapper.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/TracingRequestStreamWrapper.java index 18ceb38cbf1b..d20564ffc805 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/TracingRequestStreamWrapper.java +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/TracingRequestStreamWrapper.java @@ -23,7 +23,7 @@ */ public class TracingRequestStreamWrapper extends TracingRequestStreamHandler { - private final WrappedLambda wrappedLambda; + protected final WrappedLambda wrappedLambda; public TracingRequestStreamWrapper() { this( @@ -32,7 +32,8 @@ public TracingRequestStreamWrapper() { } // Visible for testing - TracingRequestStreamWrapper(OpenTelemetrySdk openTelemetrySdk, WrappedLambda wrappedLambda) { + protected TracingRequestStreamWrapper( + OpenTelemetrySdk openTelemetrySdk, WrappedLambda wrappedLambda) { super(openTelemetrySdk, WrapperConfiguration.flushTimeout()); this.wrappedLambda = wrappedLambda; } diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/AwsLambdaFunctionInstrumenter.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/AwsLambdaFunctionInstrumenter.java index 4136e7bed954..9341bf6f79dc 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/AwsLambdaFunctionInstrumenter.java +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/AwsLambdaFunctionInstrumenter.java @@ -11,6 +11,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.internal.ContextPropagationDebug; import io.opentelemetry.instrumentation.awslambdacore.v1_0.AwsLambdaRequest; +import java.util.HashMap; import java.util.Locale; import java.util.Map; import javax.annotation.Nullable; @@ -48,11 +49,20 @@ public void end( public Context extract(AwsLambdaRequest input) { ContextPropagationDebug.debugContextLeakIfEnabled(); + // Look in both the http headers and the custom client context + Map headers = input.getHeaders(); + if (input.getAwsContext() != null && input.getAwsContext().getClientContext() != null) { + Map customContext = input.getAwsContext().getClientContext().getCustom(); + if (customContext != null) { + headers = new HashMap<>(headers); + headers.putAll(customContext); + } + } return openTelemetry .getPropagators() .getTextMapPropagator() - .extract(Context.root(), input.getHeaders(), MapGetter.INSTANCE); + .extract(Context.root(), headers, MapGetter.INSTANCE); } private enum MapGetter implements TextMapGetter> { diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/InstrumenterExtractionTest.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/InstrumenterExtractionTest.java new file mode 100644 index 000000000000..cb19d1e56879 --- /dev/null +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/InstrumenterExtractionTest.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awslambdacore.v1_0.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.amazonaws.services.lambda.runtime.ClientContext; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.instrumentation.awslambdacore.v1_0.AwsLambdaRequest; +import java.util.HashMap; +import org.junit.jupiter.api.Test; + +class InstrumenterExtractionTest { + @Test + public void useCustomContext() { + AwsLambdaFunctionInstrumenter instr = + AwsLambdaFunctionInstrumenterFactory.createInstrumenter( + OpenTelemetry.propagating( + ContextPropagators.create(W3CTraceContextPropagator.getInstance()))); + com.amazonaws.services.lambda.runtime.Context awsContext = + mock(com.amazonaws.services.lambda.runtime.Context.class); + ClientContext clientContext = mock(ClientContext.class); + when(awsContext.getClientContext()).thenReturn(clientContext); + HashMap customMap = new HashMap<>(); + customMap.put("traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"); + when(clientContext.getCustom()).thenReturn(customMap); + + AwsLambdaRequest input = AwsLambdaRequest.create(awsContext, new HashMap<>(), new HashMap<>()); + + Context extracted = instr.extract(input); + SpanContext spanContext = Span.fromContext(extracted).getSpanContext(); + assertThat(spanContext.getTraceId()).isEqualTo("4bf92f3577b34da6a3ce929d0e0e4736"); + assertThat(spanContext.getSpanId()).isEqualTo("00f067aa0ba902b7"); + } +} diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/testing/build.gradle.kts b/instrumentation/aws-lambda/aws-lambda-core-1.0/testing/build.gradle.kts index d035a0ffc7d9..b414e5a45350 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/testing/build.gradle.kts +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/testing/build.gradle.kts @@ -12,8 +12,6 @@ dependencies { implementation("com.google.guava:guava") - implementation("org.apache.groovy:groovy") implementation("io.opentelemetry:opentelemetry-api") - implementation("org.spockframework:spock-core") implementation("com.github.stefanbirkner:system-lambda") } diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awslambdaevents/v2_2/AwsLambdaInstrumentationHelper.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awslambdaevents/v2_2/AwsLambdaInstrumentationHelper.java index 8783d93ef8bd..d55898e75053 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awslambdaevents/v2_2/AwsLambdaInstrumentationHelper.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awslambdaevents/v2_2/AwsLambdaInstrumentationHelper.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal.AwsLambdaEventsInstrumenterFactory; import io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal.AwsLambdaSqsInstrumenterFactory; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; public final class AwsLambdaInstrumentationHelper { @@ -18,7 +18,7 @@ public final class AwsLambdaInstrumentationHelper { .AwsLambdaFunctionInstrumenter FUNCTION_INSTRUMENTER = AwsLambdaEventsInstrumenterFactory.createInstrumenter( - GlobalOpenTelemetry.get(), CommonConfig.get().getKnownHttpRequestMethods()); + GlobalOpenTelemetry.get(), AgentCommonConfig.get().getKnownHttpRequestMethods()); public static io.opentelemetry.instrumentation.awslambdacore.v1_0.internal .AwsLambdaFunctionInstrumenter diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts index 6918c6fbfab0..452d42189590 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/build.gradle.kts @@ -18,6 +18,13 @@ dependencies { // in public API. library("com.amazonaws:aws-lambda-java-events:2.2.1") + // By default, "aws-lambda-java-serialization" library is enabled in the classpath + // at the AWS Lambda environment except "java8" runtime which is deprecated. + // But it is available at "java8.al2" runtime, so it is still can be used + // by Java 8 based Lambda functions. + // So that is the reason that why we add it as compile only dependency. + compileOnly("com.amazonaws:aws-lambda-java-serialization:1.1.5") + // We need Jackson for wrappers to reproduce the serialization does when Lambda invokes a RequestHandler with event // since Lambda will only be able to invoke the wrapper itself with a generic Object. // Note that Lambda itself uses Jackson, but does not expose it to the function so we need to include it here. @@ -33,6 +40,7 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") testImplementation("io.opentelemetry:opentelemetry-extension-trace-propagators") testImplementation("com.google.guava:guava") + testImplementation("com.amazonaws:aws-lambda-java-serialization:1.1.5") testImplementation(project(":instrumentation:aws-lambda:aws-lambda-events-2.2:testing")) testImplementation("uk.org.webcompere:system-stubs-jupiter") diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/LambdaParameters.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/LambdaParameters.java index ecc3a33d7003..53e68280bade 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/LambdaParameters.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/LambdaParameters.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.awslambdaevents.v2_2; import com.amazonaws.services.lambda.runtime.Context; +import java.io.InputStream; import java.lang.reflect.Method; import java.util.function.BiFunction; @@ -27,5 +28,35 @@ static Object[] toArray( return parameters; } + static Object[] toParameters(Method targetMethod, T input, Context context) { + Class[] parameterTypes = targetMethod.getParameterTypes(); + Object[] parameters = new Object[parameterTypes.length]; + for (int i = 0; i < parameterTypes.length; i++) { + Class clazz = parameterTypes[i]; + boolean isContext = clazz.equals(Context.class); + if (isContext) { + parameters[i] = context; + } else if (i == 0) { + parameters[0] = input; + } + } + return parameters; + } + + static Object toInput( + Method targetMethod, + InputStream inputStream, + BiFunction, Object> mapper) { + Class[] parameterTypes = targetMethod.getParameterTypes(); + for (int i = 0; i < parameterTypes.length; i++) { + Class clazz = parameterTypes[i]; + boolean isContext = clazz.equals(Context.class); + if (i == 0 && !isContext) { + return mapper.apply(inputStream, clazz); + } + } + return null; + } + private LambdaParameters() {} } diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestApiGatewayWrapper.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestApiGatewayWrapper.java index 00eb6e88e53b..711b7e3079a0 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestApiGatewayWrapper.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestApiGatewayWrapper.java @@ -8,8 +8,8 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.fasterxml.jackson.core.JsonProcessingException; import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.WrappedLambda; +import io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal.SerializationUtil; import io.opentelemetry.sdk.OpenTelemetrySdk; import java.util.function.BiFunction; @@ -35,12 +35,7 @@ public TracingRequestApiGatewayWrapper() { // Visible for testing static T map(APIGatewayProxyRequestEvent event, Class clazz) { - try { - return OBJECT_MAPPER.readValue(event.getBody(), clazz); - } catch (JsonProcessingException e) { - throw new IllegalStateException( - "Could not map API Gateway event body to requested parameter type: " + clazz, e); - } + return SerializationUtil.fromJson(event.getBody(), clazz); } @Override @@ -52,12 +47,8 @@ protected APIGatewayProxyResponseEvent doHandleRequest( if (result instanceof APIGatewayProxyResponseEvent) { event = (APIGatewayProxyResponseEvent) result; } else { - try { - event = new APIGatewayProxyResponseEvent(); - event.setBody(OBJECT_MAPPER.writeValueAsString(result)); - } catch (JsonProcessingException e) { - throw new IllegalStateException("Could not serialize return value.", e); - } + event = new APIGatewayProxyResponseEvent(); + event.setBody(SerializationUtil.toJson(result)); } return event; } diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapper.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapper.java index 5cbeec41cfee..484ee169d623 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapper.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapper.java @@ -5,32 +5,90 @@ package io.opentelemetry.instrumentation.awslambdaevents.v2_2; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import io.opentelemetry.instrumentation.awslambdacore.v1_0.AwsLambdaRequest; +import io.opentelemetry.instrumentation.awslambdacore.v1_0.TracingRequestStreamWrapper; +import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.ApiGatewayProxyRequest; +import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.MapUtils; import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.WrappedLambda; +import io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal.SerializationUtil; import io.opentelemetry.sdk.OpenTelemetrySdk; -import java.util.function.BiFunction; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.Map; /** - * Wrapper for {@link io.opentelemetry.instrumentation.awslambdacore.v1_0.TracingRequestHandler}. - * Allows for wrapping a regular lambda, not proxied through API Gateway. Therefore, HTTP headers - * propagation is not supported. + * Wrapper for {@link com.amazonaws.services.lambda.runtime.RequestHandler} based Lambda handlers. */ -public class TracingRequestWrapper extends TracingRequestWrapperBase { +public class TracingRequestWrapper extends TracingRequestStreamWrapper { public TracingRequestWrapper() { - super(TracingRequestWrapper::map); + super(); } // Visible for testing - TracingRequestWrapper( - OpenTelemetrySdk openTelemetrySdk, - WrappedLambda wrappedLambda, - BiFunction, Object> mapper) { - super(openTelemetrySdk, wrappedLambda, mapper); + TracingRequestWrapper(OpenTelemetrySdk openTelemetrySdk, WrappedLambda wrappedLambda) { + super(openTelemetrySdk, wrappedLambda); + } + + @Override + protected final AwsLambdaRequest createRequest( + InputStream inputStream, Context context, ApiGatewayProxyRequest proxyRequest) { + Method targetMethod = wrappedLambda.getRequestTargetMethod(); + Object input = LambdaParameters.toInput(targetMethod, inputStream, TracingRequestWrapper::map); + return AwsLambdaRequest.create(context, input, extractHeaders(input)); + } + + protected Map extractHeaders(Object input) { + if (input instanceof APIGatewayProxyRequestEvent) { + return MapUtils.emptyIfNull(((APIGatewayProxyRequestEvent) input).getHeaders()); + } + return Collections.emptyMap(); + } + + @Override + protected final void doHandleRequest( + InputStream input, OutputStream output, Context context, AwsLambdaRequest request) { + Method targetMethod = wrappedLambda.getRequestTargetMethod(); + Object[] parameters = LambdaParameters.toParameters(targetMethod, request.getInput(), context); + try { + Object result = targetMethod.invoke(wrappedLambda.getTargetObject(), parameters); + SerializationUtil.toJson(output, result); + } catch (IllegalAccessException e) { + throw new IllegalStateException("Method is inaccessible", e); + } catch (InvocationTargetException e) { + throw (e.getCause() instanceof RuntimeException + ? (RuntimeException) e.getCause() + : new IllegalStateException(e.getTargetException())); + } + } + + @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) + // Used for testing + OUTPUT handleRequest(INPUT input, Context context) throws IOException { + byte[] inputJsonData = SerializationUtil.toJsonData(input); + ByteArrayInputStream inputStream = new ByteArrayInputStream(inputJsonData); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + super.handleRequest(inputStream, outputStream, context); + + byte[] outputJsonData = outputStream.toByteArray(); + return (OUTPUT) + SerializationUtil.fromJson( + new ByteArrayInputStream(outputJsonData), + wrappedLambda.getRequestTargetMethod().getReturnType()); } // Visible for testing - static T map(Object jsonMap, Class clazz) { + static T map(InputStream inputStream, Class clazz) { try { - return OBJECT_MAPPER.convertValue(jsonMap, clazz); + return SerializationUtil.fromJson(inputStream, clazz); } catch (IllegalArgumentException e) { throw new IllegalStateException( "Could not map input to requested parameter type: " + clazz, e); diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapperBase.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapperBase.java index c435e03d2e9b..5169c8f121ee 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapperBase.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapperBase.java @@ -7,8 +7,6 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; import io.opentelemetry.instrumentation.api.internal.HttpConstants; import io.opentelemetry.instrumentation.awslambdacore.v1_0.TracingRequestHandler; import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.MapUtils; @@ -29,10 +27,6 @@ */ abstract class TracingRequestWrapperBase extends TracingRequestHandler { - protected static final ObjectMapper OBJECT_MAPPER = - new ObjectMapper() - .registerModule(new CustomJodaModule()) - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); private final WrappedLambda wrappedLambda; private final Method targetMethod; private final BiFunction, Object> parameterMapper; diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/CustomJodaModule.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/internal/CustomJodaModule.java similarity index 96% rename from instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/CustomJodaModule.java rename to instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/internal/CustomJodaModule.java index a1991b468145..1be598ae8ffb 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/CustomJodaModule.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/internal/CustomJodaModule.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.awslambdaevents.v2_2; +package io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/internal/SerializationUtil.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/internal/SerializationUtil.java new file mode 100644 index 000000000000..81649340e649 --- /dev/null +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/internal/SerializationUtil.java @@ -0,0 +1,133 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal; + +import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer; +import com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers; +import com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class SerializationUtil { + + private static final int DEFAULT_BUFFER_SIZE = 1024; + + private static final ClassValue> serializerCache = + new ClassValue>() { + @Override + protected PojoSerializer computeValue(Class type) { + return createSerializer(type); + } + }; + + private static PojoSerializer createSerializer(Class clazz) { + try { + if (LambdaEventSerializers.isLambdaSupportedEvent(clazz.getName())) { + return LambdaEventSerializers.serializerFor(clazz, clazz.getClassLoader()); + } + return JacksonFactory.getInstance().getSerializer(clazz); + } catch (NoClassDefFoundError e) { + // For "java8" runtime, "aws-lambda-java-serialization" library + // is not available in the classpath by default. + // So fall back to object mapper based legacy serialization. + return new ObjectMapperPojoSerializer(clazz); + } + } + + @SuppressWarnings("unchecked") + public static PojoSerializer getSerializer(Class clazz) { + return (PojoSerializer) serializerCache.get(clazz); + } + + public static T fromJson(String json, Class clazz) { + PojoSerializer serializer = getSerializer(clazz); + return serializer.fromJson(json); + } + + public static T fromJson(InputStream inputStream, Class clazz) { + PojoSerializer serializer = getSerializer(clazz); + return serializer.fromJson(inputStream); + } + + @SuppressWarnings("unchecked") + public static void toJson(OutputStream outputStream, T obj) { + if (obj != null) { + PojoSerializer serializer = getSerializer((Class) obj.getClass()); + serializer.toJson(obj, outputStream); + } + } + + @SuppressWarnings("unchecked") + public static String toJson(T obj) { + if (obj == null) { + return null; + } + PojoSerializer serializer = getSerializer((Class) obj.getClass()); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE); + serializer.toJson(obj, outputStream); + return new String(outputStream.toByteArray(), StandardCharsets.UTF_8); + } + + public static byte[] toJsonData(T obj) { + if (obj == null) { + return new byte[] {}; + } + ByteArrayOutputStream os = new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE); + SerializationUtil.toJson(os, obj); + return os.toByteArray(); + } + + private static class ObjectMapperPojoSerializer implements PojoSerializer { + + private final ObjectMapper objectMapper = + new ObjectMapper() + .registerModule(new CustomJodaModule()) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + private final Class clazz; + + ObjectMapperPojoSerializer(Class clazz) { + this.clazz = clazz; + } + + @Override + public T fromJson(InputStream input) { + try { + return objectMapper.readValue(input, clazz); + } catch (IOException e) { + throw new IllegalStateException("Could not deserialize from JSON input stream.", e); + } + } + + @Override + public T fromJson(String input) { + try { + return objectMapper.readValue(input, clazz); + } catch (IOException e) { + throw new IllegalStateException("Could not deserialize from JSON string.", e); + } + } + + @Override + public void toJson(T value, OutputStream output) { + try { + objectMapper.writeValue(output, value); + } catch (IOException e) { + throw new IllegalStateException("Could not serialize to JSON.", e); + } + } + } + + private SerializationUtil() {} +} diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/AwsLambdaWrapperTest.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/AwsLambdaWrapperTest.java index 87cb651713ba..12bef1d95082 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/AwsLambdaWrapperTest.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/AwsLambdaWrapperTest.java @@ -19,6 +19,7 @@ import io.opentelemetry.sdk.trace.data.StatusData; import io.opentelemetry.semconv.incubating.CloudIncubatingAttributes; import io.opentelemetry.semconv.incubating.FaasIncubatingAttributes; +import java.io.IOException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -54,12 +55,9 @@ void tearDown() { key = WrappedLambda.OTEL_LAMBDA_HANDLER_ENV_KEY, value = "io.opentelemetry.instrumentation.awslambdaevents.v2_2.AwsLambdaWrapperTest$TestRequestHandlerString::handleRequest") - void handlerTraced() { + void handlerTraced() throws IOException { TracingRequestWrapper wrapper = - new TracingRequestWrapper( - testing.getOpenTelemetrySdk(), - WrappedLambda.fromConfiguration(), - TracingRequestWrapper::map); + new TracingRequestWrapper(testing.getOpenTelemetrySdk(), WrappedLambda.fromConfiguration()); Object result = wrapper.handleRequest("hello", context); assertThat(result).isEqualTo("world"); @@ -84,10 +82,7 @@ void handlerTraced() { "io.opentelemetry.instrumentation.awslambdaevents.v2_2.AwsLambdaWrapperTest$TestRequestHandlerString::handleRequest") void handlerTracedWithException() { TracingRequestWrapper wrapper = - new TracingRequestWrapper( - testing.getOpenTelemetrySdk(), - WrappedLambda.fromConfiguration(), - TracingRequestWrapper::map); + new TracingRequestWrapper(testing.getOpenTelemetrySdk(), WrappedLambda.fromConfiguration()); Throwable thrown = catchThrowable(() -> wrapper.handleRequest("goodbye", context)); assertThat(thrown).isInstanceOf(IllegalArgumentException.class); @@ -112,12 +107,9 @@ void handlerTracedWithException() { key = WrappedLambda.OTEL_LAMBDA_HANDLER_ENV_KEY, value = "io.opentelemetry.instrumentation.awslambdaevents.v2_2.AwsLambdaWrapperTest$TestRequestHandlerInteger::handleRequest") - void handlerTraced_integer() { + void handlerTraced_integer() throws IOException { TracingRequestWrapper wrapper = - new TracingRequestWrapper( - testing.getOpenTelemetrySdk(), - WrappedLambda.fromConfiguration(), - TracingRequestWrapper::map); + new TracingRequestWrapper(testing.getOpenTelemetrySdk(), WrappedLambda.fromConfiguration()); Object result = wrapper.handleRequest(1, context); assertThat(result).isEqualTo("world"); @@ -140,12 +132,9 @@ void handlerTraced_integer() { key = WrappedLambda.OTEL_LAMBDA_HANDLER_ENV_KEY, value = "io.opentelemetry.instrumentation.awslambdaevents.v2_2.AwsLambdaWrapperTest$TestRequestHandlerCustomType::handleRequest") - void handlerTraced_custom() { + void handlerTraced_custom() throws IOException { TracingRequestWrapper wrapper = - new TracingRequestWrapper( - testing.getOpenTelemetrySdk(), - WrappedLambda.fromConfiguration(), - TracingRequestWrapper::map); + new TracingRequestWrapper(testing.getOpenTelemetrySdk(), WrappedLambda.fromConfiguration()); CustomType ct = new CustomType(); ct.key = "hello there"; ct.value = "General Kenobi"; @@ -188,9 +177,28 @@ public String handleRequest(Integer input, Context context) { } } + @SuppressWarnings("UnusedMethod") private static class CustomType { String key; String value; + + // Need getter/setter of all the attributes for serialization/deserialization + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } } public static final class TestRequestHandlerCustomType diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/LambdaParametersTest.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/LambdaParametersTest.java index 2bf8357f4334..f738b5a34932 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/LambdaParametersTest.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/LambdaParametersTest.java @@ -9,6 +9,8 @@ import static org.mockito.Mockito.mock; import com.amazonaws.services.lambda.runtime.Context; +import io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal.SerializationUtil; +import java.io.ByteArrayInputStream; import java.lang.reflect.Method; import org.junit.jupiter.api.Test; @@ -16,6 +18,10 @@ class LambdaParametersTest { public void onlyContext(Context context) {} + public void noContext(String one) {} + + public void contextOnSecond(String one, Context context) {} + public void contextOnThird(String one, String two, Context context) {} @Test @@ -30,6 +36,31 @@ void shouldSetContextOnFirstPosition() throws NoSuchMethodException { assertThat(params[0]).isEqualTo(context); } + @Test + void shouldOnlySetInputWhenNoContext() throws NoSuchMethodException { + // given + Context context = mock(Context.class); + Method method = getClass().getMethod("noContext", String.class); + // when + Object[] params = LambdaParameters.toArray(method, "", context, (o, c) -> o); + // then + assertThat(params).hasSize(1); + assertThat(params[0]).isEqualTo(""); + } + + @Test + void shouldSetContextOnTheSecondPosition() throws NoSuchMethodException { + // given + Context context = mock(Context.class); + Method method = getClass().getMethod("contextOnSecond", String.class, Context.class); + // when + Object[] params = LambdaParameters.toArray(method, "", context, (o, c) -> o); + // then + assertThat(params).hasSize(2); + assertThat(params[0]).isEqualTo(""); + assertThat(params[1]).isEqualTo(context); + } + @Test void shouldSetContextOnTheLastPosition() throws NoSuchMethodException { // given @@ -44,4 +75,103 @@ void shouldSetContextOnTheLastPosition() throws NoSuchMethodException { assertThat(params[1]).isNull(); assertThat(params[2]).isEqualTo(context); } + + @Test + void shouldNotResolveInputWhenNoInput() throws NoSuchMethodException { + // given + Method method = getClass().getMethod("onlyContext", Context.class); + String giveInput = "testInput"; + // when + Object resolvedInput = + LambdaParameters.toInput( + method, + new ByteArrayInputStream(SerializationUtil.toJsonData(giveInput)), + (i, c) -> SerializationUtil.fromJson(i, c)); + // then + assertThat(resolvedInput).isNull(); + } + + @Test + void shouldResolveInputWithContext() throws NoSuchMethodException { + // given + Method method = getClass().getMethod("contextOnSecond", String.class, Context.class); + String givenInput = "testInput"; + // when + Object resolvedInput = + LambdaParameters.toInput( + method, + new ByteArrayInputStream(SerializationUtil.toJsonData(givenInput)), + (i, c) -> SerializationUtil.fromJson(i, c)); + // then + assertThat(resolvedInput).isNotNull(); + assertThat(resolvedInput).isEqualTo(givenInput); + } + + @Test + void shouldResolveInputWithoutContext() throws NoSuchMethodException { + // given + Method method = getClass().getMethod("noContext", String.class); + String givenInput = "testInput"; + // when + Object resolvedInput = + LambdaParameters.toInput( + method, + new ByteArrayInputStream(SerializationUtil.toJsonData(givenInput)), + (i, c) -> SerializationUtil.fromJson(i, c)); + // then + assertThat(resolvedInput).isNotNull(); + assertThat(resolvedInput).isEqualTo(givenInput); + } + + @Test + void shouldResolveParametersWhenOnlyContext() throws NoSuchMethodException { + // given + Context context = mock(Context.class); + Method method = getClass().getMethod("onlyContext", Context.class); + // when + Object[] params = LambdaParameters.toParameters(method, "", context); + // then + assertThat(params).hasSize(1); + assertThat(params[0]).isEqualTo(context); + } + + @Test + void shouldResolveParametersWhenNoContext() throws NoSuchMethodException { + // given + Context context = mock(Context.class); + Method method = getClass().getMethod("noContext", String.class); + // when + Object[] params = LambdaParameters.toParameters(method, "", context); + // then + assertThat(params).hasSize(1); + assertThat(params[0]).isEqualTo(""); + } + + @Test + void shouldResolveParametersWhenContextOnTheSecondPosition() throws NoSuchMethodException { + // given + Context context = mock(Context.class); + Method method = getClass().getMethod("contextOnSecond", String.class, Context.class); + // when + Object[] params = LambdaParameters.toParameters(method, "", context); + // then + assertThat(params).hasSize(2); + assertThat(params[0]).isEqualTo(""); + assertThat(params[1]).isEqualTo(context); + } + + @Test + void shouldResolveParametersWhenContextOnTheLastPosition() throws NoSuchMethodException { + // given + Context context = mock(Context.class); + Method method = + getClass().getMethod("contextOnThird", String.class, String.class, Context.class); + // when + Object[] params = LambdaParameters.toParameters(method, "", context); + // then + assertThat(params).hasSize(3); + assertThat(params[0]).isEqualTo(""); + assertThat(params[1]).isNull(); + assertThat(params[2]).isEqualTo(context); + } } diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapperStandardEventsTest.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapperStandardEventsTest.java index 620d084a1b04..c25d911ed1cb 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapperStandardEventsTest.java +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/TracingRequestWrapperStandardEventsTest.java @@ -5,7 +5,7 @@ package io.opentelemetry.instrumentation.awslambdaevents.v2_2; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import com.amazonaws.services.lambda.runtime.Context; @@ -15,198 +15,215 @@ import com.amazonaws.services.lambda.runtime.events.SNSEvent; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.WrappedLambda; +import io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal.SerializationUtil; import io.opentelemetry.sdk.OpenTelemetrySdk; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; class TracingRequestWrapperStandardEventsTest { - private static final String SUCCESS = "success"; - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - private static final Map, String> EVENTS_JSON = buildEventExamples(); + private static final Map, EventInfo> EVENTS_JSON = buildEventExamples(); private final OpenTelemetrySdk sdk = OpenTelemetrySdk.builder().build(); private final Context context = mock(Context.class); private TracingRequestWrapper wrapper; - private static Map, String> buildEventExamples() { - Map, String> events = new HashMap<>(); + static final class EventInfo { + final Class eventType; + final String eventBody; + + EventInfo(Class eventType, String eventBody) { + this.eventType = eventType; + this.eventBody = eventBody; + } + } + + private static Map, EventInfo> buildEventExamples() { + Map, EventInfo> events = new HashMap<>(); events.put( ScheduledEventRequestHandler.class, - "{\n" - + " \"version\": \"0\",\n" - + " \"id\": \"53dc4d37-cffa-4f76-80c9-8b7d4a4d2eaa\",\n" - + " \"detail-type\": \"Scheduled Event\",\n" - + " \"source\": \"aws.events\",\n" - + " \"account\": \"123456789012\",\n" - + " \"time\": \"2015-10-08T16:53:06Z\",\n" - + " \"region\": \"us-east-1\",\n" - + " \"resources\": [\n" - + " \"arn:aws:events:us-east-1:123456789012:rule/my-scheduled-rule\"\n" - + " ],\n" - + " \"detail\": {}\n" - + "}"); + new EventInfo( + ScheduledEvent.class, + "{\n" + + " \"version\": \"0\",\n" + + " \"id\": \"53dc4d37-cffa-4f76-80c9-8b7d4a4d2eaa\",\n" + + " \"detail-type\": \"Scheduled Event\",\n" + + " \"source\": \"aws.events\",\n" + + " \"account\": \"123456789012\",\n" + + " \"time\": \"2015-10-08T16:53:06Z\",\n" + + " \"region\": \"us-east-1\",\n" + + " \"resources\": [\n" + + " \"arn:aws:events:us-east-1:123456789012:rule/my-scheduled-rule\"\n" + + " ],\n" + + " \"detail\": {}\n" + + "}")); events.put( KinesisEventRequestHandler.class, - "{\n" - + " \"Records\": [\n" - + " {\n" - + " \"kinesis\": {\n" - + " \"kinesisSchemaVersion\": \"1.0\",\n" - + " \"partitionKey\": \"1\",\n" - + " \"sequenceNumber\": \"49590338271490256608559692538361571095921575989136588898\",\n" - + " \"data\": \"SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==\",\n" - + " \"approximateArrivalTimestamp\": 1545084650.987\n" - + " },\n" - + " \"eventSource\": \"aws:kinesis\",\n" - + " \"eventVersion\": \"1.0\",\n" - + " \"eventID\": \"shardId-000000000006:49590338271490256608559692538361571095921575989136588898\",\n" - + " \"eventName\": \"aws:kinesis:record\",\n" - + " \"invokeIdentityArn\": \"arn:aws:iam::123456789012:role/lambda-role\",\n" - + " \"awsRegion\": \"us-east-2\",\n" - + " \"eventSourceARN\": \"arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream\"\n" - + " },\n" - + " {\n" - + " \"kinesis\": {\n" - + " \"kinesisSchemaVersion\": \"1.0\",\n" - + " \"partitionKey\": \"1\",\n" - + " \"sequenceNumber\": \"49590338271490256608559692540925702759324208523137515618\",\n" - + " \"data\": \"VGhpcyBpcyBvbmx5IGEgdGVzdC4=\",\n" - + " \"approximateArrivalTimestamp\": 1545084711.166\n" - + " },\n" - + " \"eventSource\": \"aws:kinesis\",\n" - + " \"eventVersion\": \"1.0\",\n" - + " \"eventID\": \"shardId-000000000006:49590338271490256608559692540925702759324208523137515618\",\n" - + " \"eventName\": \"aws:kinesis:record\",\n" - + " \"invokeIdentityArn\": \"arn:aws:iam::123456789012:role/lambda-role\",\n" - + " \"awsRegion\": \"us-east-2\",\n" - + " \"eventSourceARN\": \"arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream\"\n" - + " }\n" - + " ]\n" - + "}"); + new EventInfo( + KinesisEvent.class, + "{\n" + + " \"Records\": [\n" + + " {\n" + + " \"kinesis\": {\n" + + " \"kinesisSchemaVersion\": \"1.0\",\n" + + " \"partitionKey\": \"1\",\n" + + " \"sequenceNumber\": \"49590338271490256608559692538361571095921575989136588898\",\n" + + " \"data\": \"SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==\",\n" + + " \"approximateArrivalTimestamp\": 1545084650.987\n" + + " },\n" + + " \"eventSource\": \"aws:kinesis\",\n" + + " \"eventVersion\": \"1.0\",\n" + + " \"eventID\": \"shardId-000000000006:49590338271490256608559692538361571095921575989136588898\",\n" + + " \"eventName\": \"aws:kinesis:record\",\n" + + " \"invokeIdentityArn\": \"arn:aws:iam::123456789012:role/lambda-role\",\n" + + " \"awsRegion\": \"us-east-2\",\n" + + " \"eventSourceARN\": \"arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream\"\n" + + " },\n" + + " {\n" + + " \"kinesis\": {\n" + + " \"kinesisSchemaVersion\": \"1.0\",\n" + + " \"partitionKey\": \"1\",\n" + + " \"sequenceNumber\": \"49590338271490256608559692540925702759324208523137515618\",\n" + + " \"data\": \"VGhpcyBpcyBvbmx5IGEgdGVzdC4=\",\n" + + " \"approximateArrivalTimestamp\": 1545084711.166\n" + + " },\n" + + " \"eventSource\": \"aws:kinesis\",\n" + + " \"eventVersion\": \"1.0\",\n" + + " \"eventID\": \"shardId-000000000006:49590338271490256608559692540925702759324208523137515618\",\n" + + " \"eventName\": \"aws:kinesis:record\",\n" + + " \"invokeIdentityArn\": \"arn:aws:iam::123456789012:role/lambda-role\",\n" + + " \"awsRegion\": \"us-east-2\",\n" + + " \"eventSourceARN\": \"arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream\"\n" + + " }\n" + + " ]\n" + + "}")); events.put( SqsEventRequestHandler.class, - "{\n" - + " \"Records\": [\n" - + " {\n" - + " \"messageId\": \"059f36b4-87a3-44ab-83d2-661975830a7d\",\n" - + " \"receiptHandle\": \"AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...\",\n" - + " \"body\": \"Test message.\",\n" - + " \"attributes\": {\n" - + " \"ApproximateReceiveCount\": \"1\",\n" - + " \"SentTimestamp\": \"1545082649183\",\n" - + " \"SenderId\": \"AIDAIENQZJOLO23YVJ4VO\",\n" - + " \"ApproximateFirstReceiveTimestamp\": \"1545082649185\"\n" - + " },\n" - + " \"messageAttributes\": {},\n" - + " \"md5OfBody\": \"e4e68fb7bd0e697a0ae8f1bb342846b3\",\n" - + " \"eventSource\": \"aws:sqs\",\n" - + " \"eventSourceARN\": \"arn:aws:sqs:us-east-2:123456789012:my-queue\",\n" - + " \"awsRegion\": \"us-east-2\"\n" - + " },\n" - + " {\n" - + " \"messageId\": \"2e1424d4-f796-459a-8184-9c92662be6da\",\n" - + " \"receiptHandle\": \"AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...\",\n" - + " \"body\": \"Test message.\",\n" - + " \"attributes\": {\n" - + " \"ApproximateReceiveCount\": \"1\",\n" - + " \"SentTimestamp\": \"1545082650636\",\n" - + " \"SenderId\": \"AIDAIENQZJOLO23YVJ4VO\",\n" - + " \"ApproximateFirstReceiveTimestamp\": \"1545082650649\"\n" - + " },\n" - + " \"messageAttributes\": {},\n" - + " \"md5OfBody\": \"e4e68fb7bd0e697a0ae8f1bb342846b3\",\n" - + " \"eventSource\": \"aws:sqs\",\n" - + " \"eventSourceARN\": \"arn:aws:sqs:us-east-2:123456789012:my-queue\",\n" - + " \"awsRegion\": \"us-east-2\"\n" - + " }\n" - + " ]\n" - + "}"); + new EventInfo( + SQSEvent.class, + "{\n" + + " \"Records\": [\n" + + " {\n" + + " \"messageId\": \"059f36b4-87a3-44ab-83d2-661975830a7d\",\n" + + " \"receiptHandle\": \"AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...\",\n" + + " \"body\": \"Test message.\",\n" + + " \"attributes\": {\n" + + " \"ApproximateReceiveCount\": \"1\",\n" + + " \"SentTimestamp\": \"1545082649183\",\n" + + " \"SenderId\": \"AIDAIENQZJOLO23YVJ4VO\",\n" + + " \"ApproximateFirstReceiveTimestamp\": \"1545082649185\"\n" + + " },\n" + + " \"messageAttributes\": {},\n" + + " \"md5OfBody\": \"e4e68fb7bd0e697a0ae8f1bb342846b3\",\n" + + " \"eventSource\": \"aws:sqs\",\n" + + " \"eventSourceARN\": \"arn:aws:sqs:us-east-2:123456789012:my-queue\",\n" + + " \"awsRegion\": \"us-east-2\"\n" + + " },\n" + + " {\n" + + " \"messageId\": \"2e1424d4-f796-459a-8184-9c92662be6da\",\n" + + " \"receiptHandle\": \"AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...\",\n" + + " \"body\": \"Test message.\",\n" + + " \"attributes\": {\n" + + " \"ApproximateReceiveCount\": \"1\",\n" + + " \"SentTimestamp\": \"1545082650636\",\n" + + " \"SenderId\": \"AIDAIENQZJOLO23YVJ4VO\",\n" + + " \"ApproximateFirstReceiveTimestamp\": \"1545082650649\"\n" + + " },\n" + + " \"messageAttributes\": {},\n" + + " \"md5OfBody\": \"e4e68fb7bd0e697a0ae8f1bb342846b3\",\n" + + " \"eventSource\": \"aws:sqs\",\n" + + " \"eventSourceARN\": \"arn:aws:sqs:us-east-2:123456789012:my-queue\",\n" + + " \"awsRegion\": \"us-east-2\"\n" + + " }\n" + + " ]\n" + + "}")); events.put( S3EventRequestHandler.class, - "{\n" - + " \"Records\": [\n" - + " {\n" - + " \"eventVersion\": \"2.1\",\n" - + " \"eventSource\": \"aws:s3\",\n" - + " \"awsRegion\": \"us-east-2\",\n" - + " \"eventTime\": \"2019-09-03T19:37:27.192Z\",\n" - + " \"eventName\": \"ObjectCreated:Put\",\n" - + " \"userIdentity\": {\n" - + " \"principalId\": \"AWS:AIDAINPONIXQXHT3IKHL2\"\n" - + " },\n" - + " \"requestParameters\": {\n" - + " \"sourceIPAddress\": \"205.255.255.255\"\n" - + " },\n" - + " \"responseElements\": {\n" - + " \"x-amz-request-id\": \"D82B88E5F771F645\",\n" - + " \"x-amz-id-2\": \"vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo=\"\n" - + " },\n" - + " \"s3\": {\n" - + " \"s3SchemaVersion\": \"1.0\",\n" - + " \"configurationId\": \"828aa6fc-f7b5-4305-8584-487c791949c1\",\n" - + " \"bucket\": {\n" - + " \"name\": \"DOC-EXAMPLE-BUCKET\",\n" - + " \"ownerIdentity\": {\n" - + " \"principalId\": \"A3I5XTEXAMAI3E\"\n" - + " },\n" - + " \"arn\": \"arn:aws:s3:::lambda-artifacts-deafc19498e3f2df\"\n" - + " },\n" - + " \"object\": {\n" - + " \"key\": \"b21b84d653bb07b05b1e6b33684dc11b\",\n" - + " \"size\": 1305107,\n" - + " \"eTag\": \"b21b84d653bb07b05b1e6b33684dc11b\",\n" - + " \"sequencer\": \"0C0F6F405D6ED209E1\"\n" - + " }\n" - + " }\n" - + " }\n" - + " ]\n" - + "}"); + new EventInfo( + S3Event.class, + "{\n" + + " \"Records\": [\n" + + " {\n" + + " \"eventVersion\": \"2.1\",\n" + + " \"eventSource\": \"aws:s3\",\n" + + " \"awsRegion\": \"us-east-2\",\n" + + " \"eventTime\": \"2019-09-03T19:37:27.192Z\",\n" + + " \"eventName\": \"ObjectCreated:Put\",\n" + + " \"userIdentity\": {\n" + + " \"principalId\": \"AWS:AIDAINPONIXQXHT3IKHL2\"\n" + + " },\n" + + " \"requestParameters\": {\n" + + " \"sourceIPAddress\": \"205.255.255.255\"\n" + + " },\n" + + " \"responseElements\": {\n" + + " \"x-amz-request-id\": \"D82B88E5F771F645\",\n" + + " \"x-amz-id-2\": \"vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo=\"\n" + + " },\n" + + " \"s3\": {\n" + + " \"s3SchemaVersion\": \"1.0\",\n" + + " \"configurationId\": \"828aa6fc-f7b5-4305-8584-487c791949c1\",\n" + + " \"bucket\": {\n" + + " \"name\": \"DOC-EXAMPLE-BUCKET\",\n" + + " \"ownerIdentity\": {\n" + + " \"principalId\": \"A3I5XTEXAMAI3E\"\n" + + " },\n" + + " \"arn\": \"arn:aws:s3:::lambda-artifacts-deafc19498e3f2df\"\n" + + " },\n" + + " \"object\": {\n" + + " \"key\": \"b21b84d653bb07b05b1e6b33684dc11b\",\n" + + " \"size\": 1305107,\n" + + " \"eTag\": \"b21b84d653bb07b05b1e6b33684dc11b\",\n" + + " \"sequencer\": \"0C0F6F405D6ED209E1\"\n" + + " }\n" + + " }\n" + + " }\n" + + " ]\n" + + "}")); events.put( SnsEventRequestHandler.class, - "{\n" - + " \"Records\": [\n" - + " {\n" - + " \"EventVersion\": \"1.0\",\n" - + " \"EventSubscriptionArn\": \"arn:aws:sns:us-east-2:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486\",\n" - + " \"EventSource\": \"aws:sns\",\n" - + " \"Sns\": {\n" - + " \"SignatureVersion\": \"1\",\n" - + " \"Timestamp\": \"2019-01-02T12:45:07.000Z\",\n" - + " \"Signature\": \"tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==\",\n" - + " \"SigningCertUrl\": \"https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem\",\n" - + " \"MessageId\": \"95df01b4-ee98-5cb9-9903-4c221d41eb5e\",\n" - + " \"Message\": \"Hello from SNS!\",\n" - + " \"MessageAttributes\": {\n" - + " \"Test\": {\n" - + " \"Type\": \"String\",\n" - + " \"Value\": \"TestString\"\n" - + " },\n" - + " \"TestBinary\": {\n" - + " \"Type\": \"Binary\",\n" - + " \"Value\": \"TestBinary\"\n" - + " }\n" - + " },\n" - + " \"Type\": \"Notification\",\n" - + " \"UnsubscribeUrl\": \"https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486\",\n" - + " \"TopicArn\":\"arn:aws:sns:us-east-2:123456789012:sns-lambda\",\n" - + " \"Subject\": \"TestInvoke\"\n" - + " }\n" - + " }\n" - + " ]\n" - + "}"); - + new EventInfo( + SNSEvent.class, + "{\n" + + " \"Records\": [\n" + + " {\n" + + " \"EventVersion\": \"1.0\",\n" + + " \"EventSubscriptionArn\": \"arn:aws:sns:us-east-2:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486\",\n" + + " \"EventSource\": \"aws:sns\",\n" + + " \"Sns\": {\n" + + " \"SignatureVersion\": \"1\",\n" + + " \"Timestamp\": \"2019-01-02T12:45:07.000Z\",\n" + + " \"Signature\": \"tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==\",\n" + + " \"SigningCertUrl\": \"https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem\",\n" + + " \"MessageId\": \"95df01b4-ee98-5cb9-9903-4c221d41eb5e\",\n" + + " \"Message\": \"Hello from SNS!\",\n" + + " \"MessageAttributes\": {\n" + + " \"Test\": {\n" + + " \"Type\": \"String\",\n" + + " \"Value\": \"TestString\"\n" + + " },\n" + + " \"TestBinary\": {\n" + + " \"Type\": \"Binary\",\n" + + " \"Value\": \"TestBinary\"\n" + + " }\n" + + " },\n" + + " \"Type\": \"Notification\",\n" + + " \"UnsubscribeUrl\": \"https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486\",\n" + + " \"TopicArn\":\"arn:aws:sns:us-east-2:123456789012:sns-lambda\",\n" + + " \"Subject\": \"TestInvoke\"\n" + + " }\n" + + " }\n" + + " ]\n" + + "}")); return events; } private TracingRequestWrapper buildWrapper(Class targetClass) { WrappedLambda wrappedLambda = new WrappedLambda(targetClass, "handleRequest"); - return new TracingRequestWrapper(sdk, wrappedLambda, TracingRequestWrapper::map); + return new TracingRequestWrapper(sdk, wrappedLambda); } @ParameterizedTest @@ -218,46 +235,61 @@ private TracingRequestWrapper buildWrapper(Class targetClass) { S3EventRequestHandler.class, SnsEventRequestHandler.class }) - void handleScheduledEvent(Class targetClass) throws JsonProcessingException { + void handleLambdaEvent(Class targetClass) throws IOException { wrapper = buildWrapper(targetClass); - Object parsedScheduledEvent = - OBJECT_MAPPER.readValue(EVENTS_JSON.get(targetClass), Object.class); - assertEquals(SUCCESS, wrapper.doHandleRequest(parsedScheduledEvent, context)); + EventInfo eventInfo = EVENTS_JSON.get(targetClass); + + Object input = SerializationUtil.fromJson(eventInfo.eventBody, eventInfo.eventType); + + // Call to object based "O handleRequest(I input, Context context)" method + // delegates to the stream based + // "handleRequest(InputStream input, OutputStream output, Context context)" method. + // So serialization/deserialization of both input and outputs are triggered to be verified here. + Object output = wrapper.handleRequest(input, context); + + assertThat(input.getClass()).isEqualTo(output.getClass()); + + // "equals" methods are not properly implemented of Lambda events, + // so we are comparing them over their serialized json data + String inputJson = SerializationUtil.toJson(input); + String outputJson = SerializationUtil.toJson(output); + assertThat(inputJson).isEqualTo(outputJson); } public static class ScheduledEventRequestHandler - implements RequestHandler { + implements RequestHandler { @Override - public String handleRequest(ScheduledEvent i, Context cntxt) { - return SUCCESS; + public ScheduledEvent handleRequest(ScheduledEvent i, Context cntxt) { + return i; } } - public static class KinesisEventRequestHandler implements RequestHandler { + public static class KinesisEventRequestHandler + implements RequestHandler { @Override - public String handleRequest(KinesisEvent i, Context cntxt) { - return SUCCESS; + public KinesisEvent handleRequest(KinesisEvent i, Context cntxt) { + return i; } } - public static class SqsEventRequestHandler implements RequestHandler { + public static class SqsEventRequestHandler implements RequestHandler { @Override - public String handleRequest(SQSEvent i, Context cntxt) { - return SUCCESS; + public SQSEvent handleRequest(SQSEvent i, Context cntxt) { + return i; } } - public static class S3EventRequestHandler implements RequestHandler { + public static class S3EventRequestHandler implements RequestHandler { @Override - public String handleRequest(S3Event i, Context cntxt) { - return SUCCESS; + public S3Event handleRequest(S3Event i, Context cntxt) { + return i; } } - public static class SnsEventRequestHandler implements RequestHandler { + public static class SnsEventRequestHandler implements RequestHandler { @Override - public String handleRequest(SNSEvent i, Context cntxt) { - return SUCCESS; + public SNSEvent handleRequest(SNSEvent i, Context cntxt) { + return i; } } } diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/internal/SerializationUtilTest.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/internal/SerializationUtilTest.java new file mode 100644 index 000000000000..7711d15779c3 --- /dev/null +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/library/src/test/java/io/opentelemetry/instrumentation/awslambdaevents/v2_2/internal/SerializationUtilTest.java @@ -0,0 +1,359 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awslambdaevents.v2_2.internal; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.amazonaws.services.lambda.runtime.events.KinesisEvent; +import com.amazonaws.services.lambda.runtime.events.S3Event; +import com.amazonaws.services.lambda.runtime.events.SNSEvent; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; +import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import org.joda.time.DateTime; +import org.junit.jupiter.api.Test; + +public class SerializationUtilTest { + + private static final Map, String> events = buildEventExamples(); + + private static Map, String> buildEventExamples() { + Map, String> events = new HashMap<>(); + events.put( + ScheduledEvent.class, + "{\n" + + " \"version\": \"0\",\n" + + " \"id\": \"53dc4d37-cffa-4f76-80c9-8b7d4a4d2eaa\",\n" + + " \"detail-type\": \"Scheduled Event\",\n" + + " \"source\": \"aws.events\",\n" + + " \"account\": \"123456789012\",\n" + + " \"time\": \"2015-10-08T16:53:06Z\",\n" + + " \"region\": \"us-east-1\",\n" + + " \"resources\": [\n" + + " \"arn:aws:events:us-east-1:123456789012:rule/my-scheduled-rule\"\n" + + " ],\n" + + " \"detail\": {}\n" + + "}"); + events.put( + KinesisEvent.class, + "{\n" + + " \"Records\": [\n" + + " {\n" + + " \"kinesis\": {\n" + + " \"kinesisSchemaVersion\": \"1.0\",\n" + + " \"partitionKey\": \"1\",\n" + + " \"sequenceNumber\": \"49590338271490256608559692538361571095921575989136588898\",\n" + + " \"data\": \"SGVsbG8sIHRoaXMgaXMgYSB0ZXN0Lg==\",\n" + + " \"approximateArrivalTimestamp\": 1545084650.987\n" + + " },\n" + + " \"eventSource\": \"aws:kinesis\",\n" + + " \"eventVersion\": \"1.0\",\n" + + " \"eventID\": \"shardId-000000000006:49590338271490256608559692538361571095921575989136588898\",\n" + + " \"eventName\": \"aws:kinesis:record\",\n" + + " \"invokeIdentityArn\": \"arn:aws:iam::123456789012:role/lambda-role\",\n" + + " \"awsRegion\": \"us-east-2\",\n" + + " \"eventSourceARN\": \"arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream\"\n" + + " },\n" + + " {\n" + + " \"kinesis\": {\n" + + " \"kinesisSchemaVersion\": \"1.0\",\n" + + " \"partitionKey\": \"1\",\n" + + " \"sequenceNumber\": \"49590338271490256608559692540925702759324208523137515618\",\n" + + " \"data\": \"VGhpcyBpcyBvbmx5IGEgdGVzdC4=\",\n" + + " \"approximateArrivalTimestamp\": 1545084711.166\n" + + " },\n" + + " \"eventSource\": \"aws:kinesis\",\n" + + " \"eventVersion\": \"1.0\",\n" + + " \"eventID\": \"shardId-000000000006:49590338271490256608559692540925702759324208523137515618\",\n" + + " \"eventName\": \"aws:kinesis:record\",\n" + + " \"invokeIdentityArn\": \"arn:aws:iam::123456789012:role/lambda-role\",\n" + + " \"awsRegion\": \"us-east-2\",\n" + + " \"eventSourceARN\": \"arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream\"\n" + + " }\n" + + " ]\n" + + "}"); + events.put( + SQSEvent.class, + "{\n" + + " \"Records\": [\n" + + " {\n" + + " \"messageId\": \"059f36b4-87a3-44ab-83d2-661975830a7d\",\n" + + " \"receiptHandle\": \"AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...\",\n" + + " \"body\": \"Test message.\",\n" + + " \"attributes\": {\n" + + " \"ApproximateReceiveCount\": \"1\",\n" + + " \"SentTimestamp\": \"1545082649183\",\n" + + " \"SenderId\": \"AIDAIENQZJOLO23YVJ4VO\",\n" + + " \"ApproximateFirstReceiveTimestamp\": \"1545082649185\"\n" + + " },\n" + + " \"messageAttributes\": {},\n" + + " \"md5OfBody\": \"e4e68fb7bd0e697a0ae8f1bb342846b3\",\n" + + " \"eventSource\": \"aws:sqs\",\n" + + " \"eventSourceARN\": \"arn:aws:sqs:us-east-2:123456789012:my-queue\",\n" + + " \"awsRegion\": \"us-east-2\"\n" + + " },\n" + + " {\n" + + " \"messageId\": \"2e1424d4-f796-459a-8184-9c92662be6da\",\n" + + " \"receiptHandle\": \"AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...\",\n" + + " \"body\": \"Test message.\",\n" + + " \"attributes\": {\n" + + " \"ApproximateReceiveCount\": \"1\",\n" + + " \"SentTimestamp\": \"1545082650636\",\n" + + " \"SenderId\": \"AIDAIENQZJOLO23YVJ4VO\",\n" + + " \"ApproximateFirstReceiveTimestamp\": \"1545082650649\"\n" + + " },\n" + + " \"messageAttributes\": {},\n" + + " \"md5OfBody\": \"e4e68fb7bd0e697a0ae8f1bb342846b3\",\n" + + " \"eventSource\": \"aws:sqs\",\n" + + " \"eventSourceARN\": \"arn:aws:sqs:us-east-2:123456789012:my-queue\",\n" + + " \"awsRegion\": \"us-east-2\"\n" + + " }\n" + + " ]\n" + + "}"); + events.put( + S3Event.class, + "{\n" + + " \"Records\": [\n" + + " {\n" + + " \"eventVersion\": \"2.1\",\n" + + " \"eventSource\": \"aws:s3\",\n" + + " \"awsRegion\": \"us-east-2\",\n" + + " \"eventTime\": \"2019-09-03T19:37:27.192Z\",\n" + + " \"eventName\": \"ObjectCreated:Put\",\n" + + " \"userIdentity\": {\n" + + " \"principalId\": \"AWS:AIDAINPONIXQXHT3IKHL2\"\n" + + " },\n" + + " \"requestParameters\": {\n" + + " \"sourceIPAddress\": \"205.255.255.255\"\n" + + " },\n" + + " \"responseElements\": {\n" + + " \"x-amz-request-id\": \"D82B88E5F771F645\",\n" + + " \"x-amz-id-2\": \"vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo=\"\n" + + " },\n" + + " \"s3\": {\n" + + " \"s3SchemaVersion\": \"1.0\",\n" + + " \"configurationId\": \"828aa6fc-f7b5-4305-8584-487c791949c1\",\n" + + " \"bucket\": {\n" + + " \"name\": \"DOC-EXAMPLE-BUCKET\",\n" + + " \"ownerIdentity\": {\n" + + " \"principalId\": \"A3I5XTEXAMAI3E\"\n" + + " },\n" + + " \"arn\": \"arn:aws:s3:::lambda-artifacts-deafc19498e3f2df\"\n" + + " },\n" + + " \"object\": {\n" + + " \"key\": \"b21b84d653bb07b05b1e6b33684dc11b\",\n" + + " \"size\": 1305107,\n" + + " \"eTag\": \"b21b84d653bb07b05b1e6b33684dc11b\",\n" + + " \"sequencer\": \"0C0F6F405D6ED209E1\"\n" + + " }\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"); + events.put( + SNSEvent.class, + "{\n" + + " \"Records\": [\n" + + " {\n" + + " \"EventVersion\": \"1.0\",\n" + + " \"EventSubscriptionArn\": \"arn:aws:sns:us-east-2:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486\",\n" + + " \"EventSource\": \"aws:sns\",\n" + + " \"Sns\": {\n" + + " \"SignatureVersion\": \"1\",\n" + + " \"Timestamp\": \"2019-01-02T12:45:07.000Z\",\n" + + " \"Signature\": \"tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==\",\n" + + " \"SigningCertUrl\": \"https://sns.us-east-2.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem\",\n" + + " \"MessageId\": \"95df01b4-ee98-5cb9-9903-4c221d41eb5e\",\n" + + " \"Message\": \"Hello from SNS!\",\n" + + " \"MessageAttributes\": {\n" + + " \"Test\": {\n" + + " \"Type\": \"String\",\n" + + " \"Value\": \"TestString\"\n" + + " },\n" + + " \"TestBinary\": {\n" + + " \"Type\": \"Binary\",\n" + + " \"Value\": \"TestBinary\"\n" + + " }\n" + + " },\n" + + " \"Type\": \"Notification\",\n" + + " \"UnsubscribeUrl\": \"https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486\",\n" + + " \"TopicArn\":\"arn:aws:sns:us-east-2:123456789012:sns-lambda\",\n" + + " \"Subject\": \"TestInvoke\"\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"); + return events; + } + + private static void assertScheduledEvent(ScheduledEvent event) { + assertThat(event).isNotNull(); + assertThat(event.getSource()).isEqualTo("aws.events"); + assertThat(event.getDetailType()).isEqualTo("Scheduled Event"); + assertThat(event.getAccount()).isEqualTo("123456789012"); + assertThat(event.getId()).isEqualTo("53dc4d37-cffa-4f76-80c9-8b7d4a4d2eaa"); + assertThat(event.getRegion()).isEqualTo("us-east-1"); + assertThat(event.getTime().getMillis()) + .isEqualTo(new DateTime("2015-10-08T16:53:06Z").getMillis()); + } + + private static void assertKinesisEvent(KinesisEvent event) { + assertThat(event).isNotNull(); + assertThat(event.getRecords()).isNotNull(); + assertThat(event.getRecords().size()).isEqualTo(2); + KinesisEvent.KinesisEventRecord record = event.getRecords().get(0); + assertThat(record.getEventSource()).isEqualTo("aws:kinesis"); + assertThat(record.getEventSourceARN()) + .isEqualTo("arn:aws:kinesis:us-east-2:123456789012:stream/lambda-stream"); + assertThat(record.getEventName()).isEqualTo("aws:kinesis:record"); + assertThat(record.getEventID()) + .isEqualTo("shardId-000000000006:49590338271490256608559692538361571095921575989136588898"); + assertThat(record.getKinesis().getPartitionKey()).isEqualTo("1"); + assertThat(record.getKinesis().getSequenceNumber()) + .isEqualTo("49590338271490256608559692538361571095921575989136588898"); + assertThat(new String(record.getKinesis().getData().array(), StandardCharsets.UTF_8)) + .isEqualTo("Hello, this is a test."); + } + + private static void assertSqsEvent(SQSEvent event) { + assertThat(event).isNotNull(); + assertThat(event.getRecords()).isNotNull(); + assertThat(event.getRecords().size()).isEqualTo(2); + SQSEvent.SQSMessage record = event.getRecords().get(0); + assertThat(record.getEventSource()).isEqualTo("aws:sqs"); + assertThat(record.getEventSourceArn()).isEqualTo("arn:aws:sqs:us-east-2:123456789012:my-queue"); + assertThat(record.getMessageId()).isEqualTo("059f36b4-87a3-44ab-83d2-661975830a7d"); + assertThat(record.getBody()).isEqualTo("Test message."); + assertThat(record.getMd5OfBody()).isEqualTo("e4e68fb7bd0e697a0ae8f1bb342846b3"); + assertThat(record.getReceiptHandle()).isEqualTo("AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a..."); + } + + private static void assertS3Event(S3Event event) { + assertThat(event).isNotNull(); + assertThat(event.getRecords()).isNotNull(); + assertThat(event.getRecords().size()).isEqualTo(1); + S3EventNotification.S3EventNotificationRecord record = event.getRecords().get(0); + assertThat(record.getEventSource()).isEqualTo("aws:s3"); + assertThat(record.getEventName()).isEqualTo("ObjectCreated:Put"); + assertThat(record.getS3().getBucket().getName()).isEqualTo("DOC-EXAMPLE-BUCKET"); + assertThat(record.getS3().getBucket().getArn()) + .isEqualTo("arn:aws:s3:::lambda-artifacts-deafc19498e3f2df"); + assertThat(record.getS3().getObject().getKey()).isEqualTo("b21b84d653bb07b05b1e6b33684dc11b"); + } + + private static void assertSnsEvent(SNSEvent event) { + assertThat(event).isNotNull(); + assertThat(event.getRecords()).isNotNull(); + assertThat(event.getRecords().size()).isEqualTo(1); + SNSEvent.SNSRecord record = event.getRecords().get(0); + assertThat(record.getEventSource()).isEqualTo("aws:sns"); + assertThat(record.getEventSubscriptionArn()) + .isEqualTo( + "arn:aws:sns:us-east-2:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486"); + assertThat(record.getSNS().getMessageId()).isEqualTo("95df01b4-ee98-5cb9-9903-4c221d41eb5e"); + assertThat(record.getSNS().getMessage()).isEqualTo("Hello from SNS!"); + assertThat(record.getSNS().getType()).isEqualTo("Notification"); + assertThat(record.getSNS().getTopicArn()) + .isEqualTo("arn:aws:sns:us-east-2:123456789012:sns-lambda"); + assertThat(record.getSNS().getSubject()).isEqualTo("TestInvoke"); + } + + @Test + void scheduledEventDeserializedFromStringJson() { + String eventBody = events.get(ScheduledEvent.class); + ScheduledEvent event = SerializationUtil.fromJson(eventBody, ScheduledEvent.class); + + assertScheduledEvent(event); + } + + @Test + void scheduledEventDeserializedFromInputStreamJson() { + String eventBody = events.get(ScheduledEvent.class); + ScheduledEvent event = + SerializationUtil.fromJson( + new ByteArrayInputStream(eventBody.getBytes(StandardCharsets.UTF_8)), + ScheduledEvent.class); + + assertScheduledEvent(event); + } + + @Test + void kinesisEventDeserializedFromStringJson() { + String eventBody = events.get(KinesisEvent.class); + KinesisEvent event = SerializationUtil.fromJson(eventBody, KinesisEvent.class); + + assertKinesisEvent(event); + } + + @Test + void kinesisEventDeserializedFromInputStreamJson() { + String eventBody = events.get(KinesisEvent.class); + KinesisEvent event = + SerializationUtil.fromJson( + new ByteArrayInputStream(eventBody.getBytes(StandardCharsets.UTF_8)), + KinesisEvent.class); + + assertKinesisEvent(event); + } + + @Test + void sqsEventDeserializedFromStringJson() { + String eventBody = events.get(SQSEvent.class); + SQSEvent event = SerializationUtil.fromJson(eventBody, SQSEvent.class); + + assertSqsEvent(event); + } + + @Test + void sqsEventDeserializedFromInputStreamJson() { + String eventBody = events.get(SQSEvent.class); + SQSEvent event = + SerializationUtil.fromJson( + new ByteArrayInputStream(eventBody.getBytes(StandardCharsets.UTF_8)), SQSEvent.class); + + assertSqsEvent(event); + } + + @Test + void s3EventDeserializedFromStringJson() { + String eventBody = events.get(S3Event.class); + S3Event event = SerializationUtil.fromJson(eventBody, S3Event.class); + + assertS3Event(event); + } + + @Test + void s3EventDeserializedFromInputStreamJson() { + String eventBody = events.get(S3Event.class); + S3Event event = + SerializationUtil.fromJson( + new ByteArrayInputStream(eventBody.getBytes(StandardCharsets.UTF_8)), S3Event.class); + + assertS3Event(event); + } + + @Test + void snsEventDeserializedFromStringJson() { + String eventBody = events.get(SNSEvent.class); + SNSEvent event = SerializationUtil.fromJson(eventBody, SNSEvent.class); + + assertSnsEvent(event); + } + + @Test + void snsEventDeserializedFromInputStreamJson() { + String eventBody = events.get(SNSEvent.class); + SNSEvent event = + SerializationUtil.fromJson( + new ByteArrayInputStream(eventBody.getBytes(StandardCharsets.UTF_8)), SNSEvent.class); + + assertSnsEvent(event); + } +} diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/testing/build.gradle.kts b/instrumentation/aws-lambda/aws-lambda-events-2.2/testing/build.gradle.kts index 8d7e6c135dce..9eb92feeae0f 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-2.2/testing/build.gradle.kts +++ b/instrumentation/aws-lambda/aws-lambda-events-2.2/testing/build.gradle.kts @@ -13,8 +13,6 @@ dependencies { implementation("com.google.guava:guava") - implementation("org.apache.groovy:groovy") implementation("io.opentelemetry:opentelemetry-api") - implementation("org.spockframework:spock-core") implementation("com.github.stefanbirkner:system-lambda") } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java index a3aa56398c7d..ff02429b910c 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java @@ -12,12 +12,14 @@ import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; // TODO: Copy & paste with only trivial adaptions from v2 -abstract class AbstractAwsSdkInstrumentationModule extends InstrumentationModule { +abstract class AbstractAwsSdkInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { protected AbstractAwsSdkInstrumentationModule(String additionalInstrumentationName) { super("aws-sdk", "aws-sdk-1.11", additionalInstrumentationName); @@ -29,8 +31,8 @@ public boolean isHelperClass(String className) { } @Override - public boolean isIndyModule() { - return false; + public String getModuleGroup() { + return "aws-sdk"; } @Override 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..89a4a6c8f673 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 @@ -10,10 +10,12 @@ import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; @AutoService(InstrumentationModule.class) -public class AwsSdkInstrumentationModule extends InstrumentationModule { +public class AwsSdkInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public AwsSdkInstrumentationModule() { super("aws-sdk", "aws-sdk-1.11", "aws-sdk-1.11-core"); } @@ -24,8 +26,8 @@ public boolean isHelperClass(String className) { } @Override - public boolean isIndyModule() { - return false; + public String getModuleGroup() { + return "aws-sdk"; } @Override diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/TracingRequestHandler.java index dee44d73f0b8..872c7303507a 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/TracingRequestHandler.java @@ -14,8 +14,8 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.awssdk.v1_11.AwsSdkTelemetry; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; /** * A {@link RequestHandler2} for use in the agent. Unlike library instrumentation, the agent will @@ -36,7 +36,7 @@ public class TracingRequestHandler extends RequestHandler2 { public static final RequestHandler2 tracingHandler = AwsSdkTelemetry.builder(GlobalOpenTelemetry.get()) .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.aws-sdk.experimental-span-attributes", false)) .setMessagingReceiveInstrumentationEnabled( ExperimentalConfig.get().messagingReceiveInstrumentationEnabled()) 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 4cfaae6135b2..9f83480f5511 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 @@ -13,6 +13,7 @@ muzzle { excludeInstrumentationName("aws-sdk-2.2-sqs") excludeInstrumentationName("aws-sdk-2.2-sns") + excludeInstrumentationName("aws-sdk-2.2-lambda") // several software.amazon.awssdk artifacts are missing for this version skip("2.17.200") @@ -43,6 +44,7 @@ muzzle { extraDependency("software.amazon.awssdk:protocol-core") excludeInstrumentationName("aws-sdk-2.2-sns") + excludeInstrumentationName("aws-sdk-2.2-lambda") // several software.amazon.awssdk artifacts are missing for this version skip("2.17.200") @@ -57,6 +59,21 @@ muzzle { extraDependency("software.amazon.awssdk:protocol-core") excludeInstrumentationName("aws-sdk-2.2-sqs") + excludeInstrumentationName("aws-sdk-2.2-lambda") + + // several software.amazon.awssdk artifacts are missing for this version + skip("2.17.200") + } + pass { + group.set("software.amazon.awssdk") + module.set("lambda") + versions.set("[2.17.0,)") + // Used by all SDK services, the only case it isn't is an SDK extension such as a custom HTTP + // client, which is not target of instrumentation anyways. + extraDependency("software.amazon.awssdk:protocol-core") + + excludeInstrumentationName("aws-sdk-2.2-sqs") + excludeInstrumentationName("aws-sdk-2.2-sns") // several software.amazon.awssdk artifacts are missing for this version skip("2.17.200") @@ -81,6 +98,7 @@ dependencies { testLibrary("software.amazon.awssdk:dynamodb:2.2.0") testLibrary("software.amazon.awssdk:ec2:2.2.0") testLibrary("software.amazon.awssdk:kinesis:2.2.0") + testLibrary("software.amazon.awssdk:lambda:2.2.0") testLibrary("software.amazon.awssdk:rds:2.2.0") testLibrary("software.amazon.awssdk:s3:2.2.0") testLibrary("software.amazon.awssdk:sqs:2.2.0") diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/LambdaAdviceBridge.java b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/LambdaAdviceBridge.java new file mode 100644 index 000000000000..3aaa17525137 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/LambdaAdviceBridge.java @@ -0,0 +1,15 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2; + +public final class LambdaAdviceBridge { + private LambdaAdviceBridge() {} + + public static void referenceForMuzzleOnly() { + throw new UnsupportedOperationException( + LambdaImpl.class.getName() + " referencing for muzzle, should never be actually called"); + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/LambdaInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/LambdaInstrumentationModule.java new file mode 100644 index 000000000000..575bb5ec7fbc --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/LambdaInstrumentationModule.java @@ -0,0 +1,47 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2; + +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; +import static net.bytebuddy.matcher.ElementMatchers.none; + +import com.google.auto.service.AutoService; +import io.opentelemetry.instrumentation.awssdk.v2_2.LambdaAdviceBridge; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.matcher.ElementMatcher; + +@AutoService(InstrumentationModule.class) +public class LambdaInstrumentationModule extends AbstractAwsSdkInstrumentationModule { + + public LambdaInstrumentationModule() { + super("aws-sdk-2.2-lambda"); + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + return hasClassesNamed( + "software.amazon.awssdk.services.lambda.model.InvokeRequest", + "software.amazon.awssdk.protocols.jsoncore.JsonNode"); + } + + @Override + public void doTransform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + none(), LambdaInstrumentationModule.class.getName() + "$RegisterAdvice"); + } + + @SuppressWarnings("unused") + public static class RegisterAdvice { + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit() { + // (indirectly) using LambdaImpl class here to make sure it is available from LambdaAccess + // (injected into app classloader) and checked by Muzzle + LambdaAdviceBridge.referenceForMuzzleOnly(); + } + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/Aws2LambdaTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/Aws2LambdaTest.java new file mode 100644 index 000000000000..0991e804956e --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/Aws2LambdaTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2; + +import io.opentelemetry.instrumentation.awssdk.v2_2.AbstractAws2LambdaTest; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.junit.jupiter.api.extension.RegisterExtension; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; + +class Aws2LambdaTest extends AbstractAws2LambdaTest { + + @RegisterExtension + private static final AgentInstrumentationExtension testing = + AgentInstrumentationExtension.create(); + + @Override + protected InstrumentationExtension getTesting() { + return testing; + } + + @Override + protected boolean canTestLambdaInvoke() { + // only supported since 2.17.0 + return Boolean.getBoolean("testLatestDeps"); + } + + @Override + protected ClientOverrideConfiguration.Builder createOverrideConfigurationBuilder() { + return ClientOverrideConfiguration.builder(); + } +} 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 94e90a82ff61..7f621f4977d2 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 @@ -17,13 +17,11 @@ dependencies { testLibrary("software.amazon.awssdk:dynamodb:2.2.0") testLibrary("software.amazon.awssdk:ec2:2.2.0") testLibrary("software.amazon.awssdk:kinesis:2.2.0") + testLibrary("software.amazon.awssdk:lambda:2.2.0") testLibrary("software.amazon.awssdk:rds:2.2.0") testLibrary("software.amazon.awssdk:s3:2.2.0") testLibrary("software.amazon.awssdk:sqs:2.2.0") testLibrary("software.amazon.awssdk:sns:2.2.0") - - // last version that does not use json protocol - latestDepTestLibrary("software.amazon.awssdk:sqs:2.21.17") } tasks { @@ -31,5 +29,6 @@ tasks { systemProperty("otel.instrumentation.aws-sdk.experimental-span-attributes", true) systemProperty("otel.instrumentation.aws-sdk.experimental-record-individual-http-error", true) systemProperty("otel.instrumentation.messaging.experimental.capture-headers", "test-message-header") + systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) } } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java index b4870cf3edda..dddb124eb938 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/AwsSdkSingletons.java @@ -10,8 +10,8 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import java.util.List; public final class AwsSdkSingletons { @@ -28,7 +28,7 @@ public final class AwsSdkSingletons { private static boolean hasAgentConfiguration() { try { - Class.forName("io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig"); + Class.forName("io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig"); return true; } catch (ClassNotFoundException e) { return false; @@ -69,7 +69,7 @@ private static boolean recordIndividualHttpError() { private static boolean getBoolean(String name, boolean defaultValue) { if (HAS_INSTRUMENTATION_CONFIG) { - return InstrumentationConfig.get().getBoolean(name, defaultValue); + return AgentInstrumentationConfig.get().getBoolean(name, defaultValue); } else { return ConfigPropertiesUtil.getBoolean(name, defaultValue); } 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 862df156ae14..e4be5bdfe30a 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 @@ -7,8 +7,11 @@ dependencies { library("software.amazon.awssdk:aws-core:2.2.0") library("software.amazon.awssdk:sqs:2.2.0") + library("software.amazon.awssdk:lambda:2.2.0") library("software.amazon.awssdk:sns:2.2.0") library("software.amazon.awssdk:aws-json-protocol:2.2.0") + // json-utils was added in 2.17.0 + compileOnly("software.amazon.awssdk:json-utils:2.17.0") compileOnly(project(":muzzle")) // For @NoMuzzle testImplementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:testing")) @@ -38,10 +41,24 @@ testing { implementation("software.amazon.awssdk:aws-core:+") implementation("software.amazon.awssdk:aws-json-protocol:+") implementation("software.amazon.awssdk:dynamodb:+") + implementation("software.amazon.awssdk:lambda:+") } else { implementation("software.amazon.awssdk:aws-core:2.2.0") implementation("software.amazon.awssdk:aws-json-protocol:2.2.0") implementation("software.amazon.awssdk:dynamodb:2.2.0") + implementation("software.amazon.awssdk:lambda:2.2.0") + } + } + } + + val testLambda by registering(JvmTestSuite::class) { + dependencies { + implementation(project()) + implementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:testing")) + if (findProperty("testLatestDeps") as Boolean) { + implementation("software.amazon.awssdk:lambda:+") + } else { + implementation("software.amazon.awssdk:lambda:2.17.0") } } } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/LambdaAccess.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/LambdaAccess.java new file mode 100644 index 000000000000..33d792c0c826 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/LambdaAccess.java @@ -0,0 +1,21 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2; + +import io.opentelemetry.context.Context; +import io.opentelemetry.javaagent.tooling.muzzle.NoMuzzle; +import software.amazon.awssdk.core.SdkRequest; + +final class LambdaAccess { + private LambdaAccess() {} + + private static final boolean enabled = PluginImplUtil.isImplPresent("LambdaImpl"); + + @NoMuzzle + public static SdkRequest modifyRequest(SdkRequest request, Context otelContext) { + return enabled ? LambdaImpl.modifyRequest(request, otelContext) : null; + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/LambdaImpl.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/LambdaImpl.java new file mode 100644 index 000000000000..fae5edf5e12a --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/LambdaImpl.java @@ -0,0 +1,102 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Nullable; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.protocols.jsoncore.JsonNode; +import software.amazon.awssdk.protocols.jsoncore.internal.ObjectJsonNode; +import software.amazon.awssdk.protocols.jsoncore.internal.StringJsonNode; +import software.amazon.awssdk.services.lambda.model.InvokeRequest; + +// this class is only used from LambdaAccess from method with @NoMuzzle annotation + +// Direct lambda invocations (e.g., not through an api gateway) currently strip +// away the otel propagation headers (but leave x-ray ones intact). Use the +// custom client context header as an additional propagation mechanism for this +// very specific scenario. For reference, the header is named "X-Amz-Client-Context" but the api to +// manipulate it abstracts that away. The client context field is documented in +// https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html#API_Invoke_RequestParameters + +final class LambdaImpl { + static { + // Force loading of InvokeRequest; this ensures that an exception is thrown at this point when + // the Lambda library is not present, which will cause DirectLambdaAccess to have + // enabled=false in library mode. + @SuppressWarnings("unused") + String invokeRequestName = InvokeRequest.class.getName(); + // was added in 2.17.0 + @SuppressWarnings("unused") + String jsonNodeName = JsonNode.class.getName(); + } + + private static final String CLIENT_CONTEXT_CUSTOM_FIELDS_KEY = "custom"; + static final int MAX_CLIENT_CONTEXT_LENGTH = 3583; // visible for testing + + private LambdaImpl() {} + + @Nullable + static SdkRequest modifyRequest( + SdkRequest request, io.opentelemetry.context.Context otelContext) { + if (isDirectLambdaInvocation(request)) { + return modifyOrAddCustomContextHeader((InvokeRequest) request, otelContext); + } + return null; + } + + static boolean isDirectLambdaInvocation(SdkRequest request) { + return request instanceof InvokeRequest; + } + + static SdkRequest modifyOrAddCustomContextHeader( + InvokeRequest request, io.opentelemetry.context.Context otelContext) { + InvokeRequest.Builder builder = request.toBuilder(); + // Unfortunately the value of this thing is a base64-encoded json with a character limit; also + // therefore not comma-composable like many http headers + String clientContextString = request.clientContext(); + String clientContextJsonString = "{}"; + if (clientContextString != null && !clientContextString.isEmpty()) { + clientContextJsonString = + new String(Base64.getDecoder().decode(clientContextString), StandardCharsets.UTF_8); + } + JsonNode jsonNode = JsonNode.parser().parse(clientContextJsonString); + if (!jsonNode.isObject()) { + return null; + } + JsonNode customNode = + jsonNode + .asObject() + .computeIfAbsent( + CLIENT_CONTEXT_CUSTOM_FIELDS_KEY, (k) -> new ObjectJsonNode(new LinkedHashMap<>())); + if (!customNode.isObject()) { + return null; + } + Map map = customNode.asObject(); + GlobalOpenTelemetry.getPropagators() + .getTextMapPropagator() + .inject(otelContext, map, (nodes, key, value) -> nodes.put(key, new StringJsonNode(value))); + if (map.isEmpty()) { + return null; + } + + // turn it back into a string (json encode) + String newJson = jsonNode.toString(); + + // turn it back into a base64 string + String newJson64 = Base64.getEncoder().encodeToString(newJson.getBytes(StandardCharsets.UTF_8)); + // check it for length (err on the safe side with >=) + if (newJson64.length() >= MAX_CLIENT_CONTEXT_LENGTH) { + return null; + } + builder.clientContext(newJson64); + return builder.build(); + } +} 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 4b718e0abc40..ada21457d45b 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 @@ -212,6 +212,10 @@ public SdkRequest modifyRequest( if (modifiedRequest != null) { return modifiedRequest; } + modifiedRequest = LambdaAccess.modifyRequest(request, otelContext); + if (modifiedRequest != null) { + return modifiedRequest; + } // Insert other special handling here, following the same pattern as SQS and SNS. diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/FieldMapperTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/FieldMapperTest.java index 756d09ef61d6..0e8309d6e059 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/FieldMapperTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/FieldMapperTest.java @@ -16,7 +16,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Test; import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemRequest; import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemResponse; import software.amazon.awssdk.services.dynamodb.model.ConsumedCapacity; @@ -25,11 +25,10 @@ import software.amazon.awssdk.services.dynamodb.model.UpdateTableRequest; import software.amazon.awssdk.services.dynamodb.model.WriteRequest; -public class FieldMapperTest { +class FieldMapperTest { @Test - public void shouldMapNestedField() { - + void shouldMapNestedField() { // given AwsSdkRequest awsSdkRequest = UpdateTable; MethodHandleFactory methodHandleFactory = new MethodHandleFactory(); @@ -56,8 +55,7 @@ public void shouldMapNestedField() { } @Test - public void shouldMapRequestFieldsOnly() { - + void shouldMapRequestFieldsOnly() { // given AwsSdkRequest awsSdkRequest = BatchWriteItem; MethodHandleFactory methodHandleFactory = new MethodHandleFactory(); @@ -76,8 +74,7 @@ public void shouldMapRequestFieldsOnly() { } @Test - public void shouldMapResponseFieldsOnly() { - + void shouldMapResponseFieldsOnly() { // given AwsSdkRequest awsSdkRequest = BatchWriteItem; MethodHandleFactory methodHandleFactory = new MethodHandleFactory(); diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/QueryProtocolModelTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/QueryProtocolModelTest.java index d5ab73e541da..f18f75f5948f 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/QueryProtocolModelTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/QueryProtocolModelTest.java @@ -12,7 +12,8 @@ class QueryProtocolModelTest extends AbstractQueryProtocolModelTest { @RegisterExtension - public final LibraryInstrumentationExtension testing = LibraryInstrumentationExtension.create(); + private static final LibraryInstrumentationExtension testing = + LibraryInstrumentationExtension.create(); @Override protected ClientOverrideConfiguration.Builder createClientOverrideConfigurationBuilder() { diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SerializerTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SerializerTest.java index aa267e524041..b2616dcaddc2 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SerializerTest.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v2_2/SerializerTest.java @@ -13,14 +13,14 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Test; import software.amazon.awssdk.core.SdkPojo; import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; -public class SerializerTest { +class SerializerTest { @Test - public void shouldSerializeSimpleString() { + void shouldSerializeSimpleString() { // given // when String serialized = new Serializer().serialize("simpleString"); @@ -29,7 +29,7 @@ public void shouldSerializeSimpleString() { } @Test - public void shouldSerializeSdkPojo() { + void shouldSerializeSdkPojo() { // given SdkPojo sdkPojo = ProvisionedThroughput.builder().readCapacityUnits(1L).writeCapacityUnits(2L).build(); @@ -40,7 +40,7 @@ public void shouldSerializeSdkPojo() { } @Test - public void shouldSerializeCollection() { + void shouldSerializeCollection() { // given List collection = Arrays.asList("one", "two", "three"); // when @@ -50,7 +50,7 @@ public void shouldSerializeCollection() { } @Test - public void shouldSerializeEmptyCollectionAsNull() { + void shouldSerializeEmptyCollectionAsNull() { // given List collection = Collections.emptyList(); // when @@ -60,7 +60,7 @@ public void shouldSerializeEmptyCollectionAsNull() { } @Test - public void shouldSerializeMapAsKeyCollection() { + void shouldSerializeMapAsKeyCollection() { // given Map map = new HashMap<>(); map.put("uno", 1L); diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/testLambda/java/io/opentelemetry/instrumentation/awssdk/v2_2/Aws2LambdaTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/testLambda/java/io/opentelemetry/instrumentation/awssdk/v2_2/Aws2LambdaTest.java new file mode 100644 index 000000000000..3bfe7788e066 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/testLambda/java/io/opentelemetry/instrumentation/awssdk/v2_2/Aws2LambdaTest.java @@ -0,0 +1,107 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.services.lambda.model.InvokeRequest; + +class Aws2LambdaTest extends AbstractAws2LambdaTest { + + @RegisterExtension + private static final LibraryInstrumentationExtension testing = + LibraryInstrumentationExtension.create(); + + private static Context context; + private static AwsSdkTelemetry telemetry; + + @BeforeAll + static void setup() { + testing.runWithHttpServerSpan( + () -> { + context = Context.current(); + }); + + telemetry = AwsSdkTelemetry.create(testing.getOpenTelemetry()); + } + + @Override + protected InstrumentationExtension getTesting() { + return testing; + } + + @Override + protected ClientOverrideConfiguration.Builder createOverrideConfigurationBuilder() { + return ClientOverrideConfiguration.builder() + .addExecutionInterceptor(telemetry.newExecutionInterceptor()); + } + + private static String base64ify(String json) { + return Base64.getEncoder().encodeToString(json.getBytes(StandardCharsets.UTF_8)); + } + + @Test + void noExistingClientContext() { + InvokeRequest request = InvokeRequest.builder().build(); + + InvokeRequest newRequest = + (InvokeRequest) LambdaImpl.modifyOrAddCustomContextHeader(request, context); + + String newClientContext = newRequest.clientContext(); + newClientContext = + new String(Base64.getDecoder().decode(newClientContext), StandardCharsets.UTF_8); + assertThat(newClientContext.contains("traceparent")).isTrue(); + } + + @Test + void withExistingClientContext() { + String clientContext = + base64ify( + "{\"otherStuff\": \"otherValue\", \"custom\": {\"preExisting\": \"somevalue\"} }"); + InvokeRequest request = InvokeRequest.builder().clientContext(clientContext).build(); + + InvokeRequest newRequest = + (InvokeRequest) LambdaImpl.modifyOrAddCustomContextHeader(request, context); + + String newClientContext = newRequest.clientContext(); + newClientContext = + new String(Base64.getDecoder().decode(newClientContext), StandardCharsets.UTF_8); + assertThat(newClientContext.contains("traceparent")).isTrue(); + assertThat(newClientContext.contains("preExisting")).isTrue(); + assertThat(newClientContext.contains("otherStuff")).isTrue(); + } + + @Test + void exceedingMaximumLengthDoesNotModify() { + // awkward way to build a valid json that is almost but not quite too long + StringBuilder buffer = new StringBuilder("x"); + String long64edClientContext = ""; + while (true) { + buffer.append("x"); + String newClientContext = base64ify("{\"" + buffer + "\": \"" + buffer + "\"}"); + if (newClientContext.length() >= LambdaImpl.MAX_CLIENT_CONTEXT_LENGTH) { + break; + } + long64edClientContext = newClientContext; + } + + InvokeRequest request = InvokeRequest.builder().clientContext(long64edClientContext).build(); + assertThat(request.clientContext().equals(long64edClientContext)).isTrue(); + + InvokeRequest newRequest = + (InvokeRequest) LambdaImpl.modifyOrAddCustomContextHeader(request, context); + assertThat(newRequest).isNull(); // null return means no modification performed + } +} 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 9981aa9a1965..f9c0791bd205 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 @@ -14,6 +14,7 @@ dependencies { compileOnly("software.amazon.awssdk:dynamodb:2.2.0") compileOnly("software.amazon.awssdk:ec2:2.2.0") compileOnly("software.amazon.awssdk:kinesis:2.2.0") + compileOnly("software.amazon.awssdk:lambda:2.2.0") compileOnly("software.amazon.awssdk:rds:2.2.0") compileOnly("software.amazon.awssdk:s3:2.2.0") compileOnly("software.amazon.awssdk:sqs:2.2.0") diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2LambdaTest.java b/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2LambdaTest.java new file mode 100644 index 000000000000..64c8a48a6c77 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2LambdaTest.java @@ -0,0 +1,78 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +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.nio.charset.StandardCharsets; +import java.util.Base64; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.lambda.LambdaClient; +import software.amazon.awssdk.services.lambda.LambdaClientBuilder; +import software.amazon.awssdk.services.lambda.model.InvokeRequest; +import software.amazon.awssdk.services.lambda.model.InvokeResponse; + +public abstract class AbstractAws2LambdaTest { + + @RegisterExtension + private static final MockWebServerExtension server = new MockWebServerExtension(); + + private static final StaticCredentialsProvider CREDENTIALS_PROVIDER = + StaticCredentialsProvider.create( + AwsBasicCredentials.create("my-access-key", "my-secret-key")); + + protected abstract InstrumentationExtension getTesting(); + + protected abstract ClientOverrideConfiguration.Builder createOverrideConfigurationBuilder(); + + protected boolean canTestLambdaInvoke() { + return true; + } + + @Test + void testInvokeLambda() { + Assumptions.assumeTrue(canTestLambdaInvoke()); + + LambdaClientBuilder builder = LambdaClient.builder(); + builder + .overrideConfiguration(createOverrideConfigurationBuilder().build()) + .endpointOverride(server.httpUri()); + builder.region(Region.AP_NORTHEAST_1).credentialsProvider(CREDENTIALS_PROVIDER); + LambdaClient client = builder.build(); + + server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, "ok")); + + InvokeRequest request = InvokeRequest.builder().functionName("test").build(); + InvokeResponse response = client.invoke(request); + assertThat(response.statusCode()).isEqualTo(200); + assertThat(response.payload().asUtf8String()).isEqualTo("ok"); + + String clientContextHeader = + server.takeRequest().request().headers().get("x-amz-client-context"); + assertThat(clientContextHeader).isNotEmpty(); + String clientContextJson = + new String(Base64.getDecoder().decode(clientContextHeader), StandardCharsets.UTF_8); + assertThat(clientContextJson).contains("traceparent"); + + getTesting() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("Lambda.Invoke").hasKind(SpanKind.CLIENT).hasNoParent())); + } +} diff --git a/instrumentation/azure-core/azure-core-1.14/library-instrumentation-shaded/build.gradle.kts b/instrumentation/azure-core/azure-core-1.14/library-instrumentation-shaded/build.gradle.kts index 25dbbc455e5e..67250df40347 100644 --- a/instrumentation/azure-core/azure-core-1.14/library-instrumentation-shaded/build.gradle.kts +++ b/instrumentation/azure-core/azure-core-1.14/library-instrumentation-shaded/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/instrumentation/azure-core/azure-core-1.19/library-instrumentation-shaded/build.gradle.kts b/instrumentation/azure-core/azure-core-1.19/library-instrumentation-shaded/build.gradle.kts index 590937930dee..ebcd721e7c19 100644 --- a/instrumentation/azure-core/azure-core-1.19/library-instrumentation-shaded/build.gradle.kts +++ b/instrumentation/azure-core/azure-core-1.19/library-instrumentation-shaded/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } 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 940331b69140..423f391f7e29 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 @@ -1,6 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java b/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java index 322bed6a7117..1fe50b3abbda 100644 --- a/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java +++ b/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/BaseSpanDecorator.java @@ -26,7 +26,7 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; import io.opentelemetry.javaagent.instrumentation.apachecamel.SpanDecorator; import java.util.Collections; @@ -41,7 +41,7 @@ class BaseSpanDecorator implements SpanDecorator { static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.camel.experimental-span-attributes", false); static final String DEFAULT_OPERATION_NAME = "CamelOperation"; diff --git a/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java b/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java index 2db260a9f088..45b368a043f1 100644 --- a/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java +++ b/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java @@ -25,7 +25,7 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import java.net.URI; @@ -36,7 +36,7 @@ class DbSpanDecorator extends BaseSpanDecorator { private static final SqlStatementSanitizer sanitizer = - SqlStatementSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + SqlStatementSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); private final String component; private final String system; diff --git a/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java b/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java index dfa923590d18..8e1c8b49f3fb 100644 --- a/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java +++ b/instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/HttpSpanDecorator.java @@ -30,7 +30,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.instrumentation.apachecamel.CamelDirection; import io.opentelemetry.semconv.HttpAttributes; import io.opentelemetry.semconv.UrlAttributes; @@ -45,7 +45,8 @@ class HttpSpanDecorator extends BaseSpanDecorator { private static final String POST_METHOD = "POST"; private static final String GET_METHOD = "GET"; - private static final Set knownMethods = CommonConfig.get().getKnownHttpRequestMethods(); + private static final Set knownMethods = + AgentCommonConfig.get().getKnownHttpRequestMethods(); protected String getProtocol() { return "http"; diff --git a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java index 7792bcd3f8ad..841f48fdbc6e 100644 --- a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java +++ b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java @@ -12,7 +12,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.network.NetworkAttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; public final class CassandraSingletons { @@ -34,7 +34,7 @@ public final class CassandraSingletons { SqlClientAttributesExtractor.builder(attributesGetter) .setTableAttribute(DbIncubatingAttributes.DB_CASSANDRA_TABLE) .setStatementSanitizationEnabled( - CommonConfig.get().isStatementSanitizationEnabled()) + AgentCommonConfig.get().isStatementSanitizationEnabled()) .build()) .addAttributesExtractor( NetworkAttributesExtractor.create(new CassandraNetworkAttributesGetter())) diff --git a/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java b/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java index 73c98569f6cf..4da5b599d0a6 100644 --- a/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java +++ b/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java @@ -12,7 +12,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.network.NetworkAttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; public final class CassandraSingletons { @@ -33,7 +33,7 @@ public final class CassandraSingletons { SqlClientAttributesExtractor.builder(attributesGetter) .setTableAttribute(DbIncubatingAttributes.DB_CASSANDRA_TABLE) .setStatementSanitizationEnabled( - CommonConfig.get().isStatementSanitizationEnabled()) + AgentCommonConfig.get().isStatementSanitizationEnabled()) .build()) .addAttributesExtractor( NetworkAttributesExtractor.create(new CassandraNetworkAttributesGetter())) diff --git a/instrumentation/cassandra/cassandra-4.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_4/CassandraSingletons.java b/instrumentation/cassandra/cassandra-4.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_4/CassandraSingletons.java index 7803fbd26174..d7151d1b5722 100644 --- a/instrumentation/cassandra/cassandra-4.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_4/CassandraSingletons.java +++ b/instrumentation/cassandra/cassandra-4.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_4/CassandraSingletons.java @@ -7,13 +7,13 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.cassandra.v4_4.CassandraTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; final class CassandraSingletons { static final CassandraTelemetry telemetry = CassandraTelemetry.builder(GlobalOpenTelemetry.get()) - .setStatementSanitizationEnabled(CommonConfig.get().isStatementSanitizationEnabled()) + .setStatementSanitizationEnabled(AgentCommonConfig.get().isStatementSanitizationEnabled()) .build(); private CassandraSingletons() {} diff --git a/instrumentation/cdi-testing/src/test/groovy/CDIContainerTest.groovy b/instrumentation/cdi-testing/src/test/groovy/CDIContainerTest.groovy deleted file mode 100644 index 3a34b98a9d26..000000000000 --- a/instrumentation/cdi-testing/src/test/groovy/CDIContainerTest.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import org.jboss.weld.environment.se.Weld -import org.jboss.weld.environment.se.WeldContainer -import org.jboss.weld.environment.se.threading.RunnableDecorator - -class CDIContainerTest extends AgentInstrumentationSpecification { - - def "CDI container starts with agent"() { - given: - Weld builder = new Weld() - .disableDiscovery() - .addDecorator(RunnableDecorator) - .addBeanClass(TestBean) - - when: - WeldContainer container = builder.initialize() - - then: - container.isRunning() - - cleanup: - container?.shutdown() - } -} diff --git a/instrumentation/cdi-testing/src/test/java/io/opentelemetry/test/cdi/CdiContainerTest.java b/instrumentation/cdi-testing/src/test/java/io/opentelemetry/test/cdi/CdiContainerTest.java new file mode 100644 index 000000000000..6d6596745021 --- /dev/null +++ b/instrumentation/cdi-testing/src/test/java/io/opentelemetry/test/cdi/CdiContainerTest.java @@ -0,0 +1,36 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.test.cdi; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import org.jboss.weld.environment.se.Weld; +import org.jboss.weld.environment.se.WeldContainer; +import org.jboss.weld.environment.se.threading.RunnableDecorator; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class CdiContainerTest { + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Test + public void cdiContainerStartsWithAgent() { + Weld builder = + new Weld() + .disableDiscovery() + .addDecorator(RunnableDecorator.class) + .addBeanClass(TestBean.class); + WeldContainer container = builder.initialize(); + + assertThat(container.isRunning()).isTrue(); + if (container != null) { + container.shutdown(); + } + } +} diff --git a/instrumentation/cdi-testing/src/test/java/TestBean.java b/instrumentation/cdi-testing/src/test/java/io/opentelemetry/test/cdi/TestBean.java similarity index 88% rename from instrumentation/cdi-testing/src/test/java/TestBean.java rename to instrumentation/cdi-testing/src/test/java/io/opentelemetry/test/cdi/TestBean.java index d7fba0156045..31ef6736f14b 100644 --- a/instrumentation/cdi-testing/src/test/java/TestBean.java +++ b/instrumentation/cdi-testing/src/test/java/io/opentelemetry/test/cdi/TestBean.java @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +package io.opentelemetry.test.cdi; + public class TestBean { private String someField; diff --git a/instrumentation/clickhouse-client-0.5/javaagent/build.gradle.kts b/instrumentation/clickhouse-client-0.5/javaagent/build.gradle.kts new file mode 100644 index 000000000000..2322b3b8b3a8 --- /dev/null +++ b/instrumentation/clickhouse-client-0.5/javaagent/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +muzzle { + pass { + group.set("com.clickhouse.client") + module.set("clickhouse-client") + versions.set("[0.5.0,)") + assertInverse.set(true) + } +} + +dependencies { + compileOnly("com.clickhouse:clickhouse-client:0.5.0") + compileOnly("com.google.auto.value:auto-value-annotations") + annotationProcessor("com.google.auto.value:auto-value") + + testLibrary("com.clickhouse:clickhouse-client:0.5.0") + testLibrary("com.clickhouse:clickhouse-http-client:0.5.0") + testLibrary("org.apache.httpcomponents.client5:httpclient5:5.2.3") +} + +tasks { + test { + usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service) + } +} diff --git a/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseAttributesGetter.java b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseAttributesGetter.java new file mode 100644 index 000000000000..2e729cdd2416 --- /dev/null +++ b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseAttributesGetter.java @@ -0,0 +1,58 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.clickhouse; + +import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter; +import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; +import javax.annotation.Nullable; + +final class ClickHouseAttributesGetter implements DbClientAttributesGetter { + @Nullable + @Override + public String getStatement(ClickHouseDbRequest request) { + if (request.getSqlStatementInfo() == null) { + return null; + } + return request.getSqlStatementInfo().getFullStatement(); + } + + @Nullable + @Override + public String getOperation(ClickHouseDbRequest request) { + if (request.getSqlStatementInfo() == null) { + return null; + } + return request.getSqlStatementInfo().getOperation(); + } + + @Nullable + @Override + public String getSystem(ClickHouseDbRequest request) { + return DbIncubatingAttributes.DbSystemValues.CLICKHOUSE; + } + + @Nullable + @Override + public String getUser(ClickHouseDbRequest request) { + return null; + } + + @Nullable + @Override + public String getName(ClickHouseDbRequest request) { + String dbName = request.getDbName(); + if (dbName == null || dbName.isEmpty()) { + return null; + } + return dbName; + } + + @Nullable + @Override + public String getConnectionString(ClickHouseDbRequest request) { + return null; + } +} diff --git a/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientInstrumentation.java b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientInstrumentation.java new file mode 100644 index 000000000000..78055968a872 --- /dev/null +++ b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientInstrumentation.java @@ -0,0 +1,101 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.clickhouse; + +import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext; +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface; +import static io.opentelemetry.javaagent.instrumentation.clickhouse.ClickHouseSingletons.instrumenter; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import com.clickhouse.client.ClickHouseClient; +import com.clickhouse.client.ClickHouseRequest; +import com.clickhouse.client.config.ClickHouseDefaults; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.javaagent.bootstrap.CallDepth; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class ClickHouseClientInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return implementsInterface(named("com.clickhouse.client.ClickHouseClient")); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + isMethod() + .and(namedOneOf("executeAndWait", "execute")) + .and(takesArgument(0, named("com.clickhouse.client.ClickHouseRequest"))), + this.getClass().getName() + "$ClickHouseExecuteAndWaitAdvice"); + } + + @SuppressWarnings("unused") + public static class ClickHouseExecuteAndWaitAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter( + @Advice.Argument(0) ClickHouseRequest clickHouseRequest, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope, + @Advice.Local("otelCallDepth") CallDepth callDepth) { + + callDepth = CallDepth.forClass(ClickHouseClient.class); + if (callDepth.getAndIncrement() > 0) { + return; + } + + if (clickHouseRequest == null) { + return; + } + + Context parentContext = currentContext(); + + ClickHouseDbRequest request = + ClickHouseDbRequest.create( + clickHouseRequest.getServer().getHost(), + clickHouseRequest.getServer().getPort(), + clickHouseRequest + .getServer() + .getDatabase() + .orElse(ClickHouseDefaults.DATABASE.getDefaultValue().toString()), + clickHouseRequest.getPreparedQuery().getOriginalQuery()); + + if (!instrumenter().shouldStart(parentContext, request)) { + return; + } + + context = instrumenter().start(parentContext, request); + scope = context.makeCurrent(); + } + + @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) + public static void onExit( + @Advice.Thrown Throwable throwable, + @Advice.Local("otelRequest") ClickHouseDbRequest clickHouseRequest, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope, + @Advice.Local("otelCallDepth") CallDepth callDepth) { + + if (callDepth.decrementAndGet() > 0) { + return; + } + + if (scope == null) { + return; + } + + scope.close(); + instrumenter().end(context, clickHouseRequest, null, throwable); + } + } +} diff --git a/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseDbRequest.java b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseDbRequest.java new file mode 100644 index 000000000000..1afe12768aa2 --- /dev/null +++ b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseDbRequest.java @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.clickhouse; + +import com.google.auto.value.AutoValue; +import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementInfo; +import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementSanitizer; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; + +@AutoValue +public abstract class ClickHouseDbRequest { + + private static final SqlStatementSanitizer sanitizer = + SqlStatementSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); + + public static ClickHouseDbRequest create(String host, int port, String dbName, String sql) { + return new AutoValue_ClickHouseDbRequest(host, port, dbName, sanitizer.sanitize(sql)); + } + + public abstract String getHost(); + + public abstract int getPort(); + + public abstract String getDbName(); + + public abstract SqlStatementInfo getSqlStatementInfo(); +} diff --git a/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseInstrumentationModule.java b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseInstrumentationModule.java new file mode 100644 index 000000000000..4477710668e8 --- /dev/null +++ b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseInstrumentationModule.java @@ -0,0 +1,26 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.clickhouse; + +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; + +@AutoService(InstrumentationModule.class) +public class ClickHouseInstrumentationModule extends InstrumentationModule { + + public ClickHouseInstrumentationModule() { + super("clickhouse", "clickhouse-client-0.5"); + } + + @Override + public List typeInstrumentations() { + return singletonList(new ClickHouseClientInstrumentation()); + } +} diff --git a/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseNetworkAttributesGetter.java b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseNetworkAttributesGetter.java new file mode 100644 index 000000000000..21a57f7f9911 --- /dev/null +++ b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseNetworkAttributesGetter.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.clickhouse; + +import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesGetter; + +final class ClickHouseNetworkAttributesGetter + implements ServerAttributesGetter { + + @Override + public String getServerAddress(ClickHouseDbRequest request) { + return request.getHost(); + } + + @Override + public Integer getServerPort(ClickHouseDbRequest request) { + return request.getPort(); + } +} diff --git a/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseSingletons.java b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseSingletons.java new file mode 100644 index 000000000000..1710cd98a6e8 --- /dev/null +++ b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseSingletons.java @@ -0,0 +1,38 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.clickhouse; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; +import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; +import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; + +public final class ClickHouseSingletons { + + private static final Instrumenter INSTRUMENTER; + + static { + ClickHouseAttributesGetter dbAttributesGetter = new ClickHouseAttributesGetter(); + + INSTRUMENTER = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + "io.opentelemetry.clickhouse-client-0.5", + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addAttributesExtractor( + ServerAttributesExtractor.create(new ClickHouseNetworkAttributesGetter())) + .buildInstrumenter(SpanKindExtractor.alwaysClient()); + } + + public static Instrumenter instrumenter() { + return INSTRUMENTER; + } + + private ClickHouseSingletons() {} +} diff --git a/instrumentation/clickhouse-client-0.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientTest.java b/instrumentation/clickhouse-client-0.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientTest.java new file mode 100644 index 000000000000..745bed68392e --- /dev/null +++ b/instrumentation/clickhouse-client-0.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientTest.java @@ -0,0 +1,344 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.clickhouse; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + +import com.clickhouse.client.ClickHouseClient; +import com.clickhouse.client.ClickHouseException; +import com.clickhouse.client.ClickHouseNode; +import com.clickhouse.client.ClickHouseParameterizedQuery; +import com.clickhouse.client.ClickHouseRequest; +import com.clickhouse.client.ClickHouseResponse; +import com.clickhouse.client.ClickHouseResponseSummary; +import com.clickhouse.data.ClickHouseFormat; +import com.google.common.collect.ImmutableMap; +import io.opentelemetry.api.common.Attributes; +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.AttributeAssertion; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestInstance.Lifecycle; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.testcontainers.containers.GenericContainer; + +@TestInstance(Lifecycle.PER_CLASS) +class ClickHouseClientTest { + + @RegisterExtension + private static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static final GenericContainer clickhouseServer = + new GenericContainer<>("clickhouse/clickhouse-server:24.4.2").withExposedPorts(8123); + + private static final String dbName = "default"; + private static final String tableName = "test_table"; + private static int port; + private static String host; + private static ClickHouseNode server; + private static ClickHouseClient client; + + @BeforeAll + void setup() throws ClickHouseException { + clickhouseServer.start(); + port = clickhouseServer.getMappedPort(8123); + host = clickhouseServer.getHost(); + server = ClickHouseNode.of("http://" + host + ":" + port + "/" + dbName + "?compress=0"); + client = ClickHouseClient.builder().build(); + + ClickHouseResponse response = + client + .read(server) + .query("create table if not exists " + tableName + "(s String) engine=Memory") + .executeAndWait(); + response.close(); + + // wait for CREATE operation and clear + testing.waitForTraces(1); + testing.clearData(); + } + + @AfterAll + void cleanup() { + if (client != null) { + client.close(); + } + clickhouseServer.stop(); + } + + @Test + void testConnectionStringWithoutDatabaseSpecifiedStillGeneratesSpans() + throws ClickHouseException { + ClickHouseNode server = ClickHouseNode.of("http://" + host + ":" + port + "?compress=0"); + ClickHouseClient client = ClickHouseClient.builder().build(); + + ClickHouseResponse response = + client + .read(server) + .format(ClickHouseFormat.RowBinaryWithNamesAndTypes) + .query("select * from " + tableName) + .executeAndWait(); + response.close(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("SELECT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasNoParent() + .hasAttributesSatisfyingExactly( + attributeAssertions("select * from " + tableName, "SELECT")))); + } + + @Test + void testExecuteAndWaitWithStringQuery() throws ClickHouseException { + testing.runWithSpan( + "parent", + () -> { + ClickHouseResponse response; + response = + client + .write(server) + .query("insert into " + tableName + " values('1')('2')('3')") + .executeAndWait(); + response.close(); + + response = + client + .read(server) + .format(ClickHouseFormat.RowBinaryWithNamesAndTypes) + .query("select * from " + tableName) + .executeAndWait(); + response.close(); + }); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasNoParent().hasAttributes(Attributes.empty()), + span -> + span.hasName("INSERT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + attributeAssertions( + "insert into " + tableName + " values(?)(?)(?)", "INSERT")), + span -> + span.hasName("SELECT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + attributeAssertions("select * from " + tableName, "SELECT")))); + } + + @Test + void testExecuteAndWaitWithStringQueryAndId() throws ClickHouseException { + testing.runWithSpan( + "parent", + () -> { + ClickHouseResponse response = + client + .read(server) + .format(ClickHouseFormat.RowBinaryWithNamesAndTypes) + .query("select * from " + tableName, "test_query_id") + .executeAndWait(); + response.close(); + }); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasNoParent().hasAttributes(Attributes.empty()), + span -> + span.hasName("SELECT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + attributeAssertions("select * from " + tableName, "SELECT")))); + } + + @Test + void testExecuteAndWaitThrowsException() { + Throwable thrown = + catchThrowable( + () -> { + ClickHouseResponse response = + client + .read(server) + .format(ClickHouseFormat.RowBinaryWithNamesAndTypes) + .query("select * from non_existent_table") + .executeAndWait(); + response.close(); + }); + + assertThat(thrown).isInstanceOf(ClickHouseException.class); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("SELECT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasStatus(StatusData.error()) + .hasException(thrown) + .hasAttributesSatisfyingExactly( + attributeAssertions("select * from non_existent_table", "SELECT")))); + } + + @Test + void testAsyncExecuteQuery() throws Exception { + CompletableFuture response = + client + .read(server) + .format(ClickHouseFormat.RowBinaryWithNamesAndTypes) + .query("select * from " + tableName) + .execute(); + + ClickHouseResponse result = response.get(); + assertThat(result).isNotNull(); + result.close(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("SELECT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasAttributesSatisfyingExactly( + attributeAssertions("select * from " + tableName, "SELECT")))); + } + + @Test + void testSendQuery() throws Exception { + testing.runWithSpan( + "parent", + () -> { + CompletableFuture> future = + ClickHouseClient.send(server, "select * from " + tableName + " limit 1"); + List results = future.get(); + assertThat(results).hasSize(1); + }); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasNoParent().hasAttributes(Attributes.empty()), + span -> + span.hasName("SELECT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + attributeAssertions( + "select * from " + tableName + " limit ?", "SELECT")))); + } + + @Test + void testSendMultipleQueries() throws Exception { + testing.runWithSpan( + "parent", + () -> { + CompletableFuture> future = + ClickHouseClient.send( + server, + "insert into " + tableName + " values('1')('2')('3')", + "select * from " + tableName + " limit 1"); + List results = future.get(); + assertThat(results).hasSize(2); + }); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasNoParent().hasAttributes(Attributes.empty()), + span -> + span.hasName("INSERT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + attributeAssertions( + "insert into " + tableName + " values(?)(?)(?)", "INSERT")), + span -> + span.hasName("SELECT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + attributeAssertions( + "select * from " + tableName + " limit ?", "SELECT")))); + } + + @Test + void testParameterizedQueryInput() throws ClickHouseException { + ClickHouseRequest request = + client.read(server).format(ClickHouseFormat.RowBinaryWithNamesAndTypes); + + testing.runWithSpan( + "parent", + () -> { + ClickHouseResponse response = + client + .write(server) + .query( + ClickHouseParameterizedQuery.of( + request.getConfig(), + "insert into " + tableName + " values(:val1)(:val2)(:val3)")) + .params(ImmutableMap.of("val1", "1", "val2", "2", "val3", "3")) + .executeAndWait(); + response.close(); + + response = + request + .query( + ClickHouseParameterizedQuery.of( + request.getConfig(), "select * from " + tableName + " where s=:val")) + .params(ImmutableMap.of("val", "'2'")) + .executeAndWait(); + response.close(); + }); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasNoParent().hasAttributes(Attributes.empty()), + span -> + span.hasName("INSERT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + attributeAssertions( + "insert into " + tableName + " values(:val1)(:val2)(:val3)", + "INSERT")), + span -> + span.hasName("SELECT " + dbName) + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + attributeAssertions( + "select * from " + tableName + " where s=:val", "SELECT")))); + } + + private static List attributeAssertions(String statement, String operation) { + return asList( + equalTo(DbIncubatingAttributes.DB_SYSTEM, DbIncubatingAttributes.DbSystemValues.CLICKHOUSE), + equalTo(DbIncubatingAttributes.DB_NAME, dbName), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(DbIncubatingAttributes.DB_STATEMENT, statement), + equalTo(DbIncubatingAttributes.DB_OPERATION, operation)); + } +} diff --git a/instrumentation/couchbase/couchbase-2-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQuerySanitizer.java b/instrumentation/couchbase/couchbase-2-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQuerySanitizer.java index 738c9819547c..2fa42b1ca6bb 100644 --- a/instrumentation/couchbase/couchbase-2-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQuerySanitizer.java +++ b/instrumentation/couchbase/couchbase-2-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseQuerySanitizer.java @@ -8,7 +8,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlDialect; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementInfo; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -17,7 +17,7 @@ public final class CouchbaseQuerySanitizer { private static final SqlStatementSanitizer sanitizer = - SqlStatementSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + SqlStatementSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); @Nullable private static final Class QUERY_CLASS; @Nullable private static final Class STATEMENT_CLASS; diff --git a/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseSingletons.java b/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseSingletons.java index a720209a8b95..0e6c3eee550a 100644 --- a/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseSingletons.java +++ b/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseSingletons.java @@ -13,7 +13,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.network.NetworkAttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class CouchbaseSingletons { @@ -36,7 +36,7 @@ public final class CouchbaseSingletons { (context, couchbaseRequest, startAttributes) -> CouchbaseRequestInfo.init(context, couchbaseRequest)); - if (InstrumentationConfig.get() + if (AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.couchbase.experimental-span-attributes", false)) { builder.addAttributesExtractor(new ExperimentalAttributesExtractor()); } diff --git a/instrumentation/couchbase/couchbase-3.1.6/tracing-opentelemetry-shaded/build.gradle.kts b/instrumentation/couchbase/couchbase-3.1.6/tracing-opentelemetry-shaded/build.gradle.kts index 366ba2c0aef4..128e45cc51f1 100644 --- a/instrumentation/couchbase/couchbase-3.1.6/tracing-opentelemetry-shaded/build.gradle.kts +++ b/instrumentation/couchbase/couchbase-3.1.6/tracing-opentelemetry-shaded/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/instrumentation/couchbase/couchbase-3.1/tracing-opentelemetry-shaded/build.gradle.kts b/instrumentation/couchbase/couchbase-3.1/tracing-opentelemetry-shaded/build.gradle.kts index 53e83b2a78dd..e1bff72f5885 100644 --- a/instrumentation/couchbase/couchbase-3.1/tracing-opentelemetry-shaded/build.gradle.kts +++ b/instrumentation/couchbase/couchbase-3.1/tracing-opentelemetry-shaded/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/instrumentation/couchbase/couchbase-3.2/tracing-opentelemetry-shaded/build.gradle.kts b/instrumentation/couchbase/couchbase-3.2/tracing-opentelemetry-shaded/build.gradle.kts index 9844a74e964e..c97e14e07e7a 100644 --- a/instrumentation/couchbase/couchbase-3.2/tracing-opentelemetry-shaded/build.gradle.kts +++ b/instrumentation/couchbase/couchbase-3.2/tracing-opentelemetry-shaded/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/instrumentation/elasticsearch/elasticsearch-api-client-7.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/apiclient/ElasticsearchApiClientInstrumentationModule.java b/instrumentation/elasticsearch/elasticsearch-api-client-7.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/apiclient/ElasticsearchApiClientInstrumentationModule.java index a0082f7a0888..75cad4dee6fd 100644 --- a/instrumentation/elasticsearch/elasticsearch-api-client-7.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/apiclient/ElasticsearchApiClientInstrumentationModule.java +++ b/instrumentation/elasticsearch/elasticsearch-api-client-7.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/apiclient/ElasticsearchApiClientInstrumentationModule.java @@ -12,11 +12,13 @@ import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; import net.bytebuddy.matcher.ElementMatcher; @AutoService(InstrumentationModule.class) -public class ElasticsearchApiClientInstrumentationModule extends InstrumentationModule { +public class ElasticsearchApiClientInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public ElasticsearchApiClientInstrumentationModule() { super("elasticsearch-api-client", "elasticsearch-api-client-7.16", "elasticsearch"); } @@ -31,10 +33,8 @@ public ElementMatcher.Junction classLoaderMatcher() { } @Override - public boolean isIndyModule() { - // java.lang.ClassCastException: class - // io.opentelemetry.javaagent.shaded.instrumentation.elasticsearch.rest.internal.ElasticsearchEndpointDefinition cannot be cast to class io.opentelemetry.javaagent.shaded.instrumentation.elasticsearch.rest.internal.ElasticsearchEndpointDefinition (io.opentelemetry.javaagent.shaded.instrumentation.elasticsearch.rest.internal.ElasticsearchEndpointDefinition is in unnamed module of loader io.opentelemetry.javaagent.tooling.instrumentation.indy.InstrumentationModuleClassLoader @6baee63b; io.opentelemetry.javaagent.shaded.instrumentation.elasticsearch.rest.internal.ElasticsearchEndpointDefinition is in unnamed module of loader 'app') - return false; + public String getModuleGroup() { + return "elasticsearch"; } @Override diff --git a/instrumentation/elasticsearch/elasticsearch-rest-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v7_0/ElasticsearchRest7InstrumentationModule.java b/instrumentation/elasticsearch/elasticsearch-rest-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v7_0/ElasticsearchRest7InstrumentationModule.java index 919a8318b359..22d00be64dbd 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v7_0/ElasticsearchRest7InstrumentationModule.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/v7_0/ElasticsearchRest7InstrumentationModule.java @@ -12,11 +12,13 @@ import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; import net.bytebuddy.matcher.ElementMatcher; @AutoService(InstrumentationModule.class) -public class ElasticsearchRest7InstrumentationModule extends InstrumentationModule { +public class ElasticsearchRest7InstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public ElasticsearchRest7InstrumentationModule() { super("elasticsearch-rest", "elasticsearch-rest-7.0", "elasticsearch"); } @@ -33,9 +35,8 @@ public ElementMatcher.Junction classLoaderMatcher() { } @Override - public boolean isIndyModule() { - // shares a virtual field with elasticsearch-api-client - return false; + public String getModuleGroup() { + return "elasticsearch"; } @Override diff --git a/instrumentation/elasticsearch/elasticsearch-rest-7.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/v7_0/RestClientWrapper.java b/instrumentation/elasticsearch/elasticsearch-rest-7.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/v7_0/RestClientWrapper.java index e605bde1959c..9c5d39be5ea5 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-7.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/v7_0/RestClientWrapper.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-7.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/v7_0/RestClientWrapper.java @@ -74,6 +74,7 @@ private static Class createProxyClass() { response = (Response) method.invoke(target, args); } catch (Throwable exception) { throwable = exception; + throw throwable; } finally { instrumenter.end(context, otelRequest, response, throwable); } @@ -102,6 +103,7 @@ private static Class createProxyClass() { return method.invoke(target, args); } catch (Throwable exception) { throwable = exception; + throw throwable; } finally { if (throwable != null) { instrumenter.end(context, otelRequest, null, throwable); diff --git a/instrumentation/elasticsearch/elasticsearch-rest-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestJavaagentInstrumenterFactory.java b/instrumentation/elasticsearch/elasticsearch-rest-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestJavaagentInstrumenterFactory.java index 6c160b9ff546..39682ce28a95 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestJavaagentInstrumenterFactory.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/rest/ElasticsearchRestJavaagentInstrumenterFactory.java @@ -9,8 +9,8 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.elasticsearch.rest.internal.ElasticsearchRestInstrumenterFactory; import io.opentelemetry.instrumentation.elasticsearch.rest.internal.ElasticsearchRestRequest; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.Collections; import java.util.function.Function; import org.elasticsearch.client.Response; @@ -18,7 +18,7 @@ public final class ElasticsearchRestJavaagentInstrumenterFactory { private static final boolean CAPTURE_SEARCH_QUERY = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.elasticsearch.capture-search-query", false); private ElasticsearchRestJavaagentInstrumenterFactory() {} @@ -30,7 +30,7 @@ public static Instrumenter create( instrumentationName, Collections.emptyList(), Function.identity(), - CommonConfig.get().getKnownHttpRequestMethods(), + AgentCommonConfig.get().getKnownHttpRequestMethods(), CAPTURE_SEARCH_QUERY); } } diff --git a/instrumentation/elasticsearch/elasticsearch-transport-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportInstrumenterFactory.java b/instrumentation/elasticsearch/elasticsearch-transport-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportInstrumenterFactory.java index e1d2320aa972..33702561b4c8 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportInstrumenterFactory.java +++ b/instrumentation/elasticsearch/elasticsearch-transport-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportInstrumenterFactory.java @@ -12,12 +12,12 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import org.elasticsearch.action.ActionResponse; public final class ElasticsearchTransportInstrumenterFactory { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.elasticsearch.experimental-span-attributes", false); public static Instrumenter create( diff --git a/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/executors/ExecutorMatchers.java b/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/executors/ExecutorMatchers.java index 1c3d7497ab35..717f088e4fcd 100644 --- a/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/executors/ExecutorMatchers.java +++ b/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/executors/ExecutorMatchers.java @@ -12,7 +12,7 @@ import static net.bytebuddy.matcher.ElementMatchers.any; import static net.bytebuddy.matcher.ElementMatchers.named; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; @@ -98,14 +98,15 @@ final class ExecutorMatchers { "scala.concurrent.Future$InternalCallbackExecutor$", "scala.concurrent.impl.ExecutionContextImpl")); combined.addAll( - InstrumentationConfig.get().getList("otel.instrumentation.executors.include", emptyList())); + AgentInstrumentationConfig.get() + .getList("otel.instrumentation.executors.include", emptyList())); INSTRUMENTED_EXECUTOR_NAMES = Collections.unmodifiableSet(combined); INSTRUMENTED_EXECUTOR_PREFIXES = Collections.singletonList("slick.util.AsyncExecutor$"); } static ElementMatcher.Junction executorNameMatcher() { - if (InstrumentationConfig.get() + if (AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.executors.include-all", false)) { return any(); } diff --git a/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/executors/ExecutorsInstrumentationModule.java b/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/executors/ExecutorsInstrumentationModule.java index ff1e753b4de9..60de54633025 100644 --- a/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/executors/ExecutorsInstrumentationModule.java +++ b/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/executors/ExecutorsInstrumentationModule.java @@ -19,11 +19,6 @@ public ExecutorsInstrumentationModule() { super("executors"); } - @Override - public boolean isIndyModule() { - return false; - } - @Override public List typeInstrumentations() { return asList( diff --git a/instrumentation/external-annotations/javaagent-unit-tests/build.gradle.kts b/instrumentation/external-annotations/javaagent-unit-tests/build.gradle.kts index 364911c6d0df..7ce37d7de0b3 100644 --- a/instrumentation/external-annotations/javaagent-unit-tests/build.gradle.kts +++ b/instrumentation/external-annotations/javaagent-unit-tests/build.gradle.kts @@ -4,6 +4,7 @@ plugins { dependencies { testImplementation(project(":instrumentation-api")) + testImplementation(project(":instrumentation-api-incubator")) testImplementation(project(":javaagent-extension-api")) testImplementation(project(":javaagent-tooling")) testImplementation(project(":instrumentation:external-annotations:javaagent")) diff --git a/instrumentation/external-annotations/javaagent-unit-tests/src/test/java/io/opentelemetry/javaagent/instrumentation/extannotations/IncludeTest.java b/instrumentation/external-annotations/javaagent-unit-tests/src/test/java/io/opentelemetry/javaagent/instrumentation/extannotations/IncludeTest.java index b1f096ced00a..9f717b107392 100644 --- a/instrumentation/external-annotations/javaagent-unit-tests/src/test/java/io/opentelemetry/javaagent/instrumentation/extannotations/IncludeTest.java +++ b/instrumentation/external-annotations/javaagent-unit-tests/src/test/java/io/opentelemetry/javaagent/instrumentation/extannotations/IncludeTest.java @@ -9,7 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; diff --git a/instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java b/instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java index 6b231d97aa5c..ee6baffd60bd 100644 --- a/instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java +++ b/instrumentation/external-annotations/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extannotations/ExternalAnnotationInstrumentation.java @@ -17,9 +17,10 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.incubator.semconv.util.ClassAndMethod; import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser; @@ -78,7 +79,7 @@ public class ExternalAnnotationInstrumentation implements TypeInstrumentation { public ExternalAnnotationInstrumentation() { Set additionalTraceAnnotations = - configureAdditionalTraceAnnotations(InstrumentationConfig.get()); + configureAdditionalTraceAnnotations(AgentInstrumentationConfig.get()); if (additionalTraceAnnotations.isEmpty()) { classLoaderOptimization = none(); @@ -146,7 +147,7 @@ private static ElementMatcher.Junction configureExcludedMetho Map> excludedMethods = MethodsConfigurationParser.parse( - InstrumentationConfig.get().getString(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); + AgentInstrumentationConfig.get().getString(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); for (Map.Entry> entry : excludedMethods.entrySet()) { String className = entry.getKey(); ElementMatcher.Junction classMather = diff --git a/instrumentation/finagle-http-23.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/finaglehttp/v23_11/ClientTest.java b/instrumentation/finagle-http-23.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/finaglehttp/v23_11/ClientTest.java index de18ece3011a..d0dbee2bb1d0 100644 --- a/instrumentation/finagle-http-23.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/finaglehttp/v23_11/ClientTest.java +++ b/instrumentation/finagle-http-23.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/finaglehttp/v23_11/ClientTest.java @@ -35,6 +35,7 @@ import java.net.URI; import java.util.Collections; import java.util.HashSet; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -103,7 +104,7 @@ private Future doSendRequest(Request request, URI uri) { protected void configure(HttpClientTestOptions.Builder optionsBuilder) { optionsBuilder.setSingleConnectionFactory( (host, port) -> { - URI uri = URI.create(String.format("http://%s:%d", host, port)); + URI uri = URI.create(String.format(Locale.ROOT, "http://%s:%d", host, port)); Service svc = getClient(uri, ClientType.SINGLE_CONN); return (path, headers) -> { // this is synchronized bc so is the Netty one; diff --git a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeDbAttributesGetter.java b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeDbAttributesGetter.java index e4382e20413f..f0f15e7f6d2b 100644 --- a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeDbAttributesGetter.java +++ b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeDbAttributesGetter.java @@ -7,14 +7,14 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; final class GeodeDbAttributesGetter implements DbClientAttributesGetter { private static final SqlStatementSanitizer sanitizer = - SqlStatementSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + SqlStatementSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); @Override public String getSystem(GeodeRequest request) { diff --git a/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientSingletons.java b/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientSingletons.java index 17e717e79a65..68039f69b3ac 100644 --- a/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientSingletons.java +++ b/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientSingletons.java @@ -7,17 +7,8 @@ import com.google.api.client.http.HttpRequest; import com.google.api.client.http.HttpResponse; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; public class GoogleHttpClientSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.google-http-client-1.19"; @@ -25,33 +16,11 @@ public class GoogleHttpClientSingletons { private static final Instrumenter INSTRUMENTER; static { - GoogleHttpClientHttpAttributesGetter httpAttributesGetter = - new GoogleHttpClientHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, + new GoogleHttpClientHttpAttributesGetter(), + HttpHeaderSetter.INSTANCE); } public static Instrumenter instrumenter() { diff --git a/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java b/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java index 41c64c6a6cc3..162a54a62728 100644 --- a/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java +++ b/instrumentation/graphql-java/graphql-java-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v12_0/GraphqlSingletons.java @@ -9,12 +9,12 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.graphql.internal.InstrumentationUtil; import io.opentelemetry.instrumentation.graphql.v12_0.GraphQLTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class GraphqlSingletons { private static final boolean QUERY_SANITIZATION_ENABLED = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.graphql.query-sanitizer.enabled", true); private static final GraphQLTelemetry TELEMETRY = diff --git a/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v20_0/GraphqlSingletons.java b/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v20_0/GraphqlSingletons.java index 96a7e2f3a728..11f08b6c841a 100644 --- a/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v20_0/GraphqlSingletons.java +++ b/instrumentation/graphql-java/graphql-java-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/graphql/v20_0/GraphqlSingletons.java @@ -9,18 +9,18 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.graphql.internal.InstrumentationUtil; import io.opentelemetry.instrumentation.graphql.v20_0.GraphQLTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class GraphqlSingletons { private static final boolean QUERY_SANITIZATION_ENABLED = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.graphql.query-sanitizer.enabled", true); private static final boolean DATA_FETCHER_ENABLED = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.graphql.data-fetcher.enabled", false); private static final boolean TRIVIAL_DATA_FETCHER_ENABLED = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.graphql.trivial-data-fetcher.enabled", false); private static final GraphQLTelemetry TELEMETRY = diff --git a/instrumentation/grizzly-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlySingletons.java b/instrumentation/grizzly-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlySingletons.java index 5b10e6a735d4..7633c3bf7d56 100644 --- a/instrumentation/grizzly-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlySingletons.java +++ b/instrumentation/grizzly-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlySingletons.java @@ -15,7 +15,7 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge; import org.glassfish.grizzly.http.HttpRequestPacket; import org.glassfish.grizzly.http.HttpResponsePacket; @@ -32,17 +32,17 @@ public final class GrizzlySingletons { GlobalOpenTelemetry.get(), "io.opentelemetry.grizzly-2.3", HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) .addAttributesExtractor( HttpServerAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addOperationMetrics(HttpServerMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { + if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { builder .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) .addOperationMetrics(HttpServerExperimentalMetrics.get()); @@ -59,7 +59,7 @@ public final class GrizzlySingletons { (context, httpRequestPacket, startAttributes) -> GrizzlyErrorHolder.init(context)) .addContextCustomizer( HttpServerRoute.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .buildServerInstrumenter(HttpRequestHeadersGetter.INSTANCE); } diff --git a/instrumentation/grpc-1.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_6/GrpcSingletons.java b/instrumentation/grpc-1.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_6/GrpcSingletons.java index 36709d9e7f67..f42fb98aab00 100644 --- a/instrumentation/grpc-1.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_6/GrpcSingletons.java +++ b/instrumentation/grpc-1.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grpc/v1_6/GrpcSingletons.java @@ -13,7 +13,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.grpc.v1_6.GrpcTelemetry; import io.opentelemetry.instrumentation.grpc.v1_6.internal.ContextStorageBridge; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -28,14 +28,14 @@ public final class GrpcSingletons { static { boolean experimentalSpanAttributes = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.grpc.experimental-span-attributes", false); List clientRequestMetadata = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getList("otel.instrumentation.grpc.capture-metadata.client.request", emptyList()); List serverRequestMetadata = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getList("otel.instrumentation.grpc.capture-metadata.server.request", emptyList()); GrpcTelemetry telemetry = diff --git a/instrumentation/guava-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/v10_0/InstrumentationHelper.java b/instrumentation/guava-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/v10_0/InstrumentationHelper.java index 9d15d8311d28..d1d8bbc637f0 100644 --- a/instrumentation/guava-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/v10_0/InstrumentationHelper.java +++ b/instrumentation/guava-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/v10_0/InstrumentationHelper.java @@ -7,14 +7,14 @@ import io.opentelemetry.instrumentation.api.annotation.support.async.AsyncOperationEndStrategies; import io.opentelemetry.instrumentation.guava.v10_0.GuavaAsyncOperationEndStrategy; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class InstrumentationHelper { static { asyncOperationEndStrategy = GuavaAsyncOperationEndStrategy.builder() .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.guava.experimental-span-attributes", false)) .build(); diff --git a/instrumentation/hibernate/hibernate-4.0/javaagent/src/test/java/spring/jpa/Customer.java b/instrumentation/hibernate/hibernate-4.0/javaagent/src/test/java/spring/jpa/Customer.java index cac701b9e950..27d780b22951 100644 --- a/instrumentation/hibernate/hibernate-4.0/javaagent/src/test/java/spring/jpa/Customer.java +++ b/instrumentation/hibernate/hibernate-4.0/javaagent/src/test/java/spring/jpa/Customer.java @@ -5,6 +5,7 @@ package spring.jpa; +import java.util.Locale; import java.util.Objects; import javax.annotation.Nullable; import javax.persistence.Entity; @@ -55,7 +56,8 @@ public void setLastName(String lastName) { @Override public String toString() { - return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); + return String.format( + Locale.ROOT, "Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); } @Override diff --git a/instrumentation/hibernate/hibernate-6.0/spring-testing/src/test/java/spring/jpa/Customer.java b/instrumentation/hibernate/hibernate-6.0/spring-testing/src/test/java/spring/jpa/Customer.java index c98d8046d583..966098c7d03e 100644 --- a/instrumentation/hibernate/hibernate-6.0/spring-testing/src/test/java/spring/jpa/Customer.java +++ b/instrumentation/hibernate/hibernate-6.0/spring-testing/src/test/java/spring/jpa/Customer.java @@ -9,6 +9,7 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import java.util.Locale; import java.util.Objects; import javax.annotation.Nullable; @@ -55,7 +56,8 @@ public void setLastName(String lastName) { @Override public String toString() { - return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); + return String.format( + Locale.ROOT, "Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); } @Override diff --git a/instrumentation/hibernate/hibernate-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/HibernateInstrumenterFactory.java b/instrumentation/hibernate/hibernate-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/HibernateInstrumenterFactory.java index b9aa1c4c4d2d..217454ef1c8f 100644 --- a/instrumentation/hibernate/hibernate-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/HibernateInstrumenterFactory.java +++ b/instrumentation/hibernate/hibernate-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/HibernateInstrumenterFactory.java @@ -8,11 +8,11 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class HibernateInstrumenterFactory { static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.hibernate.experimental-span-attributes", false); public static Instrumenter createInstrumenter( diff --git a/instrumentation/hibernate/hibernate-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/OperationNameUtil.java b/instrumentation/hibernate/hibernate-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/OperationNameUtil.java index 93e5bde1d85a..60783d0822d3 100644 --- a/instrumentation/hibernate/hibernate-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/OperationNameUtil.java +++ b/instrumentation/hibernate/hibernate-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/OperationNameUtil.java @@ -7,13 +7,13 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementInfo; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import java.util.function.Function; public final class OperationNameUtil { private static final SqlStatementSanitizer sanitizer = - SqlStatementSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + SqlStatementSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); public static String getOperationNameForQuery(String query) { // set operation to default value that is used when sql sanitizer fails to extract diff --git a/instrumentation/http-url-connection/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionSingletons.java b/instrumentation/http-url-connection/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionSingletons.java index f3eb0bd53bb8..9f8b3006dc35 100644 --- a/instrumentation/http-url-connection/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionSingletons.java +++ b/instrumentation/http-url-connection/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionSingletons.java @@ -5,17 +5,9 @@ package io.opentelemetry.javaagent.instrumentation.httpurlconnection; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import java.net.HttpURLConnection; public final class HttpUrlConnectionSingletons { @@ -23,38 +15,19 @@ public final class HttpUrlConnectionSingletons { private static final Instrumenter INSTRUMENTER; static { - HttpUrlHttpAttributesGetter httpAttributesGetter = new HttpUrlHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - "io.opentelemetry.http-url-connection", - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addAttributesExtractor( - HttpMethodAttributeExtractor.create( - CommonConfig.get().getKnownHttpRequestMethods())) - .addContextCustomizer( - (context, httpRequestPacket, startAttributes) -> - GetOutputStreamContext.init(context)) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(RequestPropertySetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + "io.opentelemetry.http-url-connection", + new HttpUrlHttpAttributesGetter(), + RequestPropertySetter.INSTANCE, + builder -> + builder + .addAttributesExtractor( + HttpMethodAttributeExtractor.create( + AgentCommonConfig.get().getKnownHttpRequestMethods())) + .addContextCustomizer( + (context, httpRequestPacket, startAttributes) -> + GetOutputStreamContext.init(context))); } public static Instrumenter instrumenter() { diff --git a/instrumentation/hystrix-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixSingletons.java b/instrumentation/hystrix-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixSingletons.java index 19848e54d7cc..8a5ea9b501c4 100644 --- a/instrumentation/hystrix-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixSingletons.java +++ b/instrumentation/hystrix-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hystrix/HystrixSingletons.java @@ -8,7 +8,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class HystrixSingletons { @@ -21,7 +21,7 @@ public final class HystrixSingletons { Instrumenter.builder( GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, HystrixRequest::spanName); - if (InstrumentationConfig.get() + if (AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.hystrix.experimental-span-attributes", false)) { builder.addAttributesExtractor(new ExperimentalAttributesExtractor()); } diff --git a/instrumentation/influxdb-2.4/javaagent/build.gradle.kts b/instrumentation/influxdb-2.4/javaagent/build.gradle.kts index d6a74c455b43..ab93583d3e03 100644 --- a/instrumentation/influxdb-2.4/javaagent/build.gradle.kts +++ b/instrumentation/influxdb-2.4/javaagent/build.gradle.kts @@ -17,6 +17,8 @@ dependencies { compileOnly("com.google.auto.value:auto-value-annotations") annotationProcessor("com.google.auto.value:auto-value") + testInstrumentation(project(":instrumentation:okhttp:okhttp-3.0:javaagent")) + // we use methods that weren't present before 2.14 in tests testLibrary("org.influxdb:influxdb-java:2.14") } @@ -44,3 +46,9 @@ tasks { } } } + +tasks.withType().configureEach { + // we disable the okhttp instrumentation, so we don't need to assert on the okhttp spans + // from the okhttp instrumentation we need OkHttp3IgnoredTypesConfigurer to fix context leaks + jvmArgs("-Dotel.instrumentation.okhttp.enabled=false") +} diff --git a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbAttributesGetter.java b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbAttributesGetter.java index a2d209f1b435..c73bf348583b 100644 --- a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbAttributesGetter.java +++ b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbAttributesGetter.java @@ -19,11 +19,10 @@ public String getStatement(InfluxDbRequest request) { @Nullable @Override public String getOperation(InfluxDbRequest request) { - if (request.getSqlStatementInfo() != null) { - String operation = request.getSqlStatementInfo().getOperation(); - return operation == null ? request.getSql() : operation; + if (request.getOperation() != null) { + return request.getOperation(); } - return null; + return request.getSqlStatementInfo().getOperation(); } @Override diff --git a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbConstants.java b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbConstants.java deleted file mode 100644 index 06cbb2832da5..000000000000 --- a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbConstants.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.influxdb.v2_4; - -final class InfluxDbConstants { - - private InfluxDbConstants() {} - - public static final String CREATE_DATABASE_STATEMENT_NEW = "CREATE DATABASE \"%s\""; - - /** In influxDB 0.x version, it uses below statement format to create a database. */ - public static final String CREATE_DATABASE_STATEMENT_OLD = "CREATE DATABASE IF NOT EXISTS \"%s\""; - - public static final String DELETE_DATABASE_STATEMENT = "DROP DATABASE \"%s\""; -} diff --git a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbImplInstrumentation.java b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbImplInstrumentation.java index 2633e1d82433..72e5ee14bb5f 100644 --- a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbImplInstrumentation.java +++ b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbImplInstrumentation.java @@ -6,9 +6,6 @@ package io.opentelemetry.javaagent.instrumentation.influxdb.v2_4; import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext; -import static io.opentelemetry.javaagent.instrumentation.influxdb.v2_4.InfluxDbConstants.CREATE_DATABASE_STATEMENT_NEW; -import static io.opentelemetry.javaagent.instrumentation.influxdb.v2_4.InfluxDbConstants.CREATE_DATABASE_STATEMENT_OLD; -import static io.opentelemetry.javaagent.instrumentation.influxdb.v2_4.InfluxDbConstants.DELETE_DATABASE_STATEMENT; import static io.opentelemetry.javaagent.instrumentation.influxdb.v2_4.InfluxDbSingletons.instrumenter; import static net.bytebuddy.matcher.ElementMatchers.isEnum; import static net.bytebuddy.matcher.ElementMatchers.isMethod; @@ -18,7 +15,6 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArguments; import io.opentelemetry.context.Context; -import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.bootstrap.CallDepth; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -73,67 +69,48 @@ public void transform(TypeTransformer transformer) { public static class InfluxDbQueryAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Query query, - @Advice.AllArguments(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object[] arguments, - @Advice.FieldValue(value = "retrofit") Retrofit retrofit, - @Advice.Local("otelCallDepth") CallDepth callDepth, - @Advice.Local("otelRequest") InfluxDbRequest influxDbRequest, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - callDepth = CallDepth.forClass(InfluxDBImpl.class); + @Advice.AssignReturned.ToAllArguments(index = 0, typing = Assigner.Typing.DYNAMIC) + public static Object[] onEnter( + @Advice.AllArguments(typing = Assigner.Typing.DYNAMIC) Object[] arguments, + @Advice.FieldValue(value = "retrofit") Retrofit retrofit) { + CallDepth callDepth = CallDepth.forClass(InfluxDBImpl.class); if (callDepth.getAndIncrement() > 0) { - return; + return null; } + Query query = arguments[0] instanceof Query ? (Query) arguments[0] : null; if (query == null) { - return; + return null; } Context parentContext = currentContext(); HttpUrl httpUrl = retrofit.baseUrl(); - influxDbRequest = + InfluxDbRequest influxDbRequest = InfluxDbRequest.create( - httpUrl.host(), httpUrl.port(), query.getDatabase(), query.getCommand()); + httpUrl.host(), httpUrl.port(), query.getDatabase(), null, query.getCommand()); if (!instrumenter().shouldStart(parentContext, influxDbRequest)) { - return; + return null; } // wrap callbacks so they'd run in the context of the parent span Object[] newArguments = new Object[arguments.length]; - boolean hasChangedArgument = false; for (int i = 0; i < arguments.length; i++) { newArguments[i] = InfluxDbObjetWrapper.wrap(arguments[i], parentContext); - hasChangedArgument |= newArguments[i] != arguments[i]; - } - if (hasChangedArgument) { - arguments = newArguments; } - context = instrumenter().start(parentContext, influxDbRequest); - scope = context.makeCurrent(); + return new Object[] {newArguments, InfluxDbScope.start(parentContext, influxDbRequest)}; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void onExit( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelCallDepth") CallDepth callDepth, - @Advice.Local("otelRequest") InfluxDbRequest influxDbRequest, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - - if (callDepth.decrementAndGet() > 0) { - return; - } - - if (scope == null) { + @Advice.Thrown Throwable throwable, @Advice.Enter Object[] enterArgs) { + CallDepth callDepth = CallDepth.forClass(InfluxDBImpl.class); + if (callDepth.decrementAndGet() > 0 || enterArgs == null) { return; } - scope.close(); - - instrumenter().end(context, influxDbRequest, null, throwable); + ((InfluxDbScope) enterArgs[1]).end(throwable); } } @@ -141,22 +118,17 @@ public static void onExit( public static class InfluxDbModifyAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.This InfluxDBImpl influxDbImpl, + public static InfluxDbScope onEnter( @Advice.Origin("#m") String methodName, @Advice.Argument(0) Object arg0, - @Advice.FieldValue(value = "retrofit") Retrofit retrofit, - @Advice.Local("otelCallDepth") CallDepth callDepth, - @Advice.Local("otelRequest") InfluxDbRequest influxDbRequest, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - callDepth = CallDepth.forClass(InfluxDBImpl.class); + @Advice.FieldValue(value = "retrofit") Retrofit retrofit) { + CallDepth callDepth = CallDepth.forClass(InfluxDBImpl.class); if (callDepth.getAndIncrement() > 0) { - return; + return null; } if (arg0 == null) { - return; + return null; } Context parentContext = currentContext(); @@ -168,44 +140,34 @@ public static void onEnter( // write data by UDP protocol, in this way, can't get database name. : arg0 instanceof Integer ? "" : String.valueOf(arg0); - String sql = methodName; + String operation; if ("createDatabase".equals(methodName)) { - sql = - influxDbImpl.version().startsWith("0.") - ? String.format(CREATE_DATABASE_STATEMENT_OLD, database) - : String.format(CREATE_DATABASE_STATEMENT_NEW, database); + operation = "CREATE DATABASE"; } else if ("deleteDatabase".equals(methodName)) { - sql = String.format(DELETE_DATABASE_STATEMENT, database); + operation = "DROP DATABASE"; + } else { + operation = "WRITE"; } - influxDbRequest = InfluxDbRequest.create(httpUrl.host(), httpUrl.port(), database, sql); + InfluxDbRequest influxDbRequest = + InfluxDbRequest.create(httpUrl.host(), httpUrl.port(), database, operation, null); if (!instrumenter().shouldStart(parentContext, influxDbRequest)) { - return; + return null; } - context = instrumenter().start(parentContext, influxDbRequest); - scope = context.makeCurrent(); + return InfluxDbScope.start(parentContext, influxDbRequest); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void onExit( - @Advice.Thrown Throwable throwable, - @Advice.Local("otelCallDepth") CallDepth callDepth, - @Advice.Local("otelRequest") InfluxDbRequest influxDbRequest, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - - if (callDepth.decrementAndGet() > 0) { - return; - } - - if (scope == null) { + @Advice.Thrown Throwable throwable, @Advice.Enter InfluxDbScope scope) { + CallDepth callDepth = CallDepth.forClass(InfluxDBImpl.class); + if (callDepth.decrementAndGet() > 0 || scope == null) { return; } - scope.close(); - instrumenter().end(context, influxDbRequest, null, throwable); + scope.end(throwable); } } } diff --git a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbInstrumentationModule.java b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbInstrumentationModule.java index 3b95cc8b1c29..3aba153fc408 100644 --- a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbInstrumentationModule.java +++ b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbInstrumentationModule.java @@ -23,10 +23,4 @@ public InfluxDbInstrumentationModule() { public List typeInstrumentations() { return singletonList(new InfluxDbImplInstrumentation()); } - - @Override - public boolean isIndyModule() { - // Uses multiple Advice.Locals and argument assignment - return false; - } } diff --git a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbRequest.java b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbRequest.java index 265b911d7102..560993c266d4 100644 --- a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbRequest.java +++ b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbRequest.java @@ -8,25 +8,28 @@ import com.google.auto.value.AutoValue; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementInfo; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlStatementSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import javax.annotation.Nullable; @AutoValue public abstract class InfluxDbRequest { private static final SqlStatementSanitizer sanitizer = - SqlStatementSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + SqlStatementSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); - public static InfluxDbRequest create(String host, Integer port, String dbName, String sql) { - return new AutoValue_InfluxDbRequest(host, port, dbName, sql, sanitizer.sanitize(sql)); + public static InfluxDbRequest create( + String host, int port, String dbName, String operation, String sql) { + return new AutoValue_InfluxDbRequest(host, port, dbName, operation, sanitizer.sanitize(sql)); } public abstract String getHost(); - public abstract Integer getPort(); + public abstract int getPort(); public abstract String getDbName(); - public abstract String getSql(); + @Nullable + public abstract String getOperation(); public abstract SqlStatementInfo getSqlStatementInfo(); } diff --git a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbScope.java b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbScope.java new file mode 100644 index 000000000000..6daaea80f727 --- /dev/null +++ b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbScope.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.influxdb.v2_4; + +import static io.opentelemetry.javaagent.instrumentation.influxdb.v2_4.InfluxDbSingletons.instrumenter; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; + +/** Container used to carry state between enter and exit advices */ +public final class InfluxDbScope { + private final InfluxDbRequest influxDbRequest; + private final Context context; + private final Scope scope; + + private InfluxDbScope(InfluxDbRequest influxDbRequest, Context context, Scope scope) { + this.influxDbRequest = influxDbRequest; + this.context = context; + this.scope = scope; + } + + public static InfluxDbScope start(Context parentContext, InfluxDbRequest influxDbRequest) { + Context context = instrumenter().start(parentContext, influxDbRequest); + return new InfluxDbScope(influxDbRequest, context, context.makeCurrent()); + } + + public void end(Throwable throwable) { + if (scope == null) { + return; + } + + scope.close(); + + instrumenter().end(context, influxDbRequest, null, throwable); + } +} diff --git a/instrumentation/influxdb-2.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbClientTest.java b/instrumentation/influxdb-2.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbClientTest.java index d239606bfd37..40d5300fe5d8 100644 --- a/instrumentation/influxdb-2.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbClientTest.java +++ b/instrumentation/influxdb-2.4/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbClientTest.java @@ -5,8 +5,6 @@ package io.opentelemetry.javaagent.instrumentation.influxdb.v2_4; -import static io.opentelemetry.javaagent.instrumentation.influxdb.v2_4.InfluxDbConstants.CREATE_DATABASE_STATEMENT_NEW; -import static io.opentelemetry.javaagent.instrumentation.influxdb.v2_4.InfluxDbConstants.DELETE_DATABASE_STATEMENT; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; @@ -108,16 +106,13 @@ void testQueryAndModifyWithOneArgument() { span.hasName("CREATE DATABASE " + dbName) .hasKind(SpanKind.CLIENT) .hasAttributesSatisfying( - attributeAssertions( - String.format(CREATE_DATABASE_STATEMENT_NEW, dbName), - "CREATE DATABASE", - dbName))), + attributeAssertions(null, "CREATE DATABASE", dbName))), trace -> trace.hasSpansSatisfyingExactly( span -> - span.hasName("write " + dbName) + span.hasName("WRITE " + dbName) .hasKind(SpanKind.CLIENT) - .hasAttributesSatisfying(attributeAssertions("write", "write", dbName))), + .hasAttributesSatisfying(attributeAssertions(null, "WRITE", dbName))), trace -> trace.hasSpansSatisfyingExactly( span -> @@ -131,10 +126,7 @@ void testQueryAndModifyWithOneArgument() { span.hasName("DROP DATABASE " + dbName) .hasKind(SpanKind.CLIENT) .hasAttributesSatisfying( - attributeAssertions( - String.format(DELETE_DATABASE_STATEMENT, dbName), - "DROP DATABASE", - dbName)))); + attributeAssertions(null, "DROP DATABASE", dbName)))); } @Test @@ -279,10 +271,10 @@ void testWriteWithFourArguments() { trace -> trace.hasSpansSatisfyingExactly( span -> - span.hasName("write " + databaseName) + span.hasName("WRITE " + databaseName) .hasKind(SpanKind.CLIENT) .hasAttributesSatisfying( - attributeAssertions("write", "write", databaseName)))); + attributeAssertions(null, "WRITE", databaseName)))); } @Test @@ -297,10 +289,10 @@ void testWriteWithFiveArguments() { trace -> trace.hasSpansSatisfyingExactly( span -> - span.hasName("write " + databaseName) + span.hasName("WRITE " + databaseName) .hasKind(SpanKind.CLIENT) .hasAttributesSatisfying( - attributeAssertions("write", "write", databaseName)))); + attributeAssertions(null, "WRITE", databaseName)))); } @Test @@ -316,19 +308,24 @@ void testWriteWithUdp() { trace -> trace.hasSpansSatisfyingExactly( span -> - span.hasName("write") + span.hasName("WRITE") .hasKind(SpanKind.CLIENT) - .hasAttributesSatisfying(attributeAssertions("write", "write", null)))); + .hasAttributesSatisfying(attributeAssertions(null, "WRITE", null)))); } private static List attributeAssertions( String statement, String operation, String databaseName) { - return asList( - equalTo(DbIncubatingAttributes.DB_SYSTEM, "influxdb"), - equalTo(DbIncubatingAttributes.DB_NAME, databaseName), - equalTo(ServerAttributes.SERVER_ADDRESS, host), - equalTo(ServerAttributes.SERVER_PORT, port), - equalTo(DbIncubatingAttributes.DB_STATEMENT, statement), - equalTo(DbIncubatingAttributes.DB_OPERATION, operation)); + List result = new ArrayList<>(); + result.addAll( + asList( + equalTo(DbIncubatingAttributes.DB_SYSTEM, "influxdb"), + equalTo(DbIncubatingAttributes.DB_NAME, databaseName), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(DbIncubatingAttributes.DB_OPERATION, operation))); + if (statement != null) { + result.add(equalTo(DbIncubatingAttributes.DB_STATEMENT, statement)); + } + return result; } } diff --git a/instrumentation/influxdb-2.4/javaagent/src/test24/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbClient24Test.java b/instrumentation/influxdb-2.4/javaagent/src/test24/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbClient24Test.java index faed6afea662..3cd33152551c 100644 --- a/instrumentation/influxdb-2.4/javaagent/src/test24/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbClient24Test.java +++ b/instrumentation/influxdb-2.4/javaagent/src/test24/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbClient24Test.java @@ -5,8 +5,6 @@ package io.opentelemetry.javaagent.instrumentation.influxdb.v2_4; -import static io.opentelemetry.javaagent.instrumentation.influxdb.v2_4.InfluxDbConstants.CREATE_DATABASE_STATEMENT_NEW; -import static io.opentelemetry.javaagent.instrumentation.influxdb.v2_4.InfluxDbConstants.DELETE_DATABASE_STATEMENT; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; @@ -17,6 +15,7 @@ import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.semconv.ServerAttributes; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import org.influxdb.InfluxDB; @@ -101,16 +100,13 @@ void testQueryAndModifyWithOneArgument() { span.hasName("CREATE DATABASE " + dbName) .hasKind(SpanKind.CLIENT) .hasAttributesSatisfying( - attributeAssertions( - String.format(CREATE_DATABASE_STATEMENT_NEW, dbName), - "CREATE DATABASE", - dbName))), + attributeAssertions(null, "CREATE DATABASE", dbName))), trace -> trace.hasSpansSatisfyingExactly( span -> - span.hasName("write " + dbName) + span.hasName("WRITE " + dbName) .hasKind(SpanKind.CLIENT) - .hasAttributesSatisfying(attributeAssertions("write", "write", dbName))), + .hasAttributesSatisfying(attributeAssertions(null, "WRITE", dbName))), trace -> trace.hasSpansSatisfyingExactly( span -> @@ -124,10 +120,7 @@ void testQueryAndModifyWithOneArgument() { span.hasName("DROP DATABASE " + dbName) .hasKind(SpanKind.CLIENT) .hasAttributesSatisfying( - attributeAssertions( - String.format(DELETE_DATABASE_STATEMENT, dbName), - "DROP DATABASE", - dbName)))); + attributeAssertions(null, "DROP DATABASE", dbName)))); } @Test @@ -150,12 +143,17 @@ void testQueryWithTwoArguments() { private static List attributeAssertions( String statement, String operation, String databaseName) { - return asList( - equalTo(DbIncubatingAttributes.DB_SYSTEM, "influxdb"), - equalTo(DbIncubatingAttributes.DB_NAME, databaseName), - equalTo(ServerAttributes.SERVER_ADDRESS, host), - equalTo(ServerAttributes.SERVER_PORT, port), - equalTo(DbIncubatingAttributes.DB_STATEMENT, statement), - equalTo(DbIncubatingAttributes.DB_OPERATION, operation)); + List result = new ArrayList<>(); + result.addAll( + asList( + equalTo(DbIncubatingAttributes.DB_SYSTEM, "influxdb"), + equalTo(DbIncubatingAttributes.DB_NAME, databaseName), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(DbIncubatingAttributes.DB_OPERATION, operation))); + if (statement != null) { + result.add(equalTo(DbIncubatingAttributes.DB_STATEMENT, statement)); + } + return result; } } diff --git a/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/JavaHttpClientSingletons.java b/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/JavaHttpClientSingletons.java index 73d7d2aef13a..9adaf4847367 100644 --- a/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/JavaHttpClientSingletons.java +++ b/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpclient/JavaHttpClientSingletons.java @@ -5,18 +5,13 @@ package io.opentelemetry.javaagent.instrumentation.httpclient; -import static java.util.Collections.singletonList; - import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.httpclient.internal.HttpHeadersSetter; -import io.opentelemetry.instrumentation.httpclient.internal.JavaHttpClientAttributesGetter; -import io.opentelemetry.instrumentation.httpclient.internal.JavaHttpClientInstrumenterFactory; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.instrumentation.httpclient.internal.JavaHttpClientInstrumenterBuilderFactory; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.util.function.Function; public class JavaHttpClientSingletons { @@ -27,20 +22,8 @@ public class JavaHttpClientSingletons { SETTER = new HttpHeadersSetter(GlobalOpenTelemetry.getPropagators()); INSTRUMENTER = - JavaHttpClientInstrumenterFactory.createInstrumenter( - GlobalOpenTelemetry.get(), - builder -> - builder - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - Function.identity(), - singletonList( - HttpClientPeerServiceAttributesExtractor.create( - JavaHttpClientAttributesGetter.INSTANCE, - CommonConfig.get().getPeerServiceResolver())), - CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + JavaagentHttpClientInstrumenters.create( + JavaHttpClientInstrumenterBuilderFactory.create(GlobalOpenTelemetry.get())); } public static Instrumenter> instrumenter() { diff --git a/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/JavaHttpClientTelemetryBuilder.java b/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/JavaHttpClientTelemetryBuilder.java index ca1f753044a7..1e5cbd0c1490 100644 --- a/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/JavaHttpClientTelemetryBuilder.java +++ b/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/JavaHttpClientTelemetryBuilder.java @@ -7,37 +7,24 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; import io.opentelemetry.instrumentation.httpclient.internal.HttpHeadersSetter; -import io.opentelemetry.instrumentation.httpclient.internal.JavaHttpClientInstrumenterFactory; +import io.opentelemetry.instrumentation.httpclient.internal.JavaHttpClientInstrumenterBuilderFactory; import java.net.http.HttpRequest; import java.net.http.HttpResponse; -import java.util.ArrayList; import java.util.List; import java.util.Set; -import java.util.function.Consumer; import java.util.function.Function; public final class JavaHttpClientTelemetryBuilder { - private final OpenTelemetry openTelemetry; - - private final List>> - additionalExtractors = new ArrayList<>(); - private Consumer>> - extractorConfigurer = builder -> {}; - private Consumer> spanNameExtractorConfigurer = - builder -> {}; - private Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer = Function.identity(); - private boolean emitExperimentalHttpClientMetrics = false; + private final DefaultHttpClientInstrumenterBuilder> builder; JavaHttpClientTelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + builder = JavaHttpClientInstrumenterBuilderFactory.create(openTelemetry); } /** @@ -47,31 +34,29 @@ public final class JavaHttpClientTelemetryBuilder { @CanIgnoreReturnValue public JavaHttpClientTelemetryBuilder addAttributeExtractor( AttributesExtractor> attributesExtractor) { - additionalExtractors.add(attributesExtractor); + builder.addAttributeExtractor(attributesExtractor); return this; } /** - * Configures the HTTP client request headers that will be captured as span attributes. + * Configures the HTTP request headers that will be captured as span attributes. * * @param requestHeaders A list of HTTP header names. */ @CanIgnoreReturnValue public JavaHttpClientTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setCapturedRequestHeaders(requestHeaders)); + builder.setCapturedRequestHeaders(requestHeaders); return this; } /** - * Configures the HTTP client response headers that will be captured as span attributes. + * Configures the HTTP response headers that will be captured as span attributes. * * @param responseHeaders A list of HTTP header names. */ @CanIgnoreReturnValue public JavaHttpClientTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setCapturedResponseHeaders(responseHeaders)); + builder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -90,10 +75,7 @@ public JavaHttpClientTelemetryBuilder setCapturedResponseHeaders(List re */ @CanIgnoreReturnValue public JavaHttpClientTelemetryBuilder setKnownMethods(Set knownMethods) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); - spanNameExtractorConfigurer = - spanNameExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); + builder.setKnownMethods(knownMethods); return this; } @@ -106,7 +88,7 @@ public JavaHttpClientTelemetryBuilder setKnownMethods(Set knownMethods) @CanIgnoreReturnValue public JavaHttpClientTelemetryBuilder setEmitExperimentalHttpClientMetrics( boolean emitExperimentalHttpClientMetrics) { - this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; + builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics); return this; } @@ -115,21 +97,12 @@ public JavaHttpClientTelemetryBuilder setEmitExperimentalHttpClientMetrics( public JavaHttpClientTelemetryBuilder setSpanNameExtractor( Function, ? extends SpanNameExtractor> spanNameExtractorTransformer) { - this.spanNameExtractorTransformer = spanNameExtractorTransformer; + builder.setSpanNameExtractor(spanNameExtractorTransformer); return this; } public JavaHttpClientTelemetry build() { - Instrumenter> instrumenter = - JavaHttpClientInstrumenterFactory.createInstrumenter( - openTelemetry, - extractorConfigurer, - spanNameExtractorConfigurer, - spanNameExtractorTransformer, - additionalExtractors, - emitExperimentalHttpClientMetrics); - return new JavaHttpClientTelemetry( - instrumenter, new HttpHeadersSetter(openTelemetry.getPropagators())); + builder.build(), new HttpHeadersSetter(builder.getOpenTelemetry().getPropagators())); } } diff --git a/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientAttributesGetter.java b/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientAttributesGetter.java index 1c80acc173aa..e60a23b8c704 100644 --- a/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientAttributesGetter.java +++ b/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientAttributesGetter.java @@ -12,11 +12,7 @@ import java.util.List; import javax.annotation.Nullable; -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public enum JavaHttpClientAttributesGetter +enum JavaHttpClientAttributesGetter implements HttpClientAttributesGetter> { INSTANCE; diff --git a/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientInstrumenterBuilderFactory.java b/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientInstrumenterBuilderFactory.java new file mode 100644 index 000000000000..9f9bb506f643 --- /dev/null +++ b/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientInstrumenterBuilderFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.httpclient.internal; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class JavaHttpClientInstrumenterBuilderFactory { + private JavaHttpClientInstrumenterBuilderFactory() {} + + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.java-http-client"; + + public static DefaultHttpClientInstrumenterBuilder> create( + OpenTelemetry openTelemetry) { + return new DefaultHttpClientInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, JavaHttpClientAttributesGetter.INSTANCE); + } +} diff --git a/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientInstrumenterFactory.java b/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientInstrumenterFactory.java deleted file mode 100644 index 12c5439fcb7b..000000000000 --- a/instrumentation/java-http-client/library/src/main/java/io/opentelemetry/instrumentation/httpclient/internal/JavaHttpClientInstrumenterFactory.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.httpclient.internal; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public final class JavaHttpClientInstrumenterFactory { - private static final String INSTRUMENTATION_NAME = "io.opentelemetry.java-http-client"; - - public static Instrumenter> createInstrumenter( - OpenTelemetry openTelemetry, - Consumer>> - extractorConfigurer, - Consumer> spanNameExtractorConfigurer, - Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer, - List>> additionalExtractors, - boolean emitExperimentalHttpClientMetrics) { - - JavaHttpClientAttributesGetter httpAttributesGetter = JavaHttpClientAttributesGetter.INSTANCE; - - HttpClientAttributesExtractorBuilder> - httpAttributesExtractorBuilder = - HttpClientAttributesExtractor.builder(httpAttributesGetter); - extractorConfigurer.accept(httpAttributesExtractorBuilder); - - HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(httpAttributesGetter); - spanNameExtractorConfigurer.accept(httpSpanNameExtractorBuilder); - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder> builder = - Instrumenter.>builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(httpAttributesExtractorBuilder.build()) - .addAttributesExtractors(additionalExtractors) - .addOperationMetrics(HttpClientMetrics.get()); - if (emitExperimentalHttpClientMetrics) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); - } - - private JavaHttpClientInstrumenterFactory() {} -} diff --git a/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java b/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java index 434ec148421a..780e7307c845 100644 --- a/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java +++ b/instrumentation/java-util-logging/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jul/JavaUtilLoggingHelper.java @@ -12,7 +12,7 @@ import io.opentelemetry.api.logs.LogRecordBuilder; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.semconv.ExceptionAttributes; import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes; import java.io.PrintWriter; @@ -27,7 +27,7 @@ public final class JavaUtilLoggingHelper { private static final Formatter FORMATTER = new AccessibleFormatter(); private static final boolean captureExperimentalAttributes = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.java-util-logging.experimental-log-attributes", false); public static void capture(Logger logger, LogRecord logRecord) { diff --git a/instrumentation/javalin-5.0/javaagent/build.gradle.kts b/instrumentation/javalin-5.0/javaagent/build.gradle.kts new file mode 100644 index 000000000000..e231ce371748 --- /dev/null +++ b/instrumentation/javalin-5.0/javaagent/build.gradle.kts @@ -0,0 +1,24 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +muzzle { + pass { + group.set("io.javalin") + module.set("javalin") + versions.set("[5.0.0,)") + // 3.2.0 depends on org.meteogroup.jbrotli:jbrotli:0.5.0 that is not available in central + skip("3.2.0") + assertInverse.set(true) + } +} + +otelJava { + minJavaVersionSupported.set(JavaVersion.VERSION_11) +} + +dependencies { + library("io.javalin:javalin:5.0.0") + + testInstrumentation(project(":instrumentation:jetty:jetty-11.0:javaagent")) +} diff --git a/instrumentation/javalin-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/JavalinInstrumentation.java b/instrumentation/javalin-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/JavalinInstrumentation.java new file mode 100644 index 000000000000..b7ae2a4a5d0e --- /dev/null +++ b/instrumentation/javalin-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/JavalinInstrumentation.java @@ -0,0 +1,48 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.javalin.v5_0; + +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasSuperType; +import static net.bytebuddy.matcher.ElementMatchers.isInterface; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.not; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import io.javalin.http.Context; +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteSource; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class JavalinInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return hasSuperType(named("io.javalin.http.Handler")).and(not(isInterface())); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("handle").and(takesArgument(0, named("io.javalin.http.Context"))), + this.getClass().getName() + "$HandlerAdapterAdvice"); + } + + @SuppressWarnings("unused") + public static class HandlerAdapterAdvice { + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onAfterExecute(@Advice.Argument(0) Context ctx, @Advice.Thrown Throwable t) { + HttpServerRoute.update( + io.opentelemetry.context.Context.current(), + HttpServerRouteSource.CONTROLLER, + ctx.endpointHandlerPath()); + } + } +} diff --git a/instrumentation/javalin-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/JavalinInstrumentationModule.java b/instrumentation/javalin-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/JavalinInstrumentationModule.java new file mode 100644 index 000000000000..09d81be0b083 --- /dev/null +++ b/instrumentation/javalin-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/JavalinInstrumentationModule.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.javalin.v5_0; + +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; + +@SuppressWarnings("unused") +@AutoService(InstrumentationModule.class) +public class JavalinInstrumentationModule extends InstrumentationModule { + + public JavalinInstrumentationModule() { + super("javalin", "javalin-5"); + } + + @Override + public List typeInstrumentations() { + return singletonList(new JavalinInstrumentation()); + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + return hasClassesNamed("io.javalin.http.Handler"); + } +} diff --git a/instrumentation/javalin-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/JavalinTest.java b/instrumentation/javalin-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/JavalinTest.java new file mode 100644 index 000000000000..b9c16a4b941c --- /dev/null +++ b/instrumentation/javalin-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/JavalinTest.java @@ -0,0 +1,170 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.javalin.v5_0; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.HttpAttributes.HTTP_ROUTE; + +import io.javalin.Javalin; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.test.utils.PortUtils; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.semconv.ClientAttributes; +import io.opentelemetry.semconv.ErrorAttributes; +import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.NetworkAttributes; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.UrlAttributes; +import io.opentelemetry.semconv.UserAgentAttributes; +import io.opentelemetry.testing.internal.armeria.client.WebClient; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JavalinTest { + + @RegisterExtension + private static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static Javalin app; + private static int port; + private static WebClient client; + + @BeforeAll + static void setup() { + port = PortUtils.findOpenPort(); + app = TestJavalinJavaApplication.initJavalin(port); + client = WebClient.of("http://localhost:" + port); + } + + @AfterAll + static void cleanup() { + app.stop(); + } + + @Test + void testSpanNameAndHttpRouteSpanWithPathParamResponseSuccessful() { + String id = "123"; + AggregatedHttpResponse response = client.get("/param/" + id).aggregate().join(); + String content = response.contentUtf8(); + + assertThat(content).isEqualTo(id); + assertThat(response.status().code()).isEqualTo(200); + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET /param/{id}") + .hasKind(SpanKind.SERVER) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(UrlAttributes.URL_SCHEME, "http"), + equalTo(UrlAttributes.URL_PATH, "/param/" + id), + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + satisfies( + UserAgentAttributes.USER_AGENT_ORIGINAL, + val -> val.isInstanceOf(String.class)), + equalTo(HTTP_ROUTE, "/param/{id}"), + equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"), + satisfies( + NetworkAttributes.NETWORK_PEER_PORT, + val -> val.isInstanceOf(Long.class))))); + } + + @Test + void testSpanNameAndHttpRouteSpanResponseError() { + client.get("/error").aggregate().join(); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET /error") + .hasKind(SpanKind.SERVER) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(UrlAttributes.URL_SCHEME, "http"), + equalTo(UrlAttributes.URL_PATH, "/error"), + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 500), + satisfies( + UserAgentAttributes.USER_AGENT_ORIGINAL, + val -> val.isInstanceOf(String.class)), + equalTo(HTTP_ROUTE, "/error"), + equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(ErrorAttributes.ERROR_TYPE, "500"), + equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"), + satisfies( + NetworkAttributes.NETWORK_PEER_PORT, + val -> val.isInstanceOf(Long.class))))); + } + + @Test + public void testSpanNameAndHttpRouteSpanAsyncRouteResponseSuccessful() { + AggregatedHttpResponse response = client.get("/async").aggregate().join(); + + assertThat(response.status().code()).isEqualTo(200); + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET /async") + .hasKind(SpanKind.SERVER) + .hasNoParent() + .hasAttributesSatisfyingExactly( + equalTo(UrlAttributes.URL_SCHEME, "http"), + equalTo(UrlAttributes.URL_PATH, "/async"), + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + satisfies( + UserAgentAttributes.USER_AGENT_ORIGINAL, + val -> val.isInstanceOf(String.class)), + equalTo(HTTP_ROUTE, "/async"), + equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"), + satisfies( + NetworkAttributes.NETWORK_PEER_PORT, + val -> val.isInstanceOf(Long.class))))); + } + + @Test + void testHttpRouteMetricWithPathParamResponseSuccessful() { + String id = "123"; + AggregatedHttpResponse response = client.get("/param/" + id).aggregate().join(); + String content = response.contentUtf8(); + String instrumentation = "io.opentelemetry.jetty-11.0"; + + assertThat(content).isEqualTo(id); + assertThat(response.status().code()).isEqualTo(200); + testing.waitAndAssertMetrics( + instrumentation, + "http.server.request.duration", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> point.hasAttribute(HTTP_ROUTE, "/param/{id}"))))); + } +} diff --git a/instrumentation/javalin-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/TestJavalinJavaApplication.java b/instrumentation/javalin-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/TestJavalinJavaApplication.java new file mode 100644 index 000000000000..14f7ce45987d --- /dev/null +++ b/instrumentation/javalin-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/javalin/v5_0/TestJavalinJavaApplication.java @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.javalin.v5_0; + +import io.javalin.Javalin; + +public class TestJavalinJavaApplication { + + private TestJavalinJavaApplication() {} + + public static Javalin initJavalin(int port) { + Javalin app = Javalin.create().start(port); + app.get( + "/param/{id}", + ctx -> { + String paramId = ctx.pathParam("id"); + ctx.result(paramId); + }); + app.get( + "/error", + ctx -> { + throw new RuntimeException("boom"); + }); + app.get("/async", ctx -> ctx.async(() -> ctx.result("ok"))); + return app; + } +} diff --git a/instrumentation/jaxrs/jaxrs-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/JaxrsConfig.java b/instrumentation/jaxrs/jaxrs-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/JaxrsConfig.java index 5327611e44f7..3457cfba7f24 100644 --- a/instrumentation/jaxrs/jaxrs-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/JaxrsConfig.java +++ b/instrumentation/jaxrs/jaxrs-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/JaxrsConfig.java @@ -5,12 +5,12 @@ package io.opentelemetry.javaagent.instrumentation.jaxrs; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class JaxrsConfig { public static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.jaxrs.experimental-span-attributes", false); private JaxrsConfig() {} diff --git a/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java b/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java index 66c685c968d4..b8e13d2f3e19 100644 --- a/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java +++ b/instrumentation/jboss-logmanager/jboss-logmanager-appender-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/appender/v1_1/LoggingEventMapper.java @@ -16,7 +16,7 @@ import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.internal.cache.Cache; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.semconv.ExceptionAttributes; import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes; import java.io.PrintWriter; @@ -37,7 +37,7 @@ public final class LoggingEventMapper { private final List captureMdcAttributes; private static final boolean captureExperimentalAttributes = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.jboss-logmanager.experimental-log-attributes", false); // cached as an optimization @@ -45,7 +45,7 @@ public final class LoggingEventMapper { private LoggingEventMapper() { this.captureMdcAttributes = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getList( "otel.instrumentation.jboss-logmanager.experimental.capture-mdc-attributes", emptyList()); diff --git a/instrumentation/jboss-logmanager/jboss-logmanager-mdc-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/mdc/v1_1/JbossExtLogRecordInstrumentation.java b/instrumentation/jboss-logmanager/jboss-logmanager-mdc-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/mdc/v1_1/JbossExtLogRecordInstrumentation.java index b192eee169f4..5fb6ce47fc0b 100644 --- a/instrumentation/jboss-logmanager/jboss-logmanager-mdc-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/mdc/v1_1/JbossExtLogRecordInstrumentation.java +++ b/instrumentation/jboss-logmanager/jboss-logmanager-mdc-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/mdc/v1_1/JbossExtLogRecordInstrumentation.java @@ -15,7 +15,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import java.util.Map; @@ -55,9 +55,9 @@ public static void onExit( @Advice.This ExtLogRecord record, @Advice.Argument(0) String key, @Advice.Return(readOnly = false) String value) { - if (CommonConfig.get().getTraceIdKey().equals(key) - || CommonConfig.get().getSpanIdKey().equals(key) - || CommonConfig.get().getTraceFlagsKey().equals(key)) { + if (AgentCommonConfig.get().getTraceIdKey().equals(key) + || AgentCommonConfig.get().getSpanIdKey().equals(key) + || AgentCommonConfig.get().getTraceFlagsKey().equals(key)) { if (value != null) { // Assume already instrumented event if traceId/spanId/sampled is present. return; @@ -72,13 +72,13 @@ public static void onExit( return; } - if (CommonConfig.get().getTraceIdKey().equals(key)) { + if (AgentCommonConfig.get().getTraceIdKey().equals(key)) { value = spanContext.getTraceId(); } - if (CommonConfig.get().getSpanIdKey().equals(key)) { + if (AgentCommonConfig.get().getSpanIdKey().equals(key)) { value = spanContext.getSpanId(); } - if (CommonConfig.get().getTraceFlagsKey().equals(key)) { + if (AgentCommonConfig.get().getTraceFlagsKey().equals(key)) { value = spanContext.getTraceFlags().asHex(); } } @@ -93,9 +93,9 @@ public static void onExit( @Advice.This ExtLogRecord record, @Advice.Return(readOnly = false) Map value) { - if (value.containsKey(CommonConfig.get().getTraceIdKey()) - && value.containsKey(CommonConfig.get().getSpanIdKey()) - && value.containsKey(CommonConfig.get().getTraceFlagsKey())) { + if (value.containsKey(AgentCommonConfig.get().getTraceIdKey()) + && value.containsKey(AgentCommonConfig.get().getSpanIdKey()) + && value.containsKey(AgentCommonConfig.get().getTraceFlagsKey())) { return; } @@ -109,16 +109,16 @@ public static void onExit( return; } - if (!value.containsKey(CommonConfig.get().getTraceIdKey())) { - value.put(CommonConfig.get().getTraceIdKey(), spanContext.getTraceId()); + if (!value.containsKey(AgentCommonConfig.get().getTraceIdKey())) { + value.put(AgentCommonConfig.get().getTraceIdKey(), spanContext.getTraceId()); } - if (!value.containsKey(CommonConfig.get().getSpanIdKey())) { - value.put(CommonConfig.get().getSpanIdKey(), spanContext.getSpanId()); + if (!value.containsKey(AgentCommonConfig.get().getSpanIdKey())) { + value.put(AgentCommonConfig.get().getSpanIdKey(), spanContext.getSpanId()); } - if (!value.containsKey(CommonConfig.get().getTraceFlagsKey())) { - value.put(CommonConfig.get().getTraceFlagsKey(), spanContext.getTraceFlags().asHex()); + if (!value.containsKey(AgentCommonConfig.get().getTraceFlagsKey())) { + value.put(AgentCommonConfig.get().getTraceFlagsKey(), spanContext.getTraceFlags().asHex()); } } } diff --git a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcSingletons.java b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcSingletons.java index 7083282e8aba..afc92f2fcad9 100644 --- a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcSingletons.java +++ b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/JdbcSingletons.java @@ -17,8 +17,8 @@ import io.opentelemetry.instrumentation.jdbc.internal.DbRequest; import io.opentelemetry.instrumentation.jdbc.internal.JdbcAttributesGetter; import io.opentelemetry.instrumentation.jdbc.internal.JdbcNetworkAttributesGetter; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.jdbc.DbInfo; import javax.sql.DataSource; @@ -41,15 +41,15 @@ public final class JdbcSingletons { .addAttributesExtractor( SqlClientAttributesExtractor.builder(dbAttributesGetter) .setStatementSanitizationEnabled( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean( "otel.instrumentation.jdbc.statement-sanitizer.enabled", - CommonConfig.get().isStatementSanitizationEnabled())) + AgentCommonConfig.get().isStatementSanitizationEnabled())) .build()) .addAttributesExtractor(ServerAttributesExtractor.create(netAttributesGetter)) .addAttributesExtractor( PeerServiceAttributesExtractor.create( - netAttributesGetter, CommonConfig.get().getPeerServiceResolver())) + netAttributesGetter, AgentCommonConfig.get().getPeerServiceResolver())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/jdbc/library/build.gradle.kts b/instrumentation/jdbc/library/build.gradle.kts index e5c6649cff54..02af72e4c9dc 100644 --- a/instrumentation/jdbc/library/build.gradle.kts +++ b/instrumentation/jdbc/library/build.gradle.kts @@ -4,7 +4,7 @@ */ plugins { - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") id("otel.library-instrumentation") } diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesGetter.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesGetter.java index 3ae3372ca95f..8ad1c67c30cb 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesGetter.java +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesGetter.java @@ -7,14 +7,14 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter; import io.opentelemetry.instrumentation.api.incubator.semconv.db.RedisCommandSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; final class JedisDbAttributesGetter implements DbClientAttributesGetter { private static final RedisCommandSanitizer sanitizer = - RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + RedisCommandSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); @Override public String getSystem(JedisRequest request) { diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java index d9ce8ccaedf5..6bf94ca5988d 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java @@ -12,7 +12,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; public final class JedisSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jedis-1.4"; @@ -32,7 +32,7 @@ public final class JedisSingletons { .addAttributesExtractor(ServerAttributesExtractor.create(netAttributesGetter)) .addAttributesExtractor( PeerServiceAttributesExtractor.create( - netAttributesGetter, CommonConfig.get().getPeerServiceResolver())) + netAttributesGetter, AgentCommonConfig.get().getPeerServiceResolver())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisRequest.java b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisRequest.java index 0c5b24df709a..36b71513660e 100644 --- a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisRequest.java +++ b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisRequest.java @@ -7,7 +7,7 @@ import com.google.auto.value.AutoValue; import io.opentelemetry.instrumentation.api.incubator.semconv.db.RedisCommandSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import java.nio.charset.StandardCharsets; import java.util.List; import redis.clients.jedis.Connection; @@ -18,7 +18,7 @@ public abstract class JedisRequest { private static final RedisCommandSanitizer sanitizer = - RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + RedisCommandSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); public static JedisRequest create( Connection connection, ProtocolCommand command, List args) { diff --git a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java index cb406ae43a9a..d52152caccab 100644 --- a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java +++ b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java @@ -13,7 +13,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.network.NetworkAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; public final class JedisSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jedis-3.0"; @@ -34,7 +34,7 @@ public final class JedisSingletons { .addAttributesExtractor(NetworkAttributesExtractor.create(netAttributesGetter)) .addAttributesExtractor( PeerServiceAttributesExtractor.create( - netAttributesGetter, CommonConfig.get().getPeerServiceResolver())) + netAttributesGetter, AgentCommonConfig.get().getPeerServiceResolver())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisRequest.java b/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisRequest.java index 3cb189d3fa3e..a8c26bfaabbb 100644 --- a/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisRequest.java +++ b/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisRequest.java @@ -7,7 +7,7 @@ import com.google.auto.value.AutoValue; import io.opentelemetry.instrumentation.api.incubator.semconv.db.RedisCommandSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import java.net.Socket; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; @@ -22,7 +22,7 @@ public abstract class JedisRequest { private static final RedisCommandSanitizer sanitizer = - RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + RedisCommandSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); public static JedisRequest create(ProtocolCommand command, List args) { return new AutoValue_JedisRequest(command, args); diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts new file mode 100644 index 000000000000..ae4b56855e0c --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +muzzle { + pass { + group.set("org.eclipse.jetty") + module.set("jetty-client") + versions.set("[12,)") + } +} + +otelJava { + minJavaVersionSupported.set(JavaVersion.VERSION_17) +} + +dependencies { + implementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:library")) + + library("org.eclipse.jetty:jetty-client:12.0.0") + + testInstrumentation(project(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:javaagent")) + + testImplementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:testing")) +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java new file mode 100644 index 000000000000..940ede1b69d1 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java @@ -0,0 +1,108 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.JETTY_CLIENT_CONTEXT_KEY; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; +import static net.bytebuddy.matcher.ElementMatchers.nameContains; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.client.Result; + +public class JettyClient12ResponseListenersInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("org.eclipse.jetty.client.transport.ResponseListeners"); + } + + @Override + public void transform(TypeTransformer transformer) { + // for response listeners + transformer.applyAdviceToMethod( + isMethod() + .and( + nameContains("notify") + .and(isPublic()) + .and(takesArgument(0, named("org.eclipse.jetty.client.Response")))), + JettyClient12ResponseListenersInstrumentation.class.getName() + + "$JettyHttpClient12RespListenersNotifyAdvice"); + + // for complete listeners + transformer.applyAdviceToMethod( + isMethod() + .and( + nameContains("notifyComplete") + .and(isPublic()) + .and(takesArgument(0, named("org.eclipse.jetty.client.Result")))), + JettyClient12ResponseListenersInstrumentation.class.getName() + + "$JettyHttpClient12CompleteListenersNotifyAdvice"); + } + + @SuppressWarnings("unused") + public static class JettyHttpClient12RespListenersNotifyAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnterNotify( + @Advice.Argument(0) Response response, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + context = (Context) response.getRequest().getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); + if (context != null) { + scope = context.makeCurrent(); + } + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExitNotify( + @Advice.Argument(0) Response response, + @Advice.Thrown Throwable throwable, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + if (scope == null) { + return; + } + + scope.close(); + } + } + + @SuppressWarnings("unused") + public static class JettyHttpClient12CompleteListenersNotifyAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnterComplete( + @Advice.Argument(0) Result result, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + context = (Context) result.getRequest().getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); + if (context != null) { + scope = context.makeCurrent(); + } + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExitComplete( + @Advice.Argument(0) Result result, + @Advice.Thrown Throwable throwable, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + if (scope == null) { + return; + } + + scope.close(); + } + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java new file mode 100644 index 000000000000..9ba900164b36 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java @@ -0,0 +1,107 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.JETTY_CLIENT_CONTEXT_KEY; +import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.instrumenter; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.nameContains; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientTracingListener; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.eclipse.jetty.client.transport.HttpRequest; + +public class JettyHttpClient12Instrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("org.eclipse.jetty.client.transport.HttpRequest"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + isMethod() + .and(named("send")) + .and(takesArgument(0, named("org.eclipse.jetty.client.Response$CompleteListener"))), + JettyHttpClient12Instrumentation.class.getName() + "$JettyHttpClient12SendAdvice"); + // For request listeners + transformer.applyAdviceToMethod( + isMethod().and(nameContains("notify")), + JettyHttpClient12Instrumentation.class.getName() + "$JettyHttpClient12NotifyAdvice"); + } + + @SuppressWarnings("unused") + public static class JettyHttpClient12SendAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnterSend( + @Advice.This HttpRequest request, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + // start span + Context parentContext = Context.current(); + context = JettyClientTracingListener.handleRequest(parentContext, request, instrumenter()); + if (context == null) { + return; + } + // set context for responseListeners + request.attribute(JETTY_CLIENT_CONTEXT_KEY, parentContext); + + scope = context.makeCurrent(); + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExitSend( + @Advice.This HttpRequest request, + @Advice.Thrown Throwable throwable, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + if (scope == null) { + return; + } + + // not ending span here unless error, span ended in the interceptor + scope.close(); + if (throwable != null) { + instrumenter().end(context, request, null, throwable); + } + } + } + + @SuppressWarnings("unused") + public static class JettyHttpClient12NotifyAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnterNotify( + @Advice.This HttpRequest request, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + context = (Context) request.getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); + if (context == null) { + return; + } + scope = context.makeCurrent(); + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExitNotify( + @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { + if (scope == null) { + return; + } + + scope.close(); + } + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java new file mode 100644 index 000000000000..5d9690dbc7f4 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java @@ -0,0 +1,27 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import static java.util.Arrays.asList; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import java.util.List; + +@AutoService(InstrumentationModule.class) +public class JettyHttpClient12InstrumentationModule extends InstrumentationModule { + public JettyHttpClient12InstrumentationModule() { + super("jetty-httpclient", "jetty-httpclient-12.0"); + } + + @Override + public List typeInstrumentations() { + return asList( + new JettyHttpClient12Instrumentation(), + new JettyClient12ResponseListenersInstrumentation()); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java new file mode 100644 index 000000000000..68a9bca5adda --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyHttpClientInstrumenterBuilderFactory; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; + +public final class JettyHttpClientSingletons { + + static final String JETTY_CLIENT_CONTEXT_KEY = "otel-jetty-client-context"; + + private static final Instrumenter INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + JettyHttpClientInstrumenterBuilderFactory.create(GlobalOpenTelemetry.get())); + + public static Instrumenter instrumenter() { + return INSTRUMENTER; + } + + private JettyHttpClientSingletons() {} +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java new file mode 100644 index 000000000000..7884e15938e7 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java @@ -0,0 +1,31 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.AbstractJettyClient12Test; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JettyHttpClient12AgentTest extends AbstractJettyClient12Test { + + @RegisterExtension + static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); + + @Override + protected HttpClient createStandardClient() { + return new HttpClient(); + } + + @Override + protected HttpClient createHttpsClient(SslContextFactory.Client sslContextFactory) { + HttpClient httpClient = new HttpClient(); + httpClient.setSslContextFactory(sslContextFactory); + return httpClient; + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts new file mode 100644 index 000000000000..da2df5c220a1 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + id("otel.library-instrumentation") +} + +otelJava { + minJavaVersionSupported.set(JavaVersion.VERSION_17) +} + +dependencies { + library("org.eclipse.jetty:jetty-client:12.0.0") + + testImplementation(project(":instrumentation:jetty-httpclient::jetty-httpclient-12.0:testing")) +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetry.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetry.java new file mode 100644 index 000000000000..3e123801321a --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetry.java @@ -0,0 +1,37 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.api.OpenTelemetry; +import org.eclipse.jetty.client.HttpClient; + +/** Entrypoint for instrumenting Jetty client. */ +public final class JettyClientTelemetry { + + /** Returns a new {@link JettyClientTelemetry} configured with the given {@link OpenTelemetry}. */ + public static JettyClientTelemetry create(OpenTelemetry openTelemetry) { + JettyClientTelemetryBuilder builder = builder(openTelemetry); + return builder.build(); + } + + /** + * Returns a new {@link JettyClientTelemetryBuilder} configured with the given {@link + * OpenTelemetry}. + */ + public static JettyClientTelemetryBuilder builder(OpenTelemetry openTelemetry) { + return new JettyClientTelemetryBuilder(openTelemetry); + } + + private final HttpClient httpClient; + + JettyClientTelemetry(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public HttpClient getHttpClient() { + return httpClient; + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java new file mode 100644 index 000000000000..a914f73d266f --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java @@ -0,0 +1,131 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyHttpClientInstrumenterBuilderFactory; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import org.eclipse.jetty.client.HttpClientTransport; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +public final class JettyClientTelemetryBuilder { + + private final DefaultHttpClientInstrumenterBuilder builder; + private HttpClientTransport httpClientTransport; + private SslContextFactory.Client sslContextFactory; + + JettyClientTelemetryBuilder(OpenTelemetry openTelemetry) { + builder = JettyHttpClientInstrumenterBuilderFactory.create(openTelemetry); + } + + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setHttpClientTransport( + HttpClientTransport httpClientTransport) { + this.httpClientTransport = httpClientTransport; + return this; + } + + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setSslContextFactory( + SslContextFactory.Client sslContextFactory) { + this.sslContextFactory = sslContextFactory; + return this; + } + + /** + * Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented + * items. + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder addAttributeExtractor( + AttributesExtractor attributesExtractor) { + builder.addAttributeExtractor(attributesExtractor); + return this; + } + + /** + * Configures the HTTP request headers that will be captured as span attributes. + * + * @param requestHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { + builder.setCapturedRequestHeaders(requestHeaders); + return this; + } + + /** + * Configures the HTTP response headers that will be captured as span attributes. + * + * @param responseHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { + builder.setCapturedResponseHeaders(responseHeaders); + return this; + } + + /** + * Configures the instrumentation to recognize an alternative set of HTTP request methods. + * + *

By default, this instrumentation defines "known" methods as the ones listed in RFC9110 and the PATCH + * method defined in RFC5789. + * + *

Note: calling this method overrides the default known method sets completely; it does + * not supplement it. + * + * @param knownMethods A set of recognized HTTP request methods. + * @see HttpClientAttributesExtractorBuilder#setKnownMethods(Set) + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setKnownMethods(Set knownMethods) { + builder.setKnownMethods(knownMethods); + return this; + } + + /** + * Configures the instrumentation to emit experimental HTTP client metrics. + * + * @param emitExperimentalHttpClientMetrics {@code true} if the experimental HTTP client metrics + * are to be emitted. + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setEmitExperimentalHttpClientMetrics( + boolean emitExperimentalHttpClientMetrics) { + builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics); + return this; + } + + /** Sets custom {@link SpanNameExtractor} via transform function. */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setSpanNameExtractor( + Function, ? extends SpanNameExtractor> + spanNameExtractorTransformer) { + builder.setSpanNameExtractor(spanNameExtractorTransformer); + return this; + } + + /** + * Returns a new {@link JettyClientTelemetry} with the settings of this {@link + * JettyClientTelemetryBuilder}. + */ + public JettyClientTelemetry build() { + TracingHttpClient tracingHttpClient = + TracingHttpClient.buildNew(builder.build(), sslContextFactory, httpClientTransport); + + return new JettyClientTelemetry(tracingHttpClient); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java new file mode 100644 index 000000000000..6507d00bd7dd --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java @@ -0,0 +1,60 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import java.net.URI; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpClientTransport; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.client.transport.HttpConversation; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +class TracingHttpClient extends HttpClient { + + private final Instrumenter instrumenter; + + TracingHttpClient(Instrumenter instrumenter) { + this.instrumenter = instrumenter; + } + + TracingHttpClient( + Instrumenter instrumenter, SslContextFactory.Client sslContextFactory) { + setSslContextFactory(sslContextFactory); + this.instrumenter = instrumenter; + } + + TracingHttpClient( + Instrumenter instrumenter, + HttpClientTransport transport, + SslContextFactory.Client sslContextFactory) { + super(transport); + setSslContextFactory(sslContextFactory); + this.instrumenter = instrumenter; + } + + static TracingHttpClient buildNew( + Instrumenter instrumenter, + SslContextFactory.Client sslContextFactory, + HttpClientTransport httpClientTransport) { + TracingHttpClient tracingHttpClient; + if (sslContextFactory != null && httpClientTransport != null) { + tracingHttpClient = + new TracingHttpClient(instrumenter, httpClientTransport, sslContextFactory); + } else if (sslContextFactory != null) { + tracingHttpClient = new TracingHttpClient(instrumenter, sslContextFactory); + } else { + tracingHttpClient = new TracingHttpClient(instrumenter); + } + return tracingHttpClient; + } + + @Override + public Request newRequest(URI uri) { + return new TracingHttpRequest(this, new HttpConversation(), uri, instrumenter); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java new file mode 100644 index 000000000000..9bdc687c250d --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java @@ -0,0 +1,99 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientTracingListener; +import java.net.URI; +import java.nio.ByteBuffer; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.client.transport.HttpConversation; +import org.eclipse.jetty.client.transport.HttpRequest; + +class TracingHttpRequest extends HttpRequest { + + private final Instrumenter instrumenter; + private Context parentContext; + + public TracingHttpRequest( + HttpClient client, + HttpConversation conversation, + URI uri, + Instrumenter instrumenter) { + super(client, conversation, uri); + this.instrumenter = instrumenter; + } + + @Override + public void send(Response.CompleteListener listener) { + parentContext = Context.current(); + // start span and attach listeners. + JettyClientTracingListener.handleRequest(parentContext, this, instrumenter); + super.send( + result -> { + try (Scope scope = openScope()) { + listener.onComplete(result); + } + }); + } + + private Scope openScope() { + return parentContext != null ? parentContext.makeCurrent() : null; + } + + @Override + public void notifyQueued() { + try (Scope scope = openScope()) { + super.notifyQueued(); + } + } + + @Override + public void notifyBegin() { + try (Scope scope = openScope()) { + super.notifyBegin(); + } + } + + @Override + public void notifyHeaders() { + try (Scope scope = openScope()) { + super.notifyHeaders(); + } + } + + @Override + public void notifyCommit() { + try (Scope scope = openScope()) { + super.notifyCommit(); + } + } + + @Override + public void notifyContent(ByteBuffer byteBuffer) { + try (Scope scope = openScope()) { + super.notifyContent(byteBuffer); + } + } + + @Override + public void notifySuccess() { + try (Scope scope = openScope()) { + super.notifySuccess(); + } + } + + @Override + public void notifyFailure(Throwable failure) { + try (Scope scope = openScope()) { + super.notifyFailure(failure); + } + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/HttpHeaderSetter.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/HttpHeaderSetter.java new file mode 100644 index 000000000000..b094abd3a4dc --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/HttpHeaderSetter.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.context.propagation.TextMapSetter; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.http.HttpField; + +enum HttpHeaderSetter implements TextMapSetter { + INSTANCE; + + @Override + public void set(Request request, String key, String value) { + if (request != null) { + request.headers( + httpFields -> { + httpFields.put(new HttpField(key, value)); + }); + } + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java new file mode 100644 index 000000000000..6a241120fd55 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java @@ -0,0 +1,84 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.instrumentation.api.internal.HttpProtocolUtil; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; +import java.util.List; +import javax.annotation.Nullable; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.http.HttpVersion; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public enum JettyClientHttpAttributesGetter + implements HttpClientAttributesGetter { + INSTANCE; + + @Override + @Nullable + public String getHttpRequestMethod(Request request) { + return request.getMethod(); + } + + @Override + @Nullable + public String getUrlFull(Request request) { + return request.getURI().toString(); + } + + @Override + public List getHttpRequestHeader(Request request, String name) { + return request.getHeaders().getValuesList(name); + } + + @Override + public Integer getHttpResponseStatusCode( + Request request, Response response, @Nullable Throwable error) { + return response.getStatus(); + } + + @Override + public List getHttpResponseHeader(Request request, Response response, String name) { + return response.getHeaders().getValuesList(name); + } + + @Nullable + @Override + public String getNetworkProtocolName(Request request, @Nullable Response response) { + return "http"; + } + + @Nullable + @Override + public String getNetworkProtocolVersion(Request request, @Nullable Response response) { + HttpVersion httpVersion = null; + if (response != null) { + httpVersion = response.getVersion(); + } + if (httpVersion == null) { + httpVersion = request.getVersion(); + } + if (httpVersion == null) { + return null; + } + return HttpProtocolUtil.getVersion(httpVersion.toString()); + } + + @Override + @Nullable + public String getServerAddress(Request request) { + return request.getHost(); + } + + @Override + public Integer getServerPort(Request request) { + return request.getPort(); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java new file mode 100644 index 000000000000..be20a319a1cc --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java @@ -0,0 +1,63 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import javax.annotation.Nullable; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; + +/** + * JettyClientTracingListener performs two actions when {@link #handleRequest(Context, Request, + * Instrumenter)} is called 1. Start the CLIENT span 2. Set the listener callbacks for each + * lifecycle action that signal end of the request. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public final class JettyClientTracingListener + implements Request.FailureListener, Response.SuccessListener, Response.FailureListener { + + private final Context context; + + private final Instrumenter instrumenter; + + private JettyClientTracingListener( + Context context, Instrumenter instrumenter) { + this.context = context; + this.instrumenter = instrumenter; + } + + @Nullable + public static Context handleRequest( + Context parentContext, Request jettyRequest, Instrumenter instrumenter) { + if (!instrumenter.shouldStart(parentContext, jettyRequest)) { + return null; + } + + Context context = instrumenter.start(parentContext, jettyRequest); + + JettyClientTracingListener listener = new JettyClientTracingListener(context, instrumenter); + jettyRequest.onRequestFailure(listener).onResponseFailure(listener).onResponseSuccess(listener); + return context; + } + + @Override + public void onFailure(Response response, Throwable t) { + instrumenter.end(this.context, response.getRequest(), response, t); + } + + @Override + public void onFailure(Request request, Throwable t) { + instrumenter.end(this.context, request, null, t); + } + + @Override + public void onSuccess(Response response) { + instrumenter.end(this.context, response.getRequest(), response, null); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClientInstrumenterBuilderFactory.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClientInstrumenterBuilderFactory.java new file mode 100644 index 000000000000..386a5e6c816b --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClientInstrumenterBuilderFactory.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class JettyHttpClientInstrumenterBuilderFactory { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jetty-httpclient-12.0"; + + private JettyHttpClientInstrumenterBuilderFactory() {} + + public static DefaultHttpClientInstrumenterBuilder create( + OpenTelemetry openTelemetry) { + return new DefaultHttpClientInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, JettyClientHttpAttributesGetter.INSTANCE) + .setHeaderSetter(HttpHeaderSetter.INSTANCE); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/test/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12LibraryTest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/test/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12LibraryTest.java new file mode 100644 index 000000000000..e7cf65fb206d --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/test/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12LibraryTest.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; +import java.util.Collections; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JettyHttpClient12LibraryTest extends AbstractJettyClient12Test { + + @RegisterExtension + static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forLibrary(); + + @Override + protected HttpClient createStandardClient() { + return JettyClientTelemetry.builder(testing.getOpenTelemetry()) + .setCapturedRequestHeaders( + Collections.singletonList(AbstractHttpClientTest.TEST_REQUEST_HEADER)) + .setCapturedResponseHeaders( + Collections.singletonList(AbstractHttpClientTest.TEST_RESPONSE_HEADER)) + .build() + .getHttpClient(); + } + + @Override + protected HttpClient createHttpsClient(SslContextFactory.Client sslContextFactory) { + return JettyClientTelemetry.builder(testing.getOpenTelemetry()) + .setSslContextFactory(sslContextFactory) + .build() + .getHttpClient(); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts new file mode 100644 index 000000000000..6205a47c0461 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("otel.java-conventions") +} + +dependencies { + api(project(":testing-common")) + + api("org.eclipse.jetty:jetty-client:12.0.0") + + implementation("io.opentelemetry:opentelemetry-api") +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java new file mode 100644 index 000000000000..4f606242c9da --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java @@ -0,0 +1,122 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; +import java.net.URI; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.eclipse.jetty.client.ContentResponse; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; + +public abstract class AbstractJettyClient12Test extends AbstractHttpClientTest { + + protected abstract HttpClient createStandardClient(); + + protected abstract HttpClient createHttpsClient(SslContextFactory.Client sslContextFactory); + + protected HttpClient client = createStandardClient(); + protected HttpClient httpsClient; + + @BeforeEach + public void before() throws Exception { + client.setConnectTimeout(CONNECTION_TIMEOUT.toMillis()); + client.start(); + + SslContextFactory.Client tlsCtx = new SslContextFactory.Client(); + httpsClient = createHttpsClient(tlsCtx); + httpsClient.setFollowRedirects(false); + httpsClient.start(); + } + + @AfterEach + public void after() throws Exception { + client.stop(); + httpsClient.stop(); + } + + @Override + protected void configure(HttpClientTestOptions.Builder optionsBuilder) { + // disable redirect tests + optionsBuilder.disableTestRedirects(); + // jetty 12 does not support to reuse request + // use request.send() twice will block the program infinitely + optionsBuilder.disableTestReusedRequest(); + } + + @Override + public Request buildRequest(String method, URI uri, Map headers) { + HttpClient theClient = Objects.equals(uri.getScheme(), "https") ? httpsClient : client; + + Request request = theClient.newRequest(uri); + request.agent("Jetty"); + + request.method(method); + request.timeout(READ_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + + return request; + } + + @Override + public int sendRequest(Request request, String method, URI uri, Map headers) + throws ExecutionException, InterruptedException, TimeoutException { + headers.forEach((k, v) -> request.headers(httpFields -> httpFields.put(new HttpField(k, v)))); + + ContentResponse response = request.send(); + + return response.getStatus(); + } + + @Override + public void sendRequestWithCallback( + Request request, + String method, + URI uri, + Map headers, + HttpClientResult requestResult) { + JettyClientListener clientListener = new JettyClientListener(); + + request.onRequestFailure(clientListener); + request.onResponseFailure(clientListener); + headers.forEach((k, v) -> request.headers(httpFields -> httpFields.put(new HttpField(k, v)))); + + request.send( + result -> { + if (clientListener.failure != null) { + requestResult.complete(clientListener.failure); + return; + } + + requestResult.complete(result.getResponse().getStatus()); + }); + } + + private static class JettyClientListener + implements Request.FailureListener, Response.FailureListener { + volatile Throwable failure; + + @Override + public void onFailure(Request request, Throwable failure) { + this.failure = failure; + } + + @Override + public void onFailure(Response response, Throwable failure) { + this.failure = failure; + } + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts index 00e213117361..71d9062f5375 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts @@ -18,6 +18,8 @@ dependencies { library("org.eclipse.jetty:jetty-client:$jettyVers_base9") + testInstrumentation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:javaagent")) + testImplementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:testing")) latestDepTestLibrary("org.eclipse.jetty:jetty-client:9.+") // documented limitation diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9Instrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9Instrumentation.java index 7ad866f0f525..42152897660c 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9Instrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9Instrumentation.java @@ -14,7 +14,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyHttpClient9TracingInterceptor; +import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyClientTracingListener; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import java.util.List; @@ -50,19 +50,13 @@ public static void addTracingEnter( @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { Context parentContext = currentContext(); - if (!instrumenter().shouldStart(parentContext, httpRequest)) { + context = + JettyClientTracingListener.handleRequest(parentContext, httpRequest, instrumenter()); + if (context == null) { return; } - // First step is to attach the tracer to the Jetty request. Request listeners are wrapped here - JettyHttpClient9TracingInterceptor requestInterceptor = - new JettyHttpClient9TracingInterceptor(parentContext, instrumenter()); - requestInterceptor.attachToRequest(httpRequest); - - // Second step is to wrap all the important result callback listeners = wrapResponseListeners(parentContext, listeners); - - context = requestInterceptor.getContext(); scope = context.makeCurrent(); } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClientSingletons.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClientSingletons.java index 07ab0522137d..b86165be3d51 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClientSingletons.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClientSingletons.java @@ -5,35 +5,18 @@ package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v9_2; -import static java.util.Collections.singletonList; - import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyClientHttpAttributesGetter; -import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyClientInstrumenterFactory; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import java.util.function.Function; +import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyHttpClientInstrumenterBuilderFactory; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; public class JettyHttpClientSingletons { private static final Instrumenter INSTRUMENTER = - JettyClientInstrumenterFactory.create( - GlobalOpenTelemetry.get(), - builder -> - builder - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - Function.identity(), - singletonList( - HttpClientPeerServiceAttributesExtractor.create( - JettyClientHttpAttributesGetter.INSTANCE, - CommonConfig.get().getPeerServiceResolver())), - CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + JavaagentHttpClientInstrumenters.create( + JettyHttpClientInstrumenterBuilderFactory.create(GlobalOpenTelemetry.get())); public static Instrumenter instrumenter() { return INSTRUMENTER; diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/JettyClientTelemetryBuilder.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/JettyClientTelemetryBuilder.java index dd6cb72ee7f0..427980f0d244 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/JettyClientTelemetryBuilder.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/JettyClientTelemetryBuilder.java @@ -7,15 +7,13 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyClientInstrumenterFactory; -import java.util.ArrayList; +import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyHttpClientInstrumenterBuilderFactory; import java.util.List; import java.util.Set; -import java.util.function.Consumer; import java.util.function.Function; import org.eclipse.jetty.client.HttpClientTransport; import org.eclipse.jetty.client.api.Request; @@ -25,21 +23,12 @@ /** A builder of {@link JettyClientTelemetry}. */ public final class JettyClientTelemetryBuilder { - private final OpenTelemetry openTelemetry; - private final List> additionalExtractors = - new ArrayList<>(); - private Consumer> extractorConfigurer = - builder -> {}; - private Consumer> spanNameExtractorConfigurer = - builder -> {}; - private Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer = Function.identity(); - private boolean emitExperimentalHttpClientMetrics = false; + private final DefaultHttpClientInstrumenterBuilder builder; private HttpClientTransport httpClientTransport; private SslContextFactory sslContextFactory; JettyClientTelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + builder = JettyHttpClientInstrumenterBuilderFactory.create(openTelemetry); } @CanIgnoreReturnValue @@ -62,7 +51,7 @@ public JettyClientTelemetryBuilder setSslContextFactory(SslContextFactory sslCon @CanIgnoreReturnValue public JettyClientTelemetryBuilder addAttributeExtractor( AttributesExtractor attributesExtractor) { - additionalExtractors.add(attributesExtractor); + builder.addAttributeExtractor(attributesExtractor); return this; } @@ -73,8 +62,7 @@ public JettyClientTelemetryBuilder addAttributeExtractor( */ @CanIgnoreReturnValue public JettyClientTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setCapturedRequestHeaders(requestHeaders)); + builder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -85,8 +73,7 @@ public JettyClientTelemetryBuilder setCapturedRequestHeaders(List reques */ @CanIgnoreReturnValue public JettyClientTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setCapturedResponseHeaders(responseHeaders)); + builder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -105,10 +92,7 @@ public JettyClientTelemetryBuilder setCapturedResponseHeaders(List respo */ @CanIgnoreReturnValue public JettyClientTelemetryBuilder setKnownMethods(Set knownMethods) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); - spanNameExtractorConfigurer = - spanNameExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); + builder.setKnownMethods(knownMethods); return this; } @@ -121,7 +105,7 @@ public JettyClientTelemetryBuilder setKnownMethods(Set knownMethods) { @CanIgnoreReturnValue public JettyClientTelemetryBuilder setEmitExperimentalHttpClientMetrics( boolean emitExperimentalHttpClientMetrics) { - this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; + builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics); return this; } @@ -130,7 +114,7 @@ public JettyClientTelemetryBuilder setEmitExperimentalHttpClientMetrics( public JettyClientTelemetryBuilder setSpanNameExtractor( Function, ? extends SpanNameExtractor> spanNameExtractorTransformer) { - this.spanNameExtractorTransformer = spanNameExtractorTransformer; + builder.setSpanNameExtractor(spanNameExtractorTransformer); return this; } @@ -140,16 +124,7 @@ public JettyClientTelemetryBuilder setSpanNameExtractor( */ public JettyClientTelemetry build() { TracingHttpClient tracingHttpClient = - TracingHttpClient.buildNew( - JettyClientInstrumenterFactory.create( - openTelemetry, - extractorConfigurer, - spanNameExtractorConfigurer, - spanNameExtractorTransformer, - additionalExtractors, - emitExperimentalHttpClientMetrics), - sslContextFactory, - httpClientTransport); + TracingHttpClient.buildNew(builder.build(), sslContextFactory, httpClientTransport); return new JettyClientTelemetry(tracingHttpClient); } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/TracingHttpClient.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/TracingHttpClient.java index 094b38ced322..ffa837707f44 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/TracingHttpClient.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/TracingHttpClient.java @@ -9,7 +9,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyHttpClient9TracingInterceptor; +import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyClientTracingListener; import java.util.List; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClientTransport; @@ -23,7 +23,6 @@ class TracingHttpClient extends HttpClient { private final Instrumenter instrumenter; TracingHttpClient(Instrumenter instrumenter) { - super(); this.instrumenter = instrumenter; } @@ -60,10 +59,12 @@ static TracingHttpClient buildNew( @Override protected void send(HttpRequest request, List listeners) { Context parentContext = Context.current(); - JettyHttpClient9TracingInterceptor requestInterceptor = - new JettyHttpClient9TracingInterceptor(parentContext, this.instrumenter); - requestInterceptor.attachToRequest(request); - List wrapped = wrapResponseListeners(parentContext, listeners); - super.send(request, wrapped); + Context context = + JettyClientTracingListener.handleRequest(parentContext, request, instrumenter); + // wrap listeners only when a span was started (context is not null) + if (context != null) { + listeners = wrapResponseListeners(parentContext, listeners); + } + super.send(request, listeners); } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientHttpAttributesGetter.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientHttpAttributesGetter.java index 35212089eaf6..75609b760582 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientHttpAttributesGetter.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientHttpAttributesGetter.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal; +import io.opentelemetry.instrumentation.api.internal.HttpProtocolUtil; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; import java.util.List; import javax.annotation.Nullable; @@ -67,11 +68,7 @@ public String getNetworkProtocolVersion(Request request, @Nullable Response resp if (httpVersion == null) { return null; } - String version = httpVersion.toString(); - if (version.startsWith("HTTP/")) { - version = version.substring("HTTP/".length()); - } - return version; + return HttpProtocolUtil.getVersion(httpVersion.toString()); } @Override diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientInstrumenterFactory.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientInstrumenterFactory.java deleted file mode 100644 index d07edd2038af..000000000000 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientInstrumenterFactory.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.client.api.Response; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public final class JettyClientInstrumenterFactory { - - private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jetty-httpclient-9.2"; - - public static Instrumenter create( - OpenTelemetry openTelemetry, - Consumer> extractorConfigurer, - Consumer> spanNameExtractorConfigurer, - Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer, - List> additionalExtractors, - boolean emitExperimentalHttpClientMetrics) { - - JettyClientHttpAttributesGetter httpAttributesGetter = JettyClientHttpAttributesGetter.INSTANCE; - - HttpClientAttributesExtractorBuilder httpAttributesExtractorBuilder = - HttpClientAttributesExtractor.builder(httpAttributesGetter); - extractorConfigurer.accept(httpAttributesExtractorBuilder); - - HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(httpAttributesGetter); - spanNameExtractorConfigurer.accept(httpSpanNameExtractorBuilder); - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(httpAttributesExtractorBuilder.build()) - .addAttributesExtractors(additionalExtractors) - .addOperationMetrics(HttpClientMetrics.get()); - if (emitExperimentalHttpClientMetrics) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - - return builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); - } - - private JettyClientInstrumenterFactory() {} -} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClient9TracingInterceptor.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientTracingListener.java similarity index 50% rename from instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClient9TracingInterceptor.java rename to instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientTracingListener.java index b6b0b2ea0104..71909ac0557e 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClient9TracingInterceptor.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientTracingListener.java @@ -15,28 +15,23 @@ import java.util.ListIterator; import java.util.logging.Logger; import javax.annotation.Nullable; +import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; -import org.eclipse.jetty.client.api.Result; /** - * JettyHttpClient9TracingInterceptor does three jobs stimulated from the Jetty Request object from - * attachToRequest() 1. Start the CLIENT span and create the tracer 2. Set the listener callbacks - * for each important lifecycle actions that would cause the start and close of the span 3. Set - * callback wrappers on two important request-based callbacks + * JettyClientTracingListener performs three actions when {@link #handleRequest(Context, + * HttpRequest, Instrumenter)} is called 1. Start the CLIENT span 2. Set the listener callbacks for + * each lifecycle action that signal end of the request 3. Wrap request listeners to propagate + * context into the listeners * *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ -public final class JettyHttpClient9TracingInterceptor - implements Request.BeginListener, - Request.FailureListener, - Response.SuccessListener, - Response.FailureListener, - Response.CompleteListener { +public final class JettyClientTracingListener + implements Request.FailureListener, Response.SuccessListener, Response.FailureListener { - private static final Logger logger = - Logger.getLogger(JettyHttpClient9TracingInterceptor.class.getName()); + private static final Logger logger = Logger.getLogger(JettyClientTracingListener.class.getName()); private static final Class[] requestlistenerInterfaces = { Request.BeginListener.class, @@ -48,47 +43,44 @@ public final class JettyHttpClient9TracingInterceptor Request.QueuedListener.class }; - @Nullable private Context context; - - @Nullable - public Context getContext() { - return this.context; - } - - private final Context parentContext; - + private final Context context; private final Instrumenter instrumenter; - public JettyHttpClient9TracingInterceptor( - Context parentCtx, Instrumenter instrumenter) { - this.parentContext = parentCtx; + private JettyClientTracingListener( + Context context, Instrumenter instrumenter) { + this.context = context; this.instrumenter = instrumenter; } - public void attachToRequest(Request jettyRequest) { - List current = - jettyRequest.getRequestListeners(JettyHttpClient9TracingInterceptor.class); - + @Nullable + public static Context handleRequest( + Context parentContext, HttpRequest request, Instrumenter instrumenter) { + List current = + request.getRequestListeners(JettyClientTracingListener.class); if (!current.isEmpty()) { - logger.warning("A tracing interceptor is already in place for this request!"); - return; + logger.warning("A tracing request listener is already in place for this request!"); + return null; } - startSpan(jettyRequest); + + if (!instrumenter.shouldStart(parentContext, request)) { + return null; + } + + Context context = instrumenter.start(parentContext, request); // wrap all important request-based listeners that may already be attached, null should ensure - // are returned here - List existingListeners = jettyRequest.getRequestListeners(null); - wrapRequestListeners(existingListeners); - - jettyRequest - .onRequestBegin(this) - .onRequestFailure(this) - .onResponseFailure(this) - .onResponseSuccess(this); - } + // that all listeners are returned here + List existingListeners = request.getRequestListeners(null); + wrapRequestListeners(existingListeners, context); - private void wrapRequestListeners(List requestListeners) { + JettyClientTracingListener listener = new JettyClientTracingListener(context, instrumenter); + request.onRequestFailure(listener).onResponseFailure(listener).onResponseSuccess(listener); + return context; + } + + private static void wrapRequestListeners( + List requestListeners, Context context) { ListIterator iterator = requestListeners.listIterator(); while (iterator.hasNext()) { @@ -124,47 +116,18 @@ private void wrapRequestListeners(List requestListeners } } - private void startSpan(Request request) { - - if (!instrumenter.shouldStart(this.parentContext, request)) { - return; - } - this.context = instrumenter.start(this.parentContext, request); - } - - @Override - public void onBegin(Request request) {} - - @Override - public void onComplete(Result result) { - closeIfPossible(result.getResponse()); - } - @Override public void onSuccess(Response response) { - closeIfPossible(response); + instrumenter.end(this.context, response.getRequest(), response, null); } @Override public void onFailure(Request request, Throwable t) { - if (this.context != null) { - instrumenter.end(this.context, request, null, t); - } + instrumenter.end(this.context, request, null, t); } @Override public void onFailure(Response response, Throwable t) { - if (this.context != null) { - instrumenter.end(this.context, response.getRequest(), response, t); - } - } - - private void closeIfPossible(Response response) { - - if (this.context != null) { - instrumenter.end(this.context, response.getRequest(), response, null); - } else { - logger.fine("onComplete - could not find an otel context"); - } + instrumenter.end(this.context, response.getRequest(), response, t); } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientWrapUtil.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientWrapUtil.java index b6885bd3edaf..53a76256daa2 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientWrapUtil.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientWrapUtil.java @@ -50,7 +50,7 @@ public static List wrapResponseListeners( private static Response.ResponseListener wrapTheListener( Response.ResponseListener listener, Context context) { - if (listener == null || listener instanceof JettyHttpClient9TracingInterceptor) { + if (listener == null || listener instanceof JettyClientTracingListener) { return listener; } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClientInstrumenterBuilderFactory.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClientInstrumenterBuilderFactory.java new file mode 100644 index 000000000000..f2be57153580 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClientInstrumenterBuilderFactory.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.api.Response; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class JettyHttpClientInstrumenterBuilderFactory { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jetty-httpclient-9.2"; + + private JettyHttpClientInstrumenterBuilderFactory() {} + + public static DefaultHttpClientInstrumenterBuilder create( + OpenTelemetry openTelemetry) { + return new DefaultHttpClientInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, JettyClientHttpAttributesGetter.INSTANCE) + .setHeaderSetter(HttpHeaderSetter.INSTANCE); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/AbstractJettyClient9Test.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/AbstractJettyClient9Test.java index 7099694776ef..9a53e6014e7a 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/AbstractJettyClient9Test.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/AbstractJettyClient9Test.java @@ -19,7 +19,9 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.TestInstance; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public abstract class AbstractJettyClient9Test extends AbstractHttpClientTest { private HttpClient client; diff --git a/instrumentation/jetty/jetty-11.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v11_0/Jetty11Singletons.java b/instrumentation/jetty/jetty-11.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v11_0/Jetty11Singletons.java index 240a96c39aca..0e7fe4081a1e 100644 --- a/instrumentation/jetty/jetty-11.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v11_0/Jetty11Singletons.java +++ b/instrumentation/jetty/jetty-11.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v11_0/Jetty11Singletons.java @@ -24,6 +24,7 @@ public final class Jetty11Singletons { ServletInstrumenterBuilder.create() .addContextCustomizer( (context, request, attributes) -> new AppServerBridge.Builder().init(context)) + .propagateOperationListenersToOnEnd() .build(INSTRUMENTATION_NAME, Servlet5Accessor.INSTANCE); private static final JettyHelper HELPER = diff --git a/instrumentation/jetty/jetty-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v12_0/Jetty12Singletons.java b/instrumentation/jetty/jetty-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v12_0/Jetty12Singletons.java index d51e70378a14..b9866c2cef93 100644 --- a/instrumentation/jetty/jetty-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v12_0/Jetty12Singletons.java +++ b/instrumentation/jetty/jetty-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v12_0/Jetty12Singletons.java @@ -15,7 +15,7 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; @@ -33,18 +33,18 @@ public final class Jetty12Singletons { GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) .addAttributesExtractor( HttpServerAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addContextCustomizer( HttpServerRoute.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addContextCustomizer( (context, request, attributes) -> @@ -53,7 +53,7 @@ public final class Jetty12Singletons { .recordException() .init(context)) .addOperationMetrics(HttpServerMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { + if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { builder .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) .addOperationMetrics(HttpServerExperimentalMetrics.get()); diff --git a/instrumentation/jetty/jetty-8.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v8_0/Jetty8Singletons.java b/instrumentation/jetty/jetty-8.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v8_0/Jetty8Singletons.java index ed503f12ab4e..fd26bb40a698 100644 --- a/instrumentation/jetty/jetty-8.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v8_0/Jetty8Singletons.java +++ b/instrumentation/jetty/jetty-8.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v8_0/Jetty8Singletons.java @@ -24,6 +24,7 @@ public final class Jetty8Singletons { ServletInstrumenterBuilder.create() .addContextCustomizer( (context, request, attributes) -> new AppServerBridge.Builder().init(context)) + .propagateOperationListenersToOnEnd() .build(INSTRUMENTATION_NAME, Servlet3Accessor.INSTANCE); private static final JettyHelper HELPER = diff --git a/instrumentation/jodd-http-4.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/joddhttp/v4_2/JoddHttpSingletons.java b/instrumentation/jodd-http-4.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/joddhttp/v4_2/JoddHttpSingletons.java index ec1e8bb99acb..9bc4838f4b1f 100644 --- a/instrumentation/jodd-http-4.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/joddhttp/v4_2/JoddHttpSingletons.java +++ b/instrumentation/jodd-http-4.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/joddhttp/v4_2/JoddHttpSingletons.java @@ -5,17 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import jodd.http.HttpRequest; import jodd.http.HttpResponse; @@ -25,32 +16,9 @@ public final class JoddHttpSingletons { private static final Instrumenter INSTRUMENTER; static { - JoddHttpHttpAttributesGetter httpAttributesGetter = new JoddHttpHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, new JoddHttpHttpAttributesGetter(), HttpHeaderSetter.INSTANCE); } public static Instrumenter instrumenter() { diff --git a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/groovy/BaseJsfTest.groovy b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/groovy/BaseJsfTest.groovy deleted file mode 100644 index 5ad68cf4646b..000000000000 --- a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/groovy/BaseJsfTest.groovy +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.api.trace.SpanKind -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTestTrait -import io.opentelemetry.sdk.trace.data.SpanData -import io.opentelemetry.semconv.ServerAttributes -import io.opentelemetry.semconv.ClientAttributes -import io.opentelemetry.semconv.UserAgentAttributes -import io.opentelemetry.semconv.HttpAttributes -import io.opentelemetry.semconv.NetworkAttributes -import io.opentelemetry.semconv.UrlAttributes -import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpRequest -import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse -import io.opentelemetry.testing.internal.armeria.common.HttpData -import io.opentelemetry.testing.internal.armeria.common.HttpMethod -import io.opentelemetry.testing.internal.armeria.common.MediaType -import io.opentelemetry.testing.internal.armeria.common.QueryParams -import io.opentelemetry.testing.internal.armeria.common.RequestHeaders -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.util.resource.Resource -import org.eclipse.jetty.webapp.WebAppContext -import org.jsoup.Jsoup -import spock.lang.Unroll - -import static io.opentelemetry.api.trace.SpanKind.INTERNAL -import static io.opentelemetry.api.trace.StatusCode.ERROR - -abstract class BaseJsfTest extends AgentInstrumentationSpecification implements HttpServerTestTrait { - - def setupSpec() { - setupServer() - } - - def cleanupSpec() { - cleanupServer() - } - - @Override - Server startServer(int port) { - WebAppContext webAppContext = new WebAppContext() - webAppContext.setContextPath(getContextPath()) - // set up test application - webAppContext.setBaseResource(Resource.newSystemResource("test-app")) - - Resource extraResource = Resource.newSystemResource("test-app-extra") - if (extraResource != null) { - webAppContext.getMetaData().addWebInfResource(extraResource) - } - - def jettyServer = new Server(port) - jettyServer.connectors.each { - it.setHost('localhost') - } - - jettyServer.setHandler(webAppContext) - jettyServer.start() - - return jettyServer - } - - @Override - void stopServer(Server server) { - server.stop() - server.destroy() - } - - @Override - String getContextPath() { - return "/jetty-context" - } - - @Unroll - def "test #path"() { - setup: - AggregatedHttpResponse response = client.get(address.resolve(path).toString()).aggregate().join() - - expect: - response.status().code() == 200 - response.contentUtf8().trim() == "Hello" - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name getContextPath() + "/hello.xhtml" - kind SpanKind.SERVER - hasNoParent() - attributes { - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" "/jetty-context/" + path - "$UserAgentAttributes.USER_AGENT_ORIGINAL" TEST_USER_AGENT - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$HttpAttributes.HTTP_ROUTE" "/jetty-context/" + route - "$ClientAttributes.CLIENT_ADDRESS" { it == null || it == TEST_CLIENT_IP } - } - } - } - } - - where: - path | route - "hello.xhtml" | "*.xhtml" - "faces/hello.xhtml" | "faces/*" - } - - def "test greeting"() { - // we need to display the page first before posting data to it - setup: - AggregatedHttpResponse response = client.get(address.resolve("greeting.xhtml").toString()).aggregate().join() - def doc = Jsoup.parse(response.contentUtf8()) - - expect: - response.status().code() == 200 - doc.selectFirst("title").text() == "Hello, World!" - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name getContextPath() + "/greeting.xhtml" - kind SpanKind.SERVER - hasNoParent() - } - } - } - clearExportedData() - - when: - // extract parameters needed to post back form - def viewState = doc.selectFirst("[name=jakarta.faces.ViewState]")?.val() - def formAction = doc.selectFirst("#app-form").attr("action") - def jsessionid = formAction.substring(formAction.indexOf("jsessionid=") + "jsessionid=".length()) - - then: - viewState != null - jsessionid != null - - when: - // set up form parameter for post - QueryParams formBody = QueryParams.builder() - .add("app-form", "app-form") - // value used for name is returned in app-form:output-message element - .add("app-form:name", "test") - .add("app-form:submit", "Say hello") - .add("app-form_SUBMIT", "1") // MyFaces - .add("jakarta.faces.ViewState", viewState) - .build() - // use the session created for first request - def request2 = AggregatedHttpRequest.of( - RequestHeaders.builder(HttpMethod.POST, address.resolve("greeting.xhtml;jsessionid=" + jsessionid).toString()) - .contentType(MediaType.FORM_DATA) - .build(), - HttpData.ofUtf8(formBody.toQueryString())) - AggregatedHttpResponse response2 = client.execute(request2).aggregate().join() - def responseContent = response2.contentUtf8() - def doc2 = Jsoup.parse(responseContent) - - then: - response2.status().code() == 200 - doc2.getElementById("app-form:output-message").text() == "Hello test" - - and: - assertTraces(1) { - trace(0, 2) { - span(0) { - name getContextPath() + "/greeting.xhtml" - kind SpanKind.SERVER - hasNoParent() - } - handlerSpan(it, 1, span(0), "#{greetingForm.submit()}") - } - } - } - - def "test exception"() { - // we need to display the page first before posting data to it - setup: - AggregatedHttpResponse response = client.get(address.resolve("greeting.xhtml").toString()).aggregate().join() - def doc = Jsoup.parse(response.contentUtf8()) - - expect: - response.status().code() == 200 - doc.selectFirst("title").text() == "Hello, World!" - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name getContextPath() + "/greeting.xhtml" - kind SpanKind.SERVER - hasNoParent() - } - } - } - clearExportedData() - - when: - // extract parameters needed to post back form - def viewState = doc.selectFirst("[name=jakarta.faces.ViewState]").val() - def formAction = doc.selectFirst("#app-form").attr("action") - def jsessionid = formAction.substring(formAction.indexOf("jsessionid=") + "jsessionid=".length()) - - then: - viewState != null - jsessionid != null - - when: - // set up form parameter for post - QueryParams formBody = QueryParams.builder() - .add("app-form", "app-form") - // setting name parameter to "exception" triggers throwing exception in GreetingForm - .add("app-form:name", "exception") - .add("app-form:submit", "Say hello") - .add("app-form_SUBMIT", "1") // MyFaces - .add("jakarta.faces.ViewState", viewState) - .build() - // use the session created for first request - def request2 = AggregatedHttpRequest.of( - RequestHeaders.builder(HttpMethod.POST, address.resolve("greeting.xhtml;jsessionid=" + jsessionid).toString()) - .contentType(MediaType.FORM_DATA) - .build(), - HttpData.ofUtf8(formBody.toQueryString())) - AggregatedHttpResponse response2 = client.execute(request2).aggregate().join() - - then: - response2.status().code() == 500 - def ex = new Exception("submit exception") - - and: - assertTraces(1) { - trace(0, 2) { - span(0) { - name getContextPath() + "/greeting.xhtml" - kind SpanKind.SERVER - hasNoParent() - status ERROR - errorEvent(ex.class, ex.message) - } - handlerSpan(it, 1, span(0), "#{greetingForm.submit()}", ex) - } - } - } - - void handlerSpan(TraceAssert trace, int index, Object parent, String spanName, Exception expectedException = null) { - trace.span(index) { - name spanName - kind INTERNAL - if (expectedException != null) { - status ERROR - errorEvent(expectedException.getClass(), expectedException.getMessage()) - } - childOf((SpanData) parent) - } - } -} diff --git a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/groovy/ExceptionFilter.groovy b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/groovy/ExceptionFilter.groovy deleted file mode 100644 index 40aa7ac24eaa..000000000000 --- a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/groovy/ExceptionFilter.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import jakarta.servlet.Filter -import jakarta.servlet.FilterChain -import jakarta.servlet.FilterConfig -import jakarta.servlet.ServletException -import jakarta.servlet.ServletRequest -import jakarta.servlet.ServletResponse - -class ExceptionFilter implements Filter { - @Override - void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - try { - chain.doFilter(request, response) - } catch (Exception exception) { - // to ease testing unwrap our exception to root cause - Exception tmp = exception - while (tmp.getCause() != null) { - tmp = tmp.getCause() - } - if (tmp.getMessage() != null && tmp.getMessage().contains("submit exception")) { - throw tmp - } - throw exception - } - } - - @Override - void destroy() { - } -} diff --git a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/groovy/GreetingForm.groovy b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/groovy/GreetingForm.groovy deleted file mode 100644 index f8d429f4ee2a..000000000000 --- a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/groovy/GreetingForm.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class GreetingForm { - - String name = "" - String message = "" - - String getName() { - name - } - - void setName(String name) { - this.name = name - } - - String getMessage() { - return message - } - - void submit() { - message = "Hello " + name - if (name == "exception") { - throw new Exception("submit exception") - } - } -} diff --git a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/jakarta/BaseJsfTest.java b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/jakarta/BaseJsfTest.java new file mode 100644 index 000000000000..d375a64b6e12 --- /dev/null +++ b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/jakarta/BaseJsfTest.java @@ -0,0 +1,287 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsf.jakarta; + +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.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerUsingTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; +import io.opentelemetry.sdk.testing.assertj.TraceAssert; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.semconv.ClientAttributes; +import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.NetworkAttributes; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.UrlAttributes; +import io.opentelemetry.semconv.UserAgentAttributes; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpRequest; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import io.opentelemetry.testing.internal.armeria.common.HttpData; +import io.opentelemetry.testing.internal.armeria.common.HttpMethod; +import io.opentelemetry.testing.internal.armeria.common.MediaType; +import io.opentelemetry.testing.internal.armeria.common.QueryParams; +import io.opentelemetry.testing.internal.armeria.common.RequestHeaders; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Stream; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.webapp.WebAppContext; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; + +public abstract class BaseJsfTest extends AbstractHttpServerUsingTest { + + @RegisterExtension + public static final InstrumentationExtension testing = + HttpServerInstrumentationExtension.forAgent(); + + @BeforeAll + protected void setUp() { + startServer(); + } + + @AfterAll + protected void cleanUp() { + cleanupServer(); + } + + @Override + protected Server setupServer() throws Exception { + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setContextPath(getContextPath()); + // set up test application + webAppContext.setBaseResource(Resource.newSystemResource("test-app")); + + Resource extraResource = Resource.newSystemResource("test-app-extra"); + if (extraResource != null) { + webAppContext.getMetaData().addWebInfResource(extraResource); + } + + Server jettyServer = new Server(port); + jettyServer.setHandler(webAppContext); + jettyServer.start(); + + return jettyServer; + } + + @Override + protected void stopServer(Server server) throws Exception { + server.stop(); + server.destroy(); + } + + @Override + protected String getContextPath() { + return "/jetty-context"; + } + + @ParameterizedTest + @ArgumentsSource(PathTestArgs.class) + void testPath(String path, String route) { + AggregatedHttpResponse response = + client.get(address.resolve(path).toString()).aggregate().join(); + assertThat(response.status().code()).isEqualTo(200); + assertThat(response.contentUtf8().trim()).isEqualTo("Hello"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/hello.xhtml") + .hasKind(SpanKind.SERVER) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"), + satisfies( + NetworkAttributes.NETWORK_PEER_PORT, + val -> val.isInstanceOf(Long.class)), + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(UrlAttributes.URL_SCHEME, "http"), + equalTo(UrlAttributes.URL_PATH, getContextPath() + "/" + path), + equalTo(UserAgentAttributes.USER_AGENT_ORIGINAL, TEST_USER_AGENT), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + equalTo(HttpAttributes.HTTP_ROUTE, getContextPath() + "/" + route), + satisfies( + ClientAttributes.CLIENT_ADDRESS, + val -> + val.satisfiesAnyOf( + v -> assertThat(v).isEqualTo(TEST_CLIENT_IP), + v -> assertThat(v).isNull()))))); + } + + static class PathTestArgs implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of("hello.xhtml", "*.xhtml"), Arguments.of("faces/hello.xhtml", "faces/*")); + } + } + + @Test + void testGreeting() { + AggregatedHttpResponse response = + client.get(address.resolve("greeting.xhtml").toString()).aggregate().join(); + Document doc = Jsoup.parse(response.contentUtf8()); + + assertThat(response.status().code()).isEqualTo(200); + assertThat(doc.selectFirst("title").text()).isEqualTo("Hello, World!"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/greeting.xhtml") + .hasKind(SpanKind.SERVER) + .hasNoParent())); + + testing.clearData(); + + String viewState = doc.selectFirst("[name=jakarta.faces.ViewState]").val(); + String formAction = doc.selectFirst("#app-form").attr("action"); + String jsessionid = + formAction.substring(formAction.indexOf("jsessionid=") + "jsessionid=".length()); + + assertThat(viewState).isNotNull(); + assertThat(jsessionid).isNotNull(); + + // set up form parameter for post + QueryParams formBody = + QueryParams.builder() + .add("app-form", "app-form") + // value used for name is returned in app-form:output-message element + .add("app-form:name", "test") + .add("app-form:submit", "Say hello") + .add("app-form_SUBMIT", "1") // MyFaces + .add("jakarta.faces.ViewState", viewState) + .build(); + + // use the session created for first request + AggregatedHttpRequest request2 = + AggregatedHttpRequest.of( + RequestHeaders.builder( + HttpMethod.POST, + address.resolve("greeting.xhtml;jsessionid=" + jsessionid).toString()) + .contentType(MediaType.FORM_DATA) + .build(), + HttpData.ofUtf8(formBody.toQueryString())); + AggregatedHttpResponse response2 = client.execute(request2).aggregate().join(); + String responseContent = response2.contentUtf8(); + Document doc2 = Jsoup.parse(responseContent); + + assertThat(response2.status().code()).isEqualTo(200); + assertThat(doc2.getElementById("app-form:output-message").text()).isEqualTo("Hello test"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/greeting.xhtml") + .hasKind(SpanKind.SERVER) + .hasNoParent(), + span -> handlerSpan(trace, 0, "#{greetingForm.submit()}", null))); + } + + @Test + void testException() { + // we need to display the page first before posting data to it + AggregatedHttpResponse response = + client.get(address.resolve("greeting.xhtml").toString()).aggregate().join(); + Document doc = Jsoup.parse(response.contentUtf8()); + + assertThat(response.status().code()).isEqualTo(200); + assertThat(doc.selectFirst("title").text()).isEqualTo("Hello, World!"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/greeting.xhtml") + .hasKind(SpanKind.SERVER) + .hasNoParent())); + + testing.clearData(); + + String viewState = doc.selectFirst("[name=jakarta.faces.ViewState]").val(); + String formAction = doc.selectFirst("#app-form").attr("action"); + String jsessionid = + formAction.substring(formAction.indexOf("jsessionid=") + "jsessionid=".length()); + + assertThat(viewState).isNotNull(); + assertThat(jsessionid).isNotNull(); + + // set up form parameter for post + QueryParams formBody = + QueryParams.builder() + .add("app-form", "app-form") + // setting name parameter to "exception" triggers throwing exception in GreetingForm + .add("app-form:name", "exception") + .add("app-form:submit", "Say hello") + .add("app-form_SUBMIT", "1") // MyFaces + .add("jakarta.faces.ViewState", viewState) + .build(); + + // use the session created for first request + AggregatedHttpRequest request2 = + AggregatedHttpRequest.of( + RequestHeaders.builder( + HttpMethod.POST, + address.resolve("greeting.xhtml;jsessionid=" + jsessionid).toString()) + .contentType(MediaType.FORM_DATA) + .build(), + HttpData.ofUtf8(formBody.toQueryString())); + + AggregatedHttpResponse response2 = client.execute(request2).aggregate().join(); + assertThat(response2.status().code()).isEqualTo(500); + + IllegalStateException expectedException = new IllegalStateException("submit exception"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/greeting.xhtml") + .hasKind(SpanKind.SERVER) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(expectedException), + span -> handlerSpan(trace, 0, "#{greetingForm.submit()}", expectedException))); + } + + List> handlerSpan( + TraceAssert trace, int parentIndex, String spanName, Exception expectedException) { + List> assertions = + new ArrayList<>( + Arrays.asList( + span -> + span.hasName(spanName) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(parentIndex)))); + + if (expectedException != null) { + assertions.add(span -> span.hasStatus(StatusData.error()).hasException(expectedException)); + } + return assertions; + } +} diff --git a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/jakarta/ExceptionFilter.java b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/jakarta/ExceptionFilter.java new file mode 100644 index 000000000000..217a0c38beea --- /dev/null +++ b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/jakarta/ExceptionFilter.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsf.jakarta; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import java.io.IOException; + +public class ExceptionFilter implements Filter { + @Override + public void init(FilterConfig filterConfig) {} + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws ServletException, IOException { + try { + chain.doFilter(request, response); + } catch (ServletException exception) { + // to ease testing unwrap our exception to root cause + Throwable tmp = exception; + while (tmp.getCause() != null) { + tmp = tmp.getCause(); + } + if (tmp.getMessage() != null && tmp.getMessage().contains("submit exception")) { + throw (IllegalStateException) tmp; + } + throw exception; + } + } + + @Override + public void destroy() {} +} diff --git a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/jakarta/GreetingForm.java b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/jakarta/GreetingForm.java new file mode 100644 index 000000000000..8ca071c34972 --- /dev/null +++ b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/jakarta/GreetingForm.java @@ -0,0 +1,31 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsf.jakarta; + +public class GreetingForm { + + private String name = ""; + private String message = ""; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMessage() { + return message; + } + + public void submit() { + message = "Hello " + name; + if (name.equals("exception")) { + throw new IllegalStateException("submit exception"); + } + } +} diff --git a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/resources/test-app/WEB-INF/faces-config.xml b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/resources/test-app/WEB-INF/faces-config.xml index b076ae885c01..4fe311004299 100644 --- a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/resources/test-app/WEB-INF/faces-config.xml +++ b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/resources/test-app/WEB-INF/faces-config.xml @@ -5,7 +5,7 @@ greetingForm - GreetingForm + io.opentelemetry.javaagent.instrumentation.jsf.jakarta.GreetingForm request diff --git a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/resources/test-app/WEB-INF/web.xml b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/resources/test-app/WEB-INF/web.xml index 85042614b120..b22bc5526fae 100644 --- a/instrumentation/jsf/jsf-jakarta-common/testing/src/main/resources/test-app/WEB-INF/web.xml +++ b/instrumentation/jsf/jsf-jakarta-common/testing/src/main/resources/test-app/WEB-INF/web.xml @@ -5,7 +5,7 @@ ExceptionFilter - ExceptionFilter + io.opentelemetry.javaagent.instrumentation.jsf.jakarta.ExceptionFilter ExceptionFilter diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/groovy/BaseJsfTest.groovy b/instrumentation/jsf/jsf-javax-common/testing/src/main/groovy/BaseJsfTest.groovy deleted file mode 100644 index 8eec22ce6c76..000000000000 --- a/instrumentation/jsf/jsf-javax-common/testing/src/main/groovy/BaseJsfTest.groovy +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.api.trace.SpanKind -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTestTrait -import io.opentelemetry.sdk.trace.data.SpanData -import io.opentelemetry.semconv.ServerAttributes -import io.opentelemetry.semconv.ClientAttributes -import io.opentelemetry.semconv.UserAgentAttributes -import io.opentelemetry.semconv.HttpAttributes -import io.opentelemetry.semconv.NetworkAttributes -import io.opentelemetry.semconv.UrlAttributes -import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpRequest -import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse -import io.opentelemetry.testing.internal.armeria.common.HttpData -import io.opentelemetry.testing.internal.armeria.common.HttpMethod -import io.opentelemetry.testing.internal.armeria.common.MediaType -import io.opentelemetry.testing.internal.armeria.common.QueryParams -import io.opentelemetry.testing.internal.armeria.common.RequestHeaders -import org.eclipse.jetty.annotations.AnnotationConfiguration -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.util.resource.Resource -import org.eclipse.jetty.webapp.WebAppContext -import org.jsoup.Jsoup -import spock.lang.Unroll - -import static io.opentelemetry.api.trace.SpanKind.INTERNAL -import static io.opentelemetry.api.trace.StatusCode.ERROR - -abstract class BaseJsfTest extends AgentInstrumentationSpecification implements HttpServerTestTrait { - - def setupSpec() { - setupServer() - } - - def cleanupSpec() { - cleanupServer() - } - - @Override - Server startServer(int port) { - String jsfVersion = getJsfVersion() - - List configurationClasses = new ArrayList<>() - Collections.addAll(configurationClasses, WebAppContext.getDefaultConfigurationClasses()) - configurationClasses.add(AnnotationConfiguration.getName()) - - WebAppContext webAppContext = new WebAppContext() - webAppContext.setContextPath(getContextPath()) - webAppContext.setConfigurationClasses(configurationClasses) - // set up test application - webAppContext.setBaseResource(Resource.newSystemResource("test-app-" + jsfVersion)) - // add additional resources for test app - Resource extraResource = Resource.newSystemResource("test-app-" + jsfVersion + "-extra") - if (extraResource != null) { - webAppContext.getMetaData().addWebInfJar(extraResource) - } - webAppContext.getMetaData().getWebInfClassesDirs().add(Resource.newClassPathResource("/")) - - def jettyServer = new Server(port) - jettyServer.connectors.each { - it.setHost('localhost') - } - - jettyServer.setHandler(webAppContext) - jettyServer.start() - - return jettyServer - } - - abstract String getJsfVersion(); - - @Override - void stopServer(Server server) { - server.stop() - server.destroy() - } - - @Override - String getContextPath() { - return "/jetty-context" - } - - @Unroll - def "test #path"() { - setup: - AggregatedHttpResponse response = client.get(address.resolve(path).toString()).aggregate().join() - - expect: - response.status().code() == 200 - response.contentUtf8().trim() == "Hello" - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name getContextPath() + "/hello.xhtml" - kind SpanKind.SERVER - hasNoParent() - attributes { - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" "/jetty-context/" + path - "$UserAgentAttributes.USER_AGENT_ORIGINAL" TEST_USER_AGENT - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$HttpAttributes.HTTP_ROUTE" "/jetty-context/" + route - "$ClientAttributes.CLIENT_ADDRESS" { it == null || it == TEST_CLIENT_IP } - } - } - } - } - - where: - path | route - "hello.jsf" | "*.jsf" - "faces/hello.xhtml" | "faces/*" - } - - def "test greeting"() { - // we need to display the page first before posting data to it - setup: - AggregatedHttpResponse response = client.get(address.resolve("greeting.jsf").toString()).aggregate().join() - def doc = Jsoup.parse(response.contentUtf8()) - - expect: - response.status().code() == 200 - doc.selectFirst("title").text() == "Hello, World!" - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name getContextPath() + "/greeting.xhtml" - kind SpanKind.SERVER - hasNoParent() - } - } - } - clearExportedData() - - when: - // extract parameters needed to post back form - def viewState = doc.selectFirst("[name=javax.faces.ViewState]")?.val() - def formAction = doc.selectFirst("#app-form").attr("action") - def jsessionid = formAction.substring(formAction.indexOf("jsessionid=") + "jsessionid=".length()) - - then: - viewState != null - jsessionid != null - - when: - // set up form parameter for post - QueryParams formBody = QueryParams.builder() - .add("app-form", "app-form") - // value used for name is returned in app-form:output-message element - .add("app-form:name", "test") - .add("app-form:submit", "Say hello") - .add("app-form_SUBMIT", "1") // MyFaces - .add("javax.faces.ViewState", viewState) - .build() - // use the session created for first request - def request2 = AggregatedHttpRequest.of( - RequestHeaders.builder(HttpMethod.POST, address.resolve("greeting.jsf;jsessionid=" + jsessionid).toString()) - .contentType(MediaType.FORM_DATA) - .build(), - HttpData.ofUtf8(formBody.toQueryString())) - AggregatedHttpResponse response2 = client.execute(request2).aggregate().join() - def responseContent = response2.contentUtf8() - def doc2 = Jsoup.parse(responseContent) - - then: - response2.status().code() == 200 - doc2.getElementById("app-form:output-message").text() == "Hello test" - - and: - assertTraces(1) { - trace(0, 2) { - span(0) { - name getContextPath() + "/greeting.xhtml" - kind SpanKind.SERVER - hasNoParent() - } - handlerSpan(it, 1, span(0), "#{greetingForm.submit()}") - } - } - } - - def "test exception"() { - // we need to display the page first before posting data to it - setup: - AggregatedHttpResponse response = client.get(address.resolve("greeting.jsf").toString()).aggregate().join() - def doc = Jsoup.parse(response.contentUtf8()) - - expect: - response.status().code() == 200 - doc.selectFirst("title").text() == "Hello, World!" - - and: - assertTraces(1) { - trace(0, 1) { - span(0) { - name getContextPath() + "/greeting.xhtml" - kind SpanKind.SERVER - hasNoParent() - } - } - } - clearExportedData() - - when: - // extract parameters needed to post back form - def viewState = doc.selectFirst("[name=javax.faces.ViewState]").val() - def formAction = doc.selectFirst("#app-form").attr("action") - def jsessionid = formAction.substring(formAction.indexOf("jsessionid=") + "jsessionid=".length()) - - then: - viewState != null - jsessionid != null - - when: - // set up form parameter for post - QueryParams formBody = QueryParams.builder() - .add("app-form", "app-form") - // setting name parameter to "exception" triggers throwing exception in GreetingForm - .add("app-form:name", "exception") - .add("app-form:submit", "Say hello") - .add("app-form_SUBMIT", "1") // MyFaces - .add("javax.faces.ViewState", viewState) - .build() - // use the session created for first request - def request2 = AggregatedHttpRequest.of( - RequestHeaders.builder(HttpMethod.POST, address.resolve("greeting.jsf;jsessionid=" + jsessionid).toString()) - .contentType(MediaType.FORM_DATA) - .build(), - HttpData.ofUtf8(formBody.toQueryString())) - AggregatedHttpResponse response2 = client.execute(request2).aggregate().join() - - then: - response2.status().code() == 500 - def ex = new Exception("submit exception") - - and: - assertTraces(1) { - trace(0, 2) { - span(0) { - name getContextPath() + "/greeting.xhtml" - kind SpanKind.SERVER - hasNoParent() - status ERROR - errorEvent(ex.class, ex.message) - } - handlerSpan(it, 1, span(0), "#{greetingForm.submit()}", ex) - } - } - } - - void handlerSpan(TraceAssert trace, int index, Object parent, String spanName, Exception expectedException = null) { - trace.span(index) { - name spanName - kind INTERNAL - if (expectedException != null) { - status ERROR - errorEvent(expectedException.getClass(), expectedException.getMessage()) - } - childOf((SpanData) parent) - } - } -} diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/groovy/ExceptionFilter.groovy b/instrumentation/jsf/jsf-javax-common/testing/src/main/groovy/ExceptionFilter.groovy deleted file mode 100644 index 9efcd3acc017..000000000000 --- a/instrumentation/jsf/jsf-javax-common/testing/src/main/groovy/ExceptionFilter.groovy +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import javax.servlet.Filter -import javax.servlet.FilterChain -import javax.servlet.FilterConfig -import javax.servlet.ServletException -import javax.servlet.ServletRequest -import javax.servlet.ServletResponse - -class ExceptionFilter implements Filter { - @Override - void init(FilterConfig filterConfig) throws ServletException { - } - - @Override - void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - try { - chain.doFilter(request, response) - } catch (Exception exception) { - // to ease testing unwrap our exception to root cause - Exception tmp = exception - while (tmp.getCause() != null) { - tmp = tmp.getCause() - } - if (tmp.getMessage() != null && tmp.getMessage().contains("submit exception")) { - throw tmp - } - throw exception - } - } - - @Override - void destroy() { - } -} diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/groovy/GreetingForm.groovy b/instrumentation/jsf/jsf-javax-common/testing/src/main/groovy/GreetingForm.groovy deleted file mode 100644 index f8d429f4ee2a..000000000000 --- a/instrumentation/jsf/jsf-javax-common/testing/src/main/groovy/GreetingForm.groovy +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class GreetingForm { - - String name = "" - String message = "" - - String getName() { - name - } - - void setName(String name) { - this.name = name - } - - String getMessage() { - return message - } - - void submit() { - message = "Hello " + name - if (name == "exception") { - throw new Exception("submit exception") - } - } -} diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/javax/BaseJsfTest.java b/instrumentation/jsf/jsf-javax-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/javax/BaseJsfTest.java new file mode 100644 index 000000000000..01aaf48d159e --- /dev/null +++ b/instrumentation/jsf/jsf-javax-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/javax/BaseJsfTest.java @@ -0,0 +1,296 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsf.javax; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static java.util.Collections.addAll; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerUsingTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; +import io.opentelemetry.sdk.testing.assertj.TraceAssert; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.semconv.ClientAttributes; +import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.NetworkAttributes; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.UrlAttributes; +import io.opentelemetry.semconv.UserAgentAttributes; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpRequest; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import io.opentelemetry.testing.internal.armeria.common.HttpData; +import io.opentelemetry.testing.internal.armeria.common.HttpMethod; +import io.opentelemetry.testing.internal.armeria.common.MediaType; +import io.opentelemetry.testing.internal.armeria.common.QueryParams; +import io.opentelemetry.testing.internal.armeria.common.RequestHeaders; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; +import java.util.stream.Stream; +import org.eclipse.jetty.annotations.AnnotationConfiguration; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.webapp.WebAppContext; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; + +public abstract class BaseJsfTest extends AbstractHttpServerUsingTest { + @RegisterExtension + public static final InstrumentationExtension testing = + HttpServerInstrumentationExtension.forAgent(); + + protected abstract String getJsfVersion(); + + @BeforeAll + protected void setUp() { + startServer(); + } + + @AfterAll + protected void cleanUp() { + cleanupServer(); + } + + @Override + protected Server setupServer() throws Exception { + List configurationClasses = new ArrayList<>(); + addAll(configurationClasses, WebAppContext.getDefaultConfigurationClasses()); + configurationClasses.add(AnnotationConfiguration.class.getName()); + + WebAppContext webAppContext = new WebAppContext(); + webAppContext.setContextPath(getContextPath()); + webAppContext.setConfigurationClasses(configurationClasses); + // set up test application + webAppContext.setBaseResource(Resource.newSystemResource("test-app-" + getJsfVersion())); + // add additional resources for test app + Resource extraResource = Resource.newSystemResource("test-app-" + getJsfVersion() + "-extra"); + if (extraResource != null) { + webAppContext.getMetaData().addWebInfJar(extraResource); + } + webAppContext.getMetaData().getWebInfClassesDirs().add(Resource.newClassPathResource("/")); + + Server jettyServer = new Server(port); + jettyServer.setHandler(webAppContext); + jettyServer.start(); + + return jettyServer; + } + + @Override + protected String getContextPath() { + return "/jetty-context"; + } + + @Override + protected void stopServer(Server server) throws Exception { + server.stop(); + server.destroy(); + } + + @ParameterizedTest + @ArgumentsSource(PathTestArgs.class) + void testPath(String path, String route) { + AggregatedHttpResponse response = + client.get(address.resolve(path).toString()).aggregate().join(); + assertThat(response.status().code()).isEqualTo(200); + assertThat(response.contentUtf8().trim()).isEqualTo("Hello"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/hello.xhtml") + .hasKind(SpanKind.SERVER) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"), + satisfies( + NetworkAttributes.NETWORK_PEER_PORT, + val -> val.isInstanceOf(Long.class)), + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(UrlAttributes.URL_SCHEME, "http"), + equalTo(UrlAttributes.URL_PATH, getContextPath() + "/" + path), + equalTo(UserAgentAttributes.USER_AGENT_ORIGINAL, TEST_USER_AGENT), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + equalTo(HttpAttributes.HTTP_ROUTE, getContextPath() + "/" + route), + satisfies( + ClientAttributes.CLIENT_ADDRESS, + val -> + val.satisfiesAnyOf( + v -> assertThat(v).isEqualTo(TEST_CLIENT_IP), + v -> assertThat(v).isNull()))))); + } + + static class PathTestArgs implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of("hello.jsf", "*.jsf"), Arguments.of("faces/hello.xhtml", "faces/*")); + } + } + + @Test + void testGreeting() { + // we need to display the page first before posting data to it + AggregatedHttpResponse response = + client.get(address.resolve("greeting.jsf").toString()).aggregate().join(); + Document doc = Jsoup.parse(response.contentUtf8()); + + assertThat(response.status().code()).isEqualTo(200); + assertThat(doc.selectFirst("title").text()).isEqualTo("Hello, World!"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/greeting.xhtml") + .hasKind(SpanKind.SERVER) + .hasNoParent())); + + testing.clearData(); + + String viewState = doc.selectFirst("[name=javax.faces.ViewState]").val(); + String formAction = doc.selectFirst("#app-form").attr("action"); + String jsessionid = + formAction.substring(formAction.indexOf("jsessionid=") + "jsessionid=".length()); + + assertThat(viewState).isNotNull(); + assertThat(jsessionid).isNotNull(); + + // set up form parameter for post + QueryParams formBody = + QueryParams.builder() + .add("app-form", "app-form") + // value used for name is returned in app-form:output-message element + .add("app-form:name", "test") + .add("app-form:submit", "Say hello") + .add("app-form_SUBMIT", "1") // MyFaces + .add("javax.faces.ViewState", viewState) + .build(); + + // use the session created for first request + AggregatedHttpRequest request2 = + AggregatedHttpRequest.of( + RequestHeaders.builder( + HttpMethod.POST, + address.resolve("greeting.jsf;jsessionid=" + jsessionid).toString()) + .contentType(MediaType.FORM_DATA) + .build(), + HttpData.ofUtf8(formBody.toQueryString())); + AggregatedHttpResponse response2 = client.execute(request2).aggregate().join(); + String responseContent = response2.contentUtf8(); + Document doc2 = Jsoup.parse(responseContent); + + assertThat(response2.status().code()).isEqualTo(200); + assertThat(doc2.getElementById("app-form:output-message").text()).isEqualTo("Hello test"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/greeting.xhtml") + .hasKind(SpanKind.SERVER) + .hasNoParent(), + span -> handlerSpan(trace, 0, "#{greetingForm.submit()}", null))); + } + + List> handlerSpan( + TraceAssert trace, int parentIndex, String spanName, Exception expectedException) { + List> assertions = + new ArrayList<>( + Arrays.asList( + span -> + span.hasName(spanName) + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(parentIndex)))); + + if (expectedException != null) { + assertions.add(span -> span.hasStatus(StatusData.error()).hasException(expectedException)); + } + return assertions; + } + + @Test + void testException() { + // we need to display the page first before posting data to it + AggregatedHttpResponse response = + client.get(address.resolve("greeting.jsf").toString()).aggregate().join(); + Document doc = Jsoup.parse(response.contentUtf8()); + + assertThat(response.status().code()).isEqualTo(200); + assertThat(doc.selectFirst("title").text()).isEqualTo("Hello, World!"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/greeting.xhtml") + .hasKind(SpanKind.SERVER) + .hasNoParent())); + + testing.clearData(); + + String viewState = doc.selectFirst("[name=javax.faces.ViewState]").val(); + String formAction = doc.selectFirst("#app-form").attr("action"); + String jsessionid = + formAction.substring(formAction.indexOf("jsessionid=") + "jsessionid=".length()); + + assertThat(viewState).isNotNull(); + assertThat(jsessionid).isNotNull(); + + // set up form parameter for post + QueryParams formBody = + QueryParams.builder() + .add("app-form", "app-form") + // setting name parameter to "exception" triggers throwing exception in GreetingForm + .add("app-form:name", "exception") + .add("app-form:submit", "Say hello") + .add("app-form_SUBMIT", "1") // MyFaces + .add("javax.faces.ViewState", viewState) + .build(); + + // use the session created for first request + AggregatedHttpRequest request2 = + AggregatedHttpRequest.of( + RequestHeaders.builder( + HttpMethod.POST, + address.resolve("greeting.jsf;jsessionid=" + jsessionid).toString()) + .contentType(MediaType.FORM_DATA) + .build(), + HttpData.ofUtf8(formBody.toQueryString())); + AggregatedHttpResponse response2 = client.execute(request2).aggregate().join(); + + assertThat(response2.status().code()).isEqualTo(500); + IllegalStateException expectedException = new IllegalStateException("submit exception"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName(getContextPath() + "/greeting.xhtml") + .hasKind(SpanKind.SERVER) + .hasNoParent() + .hasStatus(StatusData.error()) + .hasException(expectedException), + span -> handlerSpan(trace, 0, "#{greetingForm.submit()}", expectedException))); + } +} diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/javax/ExceptionFilter.java b/instrumentation/jsf/jsf-javax-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/javax/ExceptionFilter.java new file mode 100644 index 000000000000..9360760dd739 --- /dev/null +++ b/instrumentation/jsf/jsf-javax-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/javax/ExceptionFilter.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsf.javax; + +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +public class ExceptionFilter implements Filter { + @Override + public void init(FilterConfig filterConfig) {} + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws ServletException, IOException { + try { + chain.doFilter(request, response); + } catch (ServletException exception) { + // to ease testing unwrap our exception to root cause + Throwable tmp = exception; + while (tmp.getCause() != null) { + tmp = tmp.getCause(); + } + if (tmp.getMessage() != null && tmp.getMessage().contains("submit exception")) { + throw (IllegalStateException) tmp; + } + throw exception; + } + } + + @Override + public void destroy() {} +} diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/javax/GreetingForm.java b/instrumentation/jsf/jsf-javax-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/javax/GreetingForm.java new file mode 100644 index 000000000000..60e36f4a60d4 --- /dev/null +++ b/instrumentation/jsf/jsf-javax-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/jsf/javax/GreetingForm.java @@ -0,0 +1,31 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsf.javax; + +public class GreetingForm { + + private String name = ""; + private String message = ""; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMessage() { + return message; + } + + public void submit() { + message = "Hello " + name; + if (name.equals("exception")) { + throw new IllegalStateException("submit exception"); + } + } +} diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-1.2/WEB-INF/faces-config.xml b/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-1.2/WEB-INF/faces-config.xml index 5502993f7db5..de9a1c0a68d2 100644 --- a/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-1.2/WEB-INF/faces-config.xml +++ b/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-1.2/WEB-INF/faces-config.xml @@ -4,11 +4,11 @@ version="1.2"> greetingForm - GreetingForm + io.opentelemetry.javaagent.instrumentation.jsf.javax.GreetingForm request com.sun.facelets.FaceletViewHandler - \ No newline at end of file + diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-1.2/WEB-INF/web.xml b/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-1.2/WEB-INF/web.xml index cb64b6ae8da1..2214cec902e6 100644 --- a/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-1.2/WEB-INF/web.xml +++ b/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-1.2/WEB-INF/web.xml @@ -20,7 +20,7 @@ ExceptionFilter - ExceptionFilter + io.opentelemetry.javaagent.instrumentation.jsf.javax.ExceptionFilter @@ -33,4 +33,4 @@ .xhtml - \ No newline at end of file + diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-2/WEB-INF/faces-config.xml b/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-2/WEB-INF/faces-config.xml index 9a0ad7c89786..f83e949af4db 100644 --- a/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-2/WEB-INF/faces-config.xml +++ b/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-2/WEB-INF/faces-config.xml @@ -2,7 +2,7 @@ greetingForm - GreetingForm + io.opentelemetry.javaagent.instrumentation.jsf.javax.GreetingForm request - \ No newline at end of file + diff --git a/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-2/WEB-INF/web.xml b/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-2/WEB-INF/web.xml index 191c55b09da3..32949939fbb4 100644 --- a/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-2/WEB-INF/web.xml +++ b/instrumentation/jsf/jsf-javax-common/testing/src/main/resources/test-app-2/WEB-INF/web.xml @@ -6,7 +6,7 @@ ExceptionFilter - ExceptionFilter + io.opentelemetry.javaagent.instrumentation.jsf.javax.ExceptionFilter @@ -14,4 +14,4 @@ /* - \ No newline at end of file + diff --git a/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra12Test/groovy/Mojarra12Test.groovy b/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra12Test/groovy/Mojarra12Test.groovy deleted file mode 100644 index d47c830ed0c4..000000000000 --- a/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra12Test/groovy/Mojarra12Test.groovy +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class Mojarra12Test extends BaseJsfTest { - @Override - String getJsfVersion() { - "1.2" - } -} diff --git a/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra12Test/java/io/opentelemetry/javaagent/instrumentation/mojarra/Mojarra12Test.java b/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra12Test/java/io/opentelemetry/javaagent/instrumentation/mojarra/Mojarra12Test.java new file mode 100644 index 000000000000..991b5d9cfb25 --- /dev/null +++ b/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra12Test/java/io/opentelemetry/javaagent/instrumentation/mojarra/Mojarra12Test.java @@ -0,0 +1,15 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.mojarra; + +import io.opentelemetry.javaagent.instrumentation.jsf.javax.BaseJsfTest; + +class Mojarra12Test extends BaseJsfTest { + @Override + public String getJsfVersion() { + return "1.2"; + } +} diff --git a/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra2Test/groovy/Mojarra2Test.groovy b/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra2Test/groovy/Mojarra2Test.groovy deleted file mode 100644 index 1097bb1e6e8c..000000000000 --- a/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra2Test/groovy/Mojarra2Test.groovy +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class Mojarra2Test extends BaseJsfTest { - @Override - String getJsfVersion() { - "2" - } -} diff --git a/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra2Test/java/io/opentelemetry/javaagent/instrumentation/mojarra/Mojarra2Test.java b/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra2Test/java/io/opentelemetry/javaagent/instrumentation/mojarra/Mojarra2Test.java new file mode 100644 index 000000000000..3d6e615ab810 --- /dev/null +++ b/instrumentation/jsf/jsf-mojarra-1.2/javaagent/src/mojarra2Test/java/io/opentelemetry/javaagent/instrumentation/mojarra/Mojarra2Test.java @@ -0,0 +1,15 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.mojarra; + +import io.opentelemetry.javaagent.instrumentation.jsf.javax.BaseJsfTest; + +class Mojarra2Test extends BaseJsfTest { + @Override + public String getJsfVersion() { + return "2"; + } +} diff --git a/instrumentation/jsf/jsf-mojarra-3.0/javaagent/src/test/groovy/Mojarra3Test.groovy b/instrumentation/jsf/jsf-mojarra-3.0/javaagent/src/test/groovy/Mojarra3Test.groovy deleted file mode 100644 index 477e318d7000..000000000000 --- a/instrumentation/jsf/jsf-mojarra-3.0/javaagent/src/test/groovy/Mojarra3Test.groovy +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class Mojarra3Test extends BaseJsfTest { -} diff --git a/instrumentation/jsf/jsf-mojarra-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/mojarra/v3_0/Mojarra3Test.java b/instrumentation/jsf/jsf-mojarra-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/mojarra/v3_0/Mojarra3Test.java new file mode 100644 index 000000000000..64488faa23d5 --- /dev/null +++ b/instrumentation/jsf/jsf-mojarra-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/mojarra/v3_0/Mojarra3Test.java @@ -0,0 +1,10 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.mojarra.v3_0; + +import io.opentelemetry.javaagent.instrumentation.jsf.jakarta.BaseJsfTest; + +class Mojarra3Test extends BaseJsfTest {} diff --git a/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces12Test/groovy/Myfaces12Test.groovy b/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces12Test/groovy/Myfaces12Test.groovy deleted file mode 100644 index bc532d1a2cad..000000000000 --- a/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces12Test/groovy/Myfaces12Test.groovy +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class Myfaces12Test extends BaseJsfTest { - @Override - String getJsfVersion() { - "1.2" - } -} diff --git a/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces12Test/java/io/opentelemetry/javaagent/instrumentation/myfaces/Myfaces12Test.java b/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces12Test/java/io/opentelemetry/javaagent/instrumentation/myfaces/Myfaces12Test.java new file mode 100644 index 000000000000..564091fd300f --- /dev/null +++ b/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces12Test/java/io/opentelemetry/javaagent/instrumentation/myfaces/Myfaces12Test.java @@ -0,0 +1,15 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.myfaces; + +import io.opentelemetry.javaagent.instrumentation.jsf.javax.BaseJsfTest; + +class Myfaces12Test extends BaseJsfTest { + @Override + public String getJsfVersion() { + return "1.2"; + } +} diff --git a/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces2Test/groovy/Myfaces2Test.groovy b/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces2Test/groovy/Myfaces2Test.groovy deleted file mode 100644 index bd08b6975d42..000000000000 --- a/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces2Test/groovy/Myfaces2Test.groovy +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class Myfaces2Test extends BaseJsfTest { - @Override - String getJsfVersion() { - "2" - } -} diff --git a/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces2Test/java/io/opentelemetry/javaagent/instrumentation/myfaces/Myfaces2Test.java b/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces2Test/java/io/opentelemetry/javaagent/instrumentation/myfaces/Myfaces2Test.java new file mode 100644 index 000000000000..67c9e38861e5 --- /dev/null +++ b/instrumentation/jsf/jsf-myfaces-1.2/javaagent/src/myfaces2Test/java/io/opentelemetry/javaagent/instrumentation/myfaces/Myfaces2Test.java @@ -0,0 +1,15 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.myfaces; + +import io.opentelemetry.javaagent.instrumentation.jsf.javax.BaseJsfTest; + +class Myfaces2Test extends BaseJsfTest { + @Override + public String getJsfVersion() { + return "2"; + } +} diff --git a/instrumentation/jsf/jsf-myfaces-3.0/javaagent/src/test/groovy/Myfaces3Test.groovy b/instrumentation/jsf/jsf-myfaces-3.0/javaagent/src/test/groovy/Myfaces3Test.groovy deleted file mode 100644 index 9a98485cafbb..000000000000 --- a/instrumentation/jsf/jsf-myfaces-3.0/javaagent/src/test/groovy/Myfaces3Test.groovy +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -class Myfaces3Test extends BaseJsfTest { -} diff --git a/instrumentation/jsf/jsf-myfaces-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/myfaces/v3_0/Myfaces3Test.java b/instrumentation/jsf/jsf-myfaces-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/myfaces/v3_0/Myfaces3Test.java new file mode 100644 index 000000000000..9d6d8b04c694 --- /dev/null +++ b/instrumentation/jsf/jsf-myfaces-3.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/myfaces/v3_0/Myfaces3Test.java @@ -0,0 +1,10 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.myfaces.v3_0; + +import io.opentelemetry.javaagent.instrumentation.jsf.jakarta.BaseJsfTest; + +class Myfaces3Test extends BaseJsfTest {} diff --git a/instrumentation/jsp-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/HttpJspPageInstrumentationSingletons.java b/instrumentation/jsp-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/HttpJspPageInstrumentationSingletons.java index e4239002ad2f..fd8c74030f81 100644 --- a/instrumentation/jsp-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/HttpJspPageInstrumentationSingletons.java +++ b/instrumentation/jsp-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/HttpJspPageInstrumentationSingletons.java @@ -13,8 +13,8 @@ import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import java.net.URI; import java.net.URISyntaxException; import java.util.logging.Logger; @@ -25,7 +25,7 @@ public class HttpJspPageInstrumentationSingletons { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.jsp.experimental-span-attributes", false); private static final Instrumenter INSTRUMENTER; diff --git a/instrumentation/jsp-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspCompilationContextInstrumentationSingletons.java b/instrumentation/jsp-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspCompilationContextInstrumentationSingletons.java index c4c474c725b7..28ce32f9ecca 100644 --- a/instrumentation/jsp-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspCompilationContextInstrumentationSingletons.java +++ b/instrumentation/jsp-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jsp/JspCompilationContextInstrumentationSingletons.java @@ -11,14 +11,14 @@ import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import javax.annotation.Nullable; import org.apache.jasper.JspCompilationContext; import org.apache.jasper.compiler.Compiler; public class JspCompilationContextInstrumentationSingletons { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.jsp.experimental-span-attributes", false); private static final Instrumenter INSTRUMENTER; diff --git a/instrumentation/jsp-2.3/javaagent/src/test/groovy/JspInstrumentationBasicTests.groovy b/instrumentation/jsp-2.3/javaagent/src/test/groovy/JspInstrumentationBasicTests.groovy deleted file mode 100644 index 8990653a46d8..000000000000 --- a/instrumentation/jsp-2.3/javaagent/src/test/groovy/JspInstrumentationBasicTests.groovy +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.semconv.ExceptionAttributes -import io.opentelemetry.semconv.ServerAttributes -import io.opentelemetry.semconv.ClientAttributes -import io.opentelemetry.semconv.UserAgentAttributes -import io.opentelemetry.semconv.ErrorAttributes -import io.opentelemetry.semconv.HttpAttributes -import io.opentelemetry.semconv.NetworkAttributes -import io.opentelemetry.semconv.UrlAttributes -import io.opentelemetry.testing.internal.armeria.client.WebClient -import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse -import io.opentelemetry.testing.internal.armeria.common.HttpMethod -import io.opentelemetry.testing.internal.armeria.common.MediaType -import io.opentelemetry.testing.internal.armeria.common.RequestHeaders -import org.apache.catalina.Context -import org.apache.catalina.startup.Tomcat -import org.apache.jasper.JasperException -import spock.lang.Shared -import spock.lang.Unroll - -import java.nio.file.Files - -import static io.opentelemetry.api.trace.SpanKind.SERVER -import static io.opentelemetry.api.trace.StatusCode.ERROR - -//TODO should this be HttpServerTest? -class JspInstrumentationBasicTests extends AgentInstrumentationSpecification { - - @Shared - int port - @Shared - Tomcat tomcatServer - @Shared - Context appContext - @Shared - String jspWebappContext = "jsptest-context" - - @Shared - File baseDir - @Shared - String baseUrl - - @Shared - WebClient client - - def setupSpec() { - baseDir = Files.createTempDirectory("jsp").toFile() - baseDir.deleteOnExit() - - port = PortUtils.findOpenPort() - - tomcatServer = new Tomcat() - tomcatServer.setBaseDir(baseDir.getAbsolutePath()) - tomcatServer.setPort(port) - tomcatServer.getConnector() - // comment to debug - tomcatServer.setSilent(true) - // this is needed in tomcat 9, this triggers the creation of a connector, will not - // affect tomcat 7 and 8 - // https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed - tomcatServer.getConnector() - baseUrl = "http://localhost:$port/$jspWebappContext" - client = WebClient.of(baseUrl) - - appContext = tomcatServer.addWebapp("/$jspWebappContext", - JspInstrumentationBasicTests.getResource("/webapps/jsptest").getPath()) - - tomcatServer.start() - System.out.println( - "Tomcat server: http://" + tomcatServer.getHost().getName() + ":" + port + "/") - } - - def cleanupSpec() { - tomcatServer.stop() - tomcatServer.destroy() - } - - @Unroll - def "non-erroneous GET #test test"() { - when: - AggregatedHttpResponse res = client.get("/${jspFileName}").aggregate().join() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - def route = "/$jspWebappContext/$jspFileName" - - hasNoParent() - name "GET $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /$jspFileName" - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspClassNamePrefix$jspClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /$jspFileName" - attributes { - "jsp.requestURL" "${baseUrl}/${jspFileName}" - } - } - } - } - res.status().code() == 200 - - where: - test | jspFileName | jspClassName | jspClassNamePrefix - "no java jsp" | "nojava.jsp" | "nojava_jsp" | "" - "basic loop jsp" | "common/loop.jsp" | "loop_jsp" | "common." - "invalid HTML markup" | "invalidMarkup.jsp" | "invalidMarkup_jsp" | "" - } - - def "non-erroneous GET with query string"() { - setup: - String queryString = "HELLO" - - when: - AggregatedHttpResponse res = client.get("/getQuery.jsp?${queryString}").aggregate().join() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - def route = "/$jspWebappContext/getQuery.jsp" - - hasNoParent() - name "GET $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$UrlAttributes.URL_QUERY" queryString - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /getQuery.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.getQuery_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /getQuery.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/getQuery.jsp" - } - } - } - } - res.status().code() == 200 - } - - def "non-erroneous POST"() { - setup: - RequestHeaders headers = RequestHeaders.builder(HttpMethod.POST, "/post.jsp") - .contentType(MediaType.FORM_DATA) - .build() - - when: - AggregatedHttpResponse res = client.execute(headers, "name=world").aggregate().join() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - def route = "/$jspWebappContext/post.jsp" - - hasNoParent() - name "POST $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "POST" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /post.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.post_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /post.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/post.jsp" - } - } - } - } - res.status().code() == 200 - } - - @Unroll - def "erroneous runtime errors GET jsp with #test test"() { - when: - AggregatedHttpResponse res = client.get("/${jspFileName}").aggregate().join() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - def route = "/$jspWebappContext/$jspFileName" - - hasNoParent() - name "GET $route" - kind SERVER - status ERROR - event(0) { - eventName("exception") - attributes { - "$ExceptionAttributes.EXCEPTION_TYPE" { String tagExceptionType -> - return tagExceptionType == exceptionClass.getName() || tagExceptionType.contains(exceptionClass.getSimpleName()) - } - "$ExceptionAttributes.EXCEPTION_MESSAGE" { String tagErrorMsg -> - return errorMessageOptional || tagErrorMsg instanceof String - } - "$ExceptionAttributes.EXCEPTION_STACKTRACE" String - } - } - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 500 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - "$ErrorAttributes.ERROR_TYPE" "500" - } - } - span(1) { - childOf span(0) - name "Compile /$jspFileName" - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /$jspFileName" - status ERROR - event(0) { - eventName("exception") - attributes { - "$ExceptionAttributes.EXCEPTION_TYPE" { String tagExceptionType -> - return tagExceptionType == exceptionClass.getName() || tagExceptionType.contains(exceptionClass.getSimpleName()) - } - "$ExceptionAttributes.EXCEPTION_MESSAGE" { String tagErrorMsg -> - return errorMessageOptional || tagErrorMsg instanceof String - } - "$ExceptionAttributes.EXCEPTION_STACKTRACE" String - } - } - attributes { - "jsp.requestURL" "${baseUrl}/${jspFileName}" - } - } - } - } - res.status().code() == 500 - - where: - test | jspFileName | jspClassName | exceptionClass | errorMessageOptional - "java runtime error" | "runtimeError.jsp" | "runtimeError_jsp" | ArithmeticException | false - "invalid write" | "invalidWrite.jsp" | "invalidWrite_jsp" | IndexOutOfBoundsException | true - "missing query gives null" | "getQuery.jsp" | "getQuery_jsp" | NullPointerException | true - } - - def "non-erroneous include plain HTML GET"() { - when: - AggregatedHttpResponse res = client.get("/includes/includeHtml.jsp").aggregate().join() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - def route = "/$jspWebappContext/includes/includeHtml.jsp" - - hasNoParent() - name "GET $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /includes/includeHtml.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.includes.includeHtml_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /includes/includeHtml.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/includes/includeHtml.jsp" - } - } - } - } - res.status().code() == 200 - } - - def "non-erroneous multi GET"() { - when: - AggregatedHttpResponse res = client.get("/includes/includeMulti.jsp").aggregate().join() - - then: - assertTraces(1) { - trace(0, 7) { - span(0) { - def route = "/$jspWebappContext/includes/includeMulti.jsp" - - hasNoParent() - name "GET $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /includes/includeMulti.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.includes.includeMulti_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /includes/includeMulti.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp" - } - } - span(3) { - childOf span(2) - name "Compile /common/javaLoopH2.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(4) { - childOf span(2) - name "Render /common/javaLoopH2.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp" - } - } - span(5) { - childOf span(2) - name "Compile /common/javaLoopH2.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(6) { - childOf span(2) - name "Render /common/javaLoopH2.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp" - } - } - } - } - res.status().code() == 200 - } - - def "#test compile error should not produce render traces and spans"() { - when: - AggregatedHttpResponse res = client.get("/${jspFileName}").aggregate().join() - - then: - assertTraces(1) { - trace(0, 2) { - span(0) { - def route = "/$jspWebappContext/$jspFileName" - - hasNoParent() - name "GET $route" - kind SERVER - status ERROR - errorEvent(JasperException, String) - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 500 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - "$ErrorAttributes.ERROR_TYPE" "500" - } - } - span(1) { - childOf span(0) - name "Compile /$jspFileName" - status ERROR - errorEvent(JasperException, String) - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspClassNamePrefix$jspClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - } - } - res.status().code() == 500 - - where: - test | jspFileName | jspClassName | jspClassNamePrefix - "normal" | "compileError.jsp" | "compileError_jsp" | "" - "forward" | "forwards/forwardWithCompileError.jsp" | "forwardWithCompileError_jsp" | "forwards." - } - - def "direct static file reference"() { - when: - AggregatedHttpResponse res = client.get("/${staticFile}").aggregate().join() - - then: - res.status().code() == 200 - assertTraces(1) { - trace(0, 1) { - span(0) { - def route = "/$jspWebappContext/*" - - hasNoParent() - name "GET $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" "/$jspWebappContext/$staticFile" - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - } - } - - where: - staticFile = "common/hello.html" - } -} diff --git a/instrumentation/jsp-2.3/javaagent/src/test/groovy/JspInstrumentationForwardTests.groovy b/instrumentation/jsp-2.3/javaagent/src/test/groovy/JspInstrumentationForwardTests.groovy deleted file mode 100644 index baaa5bc4f8f9..000000000000 --- a/instrumentation/jsp-2.3/javaagent/src/test/groovy/JspInstrumentationForwardTests.groovy +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.instrumentation.test.utils.PortUtils -import io.opentelemetry.semconv.ServerAttributes -import io.opentelemetry.semconv.ClientAttributes -import io.opentelemetry.semconv.UserAgentAttributes -import io.opentelemetry.semconv.ErrorAttributes -import io.opentelemetry.semconv.HttpAttributes -import io.opentelemetry.semconv.NetworkAttributes -import io.opentelemetry.semconv.UrlAttributes -import io.opentelemetry.testing.internal.armeria.client.WebClient -import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse -import org.apache.catalina.Context -import org.apache.catalina.startup.Tomcat -import org.apache.jasper.JasperException -import spock.lang.Shared -import spock.lang.Unroll - -import java.nio.file.Files - -import static io.opentelemetry.api.trace.SpanKind.SERVER -import static io.opentelemetry.api.trace.StatusCode.ERROR -import static io.opentelemetry.api.trace.StatusCode.UNSET - -class JspInstrumentationForwardTests extends AgentInstrumentationSpecification { - - @Shared - int port - @Shared - Tomcat tomcatServer - @Shared - Context appContext - @Shared - String jspWebappContext = "jsptest-context" - - @Shared - File baseDir - @Shared - String baseUrl - - @Shared - WebClient client - - def setupSpec() { - baseDir = Files.createTempDirectory("jsp").toFile() - baseDir.deleteOnExit() - - port = PortUtils.findOpenPort() - - tomcatServer = new Tomcat() - tomcatServer.setBaseDir(baseDir.getAbsolutePath()) - tomcatServer.setPort(port) - tomcatServer.getConnector() - // comment to debug - tomcatServer.setSilent(true) - // this is needed in tomcat 9, this triggers the creation of a connector, will not - // affect tomcat 7 and 8 - // https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed - tomcatServer.getConnector() - - baseUrl = "http://localhost:$port/$jspWebappContext" - client = WebClient.of(baseUrl) - - appContext = tomcatServer.addWebapp("/$jspWebappContext", - JspInstrumentationForwardTests.getResource("/webapps/jsptest").getPath()) - - tomcatServer.start() - System.out.println( - "Tomcat server: http://" + tomcatServer.getHost().getName() + ":" + port + "/") - } - - def cleanupSpec() { - tomcatServer.stop() - tomcatServer.destroy() - } - - @Unroll - def "non-erroneous GET forward to #forwardTo"() { - when: - AggregatedHttpResponse res = client.get("/$forwardFromFileName").aggregate().join() - - then: - assertTraces(1) { - trace(0, 5) { - span(0) { - def route = "/$jspWebappContext/$forwardFromFileName" - - hasNoParent() - name "GET $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /$forwardFromFileName" - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspForwardFromClassPrefix$jspForwardFromClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /$forwardFromFileName" - attributes { - "jsp.requestURL" "${baseUrl}/$forwardFromFileName" - } - } - span(3) { - childOf span(2) - name "Compile /$forwardDestFileName" - attributes { - "jsp.classFQCN" "org.apache.jsp.$jspForwardDestClassPrefix$jspForwardDestClassName" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(4) { - childOf span(2) - name "Render /$forwardDestFileName" - attributes { - "jsp.forwardOrigin" "/$forwardFromFileName" - "jsp.requestURL" "${baseUrl}/$forwardDestFileName" - } - } - } - } - res.status().code() == 200 - - where: - forwardTo | forwardFromFileName | forwardDestFileName | jspForwardFromClassName | jspForwardFromClassPrefix | jspForwardDestClassName | jspForwardDestClassPrefix - "no java jsp" | "forwards/forwardToNoJavaJsp.jsp" | "nojava.jsp" | "forwardToNoJavaJsp_jsp" | "forwards." | "nojava_jsp" | "" - "normal java jsp" | "forwards/forwardToSimpleJava.jsp" | "common/loop.jsp" | "forwardToSimpleJava_jsp" | "forwards." | "loop_jsp" | "common." - } - - def "non-erroneous GET forward to plain HTML"() { - when: - AggregatedHttpResponse res = client.get("/forwards/forwardToHtml.jsp").aggregate().join() - - then: - assertTraces(1) { - trace(0, 3) { - span(0) { - def route = "/$jspWebappContext/forwards/forwardToHtml.jsp" - - hasNoParent() - name "GET $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToHtml.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToHtml_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToHtml.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/forwards/forwardToHtml.jsp" - } - } - } - } - res.status().code() == 200 - } - - def "non-erroneous GET forwarded to jsp with multiple includes"() { - when: - AggregatedHttpResponse res = client.get("/forwards/forwardToIncludeMulti.jsp").aggregate().join() - - then: - assertTraces(1) { - trace(0, 9) { - span(0) { - def route = "/$jspWebappContext/forwards/forwardToIncludeMulti.jsp" - - hasNoParent() - name "GET $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToIncludeMulti.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToIncludeMulti_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToIncludeMulti.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/forwards/forwardToIncludeMulti.jsp" - } - } - span(3) { - childOf span(2) - name "Compile /includes/includeMulti.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.includes.includeMulti_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(4) { - childOf span(2) - name "Render /includes/includeMulti.jsp" - attributes { - "jsp.forwardOrigin" "/forwards/forwardToIncludeMulti.jsp" - "jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp" - } - } - span(5) { - childOf span(4) - name "Compile /common/javaLoopH2.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(6) { - childOf span(4) - name "Render /common/javaLoopH2.jsp" - attributes { - "jsp.forwardOrigin" "/forwards/forwardToIncludeMulti.jsp" - "jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp" - } - } - span(7) { - childOf span(4) - name "Compile /common/javaLoopH2.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.common.javaLoopH2_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(8) { - childOf span(4) - name "Render /common/javaLoopH2.jsp" - attributes { - "jsp.forwardOrigin" "/forwards/forwardToIncludeMulti.jsp" - "jsp.requestURL" "${baseUrl}/includes/includeMulti.jsp" - } - } - } - } - res.status().code() == 200 - } - - def "non-erroneous GET forward to another forward (2 forwards)"() { - when: - AggregatedHttpResponse res = client.get("/forwards/forwardToJspForward.jsp").aggregate().join() - - then: - assertTraces(1) { - trace(0, 7) { - span(0) { - def route = "/$jspWebappContext/forwards/forwardToJspForward.jsp" - - hasNoParent() - name "GET $route" - kind SERVER - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToJspForward.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToJspForward_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToJspForward.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/forwards/forwardToJspForward.jsp" - } - } - span(3) { - childOf span(2) - name "Compile /forwards/forwardToSimpleJava.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToSimpleJava_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(4) { - childOf span(2) - name "Render /forwards/forwardToSimpleJava.jsp" - attributes { - "jsp.forwardOrigin" "/forwards/forwardToJspForward.jsp" - "jsp.requestURL" "${baseUrl}/forwards/forwardToSimpleJava.jsp" - } - } - span(5) { - childOf span(4) - name "Compile /common/loop.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.common.loop_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(6) { - childOf span(4) - name "Render /common/loop.jsp" - attributes { - "jsp.forwardOrigin" "/forwards/forwardToJspForward.jsp" - "jsp.requestURL" "${baseUrl}/common/loop.jsp" - } - } - } - } - res.status().code() == 200 - } - - def "forward to jsp with compile error should not produce a 2nd render span"() { - when: - AggregatedHttpResponse res = client.get("/forwards/forwardToCompileError.jsp").aggregate().join() - - then: - assertTraces(1) { - trace(0, 4) { - span(0) { - def route = "/$jspWebappContext/forwards/forwardToCompileError.jsp" - - hasNoParent() - name "GET $route" - kind SERVER - status ERROR - errorEvent(JasperException, String) - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 500 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - "$ErrorAttributes.ERROR_TYPE" "500" - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToCompileError.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToCompileError_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToCompileError.jsp" - status ERROR - errorEvent(JasperException, String) - attributes { - "jsp.requestURL" "${baseUrl}/forwards/forwardToCompileError.jsp" - } - } - span(3) { - childOf span(2) - name "Compile /compileError.jsp" - status ERROR - errorEvent(JasperException, String) - attributes { - "jsp.classFQCN" "org.apache.jsp.compileError_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - } - } - res.status().code() == 500 - } - - def "forward to non existent jsp should be 404"() { - when: - AggregatedHttpResponse res = client.get("/forwards/forwardToNonExistent.jsp").aggregate().join() - - then: - assertTraces(1) { - trace(0, 4) { - span(0) { - def route = "/$jspWebappContext/forwards/forwardToNonExistent.jsp" - - hasNoParent() - name "GET $route" - kind SERVER - status UNSET - attributes { - "$UrlAttributes.URL_SCHEME" "http" - "$UrlAttributes.URL_PATH" route - "$HttpAttributes.HTTP_REQUEST_METHOD" "GET" - "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 404 - "$UserAgentAttributes.USER_AGENT_ORIGINAL" String - "$HttpAttributes.HTTP_ROUTE" route - "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1" - "$ServerAttributes.SERVER_ADDRESS" "localhost" - "$ServerAttributes.SERVER_PORT" port - "$ClientAttributes.CLIENT_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_ADDRESS" "127.0.0.1" - "$NetworkAttributes.NETWORK_PEER_PORT" Long - } - } - span(1) { - childOf span(0) - name "Compile /forwards/forwardToNonExistent.jsp" - attributes { - "jsp.classFQCN" "org.apache.jsp.forwards.forwardToNonExistent_jsp" - "jsp.compiler" "org.apache.jasper.compiler.JDTCompiler" - } - } - span(2) { - childOf span(0) - name "Render /forwards/forwardToNonExistent.jsp" - attributes { - "jsp.requestURL" "${baseUrl}/forwards/forwardToNonExistent.jsp" - } - } - span(3) { - childOf span(2) - name "ResponseFacade.sendError" - } - } - } - res.status().code() == 404 - } -} diff --git a/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspInstrumentationBasicTests.java b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspInstrumentationBasicTests.java new file mode 100644 index 000000000000..2114818ce287 --- /dev/null +++ b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspInstrumentationBasicTests.java @@ -0,0 +1,488 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsp; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerUsingTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.semconv.ClientAttributes; +import io.opentelemetry.semconv.ExceptionAttributes; +import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.NetworkAttributes; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.UrlAttributes; +import io.opentelemetry.semconv.UserAgentAttributes; +import io.opentelemetry.testing.internal.armeria.client.WebClient; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import io.opentelemetry.testing.internal.armeria.common.HttpMethod; +import io.opentelemetry.testing.internal.armeria.common.MediaType; +import io.opentelemetry.testing.internal.armeria.common.RequestHeaders; +import java.io.File; +import java.nio.file.Files; +import java.util.stream.Stream; +import org.apache.catalina.startup.Tomcat; +import org.apache.jasper.JasperException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; +import org.junit.jupiter.params.provider.ValueSource; + +class JspInstrumentationBasicTests extends AbstractHttpServerUsingTest { + + @RegisterExtension + public static final InstrumentationExtension testing = + HttpServerInstrumentationExtension.forAgent(); + + private static JspSpanAssertions spanAsserts; + + @Override + protected Tomcat setupServer() throws Exception { + File baseDir = Files.createTempDirectory("jsp").toFile(); + baseDir.deleteOnExit(); + + Tomcat tomcatServer = new Tomcat(); + tomcatServer.setBaseDir(baseDir.getAbsolutePath()); + tomcatServer.setPort(port); + tomcatServer.getConnector(); + + // comment to debug + tomcatServer.setSilent(true); + + // this is needed in tomcat 9, this triggers the creation of a connector, will not + // affect tomcat 7 and 8 + // https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed + tomcatServer.getConnector(); + + String baseUrl = "http://localhost:" + port + "/" + getContextPath(); + spanAsserts = new JspSpanAssertions(baseUrl, port); + client = WebClient.of(baseUrl); + + tomcatServer.addWebapp( + "/" + getContextPath(), + JspInstrumentationBasicTests.class.getResource("/webapps/jsptest").getPath()); + + tomcatServer.start(); + return tomcatServer; + } + + @Override + protected void stopServer(Tomcat tomcat) throws Exception { + tomcat.stop(); + tomcat.destroy(); + } + + @Override + protected String getContextPath() { + return "jsptest-context"; + } + + @BeforeAll + protected void setUp() { + startServer(); + } + + @AfterAll + protected void cleanUp() { + cleanupServer(); + } + + @ParameterizedTest(name = "GET {0}") + @ArgumentsSource(NonErroneousArgs.class) + void testNonErroneousGet( + String testName, String jspFileName, String jspClassName, String jspClassNamePrefix) { + AggregatedHttpResponse res = client.get(jspFileName).aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute("/" + getContextPath() + jspFileName) + .withResponseStatus(200) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute(jspFileName) + .withClassName(jspClassNamePrefix + jspClassName) + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute(jspFileName) + .build()))); + } + + static class NonErroneousArgs implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of("no java jsp", "/nojava.jsp", "nojava_jsp", ""), + Arguments.of("basic loop jsp", "/common/loop.jsp", "loop_jsp", "common."), + Arguments.of("invalid HTML markup", "/invalidMarkup.jsp", "invalidMarkup_jsp", "")); + } + } + + @Test + void testNonErroneousGetWithQueryString() { + String queryString = "HELLO"; + String route = "/" + getContextPath() + "/getQuery.jsp"; + + AggregatedHttpResponse res = client.get("/getQuery.jsp?" + queryString).aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET " + route) + .hasNoParent() + .hasKind(SpanKind.SERVER) + .hasAttributesSatisfyingExactly( + equalTo(UrlAttributes.URL_SCHEME, "http"), + equalTo(UrlAttributes.URL_PATH, route), + equalTo(UrlAttributes.URL_QUERY, queryString), + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + satisfies( + UserAgentAttributes.USER_AGENT_ORIGINAL, + val -> val.isInstanceOf(String.class)), + equalTo(HttpAttributes.HTTP_ROUTE, route), + equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"), + satisfies( + NetworkAttributes.NETWORK_PEER_PORT, + val -> val.isInstanceOf(Long.class))), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/getQuery.jsp") + .withClassName("getQuery_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/getQuery.jsp") + .build()))); + } + + @Test + void testNonErroneousPost() { + RequestHeaders headers = + RequestHeaders.builder(HttpMethod.POST, "/post.jsp") + .contentType(MediaType.FORM_DATA) + .build(); + + AggregatedHttpResponse res = client.execute(headers, "name=world").aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("POST") + .withRoute("/" + getContextPath() + "/post.jsp") + .withResponseStatus(200) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/post.jsp") + .withClassName("post_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/post.jsp") + .build()))); + } + + @ParameterizedTest(name = "GET jsp with {0}") + @ArgumentsSource(ErroneousRuntimeErrorsArgs.class) + void testErroneousRuntimeErrorsGet( + String testName, + String jspFileName, + String jspClassName, + Class exceptionClass, + boolean errorMessageOptional) { + AggregatedHttpResponse res = client.get(jspFileName).aggregate().join(); + assertThat(res.status().code()).isEqualTo(500); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute("/" + getContextPath() + jspFileName) + .withResponseStatus(500) + .withExceptionClass(exceptionClass) + .withErrorMessageOptional(errorMessageOptional) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute(jspFileName) + .withClassName(jspClassName) + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute(jspFileName) + .withErrorMessageOptional(errorMessageOptional) + .build()))); + } + + static class ErroneousRuntimeErrorsArgs implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of( + "java runtime error", + "/runtimeError.jsp", + "runtimeError_jsp", + ArithmeticException.class, + false), + Arguments.of( + "invalid write", + "/invalidWrite.jsp", + "invalidWrite_jsp", + IndexOutOfBoundsException.class, + true), + Arguments.of( + "invalid write", "/getQuery.jsp", "getQuery_jsp", NullPointerException.class, true)); + } + } + + @Test + void testNonErroneousIncludePlainHtmlGet() { + AggregatedHttpResponse res = client.get("/includes/includeHtml.jsp").aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute("/" + getContextPath() + "/includes/includeHtml.jsp") + .withResponseStatus(200) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/includes/includeHtml.jsp") + .withClassName("includes.includeHtml_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/includes/includeHtml.jsp") + .build()))); + } + + @Test + void testNonErroneousMultiGet() { + AggregatedHttpResponse res = client.get("/includes/includeMulti.jsp").aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute("/" + getContextPath() + "/includes/includeMulti.jsp") + .withResponseStatus(200) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/includes/includeMulti.jsp") + .withClassName("includes.includeMulti_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/includes/includeMulti.jsp") + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute("/common/javaLoopH2.jsp") + .withClassName("common.javaLoopH2_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute("/common/javaLoopH2.jsp") + .withRequestUrlOverride("/includes/includeMulti.jsp") + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute("/common/javaLoopH2.jsp") + .withClassName("common.javaLoopH2_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute("/common/javaLoopH2.jsp") + .withRequestUrlOverride("/includes/includeMulti.jsp") + .build()))); + } + + @ParameterizedTest + @ArgumentsSource(CompileErrorsArgs.class) + void testCompileErrorShouldNotProduceRenderTracesAndSpans( + String jspFileName, String jspClassName, String jspClassNamePrefix) { + AggregatedHttpResponse res = client.get(jspFileName).aggregate().join(); + assertThat(res.status().code()).isEqualTo(500); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute("/" + getContextPath() + jspFileName) + .withResponseStatus(500) + .withExceptionClass(JasperException.class) + .build()), + span -> + span.hasName("Compile " + jspFileName) + .hasParent(trace.getSpan(0)) + .hasStatus(StatusData.error()) + .hasEventsSatisfyingExactly( + event -> + event + .hasName("exception") + .hasAttributesSatisfyingExactly( + equalTo( + ExceptionAttributes.EXCEPTION_TYPE, + JasperException.class.getCanonicalName()), + satisfies( + ExceptionAttributes.EXCEPTION_STACKTRACE, + val -> val.isInstanceOf(String.class)), + satisfies( + ExceptionAttributes.EXCEPTION_MESSAGE, + val -> val.isInstanceOf(String.class)))) + .hasAttributesSatisfyingExactly( + equalTo( + stringKey("jsp.classFQCN"), + "org.apache.jsp." + jspClassNamePrefix + jspClassName), + equalTo( + stringKey("jsp.compiler"), + "org.apache.jasper.compiler.JDTCompiler")))); + } + + static class CompileErrorsArgs implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of("/compileError.jsp", "compileError_jsp", ""), + Arguments.of( + "/forwards/forwardWithCompileError.jsp", "forwardWithCompileError_jsp", "forwards.")); + } + } + + @ParameterizedTest + @ValueSource(strings = {"/common/hello.html"}) + void testDirectStaticFileReference(String staticFile) { + String route = "/" + getContextPath() + "/*"; + + AggregatedHttpResponse res = client.get(staticFile).aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET " + route) + .hasNoParent() + .hasKind(SpanKind.SERVER) + .hasAttributesSatisfyingExactly( + equalTo(UrlAttributes.URL_SCHEME, "http"), + equalTo(UrlAttributes.URL_PATH, "/" + getContextPath() + staticFile), + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200), + satisfies( + UserAgentAttributes.USER_AGENT_ORIGINAL, + val -> val.isInstanceOf(String.class)), + equalTo(HttpAttributes.HTTP_ROUTE, route), + equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"), + satisfies( + NetworkAttributes.NETWORK_PEER_PORT, + val -> val.isInstanceOf(Long.class))))); + } +} diff --git a/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspInstrumentationForwardTests.java b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspInstrumentationForwardTests.java new file mode 100644 index 000000000000..5ba8d5df7c49 --- /dev/null +++ b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspInstrumentationForwardTests.java @@ -0,0 +1,454 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsp; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerUsingTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.semconv.ClientAttributes; +import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.NetworkAttributes; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.UrlAttributes; +import io.opentelemetry.semconv.UserAgentAttributes; +import io.opentelemetry.testing.internal.armeria.client.WebClient; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import java.io.File; +import java.nio.file.Files; +import java.util.stream.Stream; +import org.apache.catalina.startup.Tomcat; +import org.apache.jasper.JasperException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; +import org.junit.jupiter.params.provider.ArgumentsSource; + +class JspInstrumentationForwardTests extends AbstractHttpServerUsingTest { + + @RegisterExtension + public static final InstrumentationExtension testing = + HttpServerInstrumentationExtension.forAgent(); + + private static JspSpanAssertions spanAsserts; + + @Override + protected Tomcat setupServer() throws Exception { + File baseDir = Files.createTempDirectory("jsp").toFile(); + baseDir.deleteOnExit(); + + Tomcat tomcatServer = new Tomcat(); + tomcatServer.setBaseDir(baseDir.getAbsolutePath()); + tomcatServer.setPort(port); + tomcatServer.getConnector(); + + // comment to debug + tomcatServer.setSilent(true); + + // this is needed in tomcat 9, this triggers the creation of a connector, will not + // affect tomcat 7 and 8 + // https://stackoverflow.com/questions/48998387/code-works-with-embedded-apache-tomcat-8-but-not-with-9-whats-changed + tomcatServer.getConnector(); + + String baseUrl = "http://localhost:" + port + "/" + getContextPath(); + spanAsserts = new JspSpanAssertions(baseUrl, port); + client = WebClient.of(baseUrl); + + tomcatServer.addWebapp( + "/" + getContextPath(), + JspInstrumentationForwardTests.class.getResource("/webapps/jsptest").getPath()); + + tomcatServer.start(); + return tomcatServer; + } + + @Override + protected void stopServer(Tomcat tomcat) throws Exception { + tomcat.stop(); + tomcat.destroy(); + } + + @Override + protected String getContextPath() { + return "jsptest-context"; + } + + @BeforeAll + protected void setUp() { + startServer(); + } + + @AfterAll + protected void cleanUp() { + cleanupServer(); + } + + @ParameterizedTest(name = "Forward to {0}") + @ArgumentsSource(NonErroneousGetForwardArgs.class) + void testNonErroneousGetForwardTo( + String name, + String forwardFromFileName, + String forwardDestFileName, + String jspForwardFromClassName, + String jspForwardFromClassPrefix, + String jspForwardDestClassName, + String jspForwardDestClassPrefix) { + AggregatedHttpResponse res = client.get(forwardFromFileName).aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute("/" + getContextPath() + forwardFromFileName) + .withResponseStatus(200) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute(forwardFromFileName) + .withClassName(jspForwardFromClassPrefix + jspForwardFromClassName) + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute(forwardFromFileName) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute(forwardDestFileName) + .withClassName(jspForwardDestClassPrefix + jspForwardDestClassName) + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute(forwardDestFileName) + .build()))); + } + + static class NonErroneousGetForwardArgs implements ArgumentsProvider { + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of( + "no java jsp", + "/forwards/forwardToNoJavaJsp.jsp", + "/nojava.jsp", + "forwardToNoJavaJsp_jsp", + "forwards.", + "nojava_jsp", + ""), + Arguments.of( + "normal java jsp", + "/forwards/forwardToSimpleJava.jsp", + "/common/loop.jsp", + "forwardToSimpleJava_jsp", + "forwards.", + "loop_jsp", + "common.")); + } + } + + @Test + void testNonErroneousGetForwardToPlainHtml() { + AggregatedHttpResponse res = client.get("/forwards/forwardToHtml.jsp").aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute("/" + getContextPath() + "/forwards/forwardToHtml.jsp") + .withResponseStatus(200) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToHtml.jsp") + .withClassName("forwards.forwardToHtml_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToHtml.jsp") + .build()))); + } + + @Test + void testNonErroneousGetForwardedToJspWithMultipleIncludes() { + AggregatedHttpResponse res = + client.get("/forwards/forwardToIncludeMulti.jsp").aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute( + "/" + getContextPath() + "/forwards/forwardToIncludeMulti.jsp") + .withResponseStatus(200) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToIncludeMulti.jsp") + .withClassName("forwards.forwardToIncludeMulti_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToIncludeMulti.jsp") + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute("/includes/includeMulti.jsp") + .withClassName("includes.includeMulti_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute("/includes/includeMulti.jsp") + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(4)) + .withRoute("/common/javaLoopH2.jsp") + .withClassName("common.javaLoopH2_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(4)) + .withRoute("/common/javaLoopH2.jsp") + .withRequestUrlOverride("/includes/includeMulti.jsp") + .withForwardOrigin("/forwards/forwardToIncludeMulti.jsp") + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(4)) + .withRoute("/common/javaLoopH2.jsp") + .withClassName("common.javaLoopH2_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(4)) + .withRoute("/common/javaLoopH2.jsp") + .withRequestUrlOverride("/includes/includeMulti.jsp") + .withForwardOrigin("/forwards/forwardToIncludeMulti.jsp") + .build()))); + } + + @Test + void testNonErroneousGetForwardToAnotherForward() { + AggregatedHttpResponse res = client.get("/forwards/forwardToJspForward.jsp").aggregate().join(); + assertThat(res.status().code()).isEqualTo(200); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute("/" + getContextPath() + "/forwards/forwardToJspForward.jsp") + .withResponseStatus(200) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToJspForward.jsp") + .withClassName("forwards.forwardToJspForward_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToJspForward.jsp") + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute("/forwards/forwardToSimpleJava.jsp") + .withClassName("forwards.forwardToSimpleJava_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute("/forwards/forwardToSimpleJava.jsp") + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(4)) + .withRoute("/common/loop.jsp") + .withClassName("common.loop_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(4)) + .withRoute("/common/loop.jsp") + .build()))); + } + + @Test + void testForwardToJspWithCompileErrorShouldNotProduceSecondRenderSpan() { + AggregatedHttpResponse res = + client.get("/forwards/forwardToCompileError.jsp").aggregate().join(); + assertThat(res.status().code()).isEqualTo(500); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + spanAsserts.assertServerSpan( + span, + new JspSpanAssertionBuilder() + .withMethod("GET") + .withRoute( + "/" + getContextPath() + "/forwards/forwardToCompileError.jsp") + .withResponseStatus(500) + .withExceptionClass(JasperException.class) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToCompileError.jsp") + .withClassName("forwards.forwardToCompileError_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToCompileError.jsp") + .withExceptionClass(JasperException.class) + .build()), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(2)) + .withRoute("/compileError.jsp") + .withClassName("compileError_jsp") + .withExceptionClass(JasperException.class) + .build()))); + } + + @Test + void testForwardToNonExistentJspShouldBe404() { + String route = "/" + getContextPath() + "/forwards/forwardToNonExistent.jsp"; + + AggregatedHttpResponse res = + client.get("/forwards/forwardToNonExistent.jsp").aggregate().join(); + assertThat(res.status().code()).isEqualTo(404); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("GET " + route) + .hasNoParent() + .hasKind(SpanKind.SERVER) + .hasStatus(StatusData.unset()) + .hasAttributesSatisfyingExactly( + equalTo(UrlAttributes.URL_SCHEME, "http"), + equalTo(UrlAttributes.URL_PATH, route), + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 404), + satisfies( + UserAgentAttributes.USER_AGENT_ORIGINAL, + val -> val.isInstanceOf(String.class)), + equalTo(HttpAttributes.HTTP_ROUTE, route), + equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"), + satisfies( + NetworkAttributes.NETWORK_PEER_PORT, + val -> val.isInstanceOf(Long.class))), + span -> + spanAsserts.assertCompileSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToNonExistent.jsp") + .withClassName("forwards.forwardToNonExistent_jsp") + .build()), + span -> + spanAsserts.assertRenderSpan( + span, + new JspSpanAssertionBuilder() + .withParent(trace.getSpan(0)) + .withRoute("/forwards/forwardToNonExistent.jsp") + .build()), + span -> span.hasName("ResponseFacade.sendError").hasParent(trace.getSpan(2)))); + } +} diff --git a/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspSpan.java b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspSpan.java new file mode 100644 index 000000000000..094b047087d0 --- /dev/null +++ b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspSpan.java @@ -0,0 +1,92 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsp; + +import io.opentelemetry.sdk.trace.data.SpanData; + +class JspSpan { + private SpanData parent; + private String method; + private String className; + private String requestUrlOverride; + private String forwardOrigin; + private String route; + private int responseStatus; + private Class exceptionClass; + private boolean errorMessageOptional; + + public SpanData getParent() { + return parent; + } + + public void setParent(SpanData parent) { + this.parent = parent; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public String getRequestUrlOverride() { + return requestUrlOverride; + } + + public void setRequestUrlOverride(String requestUrlOverride) { + this.requestUrlOverride = requestUrlOverride; + } + + public String getForwardOrigin() { + return forwardOrigin; + } + + public void setForwardOrigin(String forwardOrigin) { + this.forwardOrigin = forwardOrigin; + } + + public String getRoute() { + return route; + } + + public void setRoute(String route) { + this.route = route; + } + + public int getResponseStatus() { + return responseStatus; + } + + public void setResponseStatus(int responseStatus) { + this.responseStatus = responseStatus; + } + + public Class getExceptionClass() { + return exceptionClass; + } + + public void setExceptionClass(Class exceptionClass) { + this.exceptionClass = exceptionClass; + } + + public boolean getErrorMessageOptional() { + return errorMessageOptional; + } + + public void setErrorMessageOptional(boolean errorMessageOptional) { + this.errorMessageOptional = errorMessageOptional; + } +} diff --git a/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspSpanAssertionBuilder.java b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspSpanAssertionBuilder.java new file mode 100644 index 000000000000..b24f592495c4 --- /dev/null +++ b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspSpanAssertionBuilder.java @@ -0,0 +1,79 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsp; + +import io.opentelemetry.sdk.trace.data.SpanData; + +class JspSpanAssertionBuilder { + private SpanData parent; + private String method; + private String route; + private String className; + private String requestUrlOverride; + private String forwardOrigin; + private int responseStatus; + private Class exceptionClass; + private boolean errorMessageOptional; + + public JspSpanAssertionBuilder withParent(SpanData parent) { + this.parent = parent; + return this; + } + + public JspSpanAssertionBuilder withMethod(String method) { + this.method = method; + return this; + } + + public JspSpanAssertionBuilder withRoute(String route) { + this.route = route; + return this; + } + + public JspSpanAssertionBuilder withClassName(String className) { + this.className = className; + return this; + } + + public JspSpanAssertionBuilder withRequestUrlOverride(String requestUrlOverride) { + this.requestUrlOverride = requestUrlOverride; + return this; + } + + public JspSpanAssertionBuilder withForwardOrigin(String forwardOrigin) { + this.forwardOrigin = forwardOrigin; + return this; + } + + public JspSpanAssertionBuilder withResponseStatus(int responseStatus) { + this.responseStatus = responseStatus; + return this; + } + + public JspSpanAssertionBuilder withExceptionClass(Class exceptionClass) { + this.exceptionClass = exceptionClass; + return this; + } + + public JspSpanAssertionBuilder withErrorMessageOptional(boolean errorMessageOptional) { + this.errorMessageOptional = errorMessageOptional; + return this; + } + + public JspSpan build() { + JspSpan serverSpan = new JspSpan(); + serverSpan.setParent(this.parent); + serverSpan.setMethod(this.method); + serverSpan.setRoute(this.route); + serverSpan.setClassName(this.className); + serverSpan.setRequestUrlOverride(this.requestUrlOverride); + serverSpan.setForwardOrigin(this.forwardOrigin); + serverSpan.setResponseStatus(this.responseStatus); + serverSpan.setExceptionClass(this.exceptionClass); + serverSpan.setErrorMessageOptional(this.errorMessageOptional); + return serverSpan; + } +} diff --git a/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspSpanAssertions.java b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspSpanAssertions.java new file mode 100644 index 000000000000..7b9baa32c697 --- /dev/null +++ b/instrumentation/jsp-2.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jsp/JspSpanAssertions.java @@ -0,0 +1,155 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jsp; + +import static io.opentelemetry.api.common.AttributeKey.stringKey; +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.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.semconv.ClientAttributes; +import io.opentelemetry.semconv.ErrorAttributes; +import io.opentelemetry.semconv.ExceptionAttributes; +import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.NetworkAttributes; +import io.opentelemetry.semconv.ServerAttributes; +import io.opentelemetry.semconv.UrlAttributes; +import io.opentelemetry.semconv.UserAgentAttributes; + +class JspSpanAssertions { + private final String baseUrl; + private final int port; + + JspSpanAssertions(String baseUrl, int port) { + this.baseUrl = baseUrl; + this.port = port; + } + + SpanDataAssert assertServerSpan(SpanDataAssert span, JspSpan spanData) { + if (spanData.getExceptionClass() != null) { + span.hasStatus(StatusData.error()) + .hasEventsSatisfyingExactly( + event -> + event + .hasName("exception") + .hasAttributesSatisfyingExactly( + satisfies( + ExceptionAttributes.EXCEPTION_TYPE, + val -> + val.satisfiesAnyOf( + v -> val.isEqualTo(spanData.getExceptionClass().getName()), + v -> + val.contains( + spanData.getExceptionClass().getSimpleName()))), + satisfies( + ExceptionAttributes.EXCEPTION_MESSAGE, + val -> + val.satisfiesAnyOf( + v -> assertThat(spanData.getErrorMessageOptional()).isTrue(), + v -> val.isInstanceOf(String.class))), + satisfies( + ExceptionAttributes.EXCEPTION_STACKTRACE, + val -> val.isInstanceOf(String.class)))); + } + + return span.hasName(spanData.getMethod() + " " + spanData.getRoute()) + .hasNoParent() + .hasKind(SpanKind.SERVER) + .hasAttributesSatisfyingExactly( + equalTo(UrlAttributes.URL_SCHEME, "http"), + equalTo(UrlAttributes.URL_PATH, spanData.getRoute()), + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, spanData.getMethod()), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, spanData.getResponseStatus()), + satisfies( + UserAgentAttributes.USER_AGENT_ORIGINAL, val -> val.isInstanceOf(String.class)), + equalTo(HttpAttributes.HTTP_ROUTE, spanData.getRoute()), + equalTo(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, "127.0.0.1"), + satisfies(NetworkAttributes.NETWORK_PEER_PORT, val -> val.isInstanceOf(Long.class)), + satisfies( + ErrorAttributes.ERROR_TYPE, + val -> + val.satisfiesAnyOf( + v -> assertThat(spanData.getExceptionClass()).isNull(), + v -> assertThat(v).isEqualTo("500")))); + } + + SpanDataAssert assertCompileSpan(SpanDataAssert span, JspSpan spanData) { + if (spanData.getExceptionClass() != null) { + span.hasStatus(StatusData.error()) + .hasEventsSatisfyingExactly( + event -> + event + .hasName("exception") + .hasAttributesSatisfyingExactly( + equalTo( + ExceptionAttributes.EXCEPTION_TYPE, + spanData.getExceptionClass().getCanonicalName()), + satisfies( + ExceptionAttributes.EXCEPTION_STACKTRACE, + val -> val.isInstanceOf(String.class)), + satisfies( + ExceptionAttributes.EXCEPTION_MESSAGE, + val -> val.isInstanceOf(String.class)))); + } + + return span.hasName("Compile " + spanData.getRoute()) + .hasParent(spanData.getParent()) + .hasAttributesSatisfyingExactly( + equalTo(stringKey("jsp.classFQCN"), "org.apache.jsp." + spanData.getClassName()), + equalTo(stringKey("jsp.compiler"), "org.apache.jasper.compiler.JDTCompiler")); + } + + SpanDataAssert assertRenderSpan(SpanDataAssert span, JspSpan spanData) { + String requestUrl = spanData.getRoute(); + if (spanData.getRequestUrlOverride() != null) { + requestUrl = spanData.getRequestUrlOverride(); + } + + if (spanData.getExceptionClass() != null) { + span.hasStatus(StatusData.error()) + .hasEventsSatisfyingExactly( + event -> + event + .hasName("exception") + .hasAttributesSatisfyingExactly( + satisfies( + ExceptionAttributes.EXCEPTION_TYPE, + val -> + val.satisfiesAnyOf( + v -> val.isEqualTo(spanData.getExceptionClass().getName()), + v -> + val.contains( + spanData.getExceptionClass().getSimpleName()))), + satisfies( + ExceptionAttributes.EXCEPTION_MESSAGE, + val -> + val.satisfiesAnyOf( + v -> assertThat(spanData.getErrorMessageOptional()).isTrue(), + v -> val.isInstanceOf(String.class))), + satisfies( + ExceptionAttributes.EXCEPTION_STACKTRACE, + val -> val.isInstanceOf(String.class)))); + } + + return span.hasName("Render " + spanData.getRoute()) + .hasParent(spanData.getParent()) + .hasAttributesSatisfyingExactly( + equalTo(stringKey("jsp.requestURL"), baseUrl + requestUrl), + satisfies( + stringKey("jsp.forwardOrigin"), + val -> + val.satisfiesAnyOf( + v -> assertThat(spanData.getForwardOrigin()).isNull(), + v -> assertThat(v).isEqualTo(spanData.getForwardOrigin())))); + } +} diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/KafkaSingletons.java b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/KafkaSingletons.java index 736b28ab1eae..bde04943f621 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/KafkaSingletons.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/KafkaSingletons.java @@ -11,15 +11,15 @@ import io.opentelemetry.instrumentation.kafka.internal.KafkaProcessRequest; import io.opentelemetry.instrumentation.kafka.internal.KafkaProducerRequest; import io.opentelemetry.instrumentation.kafka.internal.KafkaReceiveRequest; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import org.apache.kafka.clients.producer.RecordMetadata; public final class KafkaSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11"; private static final boolean PRODUCER_PROPAGATION_ENABLED = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.kafka.producer-propagation.enabled", true); private static final Instrumenter PRODUCER_INSTRUMENTER; @@ -31,7 +31,7 @@ public final class KafkaSingletons { new KafkaInstrumenterFactory(GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.kafka.experimental-span-attributes", false)) .setMessagingReceiveInstrumentationEnabled( ExperimentalConfig.get().messagingReceiveInstrumentationEnabled()); diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/metrics/KafkaMetricsUtil.java b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/metrics/KafkaMetricsUtil.java index fcaa541aa085..e484e0fbd06e 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/metrics/KafkaMetricsUtil.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkaclients/v0_11/metrics/KafkaMetricsUtil.java @@ -9,8 +9,8 @@ import io.opentelemetry.instrumentation.kafka.internal.MetricsReporterList; import io.opentelemetry.instrumentation.kafka.internal.OpenTelemetryMetricsReporter; import io.opentelemetry.instrumentation.kafka.internal.OpenTelemetrySupplier; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.DeprecatedConfigProperties; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import java.util.List; import java.util.Map; import org.apache.kafka.clients.CommonClientConfigs; @@ -19,7 +19,7 @@ public final class KafkaMetricsUtil { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11"; private static final boolean METRICS_ENABLED = DeprecatedConfigProperties.getBoolean( - InstrumentationConfig.get(), + AgentInstrumentationConfig.get(), "otel.instrumentation.kafka.metric-reporter.enabled", "otel.instrumentation.kafka-clients-metrics.enabled", true); 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 f98d84e0fb29..f53fe5048387 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 @@ -78,7 +78,7 @@ void beforeAll() { } kafka = - new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.10")) + new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.7.0")) .withEnv("KAFKA_HEAP_OPTS", "-Xmx256m") .withLogConsumer(new Slf4jLogConsumer(logger)) .waitingFor(Wait.forLogMessage(".*started \\(kafka.server.KafkaServer\\).*", 1)) diff --git a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/io/opentelemetry/instrumentation/kafka/internal/KafkaClientBaseTest.java b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/io/opentelemetry/instrumentation/kafka/internal/KafkaClientBaseTest.java index 582d68c70a4e..078b3fc310f0 100644 --- a/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/io/opentelemetry/instrumentation/kafka/internal/KafkaClientBaseTest.java +++ b/instrumentation/kafka/kafka-clients/kafka-clients-0.11/testing/src/main/java/io/opentelemetry/instrumentation/kafka/internal/KafkaClientBaseTest.java @@ -66,7 +66,7 @@ public abstract class KafkaClientBaseTest { @BeforeAll void setupClass() throws ExecutionException, InterruptedException, TimeoutException { kafka = - new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.10")) + new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.7.0")) .withEnv("KAFKA_HEAP_OPTS", "-Xmx256m") .withLogConsumer(new Slf4jLogConsumer(logger)) .waitingFor(Wait.forLogMessage(".*started \\(kafka.server.KafkaServer\\).*", 1)) diff --git a/instrumentation/kafka/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java b/instrumentation/kafka/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java index 8abc39e5ea68..5733eaa2d18a 100644 --- a/instrumentation/kafka/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java +++ b/instrumentation/kafka/kafka-streams-0.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kafkastreams/KafkaStreamsSingletons.java @@ -9,8 +9,8 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.kafka.internal.KafkaInstrumenterFactory; import io.opentelemetry.instrumentation.kafka.internal.KafkaProcessRequest; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; public final class KafkaStreamsSingletons { @@ -20,7 +20,7 @@ public final class KafkaStreamsSingletons { new KafkaInstrumenterFactory(GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.kafka.experimental-span-attributes", false)) .setMessagingReceiveInstrumentationEnabled( ExperimentalConfig.get().messagingReceiveInstrumentationEnabled()) diff --git a/instrumentation/kafka/kafka-streams-0.11/javaagent/src/test/groovy/KafkaStreamsBaseTest.groovy b/instrumentation/kafka/kafka-streams-0.11/javaagent/src/test/groovy/KafkaStreamsBaseTest.groovy index d625531d1d53..ef3cff670b01 100644 --- a/instrumentation/kafka/kafka-streams-0.11/javaagent/src/test/groovy/KafkaStreamsBaseTest.groovy +++ b/instrumentation/kafka/kafka-streams-0.11/javaagent/src/test/groovy/KafkaStreamsBaseTest.groovy @@ -44,7 +44,7 @@ class KafkaStreamsBaseTest extends AgentInstrumentationSpecification { static CountDownLatch consumerReady = new CountDownLatch(1) def setupSpec() { - kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.10")) + kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.7.0")) .withEnv("KAFKA_HEAP_OPTS", "-Xmx256m") .withLogConsumer(new Slf4jLogConsumer(logger)) .waitingFor(Wait.forLogMessage(".*started \\(kafka.server.KafkaServer\\).*", 1)) diff --git a/instrumentation/kotlinx-coroutines/kotlinx-coroutines-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/instrumentationannotations/WithSpanInstrumentation.java b/instrumentation/kotlinx-coroutines/kotlinx-coroutines-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/instrumentationannotations/WithSpanInstrumentation.java index 1995d5f14de9..e98a11fef3fe 100644 --- a/instrumentation/kotlinx-coroutines/kotlinx-coroutines-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/instrumentationannotations/WithSpanInstrumentation.java +++ b/instrumentation/kotlinx-coroutines/kotlinx-coroutines-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/kotlinxcoroutines/instrumentationannotations/WithSpanInstrumentation.java @@ -16,7 +16,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.extension.instrumentation.internal.AsmApi; @@ -54,10 +54,10 @@ class WithSpanInstrumentation implements TypeInstrumentation { // whether to check the transformed bytecode with asm CheckClassAdapter private static final boolean CHECK_CLASS = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean( "otel.instrumentation.kotlinx-coroutines.check-class", - InstrumentationConfig.get().getBoolean("otel.javaagent.debug", false)); + AgentInstrumentationConfig.get().getBoolean("otel.javaagent.debug", false)); private final ElementMatcher.Junction annotatedMethodMatcher; // this matcher matches all methods that should be excluded from transformation diff --git a/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/HttpClientInstrumentation.java b/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/HttpClientInstrumentation.java index 0a53968f9dc8..43f89f9968a5 100644 --- a/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/HttpClientInstrumentation.java +++ b/instrumentation/ktor/ktor-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/ktor/v2_0/HttpClientInstrumentation.java @@ -16,7 +16,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.ktor.v2_0.client.KtorClientTracing; import io.opentelemetry.instrumentation.ktor.v2_0.client.KtorClientTracingBuilder; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import kotlin.Unit; @@ -56,9 +56,9 @@ public static class SetupFunction implements Function1> INSTRUMENTER; private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.kubernetes-client.experimental-span-attributes", false); private static final ContextPropagators CONTEXT_PROPAGATORS; @@ -38,9 +38,9 @@ public class KubernetesClientSingletons { .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) .addAttributesExtractor( HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getClientRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getClientResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()); if (CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) { diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/InstrumentationPoints.java b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/InstrumentationPoints.java index a6f0902635fe..514379987135 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/InstrumentationPoints.java +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/InstrumentationPoints.java @@ -16,7 +16,7 @@ import com.lambdaworks.redis.protocol.RedisCommand; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.EnumSet; import java.util.Set; import java.util.concurrent.CancellationException; @@ -24,7 +24,7 @@ public final class InstrumentationPoints { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.lettuce.experimental-span-attributes", false); private static final Set NON_INSTRUMENTING_COMMANDS = EnumSet.of(SHUTDOWN, DEBUG); diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java index cdf509ab7988..4c970bdf4973 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java @@ -16,8 +16,8 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class LettuceSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.lettuce-4.0"; @@ -48,10 +48,10 @@ public final class LettuceSingletons { .addAttributesExtractor(ServerAttributesExtractor.create(netAttributesGetter)) .addAttributesExtractor( PeerServiceAttributesExtractor.create( - netAttributesGetter, CommonConfig.get().getPeerServiceResolver())) + netAttributesGetter, AgentCommonConfig.get().getPeerServiceResolver())) .addAttributesExtractor(new LettuceConnectAttributesExtractor()) .setEnabled( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.lettuce.connection-telemetry.enabled", false)) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/EndCommandAsyncBiFunction.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/EndCommandAsyncBiFunction.java index 19f86beb0f6d..2baad6fd0692 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/EndCommandAsyncBiFunction.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/EndCommandAsyncBiFunction.java @@ -10,7 +10,7 @@ import io.lettuce.core.protocol.RedisCommand; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.concurrent.CancellationException; import java.util.function.BiFunction; @@ -27,7 +27,7 @@ public class EndCommandAsyncBiFunction implements BiFunction { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.lettuce.experimental-span-attributes", false); private final Context context; diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/EndConnectAsyncBiFunction.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/EndConnectAsyncBiFunction.java index 93ee72ce0b76..d179605e5ccc 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/EndConnectAsyncBiFunction.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/EndConnectAsyncBiFunction.java @@ -10,7 +10,7 @@ import io.lettuce.core.RedisURI; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.concurrent.CancellationException; import java.util.function.BiFunction; @@ -27,7 +27,7 @@ public class EndConnectAsyncBiFunction implements BiFunction { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.lettuce.experimental-span-attributes", false); private final Context context; diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDbAttributesGetter.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDbAttributesGetter.java index 6ecbaa3d1ee9..a3c7050e3c79 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDbAttributesGetter.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDbAttributesGetter.java @@ -9,7 +9,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter; import io.opentelemetry.instrumentation.api.incubator.semconv.db.RedisCommandSanitizer; import io.opentelemetry.instrumentation.lettuce.common.LettuceArgSplitter; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import java.util.Collections; import java.util.List; @@ -18,7 +18,7 @@ final class LettuceDbAttributesGetter implements DbClientAttributesGetter> { private static final RedisCommandSanitizer sanitizer = - RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + RedisCommandSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); @Override public String getSystem(RedisCommand request) { diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java index 0cc13a7ce472..f4de0e03fbfb 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java @@ -16,8 +16,8 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class LettuceSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.lettuce-5.0"; @@ -49,10 +49,11 @@ public final class LettuceSingletons { ServerAttributesExtractor.create(connectNetworkAttributesGetter)) .addAttributesExtractor( PeerServiceAttributesExtractor.create( - connectNetworkAttributesGetter, CommonConfig.get().getPeerServiceResolver())) + connectNetworkAttributesGetter, + AgentCommonConfig.get().getPeerServiceResolver())) .addAttributesExtractor(new LettuceConnectAttributesExtractor()) .setEnabled( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.lettuce.connection-telemetry.enabled", false)) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxTerminationRunnable.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxTerminationRunnable.java index 03ca65e4f8d3..af20fc892495 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxTerminationRunnable.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/rx/LettuceFluxTerminationRunnable.java @@ -10,7 +10,7 @@ import io.lettuce.core.protocol.RedisCommand; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.function.Consumer; import java.util.logging.Logger; import org.reactivestreams.Subscription; @@ -21,7 +21,7 @@ public class LettuceFluxTerminationRunnable implements Consumer>, Runnable { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.lettuce.experimental-span-attributes", false); private Context context; diff --git a/instrumentation/lettuce/lettuce-5.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/TracingHolder.java b/instrumentation/lettuce/lettuce-5.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/TracingHolder.java index 55f035404385..7b354788b5f9 100644 --- a/instrumentation/lettuce/lettuce-5.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/TracingHolder.java +++ b/instrumentation/lettuce/lettuce-5.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/TracingHolder.java @@ -8,13 +8,13 @@ import io.lettuce.core.tracing.Tracing; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.lettuce.v5_1.LettuceTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; public final class TracingHolder { public static final Tracing TRACING = LettuceTelemetry.builder(GlobalOpenTelemetry.get()) - .setStatementSanitizationEnabled(CommonConfig.get().isStatementSanitizationEnabled()) + .setStatementSanitizationEnabled(AgentCommonConfig.get().isStatementSanitizationEnabled()) .build() .newTracing(); diff --git a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.java b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.java index 595699bdee36..692c49243901 100644 --- a/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.java +++ b/instrumentation/lettuce/lettuce-5.1/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_1/LettuceAsyncClientTest.java @@ -24,4 +24,9 @@ public InstrumentationExtension getInstrumentationExtension() { protected RedisClient createClient(String uri) { return RedisClient.create(uri); } + + @Override + protected boolean connectHasSpans() { + return Boolean.getBoolean("testLatestDeps"); + } } diff --git a/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceAsyncClientTest.java b/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceAsyncClientTest.java index 7aecb49b892b..4cb3f7ff171b 100644 --- a/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceAsyncClientTest.java +++ b/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceAsyncClientTest.java @@ -90,6 +90,10 @@ boolean testCallback() { return true; } + protected boolean connectHasSpans() { + return false; + } + @Test void testConnectUsingGetOnConnectionFuture() throws Exception { RedisClient testConnectionClient = RedisClient.create(embeddedDbUri); @@ -103,8 +107,13 @@ void testConnectUsingGetOnConnectionFuture() throws Exception { cleanup.deferCleanup(testConnectionClient::shutdown); assertThat(connection1).isNotNull(); - // Lettuce tracing does not trace connect - assertThat(getInstrumentationExtension().spans()).isEmpty(); + if (connectHasSpans()) { + // ignore CLIENT SETINFO traces + getInstrumentationExtension().waitForTraces(2); + } else { + // Lettuce tracing does not trace connect + assertThat(getInstrumentationExtension().spans()).isEmpty(); + } } @Test diff --git a/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceClientTest.java b/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceClientTest.java index 2cd18303d9e2..38b5df08085c 100644 --- a/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceClientTest.java +++ b/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceClientTest.java @@ -8,7 +8,6 @@ import io.lettuce.core.RedisClient; import io.lettuce.core.api.StatefulRedisConnection; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; -import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.extension.RegisterExtension; @@ -22,13 +21,6 @@ abstract class AbstractLettuceClientTest { protected static final Logger logger = LoggerFactory.getLogger(AbstractLettuceClientTest.class); - @RegisterExtension - protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); - - public InstrumentationExtension getInstrumentationExtension() { - return testing; - } - @RegisterExtension static final AutoCleanupExtension cleanup = AutoCleanupExtension.create(); protected static final int DB_INDEX = 0; @@ -40,19 +32,16 @@ public InstrumentationExtension getInstrumentationExtension() { .waitingFor(Wait.forLogMessage(".*Ready to accept connections.*", 1)); protected static RedisClient redisClient; - protected static StatefulRedisConnection connection; - - protected abstract RedisClient createClient(String uri); - protected static String host; - protected static String ip; - protected static int port; - protected static String embeddedDbUri; + protected abstract RedisClient createClient(String uri); + + protected abstract InstrumentationExtension getInstrumentationExtension(); + protected ContainerConnection newContainerConnection() { GenericContainer server = new GenericContainer<>("redis:6.2.3-alpine") diff --git a/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceSyncClientAuthTest.java b/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceSyncClientAuthTest.java index a067003b9ae0..c74c918d355f 100644 --- a/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceSyncClientAuthTest.java +++ b/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceSyncClientAuthTest.java @@ -10,6 +10,7 @@ import io.lettuce.core.api.sync.RedisCommands; import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import io.opentelemetry.semconv.NetworkAttributes; import io.opentelemetry.semconv.ServerAttributes; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; @@ -59,23 +60,76 @@ void testAuthCommand() throws Exception { assertThat(result).isEqualTo("OK"); - getInstrumentationExtension() - .waitAndAssertTraces( - trace -> - trace.hasSpansSatisfyingExactly( - span -> - span.hasName("AUTH") - .hasKind(SpanKind.CLIENT) - .hasAttributesSatisfyingExactly( - equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), - equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), - equalTo(NetworkAttributes.NETWORK_PEER_PORT, port), - equalTo(ServerAttributes.SERVER_ADDRESS, host), - equalTo(ServerAttributes.SERVER_PORT, port), - equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), - equalTo(DbIncubatingAttributes.DB_STATEMENT, "AUTH ?")) - .hasEventsSatisfyingExactly( - event -> event.hasName("redis.encode.start"), - event -> event.hasName("redis.encode.end")))); + if (Boolean.getBoolean("testLatestDeps")) { + getInstrumentationExtension() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("CLIENT") + .hasKind(SpanKind.CLIENT) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), + equalTo(NetworkAttributes.NETWORK_PEER_PORT, port), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), + equalTo( + DbIncubatingAttributes.DB_STATEMENT, + "CLIENT SETINFO lib-name Lettuce"))), + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("CLIENT") + .hasKind(SpanKind.CLIENT) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), + equalTo(NetworkAttributes.NETWORK_PEER_PORT, port), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), + OpenTelemetryAssertions.satisfies( + DbIncubatingAttributes.DB_STATEMENT, + stringAssert -> + stringAssert.startsWith("CLIENT SETINFO lib-ver")))), + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("AUTH") + .hasKind(SpanKind.CLIENT) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), + equalTo(NetworkAttributes.NETWORK_PEER_PORT, port), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), + equalTo(DbIncubatingAttributes.DB_STATEMENT, "AUTH ?")) + .hasEventsSatisfyingExactly( + event -> event.hasName("redis.encode.start"), + event -> event.hasName("redis.encode.end")))); + + } else { + getInstrumentationExtension() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("AUTH") + .hasKind(SpanKind.CLIENT) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), + equalTo(NetworkAttributes.NETWORK_PEER_PORT, port), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, port), + equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), + equalTo(DbIncubatingAttributes.DB_STATEMENT, "AUTH ?")) + .hasEventsSatisfyingExactly( + event -> event.hasName("redis.encode.start"), + event -> event.hasName("redis.encode.end")))); + } } } diff --git a/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceSyncClientTest.java b/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceSyncClientTest.java index b9e53ffb83a1..2492fb4c27ec 100644 --- a/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceSyncClientTest.java +++ b/instrumentation/lettuce/lettuce-5.1/testing/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/AbstractLettuceSyncClientTest.java @@ -20,6 +20,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.test.utils.PortUtils; +import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import io.opentelemetry.semconv.NetworkAttributes; import io.opentelemetry.semconv.ServerAttributes; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; @@ -81,8 +82,13 @@ void testConnect() { StatefulRedisConnection testConnection = redisClient.connect(); cleanup.deferCleanup(testConnection); - // Lettuce tracing does not trace connect - assertThat(getInstrumentationExtension().spans()).isEmpty(); + if (Boolean.getBoolean("testLatestDeps")) { + // ignore CLIENT SETINFO traces + getInstrumentationExtension().waitForTraces(2); + } else { + // Lettuce tracing does not trace connect + assertThat(getInstrumentationExtension().spans()).isEmpty(); + } } @Test @@ -206,6 +212,12 @@ void testListCommand() { ContainerConnection containerConnection = newContainerConnection(); RedisCommands commands = containerConnection.connection.sync(); + if (Boolean.getBoolean("testLatestDeps")) { + // ignore CLIENT SETINFO traces + getInstrumentationExtension().waitForTraces(2); + getInstrumentationExtension().clearData(); + } + long res = commands.lpush("TESTLIST", "TESTLIST ELEMENT"); assertThat(res).isEqualTo(1); @@ -350,43 +362,82 @@ void testDebugSegfaultCommandWithNoArgumentProducesNoSpan() { commands.debugSegfault(); - getInstrumentationExtension() - .waitAndAssertTraces( - trace -> { - if (Boolean.getBoolean("testLatestDeps")) { - trace.hasSpansSatisfyingExactly( - span -> - span.hasName("DEBUG") - .hasKind(SpanKind.CLIENT) - .hasAttributesSatisfyingExactly( - equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), - equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), - equalTo( - NetworkAttributes.NETWORK_PEER_PORT, containerConnection.port), - equalTo(ServerAttributes.SERVER_ADDRESS, host), - equalTo(ServerAttributes.SERVER_PORT, containerConnection.port), - equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), - equalTo(DbIncubatingAttributes.DB_STATEMENT, "DEBUG SEGFAULT"))); - } else { - trace.hasSpansSatisfyingExactly( - span -> - span.hasName("DEBUG") - .hasKind(SpanKind.CLIENT) - .hasAttributesSatisfyingExactly( - equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), - equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), - equalTo( - NetworkAttributes.NETWORK_PEER_PORT, containerConnection.port), - equalTo(ServerAttributes.SERVER_ADDRESS, host), - equalTo(ServerAttributes.SERVER_PORT, containerConnection.port), - equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), - equalTo(DbIncubatingAttributes.DB_STATEMENT, "DEBUG SEGFAULT")) - // these are no longer recorded since Lettuce 6.1.6 - .hasEventsSatisfyingExactly( - event -> event.hasName("redis.encode.start"), - event -> event.hasName("redis.encode.end"))); - } - }); + if (Boolean.getBoolean("testLatestDeps")) { + getInstrumentationExtension() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("CLIENT") + .hasKind(SpanKind.CLIENT) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), + equalTo( + NetworkAttributes.NETWORK_PEER_PORT, + containerConnection.port), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, containerConnection.port), + equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), + equalTo( + DbIncubatingAttributes.DB_STATEMENT, + "CLIENT SETINFO lib-name Lettuce"))), + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("CLIENT") + .hasKind(SpanKind.CLIENT) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), + equalTo( + NetworkAttributes.NETWORK_PEER_PORT, + containerConnection.port), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, containerConnection.port), + equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), + OpenTelemetryAssertions.satisfies( + DbIncubatingAttributes.DB_STATEMENT, + stringAssert -> + stringAssert.startsWith("CLIENT SETINFO lib-ver")))), + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("DEBUG") + .hasKind(SpanKind.CLIENT) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), + equalTo( + NetworkAttributes.NETWORK_PEER_PORT, + containerConnection.port), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, containerConnection.port), + equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), + equalTo(DbIncubatingAttributes.DB_STATEMENT, "DEBUG SEGFAULT")))); + } else { + getInstrumentationExtension() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasName("DEBUG") + .hasKind(SpanKind.CLIENT) + .hasAttributesSatisfyingExactly( + equalTo(NetworkAttributes.NETWORK_TYPE, "ipv4"), + equalTo(NetworkAttributes.NETWORK_PEER_ADDRESS, ip), + equalTo( + NetworkAttributes.NETWORK_PEER_PORT, + containerConnection.port), + equalTo(ServerAttributes.SERVER_ADDRESS, host), + equalTo(ServerAttributes.SERVER_PORT, containerConnection.port), + equalTo(DbIncubatingAttributes.DB_SYSTEM, "redis"), + equalTo(DbIncubatingAttributes.DB_STATEMENT, "DEBUG SEGFAULT")) + // these are no longer recorded since Lettuce 6.1.6 + .hasEventsSatisfyingExactly( + event -> event.hasName("redis.encode.start"), + event -> event.hasName("redis.encode.end")))); + } } @Test @@ -395,6 +446,12 @@ void testShutdownCommandProducesNoSpan() { ContainerConnection containerConnection = newContainerConnection(); RedisCommands commands = containerConnection.connection.sync(); + if (Boolean.getBoolean("testLatestDeps")) { + // ignore CLIENT SETINFO traces + getInstrumentationExtension().waitForTraces(2); + getInstrumentationExtension().clearData(); + } + commands.shutdown(false); getInstrumentationExtension() diff --git a/instrumentation/liberty/liberty-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/LibertySingletons.java b/instrumentation/liberty/liberty-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/LibertySingletons.java index 7468415faf50..7cfcb21c5538 100644 --- a/instrumentation/liberty/liberty-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/LibertySingletons.java +++ b/instrumentation/liberty/liberty-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/LibertySingletons.java @@ -24,6 +24,7 @@ public final class LibertySingletons { .addContextCustomizer( (context, request, attributes) -> new AppServerBridge.Builder().recordException().init(context)) + .propagateOperationListenersToOnEnd() .build(INSTRUMENTATION_NAME, Servlet3Accessor.INSTANCE); private static final LibertyHelper HELPER = diff --git a/instrumentation/liberty/liberty-dispatcher-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/dispatcher/LibertyDispatcherSingletons.java b/instrumentation/liberty/liberty-dispatcher-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/dispatcher/LibertyDispatcherSingletons.java index d0ce75b92238..5dc10034fd21 100644 --- a/instrumentation/liberty/liberty-dispatcher-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/dispatcher/LibertyDispatcherSingletons.java +++ b/instrumentation/liberty/liberty-dispatcher-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/dispatcher/LibertyDispatcherSingletons.java @@ -15,7 +15,7 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; public final class LibertyDispatcherSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.liberty-dispatcher-20.0"; @@ -31,21 +31,21 @@ public final class LibertyDispatcherSingletons { GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) .addAttributesExtractor( HttpServerAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addContextCustomizer( HttpServerRoute.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addOperationMetrics(HttpServerMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { + if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { builder .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) .addOperationMetrics(HttpServerExperimentalMetrics.get()); diff --git a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java index da552d0756a0..522ef4ad9fb2 100644 --- a/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java +++ b/instrumentation/log4j/log4j-appender-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v1_2/LogEventMapper.java @@ -15,7 +15,7 @@ import io.opentelemetry.api.logs.Severity; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.internal.cache.Cache; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.semconv.ExceptionAttributes; import io.opentelemetry.semconv.incubating.ThreadIncubatingAttributes; import java.io.PrintWriter; @@ -39,7 +39,7 @@ public final class LogEventMapper { private static final int TRACE_INT = 5000; private static final boolean captureExperimentalAttributes = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.log4j-appender.experimental-log-attributes", false); private final Map> captureMdcAttributes; @@ -49,7 +49,7 @@ public final class LogEventMapper { private LogEventMapper() { List captureMdcAttributes = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getList( "otel.instrumentation.log4j-appender.experimental.capture-mdc-attributes", emptyList()); diff --git a/instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java b/instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java index 3c228dafa1f5..db4099bcfa84 100644 --- a/instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java +++ b/instrumentation/log4j/log4j-appender-2.17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/appender/v2_17/Log4jHelper.java @@ -9,9 +9,10 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.logs.LogRecordBuilder; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.log4j.appender.v2_17.internal.ContextDataAccessor; import io.opentelemetry.instrumentation.log4j.appender.v2_17.internal.LogEventMapper; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.time.Instant; import java.util.List; import java.util.Map; @@ -30,7 +31,7 @@ public final class Log4jHelper { private static final boolean captureExperimentalAttributes; static { - InstrumentationConfig config = InstrumentationConfig.get(); + InstrumentationConfig config = AgentInstrumentationConfig.get(); captureExperimentalAttributes = config.getBoolean("otel.instrumentation.log4j-appender.experimental-log-attributes", false); diff --git a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/contextdata/v2_7/SpanDecoratingContextDataInjector.java b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/contextdata/v2_7/SpanDecoratingContextDataInjector.java index f4d7dd9c4069..8cd437da9d38 100644 --- a/instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/contextdata/v2_7/SpanDecoratingContextDataInjector.java +++ b/instrumentation/log4j/log4j-context-data/log4j-context-data-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/contextdata/v2_7/SpanDecoratingContextDataInjector.java @@ -10,9 +10,9 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import java.util.List; import java.util.Map; import org.apache.logging.log4j.core.ContextDataInjector; @@ -23,11 +23,11 @@ public final class SpanDecoratingContextDataInjector implements ContextDataInjector { private static final boolean BAGGAGE_ENABLED = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.log4j-context-data.add-baggage", false); - private static final String TRACE_ID_KEY = CommonConfig.get().getTraceIdKey(); - private static final String SPAN_ID_KEY = CommonConfig.get().getSpanIdKey(); - private static final String TRACE_FLAGS_KEY = CommonConfig.get().getTraceFlagsKey(); + private static final String TRACE_ID_KEY = AgentCommonConfig.get().getTraceIdKey(); + private static final String SPAN_ID_KEY = AgentCommonConfig.get().getSpanIdKey(); + private static final String TRACE_FLAGS_KEY = AgentCommonConfig.get().getTraceFlagsKey(); private static final StringMap staticContextData = getStaticContextData(); diff --git a/instrumentation/log4j/log4j-mdc-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/mdc/v1_2/LoggingEventInstrumentation.java b/instrumentation/log4j/log4j-mdc-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/mdc/v1_2/LoggingEventInstrumentation.java index 74df564edfe9..4f2ac37101d5 100644 --- a/instrumentation/log4j/log4j-mdc-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/mdc/v1_2/LoggingEventInstrumentation.java +++ b/instrumentation/log4j/log4j-mdc-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/mdc/v1_2/LoggingEventInstrumentation.java @@ -15,7 +15,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -49,9 +49,9 @@ public static void onExit( @Advice.This LoggingEvent event, @Advice.Argument(0) String key, @Advice.Return(readOnly = false) Object value) { - if (CommonConfig.get().getTraceIdKey().equals(key) - || CommonConfig.get().getSpanIdKey().equals(key) - || CommonConfig.get().getTraceFlagsKey().equals(key)) { + if (AgentCommonConfig.get().getTraceIdKey().equals(key) + || AgentCommonConfig.get().getSpanIdKey().equals(key) + || AgentCommonConfig.get().getTraceFlagsKey().equals(key)) { if (value != null) { // Assume already instrumented event if traceId/spanId/sampled is present. return; @@ -67,13 +67,13 @@ public static void onExit( return; } - if (CommonConfig.get().getTraceIdKey().equals(key)) { + if (AgentCommonConfig.get().getTraceIdKey().equals(key)) { value = spanContext.getTraceId(); } - if (CommonConfig.get().getSpanIdKey().equals(key)) { + if (AgentCommonConfig.get().getSpanIdKey().equals(key)) { value = spanContext.getSpanId(); } - if (CommonConfig.get().getTraceFlagsKey().equals(key)) { + if (AgentCommonConfig.get().getTraceFlagsKey().equals(key)) { value = spanContext.getTraceFlags().asHex(); } } else if (value == null) { diff --git a/instrumentation/logback/logback-appender-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/appender/v1_0/LogbackSingletons.java b/instrumentation/logback/logback-appender-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/appender/v1_0/LogbackSingletons.java index 23d3ff8f44ab..b2b9eb8a5a92 100644 --- a/instrumentation/logback/logback-appender-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/appender/v1_0/LogbackSingletons.java +++ b/instrumentation/logback/logback-appender-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/appender/v1_0/LogbackSingletons.java @@ -7,8 +7,9 @@ import static java.util.Collections.emptyList; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.logback.appender.v1_0.internal.LoggingEventMapper; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.List; public final class LogbackSingletons { @@ -16,7 +17,7 @@ public final class LogbackSingletons { private static final LoggingEventMapper mapper; static { - InstrumentationConfig config = InstrumentationConfig.get(); + InstrumentationConfig config = AgentInstrumentationConfig.get(); boolean captureExperimentalAttributes = config.getBoolean( diff --git a/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LogbackSingletons.java b/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LogbackSingletons.java index f2bc2fbe605c..0292488a8150 100644 --- a/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LogbackSingletons.java +++ b/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LogbackSingletons.java @@ -5,15 +5,16 @@ package io.opentelemetry.javaagent.instrumentation.logback.mdc.v1_0; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class LogbackSingletons { private static final boolean ADD_BAGGAGE = - InstrumentationConfig.get().getBoolean("otel.instrumentation.logback-mdc.add-baggage", false); - private static final String TRACE_ID_KEY = CommonConfig.get().getTraceIdKey(); - private static final String SPAN_ID_KEY = CommonConfig.get().getSpanIdKey(); - private static final String TRACE_FLAGS_KEY = CommonConfig.get().getTraceFlagsKey(); + AgentInstrumentationConfig.get() + .getBoolean("otel.instrumentation.logback-mdc.add-baggage", false); + private static final String TRACE_ID_KEY = AgentCommonConfig.get().getTraceIdKey(); + private static final String SPAN_ID_KEY = AgentCommonConfig.get().getSpanIdKey(); + private static final String TRACE_FLAGS_KEY = AgentCommonConfig.get().getTraceFlagsKey(); public static boolean addBaggage() { return ADD_BAGGAGE; diff --git a/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java b/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java index 4a73ff345282..93768e2f9857 100644 --- a/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java +++ b/instrumentation/logback/logback-mdc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/mdc/v1_0/LoggingEventInstrumentation.java @@ -24,7 +24,7 @@ import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.instrumentation.logback.mdc.v1_0.internal.UnionMap; import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -63,7 +63,7 @@ public static void onExit( @Advice.This ILoggingEvent event, @Advice.Return(typing = Typing.DYNAMIC, readOnly = false) Map contextData) { - if (contextData != null && contextData.containsKey(CommonConfig.get().getTraceIdKey())) { + if (contextData != null && contextData.containsKey(AgentCommonConfig.get().getTraceIdKey())) { // Assume already instrumented event if traceId is present. return; } diff --git a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java index 38f76de04f71..120088cc77c2 100644 --- a/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java +++ b/instrumentation/methods/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/methods/MethodInstrumentationModule.java @@ -9,7 +9,7 @@ import static java.util.Collections.singletonList; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser; @@ -30,7 +30,7 @@ public MethodInstrumentationModule() { Map> classMethodsToTrace = MethodsConfigurationParser.parse( - InstrumentationConfig.get().getString(TRACE_METHODS_CONFIG)); + AgentInstrumentationConfig.get().getString(TRACE_METHODS_CONFIG)); typeInstrumentations = classMethodsToTrace.entrySet().stream() diff --git a/instrumentation/micrometer/micrometer-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/MicrometerSingletons.java b/instrumentation/micrometer/micrometer-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/MicrometerSingletons.java index 8416c35fe9f2..5c08575d0659 100644 --- a/instrumentation/micrometer/micrometer-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/MicrometerSingletons.java +++ b/instrumentation/micrometer/micrometer-1.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/micrometer/v1_5/MicrometerSingletons.java @@ -7,15 +7,16 @@ import io.micrometer.core.instrument.MeterRegistry; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.micrometer.v1_5.OpenTelemetryMeterRegistry; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class MicrometerSingletons { private static final MeterRegistry METER_REGISTRY; static { - InstrumentationConfig config = InstrumentationConfig.get(); + InstrumentationConfig config = AgentInstrumentationConfig.get(); METER_REGISTRY = OpenTelemetryMeterRegistry.builder(GlobalOpenTelemetry.get()) .setPrometheusMode( diff --git a/instrumentation/mongo/mongo-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_1/MongoInstrumentationSingletons.java b/instrumentation/mongo/mongo-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_1/MongoInstrumentationSingletons.java index f9357d0fa3e6..e943f6fbc78c 100644 --- a/instrumentation/mongo/mongo-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_1/MongoInstrumentationSingletons.java +++ b/instrumentation/mongo/mongo-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_1/MongoInstrumentationSingletons.java @@ -8,18 +8,18 @@ import com.mongodb.event.CommandListener; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.mongo.v3_1.MongoTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class MongoInstrumentationSingletons { public static final CommandListener LISTENER = MongoTelemetry.builder(GlobalOpenTelemetry.get()) .setStatementSanitizationEnabled( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean( "otel.instrumentation.mongo.statement-sanitizer.enabled", - CommonConfig.get().isStatementSanitizationEnabled())) + AgentCommonConfig.get().isStatementSanitizationEnabled())) .build() .newCommandListener(); diff --git a/instrumentation/mongo/mongo-3.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_7/MongoInstrumentationSingletons.java b/instrumentation/mongo/mongo-3.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_7/MongoInstrumentationSingletons.java index 044ce2f45a5f..9657ac335cbd 100644 --- a/instrumentation/mongo/mongo-3.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_7/MongoInstrumentationSingletons.java +++ b/instrumentation/mongo/mongo-3.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v3_7/MongoInstrumentationSingletons.java @@ -8,18 +8,18 @@ import com.mongodb.event.CommandListener; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.mongo.v3_1.MongoTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class MongoInstrumentationSingletons { public static final CommandListener LISTENER = MongoTelemetry.builder(GlobalOpenTelemetry.get()) .setStatementSanitizationEnabled( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean( "otel.instrumentation.mongo.statement-sanitizer.enabled", - CommonConfig.get().isStatementSanitizationEnabled())) + AgentCommonConfig.get().isStatementSanitizationEnabled())) .build() .newCommandListener(); diff --git a/instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/MongoInstrumentationSingletons.java b/instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/MongoInstrumentationSingletons.java index 74f3bf6cb0b8..3389cc5bb6a3 100644 --- a/instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/MongoInstrumentationSingletons.java +++ b/instrumentation/mongo/mongo-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongo/v4_0/MongoInstrumentationSingletons.java @@ -8,18 +8,18 @@ import com.mongodb.event.CommandListener; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.mongo.v3_1.MongoTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class MongoInstrumentationSingletons { public static final CommandListener LISTENER = MongoTelemetry.builder(GlobalOpenTelemetry.get()) .setStatementSanitizationEnabled( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean( "otel.instrumentation.mongo.statement-sanitizer.enabled", - CommonConfig.get().isStatementSanitizationEnabled())) + AgentCommonConfig.get().isStatementSanitizationEnabled())) .build() .newCommandListener(); diff --git a/instrumentation/mongo/mongo-async-3.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongoasync/v3_3/MongoInstrumentationSingletons.java b/instrumentation/mongo/mongo-async-3.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongoasync/v3_3/MongoInstrumentationSingletons.java index f502009eb409..2280ce533637 100644 --- a/instrumentation/mongo/mongo-async-3.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongoasync/v3_3/MongoInstrumentationSingletons.java +++ b/instrumentation/mongo/mongo-async-3.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/mongoasync/v3_3/MongoInstrumentationSingletons.java @@ -8,18 +8,18 @@ import com.mongodb.event.CommandListener; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.mongo.v3_1.MongoTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class MongoInstrumentationSingletons { public static final CommandListener LISTENER = MongoTelemetry.builder(GlobalOpenTelemetry.get()) .setStatementSanitizationEnabled( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean( "otel.instrumentation.mongo.statement-sanitizer.enabled", - CommonConfig.get().isStatementSanitizationEnabled())) + AgentCommonConfig.get().isStatementSanitizationEnabled())) .build() .newCommandListener(); diff --git a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyClientSingletons.java b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyClientSingletons.java index 2c4733f4eb57..3db67f23dc80 100644 --- a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyClientSingletons.java +++ b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyClientSingletons.java @@ -6,19 +6,14 @@ package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; import io.opentelemetry.instrumentation.netty.common.internal.NettyConnectionRequest; import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import io.opentelemetry.javaagent.instrumentation.netty.v3_8.HttpRequestAndChannel; import org.jboss.netty.channel.Channel; import org.jboss.netty.handler.codec.http.HttpResponse; @@ -31,34 +26,15 @@ public final class NettyClientSingletons { private static final Instrumenter CONNECTION_INSTRUMENTER; static { - NettyHttpClientAttributesGetter httpAttributesGetter = new NettyHttpClientAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()) - .addContextCustomizer( - (context, requestAndChannel, startAttributes) -> NettyErrorHolder.init(context)); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpRequestHeadersSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, + new NettyHttpClientAttributesGetter(), + HttpRequestHeadersSetter.INSTANCE, + builder -> { + builder.addContextCustomizer( + (context, requestAndChannel, startAttributes) -> NettyErrorHolder.init(context)); + }); CONNECTION_INSTRUMENTER = Instrumenter.builder( @@ -68,7 +44,7 @@ public final class NettyClientSingletons { .addAttributesExtractor( HttpClientPeerServiceAttributesExtractor.create( NettyConnectHttpAttributesGetter.INSTANCE, - CommonConfig.get().getPeerServiceResolver())) + AgentCommonConfig.get().getPeerServiceResolver())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyServerSingletons.java b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyServerSingletons.java index 12453a12f5bc..5a5719efe676 100644 --- a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyServerSingletons.java +++ b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyServerSingletons.java @@ -16,7 +16,7 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.instrumentation.netty.v3_8.HttpRequestAndChannel; import org.jboss.netty.handler.codec.http.HttpResponse; @@ -32,17 +32,17 @@ final class NettyServerSingletons { GlobalOpenTelemetry.get(), "io.opentelemetry.netty-3.8", HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) .addAttributesExtractor( HttpServerAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addOperationMetrics(HttpServerMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { + if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { builder .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) .addOperationMetrics(HttpServerExperimentalMetrics.get()); @@ -53,7 +53,7 @@ final class NettyServerSingletons { (context, requestAndChannel, startAttributes) -> NettyErrorHolder.init(context)) .addContextCustomizer( HttpServerRoute.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .buildServerInstrumenter(NettyHeadersGetter.INSTANCE); } diff --git a/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyClientSingletons.java b/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyClientSingletons.java index fe0ae9006dc3..1c5a49abaef8 100644 --- a/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyClientSingletons.java +++ b/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyClientSingletons.java @@ -14,18 +14,18 @@ import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyClientInstrumenterFactory; import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumenter; import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumenter; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.Collections; import java.util.function.Function; public final class NettyClientSingletons { private static final boolean connectionTelemetryEnabled = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.netty.connection-telemetry.enabled", false); private static final boolean sslTelemetryEnabled = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.netty.ssl-telemetry.enabled", false); private static final Instrumenter INSTRUMENTER; @@ -39,16 +39,17 @@ public final class NettyClientSingletons { "io.opentelemetry.netty-4.0", enabledOrErrorOnly(connectionTelemetryEnabled), enabledOrErrorOnly(sslTelemetryEnabled), - CommonConfig.get().getPeerServiceResolver(), - CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + AgentCommonConfig.get().getPeerServiceResolver(), + AgentCommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); INSTRUMENTER = factory.createHttpInstrumenter( builder -> builder - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), + .setCapturedRequestHeaders(AgentCommonConfig.get().getClientRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getClientResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()), + builder -> + builder.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()), Function.identity(), Collections.emptyList()); CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter(); diff --git a/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyServerSingletons.java b/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyServerSingletons.java index 4059c16bbfb5..e85212f363cc 100644 --- a/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyServerSingletons.java +++ b/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/server/NettyServerSingletons.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel; import io.opentelemetry.instrumentation.netty.v4.common.internal.server.NettyServerInstrumenterFactory; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; public final class NettyServerSingletons { @@ -20,12 +20,12 @@ public final class NettyServerSingletons { "io.opentelemetry.netty-4.0", builder -> builder - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()); + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()), + builder -> builder.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()), + builder -> builder.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()), + AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()); public static Instrumenter instrumenter() { return INSTRUMENTER; diff --git a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyClientSingletons.java b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyClientSingletons.java index e49c8c5375dd..72886c37ce3d 100644 --- a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyClientSingletons.java +++ b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyClientSingletons.java @@ -15,18 +15,18 @@ import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumenter; import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumenter; import io.opentelemetry.instrumentation.netty.v4_1.internal.client.NettyClientHandlerFactory; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.Collections; import java.util.function.Function; public final class NettyClientSingletons { private static final boolean connectionTelemetryEnabled = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.netty.connection-telemetry.enabled", false); private static final boolean sslTelemetryEnabled = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.netty.ssl-telemetry.enabled", false); private static final Instrumenter INSTRUMENTER; @@ -41,23 +41,24 @@ public final class NettyClientSingletons { "io.opentelemetry.netty-4.1", enabledOrErrorOnly(connectionTelemetryEnabled), enabledOrErrorOnly(sslTelemetryEnabled), - CommonConfig.get().getPeerServiceResolver(), - CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + AgentCommonConfig.get().getPeerServiceResolver(), + AgentCommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); INSTRUMENTER = factory.createHttpInstrumenter( builder -> builder - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), + .setCapturedRequestHeaders(AgentCommonConfig.get().getClientRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getClientResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()), + builder -> + builder.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()), Function.identity(), Collections.emptyList()); CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter(); SSL_INSTRUMENTER = factory.createSslInstrumenter(); CLIENT_HANDLER_FACTORY = new NettyClientHandlerFactory( - INSTRUMENTER, CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + INSTRUMENTER, AgentCommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); } public static Instrumenter instrumenter() { diff --git a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyServerSingletons.java b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyServerSingletons.java index e99d1227721f..6203880260a8 100644 --- a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyServerSingletons.java +++ b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/NettyServerSingletons.java @@ -7,7 +7,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.netty.v4_1.NettyServerTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; public final class NettyServerSingletons { @@ -15,12 +15,12 @@ public final class NettyServerSingletons { SERVER_TELEMETRY = NettyServerTelemetry.builder(GlobalOpenTelemetry.get()) .setEmitExperimentalHttpServerEvents( - CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) + AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) .setEmitExperimentalHttpServerMetrics( - CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) + AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) .build(); } diff --git a/instrumentation/okhttp/okhttp-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttp2Singletons.java b/instrumentation/okhttp/okhttp-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttp2Singletons.java index 06495ceb9e63..0cc51730f0b9 100644 --- a/instrumentation/okhttp/okhttp-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttp2Singletons.java +++ b/instrumentation/okhttp/okhttp-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v2_2/OkHttp2Singletons.java @@ -5,23 +5,12 @@ package io.opentelemetry.javaagent.instrumentation.okhttp.v2_2; -import static io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor.alwaysClient; - import com.squareup.okhttp.Interceptor; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; public final class OkHttp2Singletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.okhttp-2.2"; @@ -30,36 +19,12 @@ public final class OkHttp2Singletons { private static final TracingInterceptor TRACING_INTERCEPTOR; static { - OkHttp2HttpAttributesGetter httpAttributesGetter = new OkHttp2HttpAttributesGetter(); - - OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); - - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildInstrumenter(alwaysClient()); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, new OkHttp2HttpAttributesGetter()); - TRACING_INTERCEPTOR = new TracingInterceptor(INSTRUMENTER, openTelemetry.getPropagators()); + TRACING_INTERCEPTOR = + new TracingInterceptor(INSTRUMENTER, GlobalOpenTelemetry.get().getPropagators()); } public static Instrumenter instrumenter() { diff --git a/instrumentation/okhttp/okhttp-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttp3Singletons.java b/instrumentation/okhttp/okhttp-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttp3Singletons.java index 8c4d3a0ee8da..2cc4f6f28975 100644 --- a/instrumentation/okhttp/okhttp-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttp3Singletons.java +++ b/instrumentation/okhttp/okhttp-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/okhttp/v3_0/OkHttp3Singletons.java @@ -5,20 +5,15 @@ package io.opentelemetry.javaagent.instrumentation.okhttp.v3_0; -import static java.util.Collections.singletonList; - import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientRequestResendCount; import io.opentelemetry.instrumentation.okhttp.v3_0.internal.ConnectionErrorSpanInterceptor; -import io.opentelemetry.instrumentation.okhttp.v3_0.internal.OkHttpAttributesGetter; -import io.opentelemetry.instrumentation.okhttp.v3_0.internal.OkHttpInstrumenterFactory; +import io.opentelemetry.instrumentation.okhttp.v3_0.internal.OkHttpClientInstrumenterBuilderFactory; import io.opentelemetry.instrumentation.okhttp.v3_0.internal.TracingInterceptor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import java.util.function.Function; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; @@ -27,19 +22,8 @@ public final class OkHttp3Singletons { private static final Instrumenter INSTRUMENTER = - OkHttpInstrumenterFactory.create( - GlobalOpenTelemetry.get(), - builder -> - builder - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - Function.identity(), - singletonList( - HttpClientPeerServiceAttributesExtractor.create( - OkHttpAttributesGetter.INSTANCE, CommonConfig.get().getPeerServiceResolver())), - CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + JavaagentHttpClientInstrumenters.create( + OkHttpClientInstrumenterBuilderFactory.create(GlobalOpenTelemetry.get())); public static final Interceptor CONTEXT_INTERCEPTOR = chain -> { diff --git a/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/OkHttpTelemetryBuilder.java b/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/OkHttpTelemetryBuilder.java index 131b03648414..552db08382e0 100644 --- a/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/OkHttpTelemetryBuilder.java +++ b/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/OkHttpTelemetryBuilder.java @@ -7,15 +7,13 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.okhttp.v3_0.internal.OkHttpInstrumenterFactory; -import java.util.ArrayList; +import io.opentelemetry.instrumentation.okhttp.v3_0.internal.OkHttpClientInstrumenterBuilderFactory; import java.util.List; import java.util.Set; -import java.util.function.Consumer; import java.util.function.Function; import okhttp3.Request; import okhttp3.Response; @@ -23,19 +21,10 @@ /** A builder of {@link OkHttpTelemetry}. */ public final class OkHttpTelemetryBuilder { - private final OpenTelemetry openTelemetry; - private final List> additionalExtractors = - new ArrayList<>(); - private Consumer> extractorConfigurer = - builder -> {}; - private Consumer> spanNameExtractorConfigurer = - builder -> {}; - private Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer = Function.identity(); - private boolean emitExperimentalHttpClientMetrics = false; + private final DefaultHttpClientInstrumenterBuilder builder; OkHttpTelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + builder = OkHttpClientInstrumenterBuilderFactory.create(openTelemetry); } /** @@ -43,9 +32,9 @@ public final class OkHttpTelemetryBuilder { * items. */ @CanIgnoreReturnValue - public OkHttpTelemetryBuilder addAttributesExtractor( - AttributesExtractor attributesExtractor) { - additionalExtractors.add(attributesExtractor); + public OkHttpTelemetryBuilder addAttributeExtractor( + AttributesExtractor attributesExtractor) { + builder.addAttributeExtractor(attributesExtractor); return this; } @@ -56,8 +45,7 @@ public OkHttpTelemetryBuilder addAttributesExtractor( */ @CanIgnoreReturnValue public OkHttpTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setCapturedRequestHeaders(requestHeaders)); + builder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -68,8 +56,7 @@ public OkHttpTelemetryBuilder setCapturedRequestHeaders(List requestHead */ @CanIgnoreReturnValue public OkHttpTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setCapturedResponseHeaders(responseHeaders)); + builder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -88,10 +75,7 @@ public OkHttpTelemetryBuilder setCapturedResponseHeaders(List responseHe */ @CanIgnoreReturnValue public OkHttpTelemetryBuilder setKnownMethods(Set knownMethods) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); - spanNameExtractorConfigurer = - spanNameExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); + builder.setKnownMethods(knownMethods); return this; } @@ -104,7 +88,7 @@ public OkHttpTelemetryBuilder setKnownMethods(Set knownMethods) { @CanIgnoreReturnValue public OkHttpTelemetryBuilder setEmitExperimentalHttpClientMetrics( boolean emitExperimentalHttpClientMetrics) { - this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; + builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics); return this; } @@ -113,7 +97,7 @@ public OkHttpTelemetryBuilder setEmitExperimentalHttpClientMetrics( public OkHttpTelemetryBuilder setSpanNameExtractor( Function, ? extends SpanNameExtractor> spanNameExtractorTransformer) { - this.spanNameExtractorTransformer = spanNameExtractorTransformer; + builder.setSpanNameExtractor(spanNameExtractorTransformer); return this; } @@ -121,14 +105,6 @@ public OkHttpTelemetryBuilder setSpanNameExtractor( * Returns a new {@link OkHttpTelemetry} with the settings of this {@link OkHttpTelemetryBuilder}. */ public OkHttpTelemetry build() { - return new OkHttpTelemetry( - OkHttpInstrumenterFactory.create( - openTelemetry, - extractorConfigurer, - spanNameExtractorConfigurer, - spanNameExtractorTransformer, - additionalExtractors, - emitExperimentalHttpClientMetrics), - openTelemetry.getPropagators()); + return new OkHttpTelemetry(builder.build(), builder.getOpenTelemetry().getPropagators()); } } diff --git a/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/internal/OkHttpClientInstrumenterBuilderFactory.java b/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/internal/OkHttpClientInstrumenterBuilderFactory.java new file mode 100644 index 000000000000..9ad002acda5e --- /dev/null +++ b/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/internal/OkHttpClientInstrumenterBuilderFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.okhttp.v3_0.internal; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import okhttp3.Request; +import okhttp3.Response; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class OkHttpClientInstrumenterBuilderFactory { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.okhttp-3.0"; + + private OkHttpClientInstrumenterBuilderFactory() {} + + public static DefaultHttpClientInstrumenterBuilder create( + OpenTelemetry openTelemetry) { + return new DefaultHttpClientInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, OkHttpAttributesGetter.INSTANCE); + } +} diff --git a/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/internal/OkHttpInstrumenterFactory.java b/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/internal/OkHttpInstrumenterFactory.java deleted file mode 100644 index bc2b76f8fe67..000000000000 --- a/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/okhttp/v3_0/internal/OkHttpInstrumenterFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.okhttp.v3_0.internal; - -import static io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor.alwaysClient; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import okhttp3.Request; -import okhttp3.Response; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public final class OkHttpInstrumenterFactory { - - private static final String INSTRUMENTATION_NAME = "io.opentelemetry.okhttp-3.0"; - - public static Instrumenter create( - OpenTelemetry openTelemetry, - Consumer> extractorConfigurer, - Consumer> spanNameExtractorConfigurer, - Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer, - List> additionalAttributesExtractors, - boolean emitExperimentalHttpClientMetrics) { - - OkHttpAttributesGetter httpAttributesGetter = OkHttpAttributesGetter.INSTANCE; - - HttpClientAttributesExtractorBuilder extractorBuilder = - HttpClientAttributesExtractor.builder(httpAttributesGetter); - extractorConfigurer.accept(extractorBuilder); - - HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(httpAttributesGetter); - spanNameExtractorConfigurer.accept(httpSpanNameExtractorBuilder); - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(extractorBuilder.build()) - .addAttributesExtractors(additionalAttributesExtractors) - .addOperationMetrics(HttpClientMetrics.get()); - if (emitExperimentalHttpClientMetrics) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - - return builder.buildInstrumenter(alwaysClient()); - } - - private OkHttpInstrumenterFactory() {} -} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationDoubleGaugeBuilder.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationDoubleGaugeBuilder.java index 4878492c0b2d..365a6bcb5a6f 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationDoubleGaugeBuilder.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationDoubleGaugeBuilder.java @@ -16,7 +16,7 @@ public class ApplicationDoubleGaugeBuilder implements DoubleGaugeBuilder { private final io.opentelemetry.api.metrics.DoubleGaugeBuilder agentBuilder; - protected ApplicationDoubleGaugeBuilder( + public ApplicationDoubleGaugeBuilder( io.opentelemetry.api.metrics.DoubleGaugeBuilder agentBuilder) { this.agentBuilder = agentBuilder; } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationDoubleHistogramBuilder.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationDoubleHistogramBuilder.java index 01e534277b2f..f08ef581ebc1 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationDoubleHistogramBuilder.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationDoubleHistogramBuilder.java @@ -14,7 +14,7 @@ public class ApplicationDoubleHistogramBuilder implements DoubleHistogramBuilder private final io.opentelemetry.api.metrics.DoubleHistogramBuilder agentBuilder; - protected ApplicationDoubleHistogramBuilder( + public ApplicationDoubleHistogramBuilder( io.opentelemetry.api.metrics.DoubleHistogramBuilder agentBuilder) { this.agentBuilder = agentBuilder; } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationLongCounterBuilder.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationLongCounterBuilder.java index 71857a387eb0..4251c93c5396 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationLongCounterBuilder.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationLongCounterBuilder.java @@ -17,7 +17,7 @@ public class ApplicationLongCounterBuilder implements LongCounterBuilder { private final io.opentelemetry.api.metrics.LongCounterBuilder agentBuilder; - protected ApplicationLongCounterBuilder( + public ApplicationLongCounterBuilder( io.opentelemetry.api.metrics.LongCounterBuilder agentBuilder) { this.agentBuilder = agentBuilder; } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationLongUpDownCounterBuilder.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationLongUpDownCounterBuilder.java index 03de81fd43f3..5471c4cddf4e 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationLongUpDownCounterBuilder.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.10/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_10/metrics/ApplicationLongUpDownCounterBuilder.java @@ -17,7 +17,7 @@ public class ApplicationLongUpDownCounterBuilder implements LongUpDownCounterBui private final io.opentelemetry.api.metrics.LongUpDownCounterBuilder agentBuilder; - protected ApplicationLongUpDownCounterBuilder( + public ApplicationLongUpDownCounterBuilder( io.opentelemetry.api.metrics.LongUpDownCounterBuilder agentBuilder) { this.agentBuilder = agentBuilder; } 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 9af4f089d39e..18e2d27be404 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 @@ -16,9 +16,33 @@ dependencies { } configurations.configureEach { - if (name == "testRuntimeClasspath" || name == "testCompileClasspath") { + if (name == "testRuntimeClasspath" || name == "testCompileClasspath" || name.startsWith("noopTest")) { resolutionStrategy { force("io.opentelemetry:opentelemetry-api:1.31.0") } } } + +testing { + suites { + val noopTest by registering(JvmTestSuite::class) { + dependencies { + implementation("io.opentelemetry:opentelemetry-extension-incubator:1.31.0-alpha") + } + + targets { + all { + testTask.configure { + jvmArgs("-Dtesting.exporter.enabled=false") + } + } + } + } + } +} + +tasks { + check { + dependsOn(testing.suites) + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/incubator/metrics/ApplicationMeter131.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/incubator/metrics/ApplicationMeter131.java index a82add2467dc..105b38a0aaf3 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/incubator/metrics/ApplicationMeter131.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/incubator/metrics/ApplicationMeter131.java @@ -9,6 +9,10 @@ import application.io.opentelemetry.api.metrics.DoubleHistogramBuilder; import application.io.opentelemetry.api.metrics.LongCounterBuilder; import application.io.opentelemetry.api.metrics.LongUpDownCounterBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationDoubleGaugeBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationDoubleHistogramBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationLongCounterBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationLongUpDownCounterBuilder; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_15.metrics.ApplicationMeter115; public class ApplicationMeter131 extends ApplicationMeter115 { @@ -22,21 +26,39 @@ protected ApplicationMeter131(io.opentelemetry.api.metrics.Meter agentMeter) { @Override public LongCounterBuilder counterBuilder(String name) { - return new ApplicationLongCounterBuilder131(agentMeter.counterBuilder(name)); + io.opentelemetry.api.metrics.LongCounterBuilder builder = agentMeter.counterBuilder(name); + if (builder instanceof io.opentelemetry.api.incubator.metrics.ExtendedLongCounterBuilder) { + return new ApplicationLongCounterBuilder131(builder); + } + return new ApplicationLongCounterBuilder(builder); } @Override public LongUpDownCounterBuilder upDownCounterBuilder(String name) { - return new ApplicationLongUpDownCounterBuilder131(agentMeter.upDownCounterBuilder(name)); + io.opentelemetry.api.metrics.LongUpDownCounterBuilder builder = + agentMeter.upDownCounterBuilder(name); + if (builder + instanceof io.opentelemetry.api.incubator.metrics.ExtendedLongUpDownCounterBuilder) { + return new ApplicationLongUpDownCounterBuilder131(builder); + } + return new ApplicationLongUpDownCounterBuilder(builder); } @Override public DoubleHistogramBuilder histogramBuilder(String name) { - return new ApplicationDoubleHistogramBuilder131(agentMeter.histogramBuilder(name)); + io.opentelemetry.api.metrics.DoubleHistogramBuilder builder = agentMeter.histogramBuilder(name); + if (builder instanceof io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogramBuilder) { + return new ApplicationDoubleHistogramBuilder131(builder); + } + return new ApplicationDoubleHistogramBuilder(builder); } @Override public DoubleGaugeBuilder gaugeBuilder(String name) { - return new ApplicationDoubleGaugeBuilder131(agentMeter.gaugeBuilder(name)); + io.opentelemetry.api.metrics.DoubleGaugeBuilder builder = agentMeter.gaugeBuilder(name); + if (builder instanceof io.opentelemetry.api.incubator.metrics.ExtendedDoubleGaugeBuilder) { + return new ApplicationDoubleGaugeBuilder131(builder); + } + return new ApplicationDoubleGaugeBuilder(builder); } } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/NoopTest.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/NoopTest.java new file mode 100644 index 000000000000..bf93cb95f539 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.31/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_31/metrics/NoopTest.java @@ -0,0 +1,43 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_31.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.metrics.DoubleGaugeBuilder; +import io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.api.metrics.LongCounterBuilder; +import io.opentelemetry.api.metrics.LongUpDownCounterBuilder; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleGaugeBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedLongCounterBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedLongUpDownCounterBuilder; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class NoopTest { + @RegisterExtension + static final AgentInstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Test + void noopInstance() { + Meter meter = testing.getOpenTelemetry().getMeter("test"); + + LongCounterBuilder counterBuilder = meter.counterBuilder("test"); + assertThat(counterBuilder).isNotInstanceOf(ExtendedLongCounterBuilder.class); + + LongUpDownCounterBuilder upDownCounterBuilder = meter.upDownCounterBuilder("test"); + assertThat(upDownCounterBuilder).isNotInstanceOf(ExtendedLongUpDownCounterBuilder.class); + + DoubleGaugeBuilder gaugeBuilder = meter.gaugeBuilder("test"); + assertThat(gaugeBuilder).isNotInstanceOf(ExtendedDoubleGaugeBuilder.class); + + DoubleHistogramBuilder histogramBuilder = meter.histogramBuilder("test"); + assertThat(histogramBuilder).isNotInstanceOf(ExtendedDoubleHistogramBuilder.class); + } +} 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 index eb7a3bf0a370..5acbf5a4d4ae 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/build.gradle.kts +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/build.gradle.kts @@ -15,7 +15,9 @@ dependencies { } configurations.configureEach { - if (name.endsWith("testRuntimeClasspath", true) || name.endsWith("testCompileClasspath", true)) { + if (name.endsWith("testRuntimeClasspath", true) || + name.endsWith("testCompileClasspath", true) || + name.startsWith("noopTest")) { resolutionStrategy { force("io.opentelemetry:opentelemetry-api:1.32.0") } @@ -29,6 +31,19 @@ testing { implementation("io.opentelemetry:opentelemetry-extension-incubator:1.32.0-alpha") } } + val noopTest by registering(JvmTestSuite::class) { + dependencies { + implementation("io.opentelemetry:opentelemetry-extension-incubator:1.32.0-alpha") + } + + targets { + all { + testTask.configure { + jvmArgs("-Dtesting.exporter.enabled=false") + } + } + } + } } } 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 index 422b5c9e4c5d..d8347dc3adec 100644 --- 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 @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator.metrics; import application.io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationDoubleHistogramBuilder; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_31.incubator.metrics.ApplicationMeter131; class ApplicationMeter132Incubator extends ApplicationMeter131 { @@ -19,6 +20,10 @@ class ApplicationMeter132Incubator extends ApplicationMeter131 { @Override public DoubleHistogramBuilder histogramBuilder(String name) { - return new ApplicationDoubleHistogramBuilder132Incubator(agentMeter.histogramBuilder(name)); + io.opentelemetry.api.metrics.DoubleHistogramBuilder builder = agentMeter.histogramBuilder(name); + if (builder instanceof io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogramBuilder) { + return new ApplicationDoubleHistogramBuilder132Incubator(builder); + } + return new ApplicationDoubleHistogramBuilder(builder); } } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/NoopTest.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/NoopTest.java new file mode 100644 index 000000000000..91a555add5a5 --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.32/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_32/incubator/metrics/NoopTest.java @@ -0,0 +1,43 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_32.incubator.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.metrics.DoubleGaugeBuilder; +import io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.api.metrics.LongCounterBuilder; +import io.opentelemetry.api.metrics.LongUpDownCounterBuilder; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleGaugeBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedLongCounterBuilder; +import io.opentelemetry.extension.incubator.metrics.ExtendedLongUpDownCounterBuilder; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class NoopTest { + @RegisterExtension + static final AgentInstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Test + void noopInstance() { + Meter meter = testing.getOpenTelemetry().getMeter("test"); + + LongCounterBuilder counterBuilder = meter.counterBuilder("test"); + assertThat(counterBuilder).isNotInstanceOf(ExtendedLongCounterBuilder.class); + + LongUpDownCounterBuilder upDownCounterBuilder = meter.upDownCounterBuilder("test"); + assertThat(upDownCounterBuilder).isNotInstanceOf(ExtendedLongUpDownCounterBuilder.class); + + DoubleGaugeBuilder gaugeBuilder = meter.gaugeBuilder("test"); + assertThat(gaugeBuilder).isNotInstanceOf(ExtendedDoubleGaugeBuilder.class); + + DoubleHistogramBuilder histogramBuilder = meter.histogramBuilder("test"); + assertThat(histogramBuilder).isNotInstanceOf(ExtendedDoubleHistogramBuilder.class); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/build.gradle.kts b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/build.gradle.kts index 4970d5818950..0298ea52c101 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/build.gradle.kts +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/build.gradle.kts @@ -21,7 +21,7 @@ configurations.configureEach { force("io.opentelemetry:opentelemetry-api:1.37.0") force("io.opentelemetry:opentelemetry-api-incubator:1.37.0-alpha") } - if (name.startsWith("incubatorTest")) { + if (name.startsWith("incubatorTest") || name.startsWith("noopTest")) { resolutionStrategy { force("io.opentelemetry:opentelemetry-api-incubator:1.37.0-alpha") } @@ -47,6 +47,19 @@ testing { implementation("io.opentelemetry:opentelemetry-extension-incubator:1.32.0-alpha") } } + val noopTest by registering(JvmTestSuite::class) { + dependencies { + implementation("io.opentelemetry:opentelemetry-api-incubator:1.37.0-alpha") + } + + targets { + all { + testTask.configure { + jvmArgs("-Dtesting.exporter.enabled=false") + } + } + } + } } } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/ApplicationMeter137.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/ApplicationMeter137.java index 6ed769ccf49b..65860afca72a 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/ApplicationMeter137.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/ApplicationMeter137.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_37.incubator.metrics; import application.io.opentelemetry.api.metrics.DoubleGaugeBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationDoubleGaugeBuilder; class ApplicationMeter137 extends BaseApplicationMeter137 { @@ -18,6 +19,10 @@ protected ApplicationMeter137(io.opentelemetry.api.metrics.Meter agentMeter) { @Override public DoubleGaugeBuilder gaugeBuilder(String name) { - return new ApplicationDoubleGaugeBuilder137(agentMeter.gaugeBuilder(name)); + io.opentelemetry.api.metrics.DoubleGaugeBuilder builder = agentMeter.gaugeBuilder(name); + if (builder instanceof io.opentelemetry.api.incubator.metrics.ExtendedDoubleGaugeBuilder) { + return new ApplicationDoubleGaugeBuilder137(builder); + } + return new ApplicationDoubleGaugeBuilder(builder); } } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/BaseApplicationMeter137.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/BaseApplicationMeter137.java index 3a0c0d3ff608..b3fd0b095142 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/BaseApplicationMeter137.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/BaseApplicationMeter137.java @@ -8,6 +8,9 @@ import application.io.opentelemetry.api.metrics.DoubleHistogramBuilder; import application.io.opentelemetry.api.metrics.LongCounterBuilder; import application.io.opentelemetry.api.metrics.LongUpDownCounterBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationDoubleHistogramBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationLongCounterBuilder; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_10.metrics.ApplicationLongUpDownCounterBuilder; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_15.metrics.ApplicationMeter115; // used by both 1.37 and 1.38 @@ -22,16 +25,30 @@ protected BaseApplicationMeter137(io.opentelemetry.api.metrics.Meter agentMeter) @Override public LongCounterBuilder counterBuilder(String name) { - return new ApplicationLongCounterBuilder137(agentMeter.counterBuilder(name)); + io.opentelemetry.api.metrics.LongCounterBuilder builder = agentMeter.counterBuilder(name); + if (builder instanceof io.opentelemetry.api.incubator.metrics.ExtendedLongCounterBuilder) { + return new ApplicationLongCounterBuilder137(builder); + } + return new ApplicationLongCounterBuilder(builder); } @Override public LongUpDownCounterBuilder upDownCounterBuilder(String name) { - return new ApplicationLongUpDownCounterBuilder137(agentMeter.upDownCounterBuilder(name)); + io.opentelemetry.api.metrics.LongUpDownCounterBuilder builder = + agentMeter.upDownCounterBuilder(name); + if (builder + instanceof io.opentelemetry.api.incubator.metrics.ExtendedLongUpDownCounterBuilder) { + return new ApplicationLongUpDownCounterBuilder137(builder); + } + return new ApplicationLongUpDownCounterBuilder(builder); } @Override public DoubleHistogramBuilder histogramBuilder(String name) { - return new ApplicationDoubleHistogramBuilder137(agentMeter.histogramBuilder(name)); + io.opentelemetry.api.metrics.DoubleHistogramBuilder builder = agentMeter.histogramBuilder(name); + if (builder instanceof io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogramBuilder) { + return new ApplicationDoubleHistogramBuilder137(builder); + } + return new ApplicationDoubleHistogramBuilder(builder); } } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/NoopTest.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/NoopTest.java new file mode 100644 index 000000000000..47e92b4a862b --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.37/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_37/incubator/metrics/NoopTest.java @@ -0,0 +1,43 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_37.incubator.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.incubator.metrics.ExtendedDoubleGaugeBuilder; +import io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogramBuilder; +import io.opentelemetry.api.incubator.metrics.ExtendedLongCounterBuilder; +import io.opentelemetry.api.incubator.metrics.ExtendedLongUpDownCounterBuilder; +import io.opentelemetry.api.metrics.DoubleGaugeBuilder; +import io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.api.metrics.LongCounterBuilder; +import io.opentelemetry.api.metrics.LongUpDownCounterBuilder; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class NoopTest { + @RegisterExtension + static final AgentInstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Test + void noopInstance() { + Meter meter = testing.getOpenTelemetry().getMeter("test"); + + LongCounterBuilder counterBuilder = meter.counterBuilder("test"); + assertThat(counterBuilder).isNotInstanceOf(ExtendedLongCounterBuilder.class); + + LongUpDownCounterBuilder upDownCounterBuilder = meter.upDownCounterBuilder("test"); + assertThat(upDownCounterBuilder).isNotInstanceOf(ExtendedLongUpDownCounterBuilder.class); + + DoubleGaugeBuilder gaugeBuilder = meter.gaugeBuilder("test"); + assertThat(gaugeBuilder).isNotInstanceOf(ExtendedDoubleGaugeBuilder.class); + + DoubleHistogramBuilder histogramBuilder = meter.histogramBuilder("test"); + assertThat(histogramBuilder).isNotInstanceOf(ExtendedDoubleHistogramBuilder.class); + } +} diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/build.gradle.kts b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/build.gradle.kts index 560bdde6d565..a5f854ac5856 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/build.gradle.kts +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/build.gradle.kts @@ -21,7 +21,7 @@ configurations.configureEach { resolutionStrategy { force("io.opentelemetry:opentelemetry-api:1.38.0") } - if (name.startsWith("incubatorTest")) { + if (name.startsWith("incubatorTest") || name.startsWith("noopTest")) { resolutionStrategy { force("io.opentelemetry:opentelemetry-api-incubator:1.38.0-alpha") } @@ -37,6 +37,22 @@ testing { } } } + + suites { + val noopTest by registering(JvmTestSuite::class) { + dependencies { + implementation("io.opentelemetry:opentelemetry-api-incubator:1.38.0-alpha") + } + + targets { + all { + testTask.configure { + jvmArgs("-Dtesting.exporter.enabled=false") + } + } + } + } + } } tasks { diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/incubator/metrics/ApplicationMeter138Incubator.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/incubator/metrics/ApplicationMeter138Incubator.java index 396fdf9785bb..f28e9f5f0ebc 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/incubator/metrics/ApplicationMeter138Incubator.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/incubator/metrics/ApplicationMeter138Incubator.java @@ -7,6 +7,7 @@ import application.io.opentelemetry.api.metrics.DoubleGaugeBuilder; import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_37.incubator.metrics.BaseApplicationMeter137; +import io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_38.metrics.ApplicationDoubleGaugeBuilder138; class ApplicationMeter138Incubator extends BaseApplicationMeter137 { @@ -19,6 +20,10 @@ class ApplicationMeter138Incubator extends BaseApplicationMeter137 { @Override public DoubleGaugeBuilder gaugeBuilder(String name) { - return new ApplicationDoubleGaugeBuilder138Incubator(agentMeter.gaugeBuilder(name)); + io.opentelemetry.api.metrics.DoubleGaugeBuilder builder = agentMeter.gaugeBuilder(name); + if (builder instanceof io.opentelemetry.api.incubator.metrics.ExtendedDoubleGaugeBuilder) { + return new ApplicationDoubleGaugeBuilder138Incubator(builder); + } + return new ApplicationDoubleGaugeBuilder138(builder); } } diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/metrics/ApplicationDoubleGaugeBuilder138.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/metrics/ApplicationDoubleGaugeBuilder138.java index f5bd88c9d409..58e0c17c6ad2 100644 --- a/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/metrics/ApplicationDoubleGaugeBuilder138.java +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/metrics/ApplicationDoubleGaugeBuilder138.java @@ -17,7 +17,7 @@ public class ApplicationDoubleGaugeBuilder138 extends ApplicationDoubleGaugeBuil private final io.opentelemetry.api.metrics.DoubleGaugeBuilder agentBuilder; - protected ApplicationDoubleGaugeBuilder138( + public ApplicationDoubleGaugeBuilder138( io.opentelemetry.api.metrics.DoubleGaugeBuilder agentBuilder) { super(agentBuilder); this.agentBuilder = agentBuilder; diff --git a/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/incubator/metrics/NoopTest.java b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/incubator/metrics/NoopTest.java new file mode 100644 index 000000000000..00406416976c --- /dev/null +++ b/instrumentation/opentelemetry-api/opentelemetry-api-1.38/javaagent/src/noopTest/java/io/opentelemetry/javaagent/instrumentation/opentelemetryapi/v1_38/incubator/metrics/NoopTest.java @@ -0,0 +1,43 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.opentelemetryapi.v1_38.incubator.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.incubator.metrics.ExtendedDoubleGaugeBuilder; +import io.opentelemetry.api.incubator.metrics.ExtendedDoubleHistogramBuilder; +import io.opentelemetry.api.incubator.metrics.ExtendedLongCounterBuilder; +import io.opentelemetry.api.incubator.metrics.ExtendedLongUpDownCounterBuilder; +import io.opentelemetry.api.metrics.DoubleGaugeBuilder; +import io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.api.metrics.LongCounterBuilder; +import io.opentelemetry.api.metrics.LongUpDownCounterBuilder; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class NoopTest { + @RegisterExtension + static final AgentInstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Test + void noopInstance() { + Meter meter = testing.getOpenTelemetry().getMeter("test"); + + LongCounterBuilder counterBuilder = meter.counterBuilder("test"); + assertThat(counterBuilder).isNotInstanceOf(ExtendedLongCounterBuilder.class); + + LongUpDownCounterBuilder upDownCounterBuilder = meter.upDownCounterBuilder("test"); + assertThat(upDownCounterBuilder).isNotInstanceOf(ExtendedLongUpDownCounterBuilder.class); + + DoubleGaugeBuilder gaugeBuilder = meter.gaugeBuilder("test"); + assertThat(gaugeBuilder).isNotInstanceOf(ExtendedDoubleGaugeBuilder.class); + + DoubleHistogramBuilder histogramBuilder = meter.histogramBuilder("test"); + assertThat(histogramBuilder).isNotInstanceOf(ExtendedDoubleHistogramBuilder.class); + } +} diff --git a/instrumentation/opentelemetry-extension-annotations-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extensionannotations/WithSpanInstrumentation.java b/instrumentation/opentelemetry-extension-annotations-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extensionannotations/WithSpanInstrumentation.java index f3c39511af12..4d99fcafbd3d 100644 --- a/instrumentation/opentelemetry-extension-annotations-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extensionannotations/WithSpanInstrumentation.java +++ b/instrumentation/opentelemetry-extension-annotations-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/extensionannotations/WithSpanInstrumentation.java @@ -21,7 +21,7 @@ import io.opentelemetry.instrumentation.api.annotation.support.async.AsyncOperationEndSupport; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser; @@ -98,7 +98,7 @@ static ElementMatcher.Junction configureExcludedMethods() { Map> excludedMethods = MethodsConfigurationParser.parse( - InstrumentationConfig.get().getString(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); + AgentInstrumentationConfig.get().getString(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); for (Map.Entry> entry : excludedMethods.entrySet()) { String className = entry.getKey(); ElementMatcher.Junction matcher = diff --git a/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationannotations/AnnotationExcludedMethods.java b/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationannotations/AnnotationExcludedMethods.java index b25d6900f708..9bec0120fe70 100644 --- a/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationannotations/AnnotationExcludedMethods.java +++ b/instrumentation/opentelemetry-instrumentation-annotations-1.16/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/instrumentationannotations/AnnotationExcludedMethods.java @@ -9,7 +9,7 @@ import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; import static net.bytebuddy.matcher.ElementMatchers.none; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.tooling.config.MethodsConfigurationParser; import java.util.Map; import java.util.Set; @@ -32,7 +32,7 @@ public static ElementMatcher.Junction configureExcludedMethod Map> excludedMethods = MethodsConfigurationParser.parse( - InstrumentationConfig.get().getString(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); + AgentInstrumentationConfig.get().getString(TRACE_ANNOTATED_METHODS_EXCLUDE_CONFIG)); for (Map.Entry> entry : excludedMethods.entrySet()) { String className = entry.getKey(); ElementMatcher.Junction matcher = diff --git a/instrumentation/oshi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/oshi/MetricsRegistration.java b/instrumentation/oshi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/oshi/MetricsRegistration.java index 424ee503a640..742e20909781 100644 --- a/instrumentation/oshi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/oshi/MetricsRegistration.java +++ b/instrumentation/oshi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/oshi/MetricsRegistration.java @@ -8,7 +8,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.oshi.ProcessMetrics; import io.opentelemetry.instrumentation.oshi.SystemMetrics; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -23,7 +23,7 @@ public static void register() { observables.addAll(SystemMetrics.registerObservers(GlobalOpenTelemetry.get())); // ProcessMetrics don't follow the spec - if (InstrumentationConfig.get() + if (AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.oshi.experimental-metrics.enabled", false)) { observables.addAll(ProcessMetrics.registerObservers(GlobalOpenTelemetry.get())); } diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/client/PekkoHttpClientSingletons.java b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/client/PekkoHttpClientSingletons.java index fda4e4ed6edf..79062bf38803 100644 --- a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/client/PekkoHttpClientSingletons.java +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/client/PekkoHttpClientSingletons.java @@ -6,17 +6,8 @@ package io.opentelemetry.javaagent.instrumentation.pekkohttp.v1_0.client; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import io.opentelemetry.javaagent.instrumentation.pekkohttp.v1_0.PekkoHttpUtil; import org.apache.pekko.http.scaladsl.model.HttpRequest; import org.apache.pekko.http.scaladsl.model.HttpResponse; @@ -28,29 +19,10 @@ public class PekkoHttpClientSingletons { static { SETTER = new HttpHeaderSetter(GlobalOpenTelemetry.getPropagators()); - PekkoHttpClientAttributesGetter httpAttributesGetter = new PekkoHttpClientAttributesGetter(); - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - PekkoHttpUtil.instrumentationName(), - HttpSpanNameExtractor.create(httpAttributesGetter)) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - PeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); + + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + PekkoHttpUtil.instrumentationName(), new PekkoHttpClientAttributesGetter()); } public static Instrumenter instrumenter() { diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/PekkoHttpServerSingletons.java b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/PekkoHttpServerSingletons.java index 6128e5d13762..8618492181d6 100644 --- a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/PekkoHttpServerSingletons.java +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/PekkoHttpServerSingletons.java @@ -15,7 +15,7 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.instrumentation.pekkohttp.v1_0.PekkoHttpUtil; import org.apache.pekko.http.scaladsl.model.HttpRequest; import org.apache.pekko.http.scaladsl.model.HttpResponse; @@ -34,16 +34,16 @@ public final class PekkoHttpServerSingletons { .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) .addAttributesExtractor( HttpServerAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addOperationMetrics(HttpServerMetrics.get()) .addContextCustomizer( HttpServerRoute.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()); - if (CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { + if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { builder .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) .addOperationMetrics(HttpServerExperimentalMetrics.get()); diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/PathConcatenationInstrumentation.java b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/PathConcatenationInstrumentation.java index 2f98af499ef4..d11310208bb6 100644 --- a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/PathConcatenationInstrumentation.java +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/PathConcatenationInstrumentation.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.pekkohttp.v1_0.server.route; -import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; +import static net.bytebuddy.matcher.ElementMatchers.named; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -16,15 +16,13 @@ public class PathConcatenationInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { - return namedOneOf( - "org.apache.pekko.http.scaladsl.server.PathMatcher$$anonfun$$tilde$1", - "org.apache.pekko.http.scaladsl.server.PathMatcher"); + return named("org.apache.pekko.http.scaladsl.server.PathMatcher"); } @Override public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod( - namedOneOf("apply", "$anonfun$append$1"), this.getClass().getName() + "$ApplyAdvice"); + named("$anonfun$append$1"), this.getClass().getName() + "$ApplyAdvice"); } @SuppressWarnings("unused") diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/PekkoRouteHolder.java b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/PekkoRouteHolder.java index 1d8a5e56054d..91ece866fdbd 100644 --- a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/PekkoRouteHolder.java +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/PekkoRouteHolder.java @@ -19,7 +19,7 @@ public class PekkoRouteHolder implements ImplicitContextKeyed { private static final ContextKey KEY = named("opentelemetry-pekko-route"); private String route = ""; - private boolean newSegment; + private boolean newSegment = true; private boolean endMatched; private final Deque stack = new ArrayDeque<>(); @@ -62,6 +62,14 @@ public static void save() { } } + public static void reset() { + PekkoRouteHolder holder = Context.current().get(KEY); + if (holder != null) { + holder.route = holder.stack.peek(); + holder.newSegment = true; + } + } + public static void restore() { PekkoRouteHolder holder = Context.current().get(KEY); if (holder != null) { diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RouteConcatenationInstrumentation.java b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RouteConcatenationInstrumentation.java index e5bf3b0d005a..9a00975e6b8f 100644 --- a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RouteConcatenationInstrumentation.java +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/route/RouteConcatenationInstrumentation.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.pekkohttp.v1_0.server.route; -import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; +import static net.bytebuddy.matcher.ElementMatchers.named; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; @@ -16,15 +16,15 @@ public class RouteConcatenationInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { - return namedOneOf( - "org.apache.pekko.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation$$anonfun$$tilde$1", - "org.apache.pekko.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation"); + return named("org.apache.pekko.http.scaladsl.server.RouteConcatenation$RouteWithConcatenation"); } @Override public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod( - namedOneOf("apply", "$anonfun$$tilde$1"), this.getClass().getName() + "$ApplyAdvice"); + named("$anonfun$$tilde$1"), this.getClass().getName() + "$ApplyAdvice"); + transformer.applyAdviceToMethod( + named("$anonfun$$tilde$2"), this.getClass().getName() + "$Apply2Advice"); } @SuppressWarnings("unused") @@ -43,4 +43,13 @@ public static void onExit() { PekkoRouteHolder.restore(); } } + + @SuppressWarnings("unused") + public static class Apply2Advice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter() { + PekkoRouteHolder.reset(); + } + } } diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerJavaRouteTest.java b/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerJavaRouteTest.java new file mode 100644 index 000000000000..bb239e4058c3 --- /dev/null +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerJavaRouteTest.java @@ -0,0 +1,64 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.pekkohttp.v1_0; + +import static org.apache.pekko.http.javadsl.server.PathMatchers.integerSegment; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.instrumentation.test.utils.PortUtils; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.testing.internal.armeria.client.WebClient; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpRequest; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import io.opentelemetry.testing.internal.armeria.common.HttpMethod; +import java.util.concurrent.CompletionStage; +import org.apache.pekko.actor.ActorSystem; +import org.apache.pekko.http.javadsl.Http; +import org.apache.pekko.http.javadsl.ServerBinding; +import org.apache.pekko.http.javadsl.server.AllDirectives; +import org.apache.pekko.http.javadsl.server.Route; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class PekkoHttpServerJavaRouteTest extends AllDirectives { + @RegisterExtension + private static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private final WebClient client = WebClient.of(); + + @Test + void testRoute() { + ActorSystem system = ActorSystem.create("my-system"); + int port = PortUtils.findOpenPort(); + Http http = Http.get(system); + + Route route = + concat( + pathEndOrSingleSlash(() -> complete("root")), + pathPrefix( + "test", + () -> + concat( + pathSingleSlash(() -> complete("test")), + path(integerSegment(), (i) -> complete("ok"))))); + + CompletionStage binding = http.newServerAt("localhost", port).bind(route); + try { + AggregatedHttpRequest request = + AggregatedHttpRequest.of(HttpMethod.GET, "h1c://localhost:" + port + "/test/1"); + AggregatedHttpResponse response = client.execute(request).aggregate().join(); + + assertThat(response.status().code()).isEqualTo(200); + assertThat(response.contentUtf8()).isEqualTo("ok"); + + testing.waitAndAssertTraces( + trace -> trace.hasSpansSatisfyingExactly(span -> span.hasName("GET /test/*"))); + } finally { + binding.thenCompose(ServerBinding::unbind).thenAccept(unbound -> system.terminate()); + } + } +} diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerRouteTest.scala b/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerRouteTest.scala new file mode 100644 index 000000000000..e01f6eee0460 --- /dev/null +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/test/scala/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/PekkoHttpServerRouteTest.scala @@ -0,0 +1,113 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.pekkohttp.v1_0 + +import io.opentelemetry.instrumentation.test.utils.PortUtils +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension +import io.opentelemetry.sdk.testing.assertj.{SpanDataAssert, TraceAssert} +import io.opentelemetry.testing.internal.armeria.client.WebClient +import io.opentelemetry.testing.internal.armeria.common.{ + AggregatedHttpRequest, + HttpMethod +} +import org.apache.pekko.actor.ActorSystem +import org.apache.pekko.http.scaladsl.Http +import org.apache.pekko.http.scaladsl.server.Route +import org.apache.pekko.http.scaladsl.server.Directives.{ + IntNumber, + complete, + concat, + path, + pathEndOrSingleSlash, + pathPrefix, + pathSingleSlash +} +import org.apache.pekko.stream.ActorMaterializer +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.extension.RegisterExtension +import org.junit.jupiter.api.{AfterAll, Test, TestInstance} + +import java.net.{URI, URISyntaxException} +import java.util.function.Consumer +import scala.concurrent.Await +import scala.concurrent.duration.DurationInt + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class PekkoHttpServerRouteTest { + @RegisterExtension private val testing: AgentInstrumentationExtension = + AgentInstrumentationExtension.create + private val client: WebClient = WebClient.of() + + implicit val system: ActorSystem = ActorSystem("my-system") + implicit val materializer: ActorMaterializer = ActorMaterializer() + + private def buildAddress(port: Int): URI = try + new URI("http://localhost:" + port + "/") + catch { + case exception: URISyntaxException => + throw new IllegalStateException(exception) + } + + @Test def testSimple(): Unit = { + val route = path("test") { + complete("ok") + } + + test(route, "/test", "GET /test") + } + + @Test def testRoute(): Unit = { + val route = concat( + pathEndOrSingleSlash { + complete("root") + }, + pathPrefix("test") { + concat( + pathSingleSlash { + complete("test") + }, + path(IntNumber) { _ => + complete("ok") + } + ) + } + ) + + test(route, "/test/1", "GET /test/*") + } + + def test(route: Route, path: String, spanName: String): Unit = { + val port = PortUtils.findOpenPort + val address: URI = buildAddress(port) + val binding = + Await.result(Http().bindAndHandle(route, "localhost", port), 10.seconds) + try { + val request = AggregatedHttpRequest.of( + HttpMethod.GET, + address.resolve(path).toString + ) + val response = client.execute(request).aggregate.join + assertThat(response.status.code).isEqualTo(200) + assertThat(response.contentUtf8).isEqualTo("ok") + + testing.waitAndAssertTraces(new Consumer[TraceAssert] { + override def accept(trace: TraceAssert): Unit = + trace.hasSpansSatisfyingExactly(new Consumer[SpanDataAssert] { + override def accept(span: SpanDataAssert): Unit = { + span.hasName(spanName) + } + }) + }) + } finally { + binding.unbind() + } + } + + @AfterAll + def cleanUp(): Unit = { + system.terminate() + } +} diff --git a/instrumentation/play/play-ws/play-ws-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/PlayWsClientInstrumenterFactory.java b/instrumentation/play/play-ws/play-ws-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/PlayWsClientInstrumenterFactory.java index 44501c1ec9a3..3aa1baa07114 100644 --- a/instrumentation/play/play-ws/play-ws-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/PlayWsClientInstrumenterFactory.java +++ b/instrumentation/play/play-ws/play-ws-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/playws/PlayWsClientInstrumenterFactory.java @@ -5,49 +5,16 @@ package io.opentelemetry.javaagent.instrumentation.playws; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import play.shaded.ahc.org.asynchttpclient.Request; import play.shaded.ahc.org.asynchttpclient.Response; public final class PlayWsClientInstrumenterFactory { public static Instrumenter createInstrumenter(String instrumentationName) { - PlayWsClientHttpAttributesGetter httpAttributesGetter = new PlayWsClientHttpAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - instrumentationName, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - return builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + return JavaagentHttpClientInstrumenters.create( + instrumentationName, new PlayWsClientHttpAttributesGetter(), HttpHeaderSetter.INSTANCE); } private PlayWsClientInstrumenterFactory() {} diff --git a/instrumentation/pulsar/pulsar-2.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/telemetry/PulsarSingletons.java b/instrumentation/pulsar/pulsar-2.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/telemetry/PulsarSingletons.java index 498c075f68d6..1ab6aa3f48ac 100644 --- a/instrumentation/pulsar/pulsar-2.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/telemetry/PulsarSingletons.java +++ b/instrumentation/pulsar/pulsar-2.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/telemetry/PulsarSingletons.java @@ -13,6 +13,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessageOperation; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingAttributesGetter; +import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingProducerMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.messaging.MessagingSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; @@ -23,8 +24,8 @@ import io.opentelemetry.instrumentation.api.internal.PropagatorBasedSpanLinksExtractor; import io.opentelemetry.instrumentation.api.internal.Timer; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import io.opentelemetry.javaagent.instrumentation.pulsar.v2_8.VirtualFieldStore; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -136,9 +137,10 @@ private static Instrumenter createProducerInstrumenter() { .addAttributesExtractor( createMessagingAttributesExtractor(getter, MessageOperation.PUBLISH)) .addAttributesExtractor( - ServerAttributesExtractor.create(new PulsarNetClientAttributesGetter())); + ServerAttributesExtractor.create(new PulsarNetClientAttributesGetter())) + .addOperationMetrics(MessagingProducerMetrics.get()); - if (InstrumentationConfig.get() + if (AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.pulsar.experimental-span-attributes", false)) { builder.addAttributesExtractor(ExperimentalProducerAttributesExtractor.INSTANCE); } diff --git a/instrumentation/pulsar/pulsar-2.8/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/AbstractPulsarClientTest.java b/instrumentation/pulsar/pulsar-2.8/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/AbstractPulsarClientTest.java index f32daa20e074..7883d5082c4f 100644 --- a/instrumentation/pulsar/pulsar-2.8/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/AbstractPulsarClientTest.java +++ b/instrumentation/pulsar/pulsar-2.8/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/pulsar/v2_8/AbstractPulsarClientTest.java @@ -22,6 +22,7 @@ import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; +import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.sdk.trace.data.SpanData; import java.time.Duration; @@ -76,6 +77,10 @@ abstract class AbstractPulsarClientTest { private static final AttributeKey MESSAGE_TYPE = AttributeKey.stringKey("messaging.pulsar.message.type"); + private static final double[] DURATION_BUCKETS = + new double[] { + 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0 + }; @BeforeAll static void beforeAll() throws PulsarClientException { @@ -163,6 +168,26 @@ void testConsumeNonPartitionedTopicUsingBatchReceive() throws Exception { .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( batchReceiveAttributes(topic, null, false)))); + + assertThat(testing.metrics()) + .satisfiesExactlyInAnyOrder( + metric -> + OpenTelemetryAssertions.assertThat(metric) + .hasName("messaging.publish.duration") + .hasUnit("s") + .hasDescription("Measures the duration of publish operation.") + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> + point + .hasSumGreaterThan(0.0) + .hasAttributesSatisfying( + equalTo(MESSAGING_SYSTEM, "pulsar"), + equalTo(MESSAGING_DESTINATION_NAME, topic), + equalTo(SERVER_PORT, brokerPort), + equalTo(SERVER_ADDRESS, brokerHost)) + .hasBucketBoundaries(DURATION_BUCKETS)))); } @Test diff --git a/instrumentation/quartz-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/quartz/v2_0/QuartzSingletons.java b/instrumentation/quartz-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/quartz/v2_0/QuartzSingletons.java index f467c4d40acf..6d0b5c046575 100644 --- a/instrumentation/quartz-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/quartz/v2_0/QuartzSingletons.java +++ b/instrumentation/quartz-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/quartz/v2_0/QuartzSingletons.java @@ -7,14 +7,14 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.quartz.v2_0.QuartzTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class QuartzSingletons { public static final QuartzTelemetry TELEMETRY = QuartzTelemetry.builder(GlobalOpenTelemetry.get()) .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.quartz.experimental-span-attributes", false)) .build(); diff --git a/instrumentation/r2dbc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/R2dbcSingletons.java b/instrumentation/r2dbc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/R2dbcSingletons.java index 9be60235bfc5..36ebe81accbf 100644 --- a/instrumentation/r2dbc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/R2dbcSingletons.java +++ b/instrumentation/r2dbc-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/r2dbc/v1_0/R2dbcSingletons.java @@ -7,23 +7,24 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.r2dbc.v1_0.R2dbcTelemetry; -import io.opentelemetry.instrumentation.r2dbc.v1_0.internal.R2dbcNetAttributesGetter; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.r2dbc.v1_0.internal.shaded.R2dbcTelemetry; +import io.opentelemetry.instrumentation.r2dbc.v1_0.internal.shaded.internal.R2dbcNetAttributesGetter; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class R2dbcSingletons { private static final R2dbcTelemetry TELEMETRY = R2dbcTelemetry.builder(GlobalOpenTelemetry.get()) .setStatementSanitizationEnabled( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean( "otel.instrumentation.r2dbc.statement-sanitizer.enabled", - CommonConfig.get().isStatementSanitizationEnabled())) + AgentCommonConfig.get().isStatementSanitizationEnabled())) .addAttributeExtractor( PeerServiceAttributesExtractor.create( - R2dbcNetAttributesGetter.INSTANCE, CommonConfig.get().getPeerServiceResolver())) + R2dbcNetAttributesGetter.INSTANCE, + AgentCommonConfig.get().getPeerServiceResolver())) .build(); public static R2dbcTelemetry telemetry() { diff --git a/instrumentation/r2dbc-1.0/library-instrumentation-shaded/build.gradle.kts b/instrumentation/r2dbc-1.0/library-instrumentation-shaded/build.gradle.kts index 7551f9c0cf68..c750072d17ab 100644 --- a/instrumentation/r2dbc-1.0/library-instrumentation-shaded/build.gradle.kts +++ b/instrumentation/r2dbc-1.0/library-instrumentation-shaded/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } @@ -23,7 +22,11 @@ tasks { } relocate( "io.r2dbc.proxy", - "io.opentelemetry.instrumentation.r2dbc.v1_0.shaded.io.r2dbc.proxy" + "io.opentelemetry.instrumentation.r2dbc.v1_0.internal.shaded.io.r2dbc.proxy" + ) + relocate( + "io.opentelemetry.instrumentation.r2dbc.v1_0", + "io.opentelemetry.instrumentation.r2dbc.v1_0.internal.shaded" ) } diff --git a/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitInstrumenterHelper.java b/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitInstrumenterHelper.java index 604b2e732cb0..2f0c77addc01 100644 --- a/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitInstrumenterHelper.java +++ b/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitInstrumenterHelper.java @@ -13,7 +13,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes; import java.util.Map; @@ -21,7 +21,7 @@ public class RabbitInstrumenterHelper { static final AttributeKey RABBITMQ_COMMAND = AttributeKey.stringKey("rabbitmq.command"); private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.rabbitmq.experimental-span-attributes", false); private static final RabbitInstrumenterHelper INSTRUMENTER_HELPER = diff --git a/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitSingletons.java b/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitSingletons.java index 59490a798506..c8af3a8784d6 100644 --- a/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitSingletons.java +++ b/instrumentation/rabbitmq-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rabbitmq/RabbitSingletons.java @@ -19,15 +19,15 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.internal.PropagatorBasedSpanLinksExtractor; import io.opentelemetry.instrumentation.api.semconv.network.NetworkAttributesExtractor; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import java.util.ArrayList; import java.util.List; public final class RabbitSingletons { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.rabbitmq.experimental-span-attributes", false); private static final String instrumentationName = "io.opentelemetry.rabbitmq-2.7"; private static final Instrumenter channelInstrumenter = diff --git a/instrumentation/reactor/reactor-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/v3_1/HooksInstrumentation.java b/instrumentation/reactor/reactor-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/v3_1/HooksInstrumentation.java index aeb32f290435..0591db7569ea 100644 --- a/instrumentation/reactor/reactor-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/v3_1/HooksInstrumentation.java +++ b/instrumentation/reactor/reactor-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/v3_1/HooksInstrumentation.java @@ -10,7 +10,7 @@ import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; import io.opentelemetry.instrumentation.reactor.v3_1.ContextPropagationOperator; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; @@ -41,7 +41,7 @@ public static class ResetOnEachOperatorAdvice { public static void postStaticInitializer() { ContextPropagationOperator.builder() .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.reactor.experimental-span-attributes", false)) .build() .registerOnEachOperator(); diff --git a/instrumentation/reactor/reactor-kafka-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/kafka/v1_0/ReactorKafkaSingletons.java b/instrumentation/reactor/reactor-kafka-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/kafka/v1_0/ReactorKafkaSingletons.java index b5b8e309f58a..66b7ace29c92 100644 --- a/instrumentation/reactor/reactor-kafka-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/kafka/v1_0/ReactorKafkaSingletons.java +++ b/instrumentation/reactor/reactor-kafka-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/kafka/v1_0/ReactorKafkaSingletons.java @@ -9,8 +9,8 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.kafka.internal.KafkaInstrumenterFactory; import io.opentelemetry.instrumentation.kafka.internal.KafkaProcessRequest; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; final class ReactorKafkaSingletons { @@ -20,7 +20,7 @@ final class ReactorKafkaSingletons { new KafkaInstrumenterFactory(GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.kafka.experimental-span-attributes", false)) .setMessagingReceiveInstrumentationEnabled( ExperimentalConfig.get().messagingReceiveInstrumentationEnabled()) diff --git a/instrumentation/reactor/reactor-kafka-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/kafka/v1_0/AbstractReactorKafkaTest.java b/instrumentation/reactor/reactor-kafka-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/kafka/v1_0/AbstractReactorKafkaTest.java index becea32946d4..cefb87a770c1 100644 --- a/instrumentation/reactor/reactor-kafka-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/kafka/v1_0/AbstractReactorKafkaTest.java +++ b/instrumentation/reactor/reactor-kafka-1.0/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/reactor/kafka/v1_0/AbstractReactorKafkaTest.java @@ -69,7 +69,7 @@ public abstract class AbstractReactorKafkaTest { @BeforeAll static void setUpAll() { kafka = - new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.10")) + new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.7.0")) .withEnv("KAFKA_HEAP_OPTS", "-Xmx256m") .withLogConsumer(new Slf4jLogConsumer(logger)) .waitingFor(Wait.forLogMessage(".*started \\(kafka.server.KafkaServer\\).*", 1)) diff --git a/instrumentation/reactor/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ReactorNettySingletons.java b/instrumentation/reactor/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ReactorNettySingletons.java index 5087235c26dd..955a27503a70 100644 --- a/instrumentation/reactor/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ReactorNettySingletons.java +++ b/instrumentation/reactor/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ReactorNettySingletons.java @@ -6,20 +6,13 @@ package io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0; import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyClientInstrumenterFactory; import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumentationFlag; import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumenter; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import reactor.netty.http.client.HttpClientRequest; import reactor.netty.http.client.HttpClientResponse; @@ -28,40 +21,18 @@ public final class ReactorNettySingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.reactor-netty-1.0"; private static final boolean connectionTelemetryEnabled = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.reactor-netty.connection-telemetry.enabled", false); private static final Instrumenter INSTRUMENTER; private static final NettyConnectionInstrumenter CONNECTION_INSTRUMENTER; static { - ReactorNettyHttpClientAttributesGetter httpAttributesGetter = - new ReactorNettyHttpClientAttributesGetter(); - - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - INSTRUMENTER = builder.buildClientInstrumenter(HttpClientRequestHeadersSetter.INSTANCE); + INSTRUMENTER = + JavaagentHttpClientInstrumenters.create( + INSTRUMENTATION_NAME, + new ReactorNettyHttpClientAttributesGetter(), + HttpClientRequestHeadersSetter.INSTANCE); NettyClientInstrumenterFactory instrumenterFactory = new NettyClientInstrumenterFactory( @@ -71,8 +42,8 @@ public final class ReactorNettySingletons { ? NettyConnectionInstrumentationFlag.ENABLED : NettyConnectionInstrumentationFlag.DISABLED, NettyConnectionInstrumentationFlag.DISABLED, - CommonConfig.get().getPeerServiceResolver(), - CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + AgentCommonConfig.get().getPeerServiceResolver(), + AgentCommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); CONNECTION_INSTRUMENTER = instrumenterFactory.createConnectionInstrumenter(); } diff --git a/instrumentation/redisson/redisson-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonRequest.java b/instrumentation/redisson/redisson-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonRequest.java index 6b34e59e19c5..4d0bbc4606a7 100644 --- a/instrumentation/redisson/redisson-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonRequest.java +++ b/instrumentation/redisson/redisson-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonRequest.java @@ -11,7 +11,7 @@ import com.google.auto.value.AutoValue; import io.netty.buffer.ByteBuf; import io.opentelemetry.instrumentation.api.incubator.semconv.db.RedisCommandSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -29,7 +29,7 @@ public abstract class RedissonRequest { private static final RedisCommandSanitizer sanitizer = - RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + RedisCommandSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); public static RedissonRequest create(InetSocketAddress address, Object command) { return new AutoValue_RedissonRequest(address, command); diff --git a/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletSingletons.java b/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletSingletons.java index 25a07e75f39c..0e2332b1e984 100644 --- a/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletSingletons.java +++ b/instrumentation/restlet/restlet-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v1_1/RestletSingletons.java @@ -9,7 +9,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteGetter; import io.opentelemetry.instrumentation.restlet.v1_1.RestletTelemetry; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.bootstrap.servlet.ServletContextPath; import org.restlet.data.Request; import org.restlet.data.Response; @@ -18,9 +18,9 @@ public final class RestletSingletons { private static final Instrumenter INSTRUMENTER = RestletTelemetry.builder(GlobalOpenTelemetry.get()) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build() .getServerInstrumenter(); diff --git a/instrumentation/restlet/restlet-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v2_0/RestletSingletons.java b/instrumentation/restlet/restlet-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v2_0/RestletSingletons.java index 8e55012b8aaf..0b8f6607964c 100644 --- a/instrumentation/restlet/restlet-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v2_0/RestletSingletons.java +++ b/instrumentation/restlet/restlet-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/restlet/v2_0/RestletSingletons.java @@ -13,7 +13,7 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.restlet.v2_0.internal.RestletHttpAttributesGetter; import io.opentelemetry.instrumentation.restlet.v2_0.internal.RestletInstrumenterFactory; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.bootstrap.servlet.ServletContextPath; import java.util.Collections; import org.restlet.Request; @@ -25,18 +25,18 @@ public final class RestletSingletons { RestletInstrumenterFactory.newServerInstrumenter( GlobalOpenTelemetry.get(), HttpServerAttributesExtractor.builder(RestletHttpAttributesGetter.INSTANCE) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build(), HttpSpanNameExtractor.builder(RestletHttpAttributesGetter.INSTANCE) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build(), HttpServerRoute.builder(RestletHttpAttributesGetter.INSTANCE) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build(), Collections.emptyList(), - CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()); + AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()); public static Instrumenter instrumenter() { return INSTRUMENTER; diff --git a/instrumentation/rocketmq/rocketmq-client/rocketmq-client-4.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v4_8/RocketMqClientHooks.java b/instrumentation/rocketmq/rocketmq-client/rocketmq-client-4.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v4_8/RocketMqClientHooks.java index 0528fdd52191..7c2b958ca4f9 100644 --- a/instrumentation/rocketmq/rocketmq-client/rocketmq-client-4.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v4_8/RocketMqClientHooks.java +++ b/instrumentation/rocketmq/rocketmq-client/rocketmq-client-4.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rocketmqclient/v4_8/RocketMqClientHooks.java @@ -7,8 +7,8 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.rocketmqclient.v4_8.RocketMqTelemetry; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import org.apache.rocketmq.client.hook.ConsumeMessageHook; import org.apache.rocketmq.client.hook.SendMessageHook; @@ -19,7 +19,7 @@ public final class RocketMqClientHooks { RocketMqTelemetry.builder(GlobalOpenTelemetry.get()) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean( "otel.instrumentation.rocketmq-client.experimental-span-attributes", false)) .build(); diff --git a/instrumentation/rxjava/rxjava-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v2_0/TracingAssemblyActivation.java b/instrumentation/rxjava/rxjava-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v2_0/TracingAssemblyActivation.java index bd1a4c1a6e6e..91f3b108b71a 100644 --- a/instrumentation/rxjava/rxjava-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v2_0/TracingAssemblyActivation.java +++ b/instrumentation/rxjava/rxjava-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v2_0/TracingAssemblyActivation.java @@ -6,7 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.rxjava.v2_0; import io.opentelemetry.instrumentation.rxjava.v2_0.TracingAssembly; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.concurrent.atomic.AtomicBoolean; public final class TracingAssemblyActivation { @@ -23,7 +23,7 @@ public static void activate(Class clz) { if (activated.get(clz).compareAndSet(false, true)) { TracingAssembly.builder() .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.rxjava.experimental-span-attributes", false)) .build() .enable(); diff --git a/instrumentation/rxjava/rxjava-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v3_0/TracingAssemblyActivation.java b/instrumentation/rxjava/rxjava-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v3_0/TracingAssemblyActivation.java index 69efa44cd3d1..2dd5a0696be7 100644 --- a/instrumentation/rxjava/rxjava-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v3_0/TracingAssemblyActivation.java +++ b/instrumentation/rxjava/rxjava-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v3_0/TracingAssemblyActivation.java @@ -6,7 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.rxjava.v3_0; import io.opentelemetry.instrumentation.rxjava.v3_0.TracingAssembly; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.concurrent.atomic.AtomicBoolean; public final class TracingAssemblyActivation { @@ -23,7 +23,7 @@ public static void activate(Class clz) { if (activated.get(clz).compareAndSet(false, true)) { TracingAssembly.builder() .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.rxjava.experimental-span-attributes", false)) .build() .enable(); diff --git a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v3_1_1/TracingAssemblyActivation.java b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v3_1_1/TracingAssemblyActivation.java index 79caeb74001d..ca5126be9338 100644 --- a/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v3_1_1/TracingAssemblyActivation.java +++ b/instrumentation/rxjava/rxjava-3.1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rxjava/v3_1_1/TracingAssemblyActivation.java @@ -6,7 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.rxjava.v3_1_1; import io.opentelemetry.instrumentation.rxjava.v3_1_1.TracingAssembly; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.concurrent.atomic.AtomicBoolean; public final class TracingAssemblyActivation { @@ -23,7 +23,7 @@ public static void activate(Class clz) { if (activated.get(clz).compareAndSet(false, true)) { TracingAssembly.builder() .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.rxjava.experimental-span-attributes", false)) .build() .enable(); diff --git a/instrumentation/servlet/servlet-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2SpanNameExtractor.java b/instrumentation/servlet/servlet-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2SpanNameExtractor.java index 40403d458a13..7091be708516 100644 --- a/instrumentation/servlet/servlet-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2SpanNameExtractor.java +++ b/instrumentation/servlet/servlet-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2SpanNameExtractor.java @@ -6,7 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.servlet.v2_2; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.instrumentation.servlet.ServletAccessor; import io.opentelemetry.javaagent.instrumentation.servlet.ServletRequestContext; import java.util.Set; @@ -15,7 +15,7 @@ public class Servlet2SpanNameExtractor implements SpanNameExtractor> { private final ServletAccessor accessor; - private final Set knownMethods = CommonConfig.get().getKnownHttpRequestMethods(); + private final Set knownMethods = AgentCommonConfig.get().getKnownHttpRequestMethods(); public Servlet2SpanNameExtractor(ServletAccessor accessor) { this.accessor = accessor; diff --git a/instrumentation/servlet/servlet-3.0/javaagent/src/test/groovy/JettyServlet3Test.groovy b/instrumentation/servlet/servlet-3.0/javaagent/src/test/groovy/JettyServlet3Test.groovy index ca3187fc446f..f2f93e4c2ef9 100644 --- a/instrumentation/servlet/servlet-3.0/javaagent/src/test/groovy/JettyServlet3Test.groovy +++ b/instrumentation/servlet/servlet-3.0/javaagent/src/test/groovy/JettyServlet3Test.groovy @@ -149,13 +149,6 @@ class JettyServlet3TestAsync extends JettyServlet3Test { boolean isAsyncTest() { true } - - @Override - String getMetricsInstrumentationName() { - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - "io.opentelemetry.servlet-3.0" - } } class JettyServlet3TestFakeAsync extends JettyServlet3Test { @@ -164,13 +157,6 @@ class JettyServlet3TestFakeAsync extends JettyServlet3Test { Class servlet() { TestServlet3.FakeAsync } - - @Override - String getMetricsInstrumentationName() { - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - "io.opentelemetry.servlet-3.0" - } } class JettyServlet3TestForward extends JettyDispatchTest { @@ -247,13 +233,6 @@ class JettyServlet3TestDispatchImmediate extends JettyDispatchTest { true } - @Override - String getMetricsInstrumentationName() { - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - "io.opentelemetry.servlet-3.0" - } - @Override protected void setupServlets(ServletContextHandler context) { super.setupServlets(context) @@ -283,13 +262,6 @@ class JettyServlet3TestDispatchAsync extends JettyDispatchTest { true } - @Override - String getMetricsInstrumentationName() { - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - "io.opentelemetry.servlet-3.0" - } - @Override protected void setupServlets(ServletContextHandler context) { super.setupServlets(context) diff --git a/instrumentation/servlet/servlet-5.0/javaagent/src/test/groovy/JettyServlet5Test.groovy b/instrumentation/servlet/servlet-5.0/javaagent/src/test/groovy/JettyServlet5Test.groovy index d71f8ab8eab6..6b547b3dab93 100644 --- a/instrumentation/servlet/servlet-5.0/javaagent/src/test/groovy/JettyServlet5Test.groovy +++ b/instrumentation/servlet/servlet-5.0/javaagent/src/test/groovy/JettyServlet5Test.groovy @@ -123,13 +123,6 @@ class JettyServlet5TestAsync extends JettyServlet5Test { boolean errorEndpointUsesSendError() { false } - - @Override - String getMetricsInstrumentationName() { - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - "io.opentelemetry.servlet-5.0" - } } @IgnoreIf({ !jvm.java11Compatible }) @@ -139,13 +132,6 @@ class JettyServlet5TestFakeAsync extends JettyServlet5Test { Class servlet() { TestServlet5.FakeAsync } - - @Override - String getMetricsInstrumentationName() { - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - "io.opentelemetry.servlet-5.0" - } } @IgnoreIf({ !jvm.java11Compatible }) @@ -237,13 +223,6 @@ class JettyServlet5TestDispatchImmediate extends JettyDispatchTest { addServlet(context, "/dispatch" + INDEXED_CHILD.path, TestServlet5.DispatchImmediate) addServlet(context, "/dispatch/recursive", TestServlet5.DispatchRecursive) } - - @Override - String getMetricsInstrumentationName() { - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - "io.opentelemetry.servlet-5.0" - } } @IgnoreIf({ !jvm.java11Compatible }) @@ -275,13 +254,6 @@ class JettyServlet5TestDispatchAsync extends JettyDispatchTest { boolean errorEndpointUsesSendError() { false } - - @Override - String getMetricsInstrumentationName() { - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - "io.opentelemetry.servlet-5.0" - } } abstract class JettyDispatchTest extends JettyServlet5Test { diff --git a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/BaseServletHelper.java b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/BaseServletHelper.java index d485a2f7ea2b..076c43c1c9c3 100644 --- a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/BaseServletHelper.java +++ b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/BaseServletHelper.java @@ -14,7 +14,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge; import io.opentelemetry.javaagent.bootstrap.servlet.MappingResolver; import io.opentelemetry.javaagent.bootstrap.servlet.ServletContextPath; @@ -136,7 +136,7 @@ private void captureRequestParameters(Span serverSpan, REQUEST request) { * created by servlet instrumentation we call this method on exit from the last servlet or filter. */ private void captureEnduserId(Span serverSpan, REQUEST request) { - if (!CommonConfig.get().getEnduserConfig().isIdEnabled()) { + if (!AgentCommonConfig.get().getEnduserConfig().isIdEnabled()) { return; } diff --git a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletAdditionalAttributesExtractor.java b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletAdditionalAttributesExtractor.java index f39f3b9f2f1d..3ecebe26fe3b 100644 --- a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletAdditionalAttributesExtractor.java +++ b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletAdditionalAttributesExtractor.java @@ -11,8 +11,8 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.semconv.incubating.EnduserIncubatingAttributes; import java.security.Principal; import javax.annotation.Nullable; @@ -21,7 +21,7 @@ public class ServletAdditionalAttributesExtractor implements AttributesExtractor< ServletRequestContext, ServletResponseContext> { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.servlet.experimental-span-attributes", false); private static final AttributeKey SERVLET_TIMEOUT = longKey("servlet.timeout"); @@ -44,7 +44,7 @@ public void onEnd( ServletRequestContext requestContext, @Nullable ServletResponseContext responseContext, @Nullable Throwable error) { - if (CommonConfig.get().getEnduserConfig().isIdEnabled()) { + if (AgentCommonConfig.get().getEnduserConfig().isIdEnabled()) { Principal principal = accessor.getRequestUserPrincipal(requestContext.request()); if (principal != null) { String name = principal.getName(); diff --git a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletInstrumenterBuilder.java b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletInstrumenterBuilder.java index a0024583fe0c..10b221f613a1 100644 --- a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletInstrumenterBuilder.java +++ b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletInstrumenterBuilder.java @@ -14,13 +14,14 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesGetter; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import java.util.ArrayList; import java.util.List; @@ -31,6 +32,8 @@ private ServletInstrumenterBuilder() {} private final List>> contextCustomizers = new ArrayList<>(); + private boolean propagateOperationListenersToOnEnd; + public static ServletInstrumenterBuilder create() { return new ServletInstrumenterBuilder<>(); } @@ -42,6 +45,12 @@ public ServletInstrumenterBuilder addContextCustomizer( return this; } + @CanIgnoreReturnValue + public ServletInstrumenterBuilder propagateOperationListenersToOnEnd() { + propagateOperationListenersToOnEnd = true; + return this; + } + public Instrumenter, ServletResponseContext> build( String instrumentationName, ServletAccessor accessor, @@ -61,15 +70,15 @@ public Instrumenter, ServletResponseContext, ServletResponseContext> @@ -80,11 +89,14 @@ public Instrumenter, ServletResponseContext(accessor)); } @@ -94,7 +106,7 @@ public Instrumenter, ServletResponseContext(accessor); SpanNameExtractor> spanNameExtractor = HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build(); return build(instrumentationName, accessor, spanNameExtractor, httpAttributesGetter); diff --git a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletRequestParametersExtractor.java b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletRequestParametersExtractor.java index dec1edbaecdf..cf3c36ecc8c2 100644 --- a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletRequestParametersExtractor.java +++ b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletRequestParametersExtractor.java @@ -11,7 +11,7 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.List; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; @@ -23,7 +23,7 @@ public class ServletRequestParametersExtractor implements AttributesExtractor< ServletRequestContext, ServletResponseContext> { private static final List CAPTURE_REQUEST_PARAMETERS = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getList( "otel.instrumentation.servlet.experimental.capture-request-parameters", emptyList()); diff --git a/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/SpringBatchInstrumentationConfig.java b/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/SpringBatchInstrumentationConfig.java index 0185b64750ed..5dac88c313fa 100644 --- a/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/SpringBatchInstrumentationConfig.java +++ b/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/SpringBatchInstrumentationConfig.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.spring.batch.v3_0; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class SpringBatchInstrumentationConfig { @@ -13,10 +13,10 @@ public final class SpringBatchInstrumentationConfig { // the item level instrumentation is very chatty so it's disabled by default private static final boolean ITEM_TRACING_ENABLED = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.spring-batch.item.enabled", false); private static final boolean CREATE_ROOT_SPAN_FOR_CHUNK = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.spring-batch.experimental.chunk.new-trace", false); public static String instrumentationName() { diff --git a/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/job/JobSingletons.java b/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/job/JobSingletons.java index 2a3acdf2eea9..1f75b22ea1b1 100644 --- a/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/job/JobSingletons.java +++ b/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/v3_0/job/JobSingletons.java @@ -12,13 +12,13 @@ import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import org.springframework.batch.core.JobExecution; public class JobSingletons { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.spring-batch.experimental-span-attributes", false); private static final Instrumenter INSTRUMENTER; diff --git a/instrumentation/spring/spring-boot-autoconfigure-3/README.md b/instrumentation/spring/spring-boot-autoconfigure-3/README.md deleted file mode 100644 index 50b65c80adf9..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure-3/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Why do we need a separate module for Spring Boot 3 auto-configuration? - -`RestClientInstrumentationAutoConfiguration` imports `RestClientCustomizer`, -which is part of Spring Boot 3 (rather than Spring framework). - -If we were to include this in the `spring-boot-autoconfigure` module, we would have to -bump the Spring Boot version to 3, which would break compatibility with Spring Boot 2. diff --git a/instrumentation/spring/spring-boot-autoconfigure-3/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure-3/build.gradle.kts deleted file mode 100644 index c3cd8b9f32f6..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure-3/build.gradle.kts +++ /dev/null @@ -1,23 +0,0 @@ -plugins { - id("otel.library-instrumentation") -} - -// Name the Spring Boot modules in accordance with https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration.custom-starter -base.archivesName.set("opentelemetry-spring-boot-3") -group = "io.opentelemetry.instrumentation" - -otelJava { - minJavaVersionSupported.set(JavaVersion.VERSION_17) -} - -dependencies { - val springBootVersion = "3.2.4" - library("org.springframework.boot:spring-boot-starter-web:$springBootVersion") - compileOnly(project(":instrumentation:spring:spring-boot-autoconfigure")) - implementation(project(":instrumentation:spring:spring-web:spring-web-3.1:library")) - - testImplementation(project(":instrumentation:spring:spring-boot-autoconfigure")) - testLibrary("org.springframework.boot:spring-boot-starter-test:$springBootVersion") { - exclude("org.junit.vintage", "junit-vintage-engine") - } -} diff --git a/instrumentation/spring/spring-boot-autoconfigure-3/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestClientBeanPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure-3/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestClientBeanPostProcessor.java deleted file mode 100644 index dc7de4b22189..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure-3/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestClientBeanPostProcessor.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.http.client.ClientHttpRequestInterceptor; -import org.springframework.web.client.RestClient; - -public final class RestClientBeanPostProcessor implements BeanPostProcessor { - - private final ObjectProvider openTelemetryProvider; - - public RestClientBeanPostProcessor(ObjectProvider openTelemetryProvider) { - this.openTelemetryProvider = openTelemetryProvider; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) { - if (bean instanceof RestClient restClient) { - return addRestClientInterceptorIfNotPresent(restClient, openTelemetryProvider.getObject()); - } - return bean; - } - - private static RestClient addRestClientInterceptorIfNotPresent( - RestClient restClient, OpenTelemetry openTelemetry) { - ClientHttpRequestInterceptor instrumentationInterceptor = - SpringWebTelemetry.create(openTelemetry).newInterceptor(); - - return restClient - .mutate() - .requestInterceptors( - interceptors -> { - if (interceptors.stream() - .noneMatch( - interceptor -> - interceptor.getClass() == instrumentationInterceptor.getClass())) { - interceptors.add(0, instrumentationInterceptor); - } - }) - .build(); - } -} diff --git a/instrumentation/spring/spring-boot-autoconfigure-3/src/main/resources/META-INF/spring.factories b/instrumentation/spring/spring-boot-autoconfigure-3/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 3aa46add58d1..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure-3/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web.RestClientInstrumentationAutoConfiguration diff --git a/instrumentation/spring/spring-boot-autoconfigure-3/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/instrumentation/spring/spring-boot-autoconfigure-3/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 576dd0fab37a..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure-3/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web.RestClientInstrumentationAutoConfiguration diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index 4356534ad15e..dafd20b4f923 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -1,9 +1,9 @@ plugins { id("otel.library-instrumentation") + id("otel.japicmp-conventions") } -// Name the Spring Boot modules in accordance with https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-auto-configuration.custom-starter -base.archivesName.set("opentelemetry-spring-boot") +base.archivesName.set("opentelemetry-spring-boot-autoconfigure") group = "io.opentelemetry.instrumentation" val springBootVersion = "2.7.18" // AutoConfiguration is added in 2.7.0, but can be used with older versions @@ -18,6 +18,17 @@ sourceSets { "builtBy" to ":instrumentation:r2dbc-1.0:library-instrumentation-shaded:extractShadowJarSpring", ) } + create("javaSpring3") { + java { + setSrcDirs(listOf("src/main/javaSpring3")) + } + } +} + +configurations { + named("javaSpring3CompileOnly") { + extendsFrom(configurations["compileOnly"]) + } } dependencies { @@ -33,9 +44,7 @@ dependencies { implementation(project(":instrumentation:spring:spring-kafka-2.7:library")) implementation(project(":instrumentation:spring:spring-web:spring-web-3.1:library")) implementation(project(":instrumentation:spring:spring-webmvc:spring-webmvc-5.3:library")) - implementation(project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library")) compileOnly("javax.servlet:javax.servlet-api:3.1.0") - compileOnly("jakarta.servlet:jakarta.servlet-api:5.0.0") implementation(project(":instrumentation:spring:spring-webflux:spring-webflux-5.3:library")) implementation(project(":instrumentation:micrometer:micrometer-1.5:library")) implementation(project(":instrumentation:log4j:log4j-appender-2.17:library")) @@ -84,6 +93,16 @@ dependencies { testImplementation("io.opentelemetry:opentelemetry-exporter-otlp") testImplementation("io.opentelemetry:opentelemetry-exporter-zipkin") testImplementation(project(":instrumentation-annotations")) + + // needed for the Spring Boot 3 support + implementation(project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library")) + + // give access to common classes, e.g. InstrumentationConfigUtil + add("javaSpring3CompileOnly", files(sourceSets.main.get().output.classesDirs)) + add("javaSpring3CompileOnly", "org.springframework.boot:spring-boot-starter-web:3.2.4") + add("javaSpring3CompileOnly", "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + add("javaSpring3CompileOnly", project(":instrumentation:spring:spring-web:spring-web-3.1:library")) + add("javaSpring3CompileOnly", project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library")) } val latestDepTest = findProperty("testLatestDeps") as Boolean @@ -95,6 +114,9 @@ if (latestDepTest) { } } +val testJavaVersion = gradle.startParameter.projectProperties["testJavaVersion"]?.let(JavaVersion::toVersion) +val testSpring3 = (testJavaVersion == null || testJavaVersion.compareTo(JavaVersion.VERSION_17) >= 0) + testing { suites { val testLogbackAppender by registering(JvmTestSuite::class) { @@ -120,9 +142,7 @@ testing { } } } - } - suites { val testLogbackMissing by registering(JvmTestSuite::class) { dependencies { implementation(project()) @@ -135,6 +155,20 @@ testing { } } } + + val testSpring3 by registering(JvmTestSuite::class) { + dependencies { + implementation(project()) + implementation("org.springframework.boot:spring-boot-starter-web:3.2.4") + implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + implementation(project(":instrumentation:spring:spring-web:spring-web-3.1:library")) + implementation(project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library")) + implementation("jakarta.servlet:jakarta.servlet-api:5.0.0") + implementation("org.springframework.boot:spring-boot-starter-test:3.2.4") { + exclude("org.junit.vintage", "junit-vintage-engine") + } + } + } } } @@ -160,4 +194,24 @@ tasks { jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") jvmArgs("-XX:+IgnoreUnrecognizedVMOptions") } + + named("compileJavaSpring3Java") { + sourceCompatibility = "17" + targetCompatibility = "17" + options.release.set(17) + } + + named("compileTestSpring3Java") { + sourceCompatibility = "17" + targetCompatibility = "17" + options.release.set(17) + } + + named("testSpring3") { + isEnabled = testSpring3 + } + + withType(Jar::class) { + from(sourceSets["javaSpring3"].output) + } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/gradle.properties b/instrumentation/spring/spring-boot-autoconfigure/gradle.properties new file mode 100644 index 000000000000..45d64bec279d --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/gradle.properties @@ -0,0 +1 @@ +otel.stable=true diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EnableOpenTelemetry.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EnableOpenTelemetry.java deleted file mode 100644 index 8a5b2b95c9fa..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EnableOpenTelemetry.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.spring.autoconfigure; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - -/** Auto-configures OpenTelemetry. Enables OpenTelemetry in Spring applications */ -@Configuration -@ComponentScan(basePackages = "io.opentelemetry.instrumentation.spring.autoconfigure") -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface EnableOpenTelemetry {} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationConfigUtil.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationConfigUtil.java deleted file mode 100644 index 0fec424a5e85..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationConfigUtil.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.spring.autoconfigure.internal; - -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public class InstrumentationConfigUtil { - private InstrumentationConfigUtil() {} - - public static boolean isStatementSanitizationEnabled(ConfigProperties config, String key) { - return config.getBoolean( - key, config.getBoolean("otel.instrumentation.common.db-statement-sanitizer.enabled", true)); - } -} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java index 419c74976108..87687f668b6c 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java @@ -22,7 +22,16 @@ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) metadata.getAnnotationAttributes(ConditionalOnEnabledInstrumentation.class.getName()); String name = String.format("otel.instrumentation.%s.enabled", attributes.get("module")); + Boolean explicit = context.getEnvironment().getProperty(name, Boolean.class); + if (explicit != null) { + return explicit; + } boolean defaultValue = (boolean) attributes.get("enabledByDefault"); - return context.getEnvironment().getProperty(name, Boolean.class, defaultValue); + if (!defaultValue) { + return false; + } + return context + .getEnvironment() + .getProperty("otel.instrumentation.common.default-enabled", Boolean.class, true); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationAnnotationsAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationAnnotationsAutoConfiguration.java similarity index 82% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationAnnotationsAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationAnnotationsAutoConfiguration.java index 052f499d4a1c..0e8081622388 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationAnnotationsAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationAnnotationsAutoConfiguration.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.annotations.WithSpan; @@ -15,7 +15,12 @@ import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; -/** Configures {@link WithSpanAspect} to trace bean methods annotated with {@link WithSpan}. */ +/** + * Configures {@link WithSpanAspect} to trace bean methods annotated with {@link WithSpan}. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ @ConditionalOnEnabledInstrumentation(module = "annotations") @ConditionalOnClass(Aspect.class) @Configuration diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationWithSpanAspect.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationWithSpanAspect.java similarity index 96% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationWithSpanAspect.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationWithSpanAspect.java index 5cf80fce7ecc..90c8c2e229d5 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationWithSpanAspect.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationWithSpanAspect.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations; import io.opentelemetry.api.OpenTelemetry; import org.aspectj.lang.ProceedingJoinPoint; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/JoinPointRequest.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/JoinPointRequest.java similarity index 98% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/JoinPointRequest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/JoinPointRequest.java index a308bc80fd12..01a6a62d9894 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/JoinPointRequest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/JoinPointRequest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.annotations.WithSpan; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/JointPointCodeAttributesExtractor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/JointPointCodeAttributesExtractor.java similarity index 94% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/JointPointCodeAttributesExtractor.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/JointPointCodeAttributesExtractor.java index 1077a35c07ce..c0dc1f8be230 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/JointPointCodeAttributesExtractor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/JointPointCodeAttributesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/WithSpanAspect.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/WithSpanAspect.java similarity index 98% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/WithSpanAspect.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/WithSpanAspect.java index 246deef6f61a..f804a820924f 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/WithSpanAspect.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/WithSpanAspect.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/WithSpanAspectParameterAttributeNamesExtractor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/WithSpanAspectParameterAttributeNamesExtractor.java similarity index 98% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/WithSpanAspectParameterAttributeNamesExtractor.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/WithSpanAspectParameterAttributeNamesExtractor.java index 6c81c7dde0df..7471986cf009 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/WithSpanAspectParameterAttributeNamesExtractor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/WithSpanAspectParameterAttributeNamesExtractor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations; import io.opentelemetry.instrumentation.annotations.SpanAttribute; import io.opentelemetry.instrumentation.api.annotation.support.ParameterAttributeNamesExtractor; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/jdbc/DataSourcePostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java similarity index 96% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/jdbc/DataSourcePostProcessor.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java index d733caa22b43..875bfa3509b7 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/jdbc/DataSourcePostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.jdbc; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.jdbc; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.jdbc.datasource.JdbcTelemetry; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.InstrumentationConfigUtil; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import javax.sql.DataSource; import org.springframework.aop.scope.ScopedProxyUtils; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java similarity index 90% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java index 2e012f97687c..3ec55a5a06c2 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.jdbc; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.jdbc; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; @@ -16,6 +16,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ @ConditionalOnEnabledInstrumentation(module = "jdbc") @AutoConfiguration(after = DataSourceAutoConfiguration.class) @ConditionalOnBean({DataSource.class}) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/kafka/ConcurrentKafkaListenerContainerFactoryPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/ConcurrentKafkaListenerContainerFactoryPostProcessor.java similarity index 98% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/kafka/ConcurrentKafkaListenerContainerFactoryPostProcessor.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/ConcurrentKafkaListenerContainerFactoryPostProcessor.java index c746a72014c9..0842052409e7 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/kafka/ConcurrentKafkaListenerContainerFactoryPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/ConcurrentKafkaListenerContainerFactoryPostProcessor.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.kafka; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.kafka.v2_7.SpringKafkaTelemetry; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java similarity index 92% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java index 1eab4c4e6346..739e0275201c 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.kafka; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.kafkaclients.v2_6.KafkaTelemetry; @@ -17,6 +17,10 @@ import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; import org.springframework.kafka.core.KafkaTemplate; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ @ConditionalOnEnabledInstrumentation(module = "kafka") @ConditionalOnClass({KafkaTemplate.class, ConcurrentKafkaListenerContainerFactory.class}) @Configuration diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackAppenderApplicationListener.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderApplicationListener.java similarity index 93% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackAppenderApplicationListener.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderApplicationListener.java index 646e8119bc01..442b4715bbd9 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackAppenderApplicationListener.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderApplicationListener.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging; import org.springframework.boot.SpringApplication; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; @@ -13,6 +13,10 @@ import org.springframework.context.event.GenericApplicationListener; import org.springframework.core.ResolvableType; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ public class LogbackAppenderApplicationListener implements GenericApplicationListener { private static final Class[] SOURCE_TYPES = { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackAppenderInstaller.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java similarity index 99% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackAppenderInstaller.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java index 811dacb31bf7..ceda38ec66c3 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackAppenderInstaller.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.spi.ILoggingEvent; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/OpenTelemetryAppenderAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/OpenTelemetryAppenderAutoConfiguration.java similarity index 91% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/OpenTelemetryAppenderAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/OpenTelemetryAppenderAutoConfiguration.java index b9bb519f61ce..7fae726c9fb8 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/OpenTelemetryAppenderAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/OpenTelemetryAppenderAutoConfiguration.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; @@ -13,6 +13,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ @Configuration @SuppressWarnings("OtelPrivateConstructorForUtilityClass") public class OpenTelemetryAppenderAutoConfiguration { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/micrometer/MicrometerBridgeAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/micrometer/MicrometerBridgeAutoConfiguration.java similarity index 91% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/micrometer/MicrometerBridgeAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/micrometer/MicrometerBridgeAutoConfiguration.java index 8be9811fa84d..703051d24146 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/micrometer/MicrometerBridgeAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/micrometer/MicrometerBridgeAutoConfiguration.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.micrometer; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.micrometer; import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.MeterRegistry; @@ -19,6 +19,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ @ConditionalOnEnabledInstrumentation(module = "micrometer", enabledByDefault = false) @AutoConfigureAfter(MetricsAutoConfiguration.class) @AutoConfigureBefore(CompositeMeterRegistryAutoConfiguration.class) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java similarity index 82% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java index 279a01524cee..1fbfdbfb0178 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java @@ -3,26 +3,27 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.mongo; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.mongo; import com.mongodb.MongoClientSettings; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.mongo.v3_1.MongoTelemetry; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.InstrumentationConfigUtil; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.SdkEnabled; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ @ConditionalOnBean(OpenTelemetry.class) @ConditionalOnClass(MongoClientSettings.class) -@ConditionalOnProperty(name = "otel.instrumentation.mongo.enabled", matchIfMissing = true) -@Conditional(SdkEnabled.class) +@ConditionalOnEnabledInstrumentation(module = "mongo") @Configuration public class MongoClientInstrumentationAutoConfiguration { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java similarity index 81% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java index dd3d88e41ab6..d744b8fe1dc4 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java @@ -3,24 +3,25 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.r2dbc; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.r2dbc; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.SdkEnabled; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.r2dbc.spi.ConnectionFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ @ConditionalOnBean(OpenTelemetry.class) @ConditionalOnClass(ConnectionFactory.class) -@ConditionalOnProperty(name = "otel.instrumentation.r2dbc.enabled", matchIfMissing = true) -@Conditional(SdkEnabled.class) +@ConditionalOnEnabledInstrumentation(module = "r2dbc") @Configuration(proxyBeanMethods = false) public class R2dbcInstrumentationAutoConfiguration { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java similarity index 93% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java index d3bddb3d8055..5d75b28946ef 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java @@ -3,11 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.r2dbc; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.r2dbc; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.r2dbc.v1_0.R2dbcTelemetry; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.InstrumentationConfigUtil; +import io.opentelemetry.instrumentation.r2dbc.v1_0.internal.shaded.R2dbcTelemetry; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.r2dbc.spi.ConnectionFactory; import io.r2dbc.spi.ConnectionFactoryOptions; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateBeanPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateBeanPostProcessor.java similarity index 61% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateBeanPostProcessor.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateBeanPostProcessor.java index 43d0c52bac38..0cda4b63d686 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateBeanPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateBeanPostProcessor.java @@ -3,9 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.web.client.RestTemplate; @@ -14,8 +15,13 @@ final class RestTemplateBeanPostProcessor implements BeanPostProcessor { private final ObjectProvider openTelemetryProvider; - RestTemplateBeanPostProcessor(ObjectProvider openTelemetryProvider) { + private final ObjectProvider configPropertiesProvider; + + RestTemplateBeanPostProcessor( + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { this.openTelemetryProvider = openTelemetryProvider; + this.configPropertiesProvider = configPropertiesProvider; } @Override @@ -25,6 +31,8 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { } return RestTemplateInstrumentation.addIfNotPresent( - (RestTemplate) bean, openTelemetryProvider.getObject()); + (RestTemplate) bean, + openTelemetryProvider.getObject(), + configPropertiesProvider.getObject()); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateInstrumentation.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateInstrumentation.java similarity index 60% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateInstrumentation.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateInstrumentation.java index 58c266f09e8c..9465c534d0ce 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestTemplateInstrumentation.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateInstrumentation.java @@ -3,11 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry; +import io.opentelemetry.instrumentation.spring.web.v3_1.internal.WebTelemetryUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import java.util.List; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; @@ -17,9 +20,16 @@ class RestTemplateInstrumentation { private RestTemplateInstrumentation() {} @CanIgnoreReturnValue - static RestTemplate addIfNotPresent(RestTemplate restTemplate, OpenTelemetry openTelemetry) { + static RestTemplate addIfNotPresent( + RestTemplate restTemplate, OpenTelemetry openTelemetry, ConfigProperties config) { + ClientHttpRequestInterceptor instrumentationInterceptor = - SpringWebTelemetry.create(openTelemetry).newInterceptor(); + InstrumentationConfigUtil.configureClientBuilder( + config, + SpringWebTelemetry.builder(openTelemetry), + WebTelemetryUtil.getBuilderExtractor()) + .build() + .newInterceptor(); List restTemplateInterceptors = restTemplate.getInterceptors(); if (restTemplateInterceptors.stream() diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java similarity index 69% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java index 961ee82fea13..c4f692607eff 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java @@ -3,10 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.web.client.RestTemplateCustomizer; @@ -17,7 +18,10 @@ /** * Configures {@link RestTemplate} for tracing. * - *

Adds Open Telemetry instrumentation to RestTemplate beans after initialization + *

Adds Open Telemetry instrumentation to RestTemplate beans after initialization. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. */ @ConditionalOnEnabledInstrumentation(module = "spring-web") @ConditionalOnClass(RestTemplate.class) @@ -29,15 +33,17 @@ public SpringWebInstrumentationAutoConfiguration() {} // static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning @Bean static RestTemplateBeanPostProcessor otelRestTemplateBeanPostProcessor( - ObjectProvider openTelemetryProvider) { - return new RestTemplateBeanPostProcessor(openTelemetryProvider); + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { + return new RestTemplateBeanPostProcessor(openTelemetryProvider, configPropertiesProvider); } @Bean RestTemplateCustomizer otelRestTemplateCustomizer( - ObjectProvider openTelemetryProvider) { + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { return restTemplate -> RestTemplateInstrumentation.addIfNotPresent( - restTemplate, openTelemetryProvider.getObject()); + restTemplate, openTelemetryProvider.getObject(), configPropertiesProvider.getObject()); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java similarity index 67% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java index cfd5f5eb5ed7..bdf00acf732b 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java @@ -3,11 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @@ -18,7 +18,10 @@ /** * Configures {@link WebClient} for tracing. * - *

Adds Open Telemetry instrumentation to WebClient beans after initialization + *

Adds Open Telemetry instrumentation to WebClient beans after initialization. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. */ @ConditionalOnEnabledInstrumentation(module = "spring-webflux") @ConditionalOnClass(WebClient.class) @@ -30,14 +33,14 @@ public SpringWebfluxInstrumentationAutoConfiguration() {} // static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning @Bean static WebClientBeanPostProcessor otelWebClientBeanPostProcessor( - ObjectProvider openTelemetryProvider) { - return new WebClientBeanPostProcessor(openTelemetryProvider); + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { + return new WebClientBeanPostProcessor(openTelemetryProvider, configPropertiesProvider); } @Bean - WebFilter telemetryFilter(OpenTelemetry openTelemetry) { - return SpringWebfluxTelemetry.builder(openTelemetry) - .build() + WebFilter telemetryFilter(OpenTelemetry openTelemetry, ConfigProperties config) { + return WebClientBeanPostProcessor.getWebfluxTelemetry(openTelemetry, config) .createWebFilterAndRegisterReactorHook(); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/WebClientBeanPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java similarity index 58% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/WebClientBeanPostProcessor.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java index 1ee2c56c1da0..90dde820c4a9 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/WebClientBeanPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java @@ -3,10 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.SpringWebfluxBuilderUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.web.reactive.function.client.WebClient; @@ -19,9 +22,23 @@ final class WebClientBeanPostProcessor implements BeanPostProcessor { private final ObjectProvider openTelemetryProvider; + private final ObjectProvider configPropertiesProvider; - WebClientBeanPostProcessor(ObjectProvider openTelemetryProvider) { + WebClientBeanPostProcessor( + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { this.openTelemetryProvider = openTelemetryProvider; + this.configPropertiesProvider = configPropertiesProvider; + } + + static SpringWebfluxTelemetry getWebfluxTelemetry( + OpenTelemetry openTelemetry, ConfigProperties config) { + return InstrumentationConfigUtil.configureClientAndServerBuilder( + config, + SpringWebfluxTelemetry.builder(openTelemetry), + SpringWebfluxBuilderUtil.getClientBuilderExtractor(), + SpringWebfluxBuilderUtil.getServerBuilderExtractor()) + .build(); } @Override @@ -38,7 +55,8 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { private WebClient.Builder wrapBuilder(WebClient.Builder webClientBuilder) { SpringWebfluxTelemetry instrumentation = - SpringWebfluxTelemetry.create(openTelemetryProvider.getObject()); + getWebfluxTelemetry( + openTelemetryProvider.getObject(), configPropertiesProvider.getObject()); return webClientBuilder.filters(instrumentation::addClientTracingFilter); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java similarity index 58% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java index a57d2ab79df5..4d296a675478 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java @@ -3,11 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.webmvc.v5_3.SpringWebMvcTelemetry; +import io.opentelemetry.instrumentation.spring.webmvc.v5_3.internal.SpringMvcBuilderUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import javax.servlet.Filter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @@ -15,6 +18,10 @@ import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.servlet.DispatcherServlet; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ @ConditionalOnEnabledInstrumentation(module = "spring-webmvc") @ConditionalOnClass({Filter.class, OncePerRequestFilter.class, DispatcherServlet.class}) @Configuration @@ -22,7 +29,12 @@ public class SpringWebMvc5InstrumentationAutoConfiguration { @Bean - Filter otelWebMvcFilter(OpenTelemetry openTelemetry) { - return SpringWebMvcTelemetry.create(openTelemetry).createServletFilter(); + Filter otelWebMvcFilter(OpenTelemetry openTelemetry, ConfigProperties config) { + return InstrumentationConfigUtil.configureServerBuilder( + config, + SpringWebMvcTelemetry.builder(openTelemetry), + SpringMvcBuilderUtil.getBuilderExtractor()) + .build() + .createServletFilter(); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java new file mode 100644 index 000000000000..49d50f94cc5c --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java @@ -0,0 +1,105 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties; + +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; +import java.time.Duration; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; + +final class ConfigPropertiesBridge implements InstrumentationConfig { + + private final ConfigProperties configProperties; + + public ConfigPropertiesBridge(ConfigProperties configProperties) { + this.configProperties = configProperties; + } + + @Nullable + @Override + public String getString(String name) { + try { + return configProperties.getString(name); + } catch (ConfigurationException ignored) { + return null; + } + } + + @Override + public String getString(String name, String defaultValue) { + try { + return configProperties.getString(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public boolean getBoolean(String name, boolean defaultValue) { + try { + return configProperties.getBoolean(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public int getInt(String name, int defaultValue) { + try { + return configProperties.getInt(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public long getLong(String name, long defaultValue) { + try { + return configProperties.getLong(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public double getDouble(String name, double defaultValue) { + try { + return configProperties.getDouble(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public Duration getDuration(String name, Duration defaultValue) { + try { + return configProperties.getDuration(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public List getList(String name, List defaultValue) { + try { + return configProperties.getList(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } + + @Override + public Map getMap(String name, Map defaultValue) { + try { + return configProperties.getMap(name, defaultValue); + } catch (ConfigurationException ignored) { + return defaultValue; + } + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java new file mode 100644 index 000000000000..747cf33dcb09 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; +import io.opentelemetry.instrumentation.api.incubator.config.internal.CommonConfig; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import java.util.function.Function; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class InstrumentationConfigUtil { + private InstrumentationConfigUtil() {} + + @CanIgnoreReturnValue + public static + T configureClientAndServerBuilder( + ConfigProperties config, + T builder, + Function> + getClientBuilder, + Function> + getServerBuilder) { + CommonConfig commonConfig = getConfig(config); + getClientBuilder.apply(builder).configure(commonConfig); + getServerBuilder.apply(builder).configure(commonConfig); + return builder; + } + + @CanIgnoreReturnValue + public static T configureClientBuilder( + ConfigProperties config, + T builder, + Function> getBuilder) { + getBuilder.apply(builder).configure(getConfig(config)); + return builder; + } + + @CanIgnoreReturnValue + public static T configureServerBuilder( + ConfigProperties config, + T builder, + Function> getBuilder) { + getBuilder.apply(builder).configure(getConfig(config)); + return builder; + } + + private static CommonConfig getConfig(ConfigProperties config) { + return new CommonConfig(new ConfigPropertiesBridge(config)); + } + + public static boolean isStatementSanitizationEnabled(ConfigProperties config, String key) { + return config.getBoolean( + key, config.getBoolean("otel.instrumentation.common.db-statement-sanitizer.enabled", true)); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/OpenTelemetryAnnotationsRuntimeHints.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/OpenTelemetryAnnotationsRuntimeHints.java new file mode 100644 index 000000000000..79a9fad3c069 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/OpenTelemetryAnnotationsRuntimeHints.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations; + +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.aot.hint.TypeReference; + +class OpenTelemetryAnnotationsRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + hints + .reflection() + .registerType( + TypeReference.of( + "io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations.InstrumentationWithSpanAspect"), + hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS)); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientBeanPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientBeanPostProcessor.java new file mode 100644 index 000000000000..8ebefdd655f6 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientBeanPostProcessor.java @@ -0,0 +1,66 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; +import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry; +import io.opentelemetry.instrumentation.spring.web.v3_1.internal.WebTelemetryUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.web.client.RestClient; + +final class RestClientBeanPostProcessor implements BeanPostProcessor { + + private final ObjectProvider openTelemetryProvider; + private final ObjectProvider configPropertiesProvider; + + public RestClientBeanPostProcessor( + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { + this.openTelemetryProvider = openTelemetryProvider; + this.configPropertiesProvider = configPropertiesProvider; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) { + if (bean instanceof RestClient restClient) { + return addRestClientInterceptorIfNotPresent( + restClient, openTelemetryProvider.getObject(), configPropertiesProvider.getObject()); + } + return bean; + } + + private static RestClient addRestClientInterceptorIfNotPresent( + RestClient restClient, OpenTelemetry openTelemetry, ConfigProperties config) { + ClientHttpRequestInterceptor instrumentationInterceptor = getInterceptor(openTelemetry, config); + + return restClient + .mutate() + .requestInterceptors( + interceptors -> { + if (interceptors.stream() + .noneMatch( + interceptor -> + interceptor.getClass() == instrumentationInterceptor.getClass())) { + interceptors.add(0, instrumentationInterceptor); + } + }) + .build(); + } + + static ClientHttpRequestInterceptor getInterceptor( + OpenTelemetry openTelemetry, ConfigProperties config) { + return InstrumentationConfigUtil.configureClientBuilder( + config, + SpringWebTelemetry.builder(openTelemetry), + WebTelemetryUtil.getBuilderExtractor()) + .build() + .newInterceptor(); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure-3/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestClientInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java similarity index 68% rename from instrumentation/spring/spring-boot-autoconfigure-3/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestClientInstrumentationAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java index d3e862443187..10c8387eecd4 100644 --- a/instrumentation/spring/spring-boot-autoconfigure-3/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestClientInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java @@ -3,11 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -20,7 +20,10 @@ /** * Configures {@link RestClient} for tracing. * - *

Adds Open Telemetry instrumentation to {@link RestClient} beans after initialization + *

Adds Open Telemetry instrumentation to {@link RestClient} beans after initialization. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. */ @ConditionalOnEnabledInstrumentation(module = "spring-web") @ConditionalOnClass(RestClient.class) @@ -30,15 +33,18 @@ public class RestClientInstrumentationAutoConfiguration { @Bean static RestClientBeanPostProcessor otelRestClientBeanPostProcessor( - ObjectProvider openTelemetryProvider) { - return new RestClientBeanPostProcessor(openTelemetryProvider); + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { + return new RestClientBeanPostProcessor(openTelemetryProvider, configPropertiesProvider); } @Bean RestClientCustomizer otelRestClientCustomizer( - ObjectProvider openTelemetryProvider) { + ObjectProvider openTelemetryProvider, + ObjectProvider configPropertiesProvider) { return builder -> builder.requestInterceptor( - SpringWebTelemetry.create(openTelemetryProvider.getObject()).newInterceptor()); + RestClientBeanPostProcessor.getInterceptor( + openTelemetryProvider.getObject(), configPropertiesProvider.getObject())); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java similarity index 58% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java index ca68d0e90d19..de4007900d5d 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java @@ -3,11 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.webmvc.v6_0.SpringWebMvcTelemetry; +import io.opentelemetry.instrumentation.spring.webmvc.v6_0.internal.SpringMvcBuilderUtil; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import jakarta.servlet.Filter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @@ -15,6 +18,10 @@ import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.servlet.DispatcherServlet; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ @ConditionalOnEnabledInstrumentation(module = "spring-webmvc") @ConditionalOnClass({Filter.class, OncePerRequestFilter.class, DispatcherServlet.class}) @Configuration @@ -22,7 +29,12 @@ public class SpringWebMvc6InstrumentationAutoConfiguration { @Bean - Filter otelWebMvcFilter(OpenTelemetry openTelemetry) { - return SpringWebMvcTelemetry.create(openTelemetry).createServletFilter(); + Filter otelWebMvcFilter(OpenTelemetry openTelemetry, ConfigProperties config) { + return InstrumentationConfigUtil.configureServerBuilder( + config, + SpringWebMvcTelemetry.builder(openTelemetry), + SpringMvcBuilderUtil.getBuilderExtractor()) + .build() + .createServletFilter(); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 9bea00f40e19..3b309aae4739 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -279,6 +279,55 @@ "description": "Enables the DB statement sanitization.", "defaultValue": true }, + { + "name": "otel.instrumentation.common.default-enabled", + "type": "java.lang.Boolean", + "description": "Enables all instrumentations. Set to false to disable all instrumentations and then enable specific modules individually, e.g. otel.instrumentation.jdbc.enabled=true.", + "defaultValue": true + }, + { + "name": "otel.instrumentation.common.peer-service-mapping", + "type": "java.util.Map", + "description": "Used to specify a mapping from host names or IP addresses to peer services, as a comma-separated list of host_or_ip=user_assigned_name pairs. The peer service is added as an attribute to a span whose host or IP address match the mapping. See https://opentelemetry.io/docs/zero-code/java/agent/configuration/#peer-service-name." + }, + { + "name": "otel.instrumentation.http.client.capture-request-headers", + "type": "java.util.List", + "description": "List of HTTP request headers to capture in HTTP clients." + }, + { + "name": "otel.instrumentation.http.client.capture-response-headers", + "type": "java.util.List", + "description": "List of HTTP response headers to capture in HTTP clients." + }, + { + "name": "otel.instrumentation.http.client.emit-experimental-telemetry", + "type": "java.lang.Boolean", + "description": "Enable the capture of experimental HTTP client telemetry. Add the http.request.body.size and http.response.body.size> attributes to spans, and record the http.client.request.size and http.client.response.size metrics.", + "defaultValue": false + }, + { + "name": "otel.instrumentation.http.known-methods", + "type": "java.util.List", + "description": "Configures the instrumentation to recognize an alternative set of HTTP request methods. All other methods will be treated as _OTHER.", + "defaultValue": "CONNECT,DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,TRACE" + }, + { + "name": "otel.instrumentation.http.server.capture-request-headers", + "type": "java.util.List", + "description": "List of HTTP request headers to capture in HTTP servers." + }, + { + "name": "otel.instrumentation.http.server.capture-response-headers", + "type": "java.util.List", + "description": "List of HTTP response headers to capture in HTTP servers." + }, + { + "name": "otel.instrumentation.http.server.emit-experimental-telemetry", + "type": "java.lang.Boolean", + "description": "Enable the capture of experimental HTTP server telemetry. Add the http.request.body.size and http.response.body.size attributes to spans, and record the http.server.request.body.size and http.server.response.body.size metrics.", + "defaultValue": false + }, { "name": "otel.instrumentation.jdbc.enabled", "type": "java.lang.Boolean", diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 9ad2f41464f5..b389d6a1e381 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -1,15 +1,15 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations.InstrumentationAnnotationsAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka.KafkaInstrumentationAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.mongo.MongoClientInstrumentationAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging.OpenTelemetryAppenderAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.jdbc.JdbcInstrumentationAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.micrometer.MicrometerBridgeAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.r2dbc.R2dbcInstrumentationAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web.SpringWebInstrumentationAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc.SpringWebMvc5InstrumentationAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations.InstrumentationAnnotationsAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.kafka.KafkaInstrumentationAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.mongo.MongoClientInstrumentationAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging.OpenTelemetryAppenderAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.jdbc.JdbcInstrumentationAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.micrometer.MicrometerBridgeAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.r2dbc.R2dbcInstrumentationAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web.SpringWebInstrumentationAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc.SpringWebMvc5InstrumentationAutoConfiguration org.springframework.context.ApplicationListener=\ -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging.LogbackAppenderApplicationListener +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging.LogbackAppenderApplicationListener diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/aot.factories b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 000000000000..8d199e0f8345 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,2 @@ +org.springframework.aot.hint.RuntimeHintsRegistrar=\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations.OpenTelemetryAnnotationsRuntimeHints diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 4d7a3f31c3b4..227a59072e48 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,11 +1,12 @@ io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations.InstrumentationAnnotationsAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka.KafkaInstrumentationAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.mongo.MongoClientInstrumentationAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging.OpenTelemetryAppenderAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.jdbc.JdbcInstrumentationAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.micrometer.MicrometerBridgeAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.r2dbc.R2dbcInstrumentationAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web.SpringWebInstrumentationAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc.SpringWebMvc6InstrumentationAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations.InstrumentationAnnotationsAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.kafka.KafkaInstrumentationAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.mongo.MongoClientInstrumentationAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging.OpenTelemetryAppenderAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.jdbc.JdbcInstrumentationAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.micrometer.MicrometerBridgeAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.r2dbc.R2dbcInstrumentationAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web.SpringWebInstrumentationAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web.RestClientInstrumentationAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc.SpringWebMvc6InstrumentationAutoConfiguration diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationAnnotationsAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationAnnotationsAutoConfigurationTest.java similarity index 97% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationAnnotationsAutoConfigurationTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationAnnotationsAutoConfigurationTest.java index a625252eacef..f55e5c13f406 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationAnnotationsAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationAnnotationsAutoConfigurationTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations; import static org.assertj.core.api.Assertions.assertThat; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationWithSpanAspectTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationWithSpanAspectTest.java similarity index 99% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationWithSpanAspectTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationWithSpanAspectTest.java index 69f71af6d71b..0b4294895d7c 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/annotations/InstrumentationWithSpanAspectTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/annotations/InstrumentationWithSpanAspectTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.annotations; import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.api.trace.SpanKind.CLIENT; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/micrometer/MicrometerBridgeAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/micrometer/MicrometerBridgeAutoConfigurationTest.java similarity index 98% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/micrometer/MicrometerBridgeAutoConfigurationTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/micrometer/MicrometerBridgeAutoConfigurationTest.java index 753e660bf72e..5a32e2951d98 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/micrometer/MicrometerBridgeAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/micrometer/MicrometerBridgeAutoConfigurationTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.micrometer; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.micrometer; import static org.assertj.core.api.Assertions.assertThat; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java similarity index 98% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java index b7bc9a25b997..3c3ec9c0d665 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.r2dbc; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.r2dbc; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java similarity index 69% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java index 67b4e4e75a37..53bbd882a6d2 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java @@ -3,11 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import java.util.Collections; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -18,6 +21,9 @@ class SpringWebInstrumentationAutoConfigurationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) + .withBean( + ConfigProperties.class, + () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) .withBean(RestTemplate.class, RestTemplate::new) .withConfiguration( AutoConfigurations.of(SpringWebInstrumentationAutoConfiguration.class)); @@ -35,6 +41,7 @@ class SpringWebInstrumentationAutoConfigurationTest { void instrumentationEnabled() { contextRunner .withPropertyValues("otel.instrumentation.spring-web.enabled=true") + .withPropertyValues("otel.instrumentation.common.default-enabled=false") .run( context -> { assertThat( @@ -63,6 +70,25 @@ void instrumentationDisabled() { assertThat(context.containsBean("otelRestTemplateBeanPostProcessor")).isFalse()); } + @Test + void instrumentationDisabledButAllEnabled() { + contextRunner + .withPropertyValues("otel.instrumentation.spring-web.enabled=false") + .withPropertyValues("otel.instrumentation.common.default-enabled=true") + .run( + context -> + assertThat(context.containsBean("otelRestTemplateBeanPostProcessor")).isFalse()); + } + + @Test + void allInstrumentationDisabled() { + contextRunner + .withPropertyValues("otel.instrumentation.common.default-enabled=false") + .run( + context -> + assertThat(context.containsBean("otelRestTemplateBeanPostProcessor")).isFalse()); + } + @Test void defaultConfiguration() { contextRunner.run( diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java similarity index 83% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java index aeecebf37807..d75814732785 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java @@ -3,11 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux; import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import java.util.Collections; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -17,6 +20,9 @@ class SpringWebfluxInstrumentationAutoConfigurationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) + .withBean( + ConfigProperties.class, + () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) .withConfiguration( AutoConfigurations.of(SpringWebfluxInstrumentationAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/WebClientBeanPostProcessorTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java similarity index 75% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/WebClientBeanPostProcessorTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java index 55abca473a01..821f0fbfb647 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webflux/WebClientBeanPostProcessorTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java @@ -3,11 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux; import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import java.util.Collections; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.config.BeanPostProcessor; @@ -20,6 +23,8 @@ class WebClientBeanPostProcessorTest { static { beanFactory.registerSingleton("openTelemetry", OpenTelemetry.noop()); + beanFactory.registerSingleton( + "configProperties", DefaultConfigProperties.createFromMap(Collections.emptyMap())); } @Test @@ -27,7 +32,9 @@ class WebClientBeanPostProcessorTest { "when processed bean is NOT of type WebClient or WebClientBuilder should return Object") void returnsObject() { BeanPostProcessor underTest = - new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class)); + new WebClientBeanPostProcessor( + beanFactory.getBeanProvider(OpenTelemetry.class), + beanFactory.getBeanProvider(ConfigProperties.class)); assertThat(underTest.postProcessAfterInitialization(new Object(), "testObject")) .isExactlyInstanceOf(Object.class); @@ -37,7 +44,9 @@ void returnsObject() { @DisplayName("when processed bean is of type WebClient should return WebClient") void returnsWebClient() { BeanPostProcessor underTest = - new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class)); + new WebClientBeanPostProcessor( + beanFactory.getBeanProvider(OpenTelemetry.class), + beanFactory.getBeanProvider(ConfigProperties.class)); assertThat(underTest.postProcessAfterInitialization(WebClient.create(), "testWebClient")) .isInstanceOf(WebClient.class); @@ -47,7 +56,9 @@ void returnsWebClient() { @DisplayName("when processed bean is of type WebClientBuilder should return WebClientBuilder") void returnsWebClientBuilder() { BeanPostProcessor underTest = - new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class)); + new WebClientBeanPostProcessor( + beanFactory.getBeanProvider(OpenTelemetry.class), + beanFactory.getBeanProvider(ConfigProperties.class)); assertThat( underTest.postProcessAfterInitialization(WebClient.builder(), "testWebClientBuilder")) @@ -58,7 +69,9 @@ void returnsWebClientBuilder() { @DisplayName("when processed bean is of type WebClient should add exchange filter to WebClient") void addsExchangeFilterWebClient() { BeanPostProcessor underTest = - new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class)); + new WebClientBeanPostProcessor( + beanFactory.getBeanProvider(OpenTelemetry.class), + beanFactory.getBeanProvider(ConfigProperties.class)); WebClient webClient = WebClient.create(); Object processedWebClient = @@ -81,7 +94,9 @@ void addsExchangeFilterWebClient() { "when processed bean is of type WebClientBuilder should add ONE exchange filter to WebClientBuilder") void addsExchangeFilterWebClientBuilder() { BeanPostProcessor underTest = - new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class)); + new WebClientBeanPostProcessor( + beanFactory.getBeanProvider(OpenTelemetry.class), + beanFactory.getBeanProvider(ConfigProperties.class)); WebClient.Builder webClientBuilder = WebClient.builder(); underTest.postProcessAfterInitialization(webClientBuilder, "testWebClientBuilder"); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java similarity index 82% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java index fffc164eabfd..62112774516e 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java @@ -3,12 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeFalse; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import java.util.Collections; import javax.servlet.Filter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -20,6 +23,9 @@ class SpringWebMvcInstrumentation5AutoConfigurationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) + .withBean( + ConfigProperties.class, + () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) .withConfiguration( AutoConfigurations.of(SpringWebMvc5InstrumentationAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/properties/OtlpExporterPropertiesTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/OtlpExporterPropertiesTest.java similarity index 88% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/properties/OtlpExporterPropertiesTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/OtlpExporterPropertiesTest.java index 4146a76a090f..2fea20afec6e 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/properties/OtlpExporterPropertiesTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/OtlpExporterPropertiesTest.java @@ -3,16 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.properties; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelResourceProperties; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtlpExporterProperties; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.PropagationProperties; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.SpringConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Arrays; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/DistroVersionResourceProviderTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroVersionResourceProviderTest.java similarity index 95% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/DistroVersionResourceProviderTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroVersionResourceProviderTest.java index 1454354fdbcf..1c79c06de6f8 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/DistroVersionResourceProviderTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroVersionResourceProviderTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.resources; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources; import static org.assertj.core.api.Assertions.assertThat; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigPropertiesTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/SpringConfigPropertiesTest.java similarity index 97% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigPropertiesTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/SpringConfigPropertiesTest.java index f9488ea49955..97b30652aed5 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigPropertiesTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/SpringConfigPropertiesTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.resources; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceProviderTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/SpringResourceProviderTest.java similarity index 95% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceProviderTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/SpringResourceProviderTest.java index c8187e6040db..614f33b37273 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceProviderTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/SpringResourceProviderTest.java @@ -3,14 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.resources; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelResourceProperties; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtlpExporterProperties; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.PropagationProperties; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.SpringConfigProperties; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources.SpringResourceProvider; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testLogbackAppender/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackAppenderTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testLogbackAppender/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderTest.java similarity index 99% rename from instrumentation/spring/spring-boot-autoconfigure/src/testLogbackAppender/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackAppenderTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/testLogbackAppender/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderTest.java index 9d1336b67ff6..61200b2c6465 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testLogbackAppender/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackAppenderTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testLogbackAppender/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging; import static org.assertj.core.api.Assertions.assertThat; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testLogbackMissing/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackMissingTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testLogbackMissing/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackMissingTest.java similarity index 96% rename from instrumentation/spring/spring-boot-autoconfigure/src/testLogbackMissing/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackMissingTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/testLogbackMissing/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackMissingTest.java index 4afcc33f32aa..c40d881bc94b 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testLogbackMissing/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/logging/LogbackMissingTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testLogbackMissing/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackMissingTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/instrumentation/spring/spring-boot-autoconfigure-3/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java similarity index 88% rename from instrumentation/spring/spring-boot-autoconfigure-3/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java index eb5223c0eab2..bae340b948ef 100644 --- a/instrumentation/spring/spring-boot-autoconfigure-3/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java @@ -3,11 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import java.util.Collections; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -18,6 +21,9 @@ class RestClientInstrumentationAutoConfigurationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) + .withBean( + ConfigProperties.class, + () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) .withBean(RestClient.class, RestClient::create) .withConfiguration( AutoConfigurations.of(RestClientInstrumentationAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java similarity index 82% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java index 4b37d5819b10..d064262095c6 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java @@ -3,13 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeTrue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import jakarta.servlet.Filter; +import java.util.Collections; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -20,6 +23,9 @@ class SpringWebMvcInstrumentation6AutoConfigurationTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) + .withBean( + ConfigProperties.class, + () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) .withConfiguration( AutoConfigurations.of(SpringWebMvc6InstrumentationAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/gateway/v2_0/ServerWebExchangeHelper.java b/instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/gateway/v2_0/ServerWebExchangeHelper.java index cd337ae3a3d6..4bf8abe5fbad 100644 --- a/instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/gateway/v2_0/ServerWebExchangeHelper.java +++ b/instrumentation/spring/spring-cloud-gateway/spring-cloud-gateway-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/gateway/v2_0/ServerWebExchangeHelper.java @@ -11,7 +11,7 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.LocalRootSpan; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.regex.Pattern; import org.springframework.cloud.gateway.route.Route; import org.springframework.web.server.ServerWebExchange; @@ -38,7 +38,7 @@ public final class ServerWebExchangeHelper { static { CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean( "otel.instrumentation.spring-cloud-gateway.experimental-span-attributes", false); } diff --git a/instrumentation/spring/spring-data/spring-data-1.8/javaagent/src/test/java/spring/jpa/JpaCustomer.java b/instrumentation/spring/spring-data/spring-data-1.8/javaagent/src/test/java/spring/jpa/JpaCustomer.java index f5288a98bd9d..e11bfe8053bc 100644 --- a/instrumentation/spring/spring-data/spring-data-1.8/javaagent/src/test/java/spring/jpa/JpaCustomer.java +++ b/instrumentation/spring/spring-data/spring-data-1.8/javaagent/src/test/java/spring/jpa/JpaCustomer.java @@ -5,6 +5,7 @@ package spring.jpa; +import java.util.Locale; import java.util.Objects; import javax.annotation.Nullable; import javax.persistence.Entity; @@ -55,7 +56,8 @@ public void setLastName(String lastName) { @Override public String toString() { - return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); + return String.format( + Locale.ROOT, "Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); } @Override diff --git a/instrumentation/spring/spring-data/spring-data-3.0/testing/src/reactiveTest/java/io/opentelemetry/javaagent/instrumentation/spring/data/v3_0/repository/Customer.java b/instrumentation/spring/spring-data/spring-data-3.0/testing/src/reactiveTest/java/io/opentelemetry/javaagent/instrumentation/spring/data/v3_0/repository/Customer.java index 2c1762a89566..e1229ff4fd5e 100644 --- a/instrumentation/spring/spring-data/spring-data-3.0/testing/src/reactiveTest/java/io/opentelemetry/javaagent/instrumentation/spring/data/v3_0/repository/Customer.java +++ b/instrumentation/spring/spring-data/spring-data-3.0/testing/src/reactiveTest/java/io/opentelemetry/javaagent/instrumentation/spring/data/v3_0/repository/Customer.java @@ -5,6 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.spring.data.v3_0.repository; +import java.util.Locale; import java.util.Objects; import javax.annotation.Nullable; import org.springframework.data.annotation.Id; @@ -49,7 +50,8 @@ public void setLastName(String lastName) { @Override public String toString() { - return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); + return String.format( + Locale.ROOT, "Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); } @Override diff --git a/instrumentation/spring/spring-data/spring-data-3.0/testing/src/test/java/spring/jpa/JpaCustomer.java b/instrumentation/spring/spring-data/spring-data-3.0/testing/src/test/java/spring/jpa/JpaCustomer.java index 37e2f237c649..447399d961c6 100644 --- a/instrumentation/spring/spring-data/spring-data-3.0/testing/src/test/java/spring/jpa/JpaCustomer.java +++ b/instrumentation/spring/spring-data/spring-data-3.0/testing/src/test/java/spring/jpa/JpaCustomer.java @@ -9,6 +9,7 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import java.util.Locale; import java.util.Objects; import javax.annotation.Nullable; @@ -55,7 +56,8 @@ public void setLastName(String lastName) { @Override public String toString() { - return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); + return String.format( + Locale.ROOT, "Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); } @Override diff --git a/instrumentation/spring/spring-integration-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/integration/v4_1/SpringIntegrationSingletons.java b/instrumentation/spring/spring-integration-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/integration/v4_1/SpringIntegrationSingletons.java index 25aa7e4e565a..19cbd73fcb2e 100644 --- a/instrumentation/spring/spring-integration-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/integration/v4_1/SpringIntegrationSingletons.java +++ b/instrumentation/spring/spring-integration-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/integration/v4_1/SpringIntegrationSingletons.java @@ -9,15 +9,15 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.spring.integration.v4_1.SpringIntegrationTelemetry; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import java.util.List; import org.springframework.messaging.support.ChannelInterceptor; public final class SpringIntegrationSingletons { private static final List PATTERNS = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getList( "otel.instrumentation.spring-integration.global-channel-interceptor-patterns", singletonList("*")); @@ -26,7 +26,7 @@ public final class SpringIntegrationSingletons { SpringIntegrationTelemetry.builder(GlobalOpenTelemetry.get()) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) .setProducerSpanEnabled( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.spring-integration.producer.enabled", false)) .build() .newChannelInterceptor(); diff --git a/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/v2_7/SpringKafkaSingletons.java b/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/v2_7/SpringKafkaSingletons.java index a1e150bca3c0..fcf6f2d164b2 100644 --- a/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/v2_7/SpringKafkaSingletons.java +++ b/instrumentation/spring/spring-kafka-2.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/kafka/v2_7/SpringKafkaSingletons.java @@ -11,8 +11,8 @@ import io.opentelemetry.instrumentation.kafka.internal.KafkaReceiveRequest; import io.opentelemetry.instrumentation.spring.kafka.v2_7.SpringKafkaTelemetry; import io.opentelemetry.instrumentation.spring.kafka.v2_7.internal.SpringKafkaErrorCauseExtractor; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; public final class SpringKafkaSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-kafka-2.7"; @@ -21,7 +21,7 @@ public final class SpringKafkaSingletons { SpringKafkaTelemetry.builder(GlobalOpenTelemetry.get()) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.kafka.experimental-span-attributes", false)) .setMessagingReceiveInstrumentationEnabled( ExperimentalConfig.get().messagingReceiveInstrumentationEnabled()) @@ -33,7 +33,7 @@ public final class SpringKafkaSingletons { new KafkaInstrumenterFactory(GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.kafka.experimental-span-attributes", false)) .setMessagingReceiveInstrumentationEnabled( ExperimentalConfig.get().messagingReceiveInstrumentationEnabled()) diff --git a/instrumentation/spring/spring-kafka-2.7/library/src/main/java/io/opentelemetry/instrumentation/spring/kafka/v2_7/InstrumentedBatchInterceptor.java b/instrumentation/spring/spring-kafka-2.7/library/src/main/java/io/opentelemetry/instrumentation/spring/kafka/v2_7/InstrumentedBatchInterceptor.java index 5204d8d0c930..2c0726c79e5b 100644 --- a/instrumentation/spring/spring-kafka-2.7/library/src/main/java/io/opentelemetry/instrumentation/spring/kafka/v2_7/InstrumentedBatchInterceptor.java +++ b/instrumentation/spring/spring-kafka-2.7/library/src/main/java/io/opentelemetry/instrumentation/spring/kafka/v2_7/InstrumentedBatchInterceptor.java @@ -71,17 +71,23 @@ private static Context getParentContext(ConsumerRecords records) { @Override public void success(ConsumerRecords records, Consumer consumer) { - end(records, null); - if (decorated != null) { - decorated.success(records, consumer); + try { + if (decorated != null) { + decorated.success(records, consumer); + } + } finally { + end(records, null); } } @Override public void failure(ConsumerRecords records, Exception exception, Consumer consumer) { - end(records, exception); - if (decorated != null) { - decorated.failure(records, exception, consumer); + try { + if (decorated != null) { + decorated.failure(records, exception, consumer); + } + } finally { + end(records, exception); } } diff --git a/instrumentation/spring/spring-kafka-2.7/library/src/main/java/io/opentelemetry/instrumentation/spring/kafka/v2_7/InstrumentedRecordInterceptor.java b/instrumentation/spring/spring-kafka-2.7/library/src/main/java/io/opentelemetry/instrumentation/spring/kafka/v2_7/InstrumentedRecordInterceptor.java index 56fece666bb9..d1d5e211fea9 100644 --- a/instrumentation/spring/spring-kafka-2.7/library/src/main/java/io/opentelemetry/instrumentation/spring/kafka/v2_7/InstrumentedRecordInterceptor.java +++ b/instrumentation/spring/spring-kafka-2.7/library/src/main/java/io/opentelemetry/instrumentation/spring/kafka/v2_7/InstrumentedRecordInterceptor.java @@ -69,17 +69,23 @@ private static Context getParentContext(ConsumerRecord record) { @Override public void success(ConsumerRecord record, Consumer consumer) { - end(record, null); - if (decorated != null) { - decorated.success(record, consumer); + try { + if (decorated != null) { + decorated.success(record, consumer); + } + } finally { + end(record, null); } } @Override public void failure(ConsumerRecord record, Exception exception, Consumer consumer) { - end(record, exception); - if (decorated != null) { - decorated.failure(record, exception, consumer); + try { + if (decorated != null) { + decorated.failure(record, exception, consumer); + } + } finally { + end(record, exception); } } diff --git a/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/AbstractSpringKafkaTest.java b/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/AbstractSpringKafkaTest.java index 16d1fba123f5..bbc3bc9384ac 100644 --- a/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/AbstractSpringKafkaTest.java +++ b/instrumentation/spring/spring-kafka-2.7/testing/src/main/java/io/opentelemetry/testing/AbstractSpringKafkaTest.java @@ -46,7 +46,7 @@ public abstract class AbstractSpringKafkaTest { @BeforeAll static void setUpKafka() { kafka = - new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.10")) + new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.7.0")) .withEnv("KAFKA_HEAP_OPTS", "-Xmx256m") .waitingFor(Wait.forLogMessage(".*started \\(kafka.server.KafkaServer\\).*", 1)) .withStartupTimeout(Duration.ofMinutes(1)); diff --git a/instrumentation/spring/spring-scheduling-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/v3_1/SpringSchedulingSingletons.java b/instrumentation/spring/spring-scheduling-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/v3_1/SpringSchedulingSingletons.java index a466707ac68d..d7d6ad54f818 100644 --- a/instrumentation/spring/spring-scheduling-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/v3_1/SpringSchedulingSingletons.java +++ b/instrumentation/spring/spring-scheduling-3.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/scheduling/v3_1/SpringSchedulingSingletons.java @@ -12,12 +12,12 @@ import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class SpringSchedulingSingletons { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.spring-scheduling.experimental-span-attributes", false); private static final Instrumenter INSTRUMENTER; diff --git a/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/EnduserAttributesCapturerSingletons.java b/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/EnduserAttributesCapturerSingletons.java index 819e8a41ae7a..9b4ab9416689 100644 --- a/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/EnduserAttributesCapturerSingletons.java +++ b/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/EnduserAttributesCapturerSingletons.java @@ -6,8 +6,8 @@ package io.opentelemetry.javaagent.instrumentation.spring.security.config.v6_0; import io.opentelemetry.instrumentation.spring.security.config.v6_0.EnduserAttributesCapturer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public class EnduserAttributesCapturerSingletons { @@ -22,12 +22,12 @@ public static EnduserAttributesCapturer enduserAttributesCapturer() { private static EnduserAttributesCapturer createEndUserAttributesCapturerFromConfig() { EnduserAttributesCapturer capturer = new EnduserAttributesCapturer(); - capturer.setEnduserIdEnabled(CommonConfig.get().getEnduserConfig().isIdEnabled()); - capturer.setEnduserRoleEnabled(CommonConfig.get().getEnduserConfig().isRoleEnabled()); - capturer.setEnduserScopeEnabled(CommonConfig.get().getEnduserConfig().isScopeEnabled()); + capturer.setEnduserIdEnabled(AgentCommonConfig.get().getEnduserConfig().isIdEnabled()); + capturer.setEnduserRoleEnabled(AgentCommonConfig.get().getEnduserConfig().isRoleEnabled()); + capturer.setEnduserScopeEnabled(AgentCommonConfig.get().getEnduserConfig().isScopeEnabled()); String rolePrefix = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getString( "otel.instrumentation.spring-security.enduser.role.granted-authority-prefix"); if (rolePrefix != null) { @@ -35,7 +35,7 @@ private static EnduserAttributesCapturer createEndUserAttributesCapturerFromConf } String scopePrefix = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getString( "otel.instrumentation.spring-security.enduser.scope.granted-authority-prefix"); if (scopePrefix != null) { diff --git a/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/servlet/SpringSecurityConfigServletInstrumentationModule.java b/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/servlet/SpringSecurityConfigServletInstrumentationModule.java index 6e87a1ba17ca..926bd6d94103 100644 --- a/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/servlet/SpringSecurityConfigServletInstrumentationModule.java +++ b/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/servlet/SpringSecurityConfigServletInstrumentationModule.java @@ -9,7 +9,7 @@ import static java.util.Collections.singletonList; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -33,7 +33,7 @@ public boolean defaultEnabled(ConfigProperties config) { * If any functionality not related to enduser attributes is added to this module, * then this check will need to move elsewhere to only guard the enduser attributes logic. */ - && CommonConfig.get().getEnduserConfig().isAnyEnabled(); + && AgentCommonConfig.get().getEnduserConfig().isAnyEnabled(); } @Override diff --git a/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/webflux/SpringSecurityConfigWebFluxInstrumentationModule.java b/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/webflux/SpringSecurityConfigWebFluxInstrumentationModule.java index a219a7eccbd3..4293e2b26d5d 100644 --- a/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/webflux/SpringSecurityConfigWebFluxInstrumentationModule.java +++ b/instrumentation/spring/spring-security-config-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/security/config/v6_0/webflux/SpringSecurityConfigWebFluxInstrumentationModule.java @@ -8,7 +8,7 @@ import static java.util.Collections.singletonList; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -32,7 +32,7 @@ public boolean defaultEnabled(ConfigProperties config) { * If any functionality not related to enduser attributes is added to this module, * then this check will need to move elsewhere to only guard the enduser attributes logic. */ - && CommonConfig.get().getEnduserConfig().isAnyEnabled(); + && AgentCommonConfig.get().getEnduserConfig().isAnyEnabled(); } @Override diff --git a/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/SpringWebTelemetryBuilder.java b/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/SpringWebTelemetryBuilder.java index 20fae270a2ea..3eab8e96bf61 100644 --- a/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/SpringWebTelemetryBuilder.java +++ b/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/SpringWebTelemetryBuilder.java @@ -7,19 +7,11 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import java.util.ArrayList; +import io.opentelemetry.instrumentation.spring.web.v3_1.internal.WebTelemetryUtil; import java.util.List; import java.util.Set; import java.util.function.Function; @@ -29,21 +21,21 @@ /** A builder of {@link SpringWebTelemetry}. */ public final class SpringWebTelemetryBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-web-3.1"; + private final DefaultHttpClientInstrumenterBuilder builder; - private final OpenTelemetry openTelemetry; - private final List> additionalExtractors = - new ArrayList<>(); - private final HttpClientAttributesExtractorBuilder - httpAttributesExtractorBuilder = - HttpClientAttributesExtractor.builder(SpringWebHttpAttributesGetter.INSTANCE); - private final HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(SpringWebHttpAttributesGetter.INSTANCE); - private Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer = Function.identity(); - private boolean emitExperimentalHttpClientMetrics = false; + static { + WebTelemetryUtil.setBuilderExtractor(SpringWebTelemetryBuilder::getBuilder); + } SpringWebTelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + builder = + new DefaultHttpClientInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, SpringWebHttpAttributesGetter.INSTANCE) + .setHeaderSetter(HttpRequestSetter.INSTANCE); + } + + private DefaultHttpClientInstrumenterBuilder getBuilder() { + return builder; } /** @@ -51,9 +43,9 @@ public final class SpringWebTelemetryBuilder { * items. */ @CanIgnoreReturnValue - public SpringWebTelemetryBuilder addAttributesExtractor( - AttributesExtractor attributesExtractor) { - additionalExtractors.add(attributesExtractor); + public SpringWebTelemetryBuilder addAttributeExtractor( + AttributesExtractor attributesExtractor) { + builder.addAttributeExtractor(attributesExtractor); return this; } @@ -64,7 +56,7 @@ public SpringWebTelemetryBuilder addAttributesExtractor( */ @CanIgnoreReturnValue public SpringWebTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { - httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders); + builder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -75,7 +67,7 @@ public SpringWebTelemetryBuilder setCapturedRequestHeaders(List requestH */ @CanIgnoreReturnValue public SpringWebTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { - httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders); + builder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -83,8 +75,8 @@ public SpringWebTelemetryBuilder setCapturedResponseHeaders(List respons @CanIgnoreReturnValue public SpringWebTelemetryBuilder setSpanNameExtractor( Function, ? extends SpanNameExtractor> - spanNameExtractor) { - this.spanNameExtractorTransformer = spanNameExtractor; + spanNameExtractorTransformer) { + builder.setSpanNameExtractor(spanNameExtractorTransformer); return this; } @@ -103,8 +95,7 @@ public SpringWebTelemetryBuilder setSpanNameExtractor( */ @CanIgnoreReturnValue public SpringWebTelemetryBuilder setKnownMethods(Set knownMethods) { - httpAttributesExtractorBuilder.setKnownMethods(knownMethods); - httpSpanNameExtractorBuilder.setKnownMethods(knownMethods); + builder.setKnownMethods(knownMethods); return this; } @@ -117,7 +108,7 @@ public SpringWebTelemetryBuilder setKnownMethods(Set knownMethods) { @CanIgnoreReturnValue public SpringWebTelemetryBuilder setEmitExperimentalHttpClientMetrics( boolean emitExperimentalHttpClientMetrics) { - this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; + builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics); return this; } @@ -126,25 +117,6 @@ public SpringWebTelemetryBuilder setEmitExperimentalHttpClientMetrics( * SpringWebTelemetryBuilder}. */ public SpringWebTelemetry build() { - SpringWebHttpAttributesGetter httpAttributesGetter = SpringWebHttpAttributesGetter.INSTANCE; - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(httpAttributesExtractorBuilder.build()) - .addAttributesExtractors(additionalExtractors) - .addOperationMetrics(HttpClientMetrics.get()); - if (emitExperimentalHttpClientMetrics) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - - Instrumenter instrumenter = - builder.buildClientInstrumenter(HttpRequestSetter.INSTANCE); - return new SpringWebTelemetry(instrumenter); + return new SpringWebTelemetry(builder.build()); } } diff --git a/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/internal/WebTelemetryUtil.java b/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/internal/WebTelemetryUtil.java new file mode 100644 index 000000000000..443fdc86585e --- /dev/null +++ b/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/internal/WebTelemetryUtil.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.web.v3_1.internal; + +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetryBuilder; +import java.util.function.Function; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpResponse; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class WebTelemetryUtil { + private WebTelemetryUtil() {} + + // allows access to the private field for the spring starter + private static Function< + SpringWebTelemetryBuilder, + DefaultHttpClientInstrumenterBuilder> + builderExtractor; + + public static Function< + SpringWebTelemetryBuilder, + DefaultHttpClientInstrumenterBuilder> + getBuilderExtractor() { + return builderExtractor; + } + + public static void setBuilderExtractor( + Function< + SpringWebTelemetryBuilder, + DefaultHttpClientInstrumenterBuilder> + builderExtractor) { + WebTelemetryUtil.builderExtractor = builderExtractor; + } +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/SpringWebfluxConfig.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/SpringWebfluxConfig.java index 51035617c316..02c0cff4588f 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/SpringWebfluxConfig.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/SpringWebfluxConfig.java @@ -5,12 +5,12 @@ package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class SpringWebfluxConfig { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.spring-webflux.experimental-span-attributes", false); public static boolean captureExperimentalSpanAttributes() { diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/client/WebClientHelper.java b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/client/WebClientHelper.java index b5bd239c1388..99ee1a3f9273 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/client/WebClientHelper.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webflux/v5_0/client/WebClientHelper.java @@ -5,17 +5,12 @@ package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.client; -import static java.util.Collections.singletonList; - import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.ClientInstrumenterFactory; import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.WebClientHttpAttributesGetter; import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.WebClientTracingFilter; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import java.util.List; -import java.util.function.Function; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.ExchangeFilterFunction; @@ -23,20 +18,8 @@ public final class WebClientHelper { private static final Instrumenter instrumenter = - ClientInstrumenterFactory.create( - GlobalOpenTelemetry.get(), - builder -> - builder - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - Function.identity(), - singletonList( - HttpClientPeerServiceAttributesExtractor.create( - WebClientHttpAttributesGetter.INSTANCE, - CommonConfig.get().getPeerServiceResolver())), - CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + JavaagentHttpClientInstrumenters.create( + "io.opentelemetry.spring-webflux-5.0", WebClientHttpAttributesGetter.INSTANCE); public static void addFilter(List exchangeFilterFunctions) { for (ExchangeFilterFunction filterFunction : exchangeFilterFunctions) { diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetryBuilder.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetryBuilder.java index a24930d01695..e8387880cd32 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetryBuilder.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetryBuilder.java @@ -7,26 +7,16 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.ClientInstrumenterFactory; -import java.util.ArrayList; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.SpringWebfluxBuilderUtil; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.WebClientHttpAttributesGetter; import java.util.List; import java.util.Set; -import java.util.function.Consumer; import java.util.function.Function; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientResponse; @@ -36,38 +26,25 @@ public final class SpringWebfluxTelemetryBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webflux-5.3"; - private final OpenTelemetry openTelemetry; + private final DefaultHttpClientInstrumenterBuilder clientBuilder; + private final DefaultHttpServerInstrumenterBuilder + serverBuilder; - private final List> - clientAdditionalExtractors = new ArrayList<>(); - private final List> - serverAdditionalExtractors = new ArrayList<>(); - - private final HttpServerAttributesExtractorBuilder - httpServerAttributesExtractorBuilder = - HttpServerAttributesExtractor.builder(WebfluxServerHttpAttributesGetter.INSTANCE); - private final HttpSpanNameExtractorBuilder httpServerSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(WebfluxServerHttpAttributesGetter.INSTANCE); - private final HttpServerRouteBuilder httpServerRouteBuilder = - HttpServerRoute.builder(WebfluxServerHttpAttributesGetter.INSTANCE); - - private Function< - SpanNameExtractor, ? extends SpanNameExtractor> - clientSpanNameExtractorTransformer = Function.identity(); - private Function< - SpanNameExtractor, - ? extends SpanNameExtractor> - serverSpanNameExtractorTransformer = Function.identity(); - - private Consumer> - clientExtractorConfigurer = builder -> {}; - private Consumer> clientSpanNameExtractorConfigurer = - builder -> {}; - private boolean emitExperimentalHttpClientTelemetry = false; - private boolean emitExperimentalHttpServerTelemetry = false; + static { + SpringWebfluxBuilderUtil.setClientBuilderExtractor( + SpringWebfluxTelemetryBuilder::getClientBuilder); + SpringWebfluxBuilderUtil.setServerBuilderExtractor( + SpringWebfluxTelemetryBuilder::getServerBuilder); + } SpringWebfluxTelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + clientBuilder = + new DefaultHttpClientInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, WebClientHttpAttributesGetter.INSTANCE); + serverBuilder = + new DefaultHttpServerInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, WebfluxServerHttpAttributesGetter.INSTANCE) + .setHeaderGetter(WebfluxTextMapGetter.INSTANCE); } /** @@ -77,7 +54,7 @@ public final class SpringWebfluxTelemetryBuilder { @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder addClientAttributesExtractor( AttributesExtractor attributesExtractor) { - clientAdditionalExtractors.add(attributesExtractor); + clientBuilder.addAttributeExtractor(attributesExtractor); return this; } @@ -89,9 +66,7 @@ public SpringWebfluxTelemetryBuilder addClientAttributesExtractor( @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setCapturedClientRequestHeaders( List requestHeaders) { - clientExtractorConfigurer = - clientExtractorConfigurer.andThen( - builder -> builder.setCapturedRequestHeaders(requestHeaders)); + clientBuilder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -103,9 +78,7 @@ public SpringWebfluxTelemetryBuilder setCapturedClientRequestHeaders( @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setCapturedClientResponseHeaders( List responseHeaders) { - clientExtractorConfigurer = - clientExtractorConfigurer.andThen( - builder -> builder.setCapturedResponseHeaders(responseHeaders)); + clientBuilder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -116,7 +89,7 @@ public SpringWebfluxTelemetryBuilder setCapturedClientResponseHeaders( @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder addServerAttributesExtractor( AttributesExtractor attributesExtractor) { - serverAdditionalExtractors.add(attributesExtractor); + serverBuilder.addAttributesExtractor(attributesExtractor); return this; } @@ -129,7 +102,7 @@ public SpringWebfluxTelemetryBuilder addServerAttributesExtractor( @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setCapturedServerRequestHeaders( List requestHeaders) { - httpServerAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders); + serverBuilder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -142,7 +115,7 @@ public SpringWebfluxTelemetryBuilder setCapturedServerRequestHeaders( @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setCapturedServerResponseHeaders( List responseHeaders) { - httpServerAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders); + serverBuilder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -162,13 +135,8 @@ public SpringWebfluxTelemetryBuilder setCapturedServerResponseHeaders( */ @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setKnownMethods(Set knownMethods) { - clientExtractorConfigurer = - clientExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); - clientSpanNameExtractorConfigurer = - clientSpanNameExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); - httpServerAttributesExtractorBuilder.setKnownMethods(knownMethods); - httpServerSpanNameExtractorBuilder.setKnownMethods(knownMethods); - httpServerRouteBuilder.setKnownMethods(knownMethods); + clientBuilder.setKnownMethods(knownMethods); + serverBuilder.setKnownMethods(knownMethods); return this; } @@ -181,7 +149,7 @@ public SpringWebfluxTelemetryBuilder setKnownMethods(Set knownMethods) { @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpClientTelemetry( boolean emitExperimentalHttpClientTelemetry) { - this.emitExperimentalHttpClientTelemetry = emitExperimentalHttpClientTelemetry; + clientBuilder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientTelemetry); return this; } @@ -194,7 +162,7 @@ public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpClientTelemetry( @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpServerTelemetry( boolean emitExperimentalHttpServerTelemetry) { - this.emitExperimentalHttpServerTelemetry = emitExperimentalHttpServerTelemetry; + serverBuilder.setEmitExperimentalHttpServerMetrics(emitExperimentalHttpServerTelemetry); return this; } @@ -203,7 +171,7 @@ public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpServerTelemetry( public SpringWebfluxTelemetryBuilder setClientSpanNameExtractor( Function, ? extends SpanNameExtractor> clientSpanNameExtractor) { - this.clientSpanNameExtractorTransformer = clientSpanNameExtractor; + clientBuilder.setSpanNameExtractor(clientSpanNameExtractor); return this; } @@ -214,7 +182,7 @@ public SpringWebfluxTelemetryBuilder setServerSpanNameExtractor( SpanNameExtractor, ? extends SpanNameExtractor> serverSpanNameExtractor) { - this.serverSpanNameExtractorTransformer = serverSpanNameExtractor; + serverBuilder.setSpanNameExtractor(serverSpanNameExtractor); return this; } @@ -223,40 +191,18 @@ public SpringWebfluxTelemetryBuilder setServerSpanNameExtractor( * SpringWebfluxTelemetryBuilder}. */ public SpringWebfluxTelemetry build() { - Instrumenter clientInstrumenter = - ClientInstrumenterFactory.create( - openTelemetry, - clientExtractorConfigurer, - clientSpanNameExtractorConfigurer, - clientSpanNameExtractorTransformer, - clientAdditionalExtractors, - emitExperimentalHttpClientTelemetry); - - Instrumenter serverInstrumenter = - buildServerInstrumenter(); - return new SpringWebfluxTelemetry( - clientInstrumenter, serverInstrumenter, openTelemetry.getPropagators()); + clientBuilder.build(), + serverBuilder.build(), + clientBuilder.getOpenTelemetry().getPropagators()); } - private Instrumenter buildServerInstrumenter() { - WebfluxServerHttpAttributesGetter getter = WebfluxServerHttpAttributesGetter.INSTANCE; - SpanNameExtractor spanNameExtractor = - serverSpanNameExtractorTransformer.apply(httpServerSpanNameExtractorBuilder.build()); + private DefaultHttpClientInstrumenterBuilder getClientBuilder() { + return clientBuilder; + } - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(getter)) - .addAttributesExtractor(httpServerAttributesExtractorBuilder.build()) - .addAttributesExtractors(serverAdditionalExtractors) - .addContextCustomizer(httpServerRouteBuilder.build()) - .addOperationMetrics(HttpServerMetrics.get()); - if (emitExperimentalHttpServerTelemetry) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(getter)) - .addOperationMetrics(HttpServerExperimentalMetrics.get()); - } - return builder.buildServerInstrumenter(WebfluxTextMapGetter.INSTANCE); + private DefaultHttpServerInstrumenterBuilder + getServerBuilder() { + return serverBuilder; } } diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/ClientInstrumenterFactory.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/ClientInstrumenterFactory.java deleted file mode 100644 index bb8217539da3..000000000000 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/ClientInstrumenterFactory.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.spring.webflux.v5_3.internal; - -import static io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor.alwaysClient; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import org.springframework.web.reactive.function.client.ClientRequest; -import org.springframework.web.reactive.function.client.ClientResponse; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -// client builder is separate so that it can be used by javaagent instrumentation -// which supports 5.0, without triggering the server instrumentation which depends on webflux 5.3 -public final class ClientInstrumenterFactory { - - private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webflux-5.3"; - - public static Instrumenter create( - OpenTelemetry openTelemetry, - Consumer> - extractorConfigurer, - Consumer> spanNameExtractorConfigurer, - Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer, - List> additionalExtractors, - boolean emitExperimentalHttpClientTelemetry) { - - WebClientHttpAttributesGetter httpAttributesGetter = WebClientHttpAttributesGetter.INSTANCE; - - HttpClientAttributesExtractorBuilder extractorBuilder = - HttpClientAttributesExtractor.builder(httpAttributesGetter); - extractorConfigurer.accept(extractorBuilder); - - HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(httpAttributesGetter); - spanNameExtractorConfigurer.accept(httpSpanNameExtractorBuilder); - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder clientBuilder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(extractorBuilder.build()) - .addAttributesExtractors(additionalExtractors) - .addOperationMetrics(HttpClientMetrics.get()); - - if (emitExperimentalHttpClientTelemetry) { - clientBuilder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - - // headers are injected elsewhere; ClientRequest is immutable - return clientBuilder.buildInstrumenter(alwaysClient()); - } - - private ClientInstrumenterFactory() {} -} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/SpringWebfluxBuilderUtil.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/SpringWebfluxBuilderUtil.java new file mode 100644 index 000000000000..ec1d643b1d88 --- /dev/null +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/SpringWebfluxBuilderUtil.java @@ -0,0 +1,64 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.v5_3.internal; + +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetryBuilder; +import java.util.function.Function; +import org.springframework.web.reactive.function.client.ClientRequest; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.server.ServerWebExchange; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class SpringWebfluxBuilderUtil { + private SpringWebfluxBuilderUtil() {} + + // allows access to the private field for the spring starter + private static Function< + SpringWebfluxTelemetryBuilder, + DefaultHttpClientInstrumenterBuilder> + clientBuilderExtractor; + + // allows access to the private field for the spring starter + private static Function< + SpringWebfluxTelemetryBuilder, + DefaultHttpServerInstrumenterBuilder> + serverBuilderExtractor; + + public static Function< + SpringWebfluxTelemetryBuilder, + DefaultHttpServerInstrumenterBuilder> + getServerBuilderExtractor() { + return serverBuilderExtractor; + } + + public static void setServerBuilderExtractor( + Function< + SpringWebfluxTelemetryBuilder, + DefaultHttpServerInstrumenterBuilder> + serverBuilderExtractor) { + SpringWebfluxBuilderUtil.serverBuilderExtractor = serverBuilderExtractor; + } + + public static Function< + SpringWebfluxTelemetryBuilder, + DefaultHttpClientInstrumenterBuilder> + getClientBuilderExtractor() { + return clientBuilderExtractor; + } + + public static void setClientBuilderExtractor( + Function< + SpringWebfluxTelemetryBuilder, + DefaultHttpClientInstrumenterBuilder> + clientBuilderExtractor) { + SpringWebfluxBuilderUtil.clientBuilderExtractor = clientBuilderExtractor; + } +} diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/SpringWebMvcTelemetryBuilder.java b/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/SpringWebMvcTelemetryBuilder.java index 67a3a000b3ae..588263aff6e6 100644 --- a/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/SpringWebMvcTelemetryBuilder.java +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/SpringWebMvcTelemetryBuilder.java @@ -7,21 +7,11 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import java.util.ArrayList; +import io.opentelemetry.instrumentation.spring.webmvc.v5_3.internal.SpringMvcBuilderUtil; import java.util.List; import java.util.Set; import java.util.function.Function; @@ -33,24 +23,18 @@ public final class SpringWebMvcTelemetryBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webmvc-5.3"; - private final OpenTelemetry openTelemetry; - private final List> - additionalExtractors = new ArrayList<>(); - private final HttpServerAttributesExtractorBuilder - httpAttributesExtractorBuilder = - HttpServerAttributesExtractor.builder(SpringWebMvcHttpAttributesGetter.INSTANCE); - private final HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(SpringWebMvcHttpAttributesGetter.INSTANCE); - private final HttpServerRouteBuilder httpServerRouteBuilder = - HttpServerRoute.builder(SpringWebMvcHttpAttributesGetter.INSTANCE); - private Function< - SpanNameExtractor, - ? extends SpanNameExtractor> - spanNameExtractorTransformer = Function.identity(); - private boolean emitExperimentalHttpServerMetrics = false; + private final DefaultHttpServerInstrumenterBuilder + builder; + + static { + SpringMvcBuilderUtil.setBuilderExtractor(SpringWebMvcTelemetryBuilder::getBuilder); + } SpringWebMvcTelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + builder = + new DefaultHttpServerInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, SpringWebMvcHttpAttributesGetter.INSTANCE) + .setHeaderGetter(JavaxHttpServletRequestGetter.INSTANCE); } /** @@ -60,7 +44,7 @@ public final class SpringWebMvcTelemetryBuilder { @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder addAttributesExtractor( AttributesExtractor attributesExtractor) { - additionalExtractors.add(attributesExtractor); + builder.addAttributesExtractor(attributesExtractor); return this; } @@ -71,7 +55,7 @@ public SpringWebMvcTelemetryBuilder addAttributesExtractor( */ @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { - httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders); + builder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -82,7 +66,7 @@ public SpringWebMvcTelemetryBuilder setCapturedRequestHeaders(List reque */ @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { - httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders); + builder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -93,7 +77,7 @@ public SpringWebMvcTelemetryBuilder setSpanNameExtractor( SpanNameExtractor, ? extends SpanNameExtractor> spanNameExtractor) { - this.spanNameExtractorTransformer = spanNameExtractor; + builder.setSpanNameExtractor(spanNameExtractor); return this; } @@ -112,9 +96,7 @@ public SpringWebMvcTelemetryBuilder setSpanNameExtractor( */ @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder setKnownMethods(Set knownMethods) { - httpAttributesExtractorBuilder.setKnownMethods(knownMethods); - httpSpanNameExtractorBuilder.setKnownMethods(knownMethods); - httpServerRouteBuilder.setKnownMethods(knownMethods); + builder.setKnownMethods(knownMethods); return this; } @@ -127,7 +109,7 @@ public SpringWebMvcTelemetryBuilder setKnownMethods(Set knownMethods) { @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder setEmitExperimentalHttpServerMetrics( boolean emitExperimentalHttpServerMetrics) { - this.emitExperimentalHttpServerMetrics = emitExperimentalHttpServerMetrics; + builder.setEmitExperimentalHttpServerMetrics(emitExperimentalHttpServerMetrics); return this; } @@ -136,26 +118,11 @@ public SpringWebMvcTelemetryBuilder setEmitExperimentalHttpServerMetrics( * SpringWebMvcTelemetryBuilder}. */ public SpringWebMvcTelemetry build() { - SpringWebMvcHttpAttributesGetter httpAttributesGetter = - SpringWebMvcHttpAttributesGetter.INSTANCE; - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(httpAttributesExtractorBuilder.build()) - .addAttributesExtractors(additionalExtractors) - .addContextCustomizer(httpServerRouteBuilder.build()) - .addOperationMetrics(HttpServerMetrics.get()); - if (emitExperimentalHttpServerMetrics) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpServerExperimentalMetrics.get()); - } + return new SpringWebMvcTelemetry(builder.build()); + } - return new SpringWebMvcTelemetry( - builder.buildServerInstrumenter(JavaxHttpServletRequestGetter.INSTANCE)); + public DefaultHttpServerInstrumenterBuilder + getBuilder() { + return builder; } } diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/internal/SpringMvcBuilderUtil.java b/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/internal/SpringMvcBuilderUtil.java new file mode 100644 index 000000000000..74ac99e33d8a --- /dev/null +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/internal/SpringMvcBuilderUtil.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webmvc.v5_3.internal; + +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; +import io.opentelemetry.instrumentation.spring.webmvc.v5_3.SpringWebMvcTelemetryBuilder; +import java.util.function.Function; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class SpringMvcBuilderUtil { + private SpringMvcBuilderUtil() {} + + // allows access to the private field for the spring starter + private static Function< + SpringWebMvcTelemetryBuilder, + DefaultHttpServerInstrumenterBuilder> + builderExtractor; + + public static Function< + SpringWebMvcTelemetryBuilder, + DefaultHttpServerInstrumenterBuilder> + getBuilderExtractor() { + return builderExtractor; + } + + public static void setBuilderExtractor( + Function< + SpringWebMvcTelemetryBuilder, + DefaultHttpServerInstrumenterBuilder> + builderExtractor) { + SpringMvcBuilderUtil.builderExtractor = builderExtractor; + } +} diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/SpringWebMvcTelemetryBuilder.java b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/SpringWebMvcTelemetryBuilder.java index 9b3e3b9e4e48..7978664dd053 100644 --- a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/SpringWebMvcTelemetryBuilder.java +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/SpringWebMvcTelemetryBuilder.java @@ -7,23 +7,13 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; -import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; +import io.opentelemetry.instrumentation.spring.webmvc.v6_0.internal.SpringMvcBuilderUtil; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Function; @@ -32,25 +22,18 @@ public final class SpringWebMvcTelemetryBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webmvc-6.0"; + private final DefaultHttpServerInstrumenterBuilder + builder; - private final OpenTelemetry openTelemetry; - private final List> - additionalExtractors = new ArrayList<>(); - private final HttpServerAttributesExtractorBuilder - httpAttributesExtractorBuilder = - HttpServerAttributesExtractor.builder(SpringWebMvcHttpAttributesGetter.INSTANCE); - private final HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(SpringWebMvcHttpAttributesGetter.INSTANCE); - private final HttpServerRouteBuilder httpServerRouteBuilder = - HttpServerRoute.builder(SpringWebMvcHttpAttributesGetter.INSTANCE); - private Function< - SpanNameExtractor, - ? extends SpanNameExtractor> - spanNameExtractorTransformer = Function.identity(); - private boolean emitExperimentalHttpServerMetrics = false; + static { + SpringMvcBuilderUtil.setBuilderExtractor(SpringWebMvcTelemetryBuilder::getBuilder); + } SpringWebMvcTelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + builder = + new DefaultHttpServerInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, SpringWebMvcHttpAttributesGetter.INSTANCE) + .setHeaderGetter(JakartaHttpServletRequestGetter.INSTANCE); } /** @@ -60,7 +43,7 @@ public final class SpringWebMvcTelemetryBuilder { @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder addAttributesExtractor( AttributesExtractor attributesExtractor) { - additionalExtractors.add(attributesExtractor); + builder.addAttributesExtractor(attributesExtractor); return this; } @@ -71,7 +54,7 @@ public SpringWebMvcTelemetryBuilder addAttributesExtractor( */ @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { - httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders); + builder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -82,7 +65,7 @@ public SpringWebMvcTelemetryBuilder setCapturedRequestHeaders(List reque */ @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { - httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders); + builder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -93,7 +76,7 @@ public SpringWebMvcTelemetryBuilder setSpanNameExtractor( SpanNameExtractor, ? extends SpanNameExtractor> spanNameExtractor) { - this.spanNameExtractorTransformer = spanNameExtractor; + builder.setSpanNameExtractor(spanNameExtractor); return this; } @@ -112,9 +95,7 @@ public SpringWebMvcTelemetryBuilder setSpanNameExtractor( */ @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder setKnownMethods(Set knownMethods) { - httpAttributesExtractorBuilder.setKnownMethods(knownMethods); - httpSpanNameExtractorBuilder.setKnownMethods(knownMethods); - httpServerRouteBuilder.setKnownMethods(knownMethods); + builder.setKnownMethods(knownMethods); return this; } @@ -127,7 +108,7 @@ public SpringWebMvcTelemetryBuilder setKnownMethods(Set knownMethods) { @CanIgnoreReturnValue public SpringWebMvcTelemetryBuilder setEmitExperimentalHttpServerMetrics( boolean emitExperimentalHttpServerMetrics) { - this.emitExperimentalHttpServerMetrics = emitExperimentalHttpServerMetrics; + builder.setEmitExperimentalHttpServerMetrics(emitExperimentalHttpServerMetrics); return this; } @@ -136,26 +117,11 @@ public SpringWebMvcTelemetryBuilder setEmitExperimentalHttpServerMetrics( * SpringWebMvcTelemetryBuilder}. */ public SpringWebMvcTelemetry build() { - SpringWebMvcHttpAttributesGetter httpAttributesGetter = - SpringWebMvcHttpAttributesGetter.INSTANCE; - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(httpAttributesExtractorBuilder.build()) - .addAttributesExtractors(additionalExtractors) - .addContextCustomizer(httpServerRouteBuilder.build()) - .addOperationMetrics(HttpServerMetrics.get()); - if (emitExperimentalHttpServerMetrics) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpServerExperimentalMetrics.get()); - } + return new SpringWebMvcTelemetry(builder.build()); + } - return new SpringWebMvcTelemetry( - builder.buildServerInstrumenter(JakartaHttpServletRequestGetter.INSTANCE)); + public DefaultHttpServerInstrumenterBuilder + getBuilder() { + return builder; } } diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/internal/SpringMvcBuilderUtil.java b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/internal/SpringMvcBuilderUtil.java new file mode 100644 index 000000000000..d60102acd19a --- /dev/null +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/internal/SpringMvcBuilderUtil.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webmvc.v6_0.internal; + +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; +import io.opentelemetry.instrumentation.spring.webmvc.v6_0.SpringWebMvcTelemetryBuilder; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.function.Function; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class SpringMvcBuilderUtil { + private SpringMvcBuilderUtil() {} + + // allows access to the private field for the spring starter + private static Function< + SpringWebMvcTelemetryBuilder, + DefaultHttpServerInstrumenterBuilder> + builderExtractor; + + public static Function< + SpringWebMvcTelemetryBuilder, + DefaultHttpServerInstrumenterBuilder> + getBuilderExtractor() { + return builderExtractor; + } + + public static void setBuilderExtractor( + Function< + SpringWebMvcTelemetryBuilder, + DefaultHttpServerInstrumenterBuilder> + builderExtractor) { + SpringMvcBuilderUtil.builderExtractor = builderExtractor; + } +} diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webmvc/ModelAndViewAttributesExtractor.java b/instrumentation/spring/spring-webmvc/spring-webmvc-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webmvc/ModelAndViewAttributesExtractor.java index ccfe2f8844b3..1dcece6a87d9 100644 --- a/instrumentation/spring/spring-webmvc/spring-webmvc-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webmvc/ModelAndViewAttributesExtractor.java +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/webmvc/ModelAndViewAttributesExtractor.java @@ -8,7 +8,7 @@ import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import javax.annotation.Nullable; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; @@ -16,7 +16,7 @@ public class ModelAndViewAttributesExtractor implements AttributesExtractor { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.spring-webmvc.experimental-span-attributes", false); @Override diff --git a/instrumentation/spring/starters/spring-boot-starter/build.gradle.kts b/instrumentation/spring/starters/spring-boot-starter/build.gradle.kts index 83bc9b8f7c0b..849d7f26ca69 100644 --- a/instrumentation/spring/starters/spring-boot-starter/build.gradle.kts +++ b/instrumentation/spring/starters/spring-boot-starter/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("otel.java-conventions") id("otel.publish-conventions") + id("otel.japicmp-conventions") } group = "io.opentelemetry.instrumentation" @@ -11,7 +12,6 @@ dependencies { compileOnly("org.springframework.boot:spring-boot-starter:$springBootVersion") compileOnly("org.springframework.boot:spring-boot-starter-aop:$springBootVersion") api(project(":instrumentation:spring:spring-boot-autoconfigure")) - api(project(":instrumentation:spring:spring-boot-autoconfigure-3")) api(project(":instrumentation-annotations")) implementation(project(":instrumentation:resources:library")) implementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") @@ -23,4 +23,5 @@ dependencies { implementation("io.opentelemetry.contrib:opentelemetry-aws-resources") implementation("io.opentelemetry.contrib:opentelemetry-gcp-resources") + implementation("io.opentelemetry.contrib:opentelemetry-baggage-processor") } diff --git a/instrumentation/spring/starters/spring-boot-starter/gradle.properties b/instrumentation/spring/starters/spring-boot-starter/gradle.properties new file mode 100644 index 000000000000..45d64bec279d --- /dev/null +++ b/instrumentation/spring/starters/spring-boot-starter/gradle.properties @@ -0,0 +1 @@ +otel.stable=true diff --git a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/CompletionListener.java b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/CompletionListener.java index b83d15fc373a..b045a961be82 100644 --- a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/CompletionListener.java +++ b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/CompletionListener.java @@ -9,14 +9,14 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; public abstract class CompletionListener { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.spymemcached.experimental-span-attributes", false); private static final String DB_COMMAND_CANCELLED = "spymemcached.command.cancelled"; diff --git a/instrumentation/tomcat/tomcat-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/v10_0/Tomcat10InstrumentationModule.java b/instrumentation/tomcat/tomcat-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/v10_0/Tomcat10InstrumentationModule.java index 818438826715..0341609b0f1e 100644 --- a/instrumentation/tomcat/tomcat-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/v10_0/Tomcat10InstrumentationModule.java +++ b/instrumentation/tomcat/tomcat-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/v10_0/Tomcat10InstrumentationModule.java @@ -25,7 +25,13 @@ public Tomcat10InstrumentationModule() { @Override public ElementMatcher.Junction classLoaderMatcher() { // only matches tomcat 10.0+ - return hasClassesNamed("jakarta.servlet.http.HttpServletRequest"); + return hasClassesNamed("jakarta.servlet.http.HttpServletRequest") + .and( + // tomcat 10 has at least one of these two classes. Cache$EvictionOrder is present in + // 10.0.0, but is removed before 10.1.0. GenericUser is added before Cache$EvictionOrder + // is removed + hasClassesNamed("org.apache.catalina.users.GenericUser") + .or(hasClassesNamed("org.apache.catalina.webresources.Cache$EvictionOrder"))); } @Override diff --git a/instrumentation/tomcat/tomcat-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/tomcat/v10_0/TomcatAsyncTest.java b/instrumentation/tomcat/tomcat-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/tomcat/v10_0/TomcatAsyncTest.java index e8863716d47e..651308f9634b 100644 --- a/instrumentation/tomcat/tomcat-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/tomcat/v10_0/TomcatAsyncTest.java +++ b/instrumentation/tomcat/tomcat-10.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/tomcat/v10_0/TomcatAsyncTest.java @@ -113,10 +113,6 @@ protected void configure(HttpServerTestOptions options) { options.setExpectedException(new ServletException(EXCEPTION.getBody())); options.setHasResponseSpan(endpoint -> endpoint == NOT_FOUND || endpoint == REDIRECT); - - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - options.setMetricsInstrumentationName(() -> "io.opentelemetry.servlet-5.0"); } @Override diff --git a/instrumentation/tomcat/tomcat-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/v7_0/Tomcat7InstrumentationModule.java b/instrumentation/tomcat/tomcat-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/v7_0/Tomcat7InstrumentationModule.java index 2750dce8bea9..04e9c7a004c2 100644 --- a/instrumentation/tomcat/tomcat-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/v7_0/Tomcat7InstrumentationModule.java +++ b/instrumentation/tomcat/tomcat-7.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/v7_0/Tomcat7InstrumentationModule.java @@ -25,7 +25,8 @@ public Tomcat7InstrumentationModule() { @Override public ElementMatcher.Junction classLoaderMatcher() { // does not match tomcat 10.0+ - return hasClassesNamed("javax.servlet.http.HttpServletRequest"); + return hasClassesNamed( + "javax.servlet.http.HttpServletRequest", "org.apache.catalina.loader.Constants"); } @Override diff --git a/instrumentation/tomcat/tomcat-7.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/tomcat/v7_0/TomcatAsyncTest.java b/instrumentation/tomcat/tomcat-7.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/tomcat/v7_0/TomcatAsyncTest.java index a249300a5689..3e779cd3ef0e 100644 --- a/instrumentation/tomcat/tomcat-7.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/tomcat/v7_0/TomcatAsyncTest.java +++ b/instrumentation/tomcat/tomcat-7.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/tomcat/v7_0/TomcatAsyncTest.java @@ -108,10 +108,6 @@ protected void configure(HttpServerTestOptions options) { options.setExpectedException(new ServletException(EXCEPTION.getBody())); options.setHasResponseSpan(endpoint -> endpoint == NOT_FOUND || endpoint == REDIRECT); - - // with async requests the span is started in one instrumentation (server instrumentation) - // but ended from another (servlet instrumentation) - options.setMetricsInstrumentationName(() -> "io.opentelemetry.servlet-3.0"); } @Override diff --git a/instrumentation/tomcat/tomcat-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/common/TomcatInstrumenterFactory.java b/instrumentation/tomcat/tomcat-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/common/TomcatInstrumenterFactory.java index 816adf7cdb16..b89d70bc77d3 100644 --- a/instrumentation/tomcat/tomcat-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/common/TomcatInstrumenterFactory.java +++ b/instrumentation/tomcat/tomcat-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/common/TomcatInstrumenterFactory.java @@ -10,12 +10,13 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge; import io.opentelemetry.javaagent.instrumentation.servlet.ServletAccessor; import io.opentelemetry.javaagent.instrumentation.servlet.ServletErrorCauseExtractor; @@ -35,19 +36,19 @@ public static Instrumenter create( GlobalOpenTelemetry.get(), instrumentationName, HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) .setErrorCauseExtractor(new ServletErrorCauseExtractor<>(accessor)) .addAttributesExtractor( HttpServerAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addContextCustomizer( HttpServerRoute.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addContextCustomizer( (context, request, attributes) -> @@ -56,11 +57,12 @@ public static Instrumenter create( .recordException() .init(context)) .addOperationMetrics(HttpServerMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { + if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { builder .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) .addOperationMetrics(HttpServerExperimentalMetrics.get()); } + InstrumenterUtil.propagateOperationListenersToOnEnd(builder); return builder.buildServerInstrumenter(TomcatRequestGetter.INSTANCE); } } diff --git a/instrumentation/twilio-6.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioSingletons.java b/instrumentation/twilio-6.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioSingletons.java index d47fdd2c60a1..3c6b3296e125 100644 --- a/instrumentation/twilio-6.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioSingletons.java +++ b/instrumentation/twilio-6.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/twilio/TwilioSingletons.java @@ -11,12 +11,12 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.util.SpanNames; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class TwilioSingletons { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.twilio.experimental-span-attributes", false); private static final Instrumenter INSTRUMENTER; diff --git a/instrumentation/undertow-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/undertow/UndertowSingletons.java b/instrumentation/undertow-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/undertow/UndertowSingletons.java index 0e75d616048b..cb4e9007afab 100644 --- a/instrumentation/undertow-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/undertow/UndertowSingletons.java +++ b/instrumentation/undertow-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/undertow/UndertowSingletons.java @@ -15,7 +15,7 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge; import io.opentelemetry.javaagent.bootstrap.undertow.UndertowActiveHandlers; import io.undertow.server.HttpServerExchange; @@ -33,18 +33,18 @@ public final class UndertowSingletons { GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) .addAttributesExtractor( HttpServerAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getServerRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getServerResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setCapturedRequestHeaders(AgentCommonConfig.get().getServerRequestHeaders()) + .setCapturedResponseHeaders(AgentCommonConfig.get().getServerResponseHeaders()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addContextCustomizer( HttpServerRoute.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) + .setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()) .build()) .addContextCustomizer( (context, request, attributes) -> { @@ -58,7 +58,7 @@ public final class UndertowSingletons { .init(context); }) .addOperationMetrics(HttpServerMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { + if (AgentCommonConfig.get().shouldEmitExperimentalHttpServerTelemetry()) { builder .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) .addOperationMetrics(HttpServerExperimentalMetrics.get()); diff --git a/instrumentation/vertx/vertx-http-client/vertx-http-client-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/client/VertxClientInstrumenterFactory.java b/instrumentation/vertx/vertx-http-client/vertx-http-client-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/client/VertxClientInstrumenterFactory.java index 7817020fa808..5f4801f43e13 100644 --- a/instrumentation/vertx/vertx-http-client/vertx-http-client-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/client/VertxClientInstrumenterFactory.java +++ b/instrumentation/vertx/vertx-http-client/vertx-http-client-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/client/VertxClientInstrumenterFactory.java @@ -5,17 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.vertx.client; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import io.vertx.core.http.HttpClientRequest; import io.vertx.core.http.HttpClientResponse; @@ -24,31 +15,8 @@ public final class VertxClientInstrumenterFactory { public static Instrumenter create( String instrumentationName, AbstractVertxHttpAttributesGetter httpAttributesGetter) { - InstrumenterBuilder builder = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - instrumentationName, - HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor( - HttpClientAttributesExtractor.builder(httpAttributesGetter) - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()) - .build()) - .addAttributesExtractor( - HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, CommonConfig.get().getPeerServiceResolver())) - .addOperationMetrics(HttpClientMetrics.get()); - if (CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - - return builder.buildClientInstrumenter(new HttpRequestHeaderSetter()); + return JavaagentHttpClientInstrumenters.create( + instrumentationName, httpAttributesGetter, new HttpRequestHeaderSetter()); } private VertxClientInstrumenterFactory() {} diff --git a/instrumentation/vertx/vertx-kafka-client-3.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/kafka/v3_6/VertxKafkaSingletons.java b/instrumentation/vertx/vertx-kafka-client-3.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/kafka/v3_6/VertxKafkaSingletons.java index 5b09afb40110..afdfe735b92b 100644 --- a/instrumentation/vertx/vertx-kafka-client-3.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/kafka/v3_6/VertxKafkaSingletons.java +++ b/instrumentation/vertx/vertx-kafka-client-3.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/kafka/v3_6/VertxKafkaSingletons.java @@ -10,8 +10,8 @@ import io.opentelemetry.instrumentation.kafka.internal.KafkaInstrumenterFactory; import io.opentelemetry.instrumentation.kafka.internal.KafkaProcessRequest; import io.opentelemetry.instrumentation.kafka.internal.KafkaReceiveRequest; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; public final class VertxKafkaSingletons { @@ -25,7 +25,7 @@ public final class VertxKafkaSingletons { new KafkaInstrumenterFactory(GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME) .setCapturedHeaders(ExperimentalConfig.get().getMessagingHeaders()) .setCaptureExperimentalSpanAttributes( - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.kafka.experimental-span-attributes", false)) .setMessagingReceiveInstrumentationEnabled( ExperimentalConfig.get().messagingReceiveInstrumentationEnabled()); diff --git a/instrumentation/vertx/vertx-kafka-client-3.6/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/kafka/v3_6/AbstractVertxKafkaTest.java b/instrumentation/vertx/vertx-kafka-client-3.6/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/kafka/v3_6/AbstractVertxKafkaTest.java index 2fdacdf5f531..59d3b0bbe28f 100644 --- a/instrumentation/vertx/vertx-kafka-client-3.6/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/kafka/v3_6/AbstractVertxKafkaTest.java +++ b/instrumentation/vertx/vertx-kafka-client-3.6/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/kafka/v3_6/AbstractVertxKafkaTest.java @@ -61,7 +61,7 @@ public abstract class AbstractVertxKafkaTest { @BeforeAll static void setUpAll() { kafka = - new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.10")) + new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.7.0")) .withEnv("KAFKA_HEAP_OPTS", "-Xmx256m") .withLogConsumer(new Slf4jLogConsumer(logger)) .waitingFor(Wait.forLogMessage(".*started \\(kafka.server.KafkaServer\\).*", 1)) diff --git a/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientAttributesGetter.java b/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientAttributesGetter.java index da2cb4f6cf94..d662aa053ad6 100644 --- a/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientAttributesGetter.java +++ b/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientAttributesGetter.java @@ -7,7 +7,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter; import io.opentelemetry.instrumentation.api.incubator.semconv.db.RedisCommandSanitizer; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; @@ -16,7 +16,7 @@ public enum VertxRedisClientAttributesGetter INSTANCE; private static final RedisCommandSanitizer sanitizer = - RedisCommandSanitizer.create(CommonConfig.get().isStatementSanitizationEnabled()); + RedisCommandSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); @Override public String getSystem(VertxRedisClientRequest request) { diff --git a/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientSingletons.java b/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientSingletons.java index 090966f719ad..b5164522897c 100644 --- a/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientSingletons.java +++ b/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientSingletons.java @@ -18,7 +18,7 @@ import io.opentelemetry.instrumentation.api.semconv.network.NetworkAttributesExtractor; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; import io.opentelemetry.instrumentation.api.util.VirtualField; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.vertx.core.Future; import io.vertx.redis.client.Command; import io.vertx.redis.client.impl.RedisStandaloneConnection; @@ -52,7 +52,7 @@ public final class VertxRedisClientSingletons { .addAttributesExtractor( PeerServiceAttributesExtractor.create( VertxRedisClientNetAttributesGetter.INSTANCE, - CommonConfig.get().getPeerServiceResolver())); + AgentCommonConfig.get().getPeerServiceResolver())); INSTRUMENTER = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientSingletons.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientSingletons.java index 0167c7d9d28a..a77338e5c811 100644 --- a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientSingletons.java +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientSingletons.java @@ -17,7 +17,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; import io.opentelemetry.instrumentation.api.util.VirtualField; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.vertx.core.Future; import io.vertx.core.Promise; import io.vertx.sqlclient.SqlConnectOptions; @@ -40,14 +40,14 @@ public final class VertxSqlClientSingletons { .addAttributesExtractor( SqlClientAttributesExtractor.builder(VertxSqlClientAttributesGetter.INSTANCE) .setStatementSanitizationEnabled( - CommonConfig.get().isStatementSanitizationEnabled()) + AgentCommonConfig.get().isStatementSanitizationEnabled()) .build()) .addAttributesExtractor( ServerAttributesExtractor.create(VertxSqlClientNetAttributesGetter.INSTANCE)) .addAttributesExtractor( PeerServiceAttributesExtractor.create( VertxSqlClientNetAttributesGetter.INSTANCE, - CommonConfig.get().getPeerServiceResolver())); + AgentCommonConfig.get().getPeerServiceResolver())); INSTRUMENTER = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/xxl-job/xxl-job-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/xxljob/common/XxlJobInstrumenterFactory.java b/instrumentation/xxl-job/xxl-job-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/xxljob/common/XxlJobInstrumenterFactory.java index 4a5f713808e2..1544504bdac6 100644 --- a/instrumentation/xxl-job/xxl-job-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/xxljob/common/XxlJobInstrumenterFactory.java +++ b/instrumentation/xxl-job/xxl-job-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/xxljob/common/XxlJobInstrumenterFactory.java @@ -12,12 +12,12 @@ import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; public final class XxlJobInstrumenterFactory { private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.xxl-job.experimental-span-attributes", false); public static Instrumenter create(String instrumentationName) { diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/AgentCommonConfig.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/AgentCommonConfig.java new file mode 100644 index 000000000000..e5ee4b396871 --- /dev/null +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/AgentCommonConfig.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.bootstrap.internal; + +import io.opentelemetry.instrumentation.api.incubator.config.internal.CommonConfig; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class AgentCommonConfig { + private AgentCommonConfig() {} + + private static final CommonConfig instance = new CommonConfig(AgentInstrumentationConfig.get()); + + public static CommonConfig get() { + return instance; + } +} diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/AgentInstrumentationConfig.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/AgentInstrumentationConfig.java new file mode 100644 index 000000000000..081050ef76ac --- /dev/null +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/AgentInstrumentationConfig.java @@ -0,0 +1,47 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.bootstrap.internal; + +import static java.util.Objects.requireNonNull; + +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import java.util.logging.Logger; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class AgentInstrumentationConfig { + private AgentInstrumentationConfig() {} + + private static final Logger logger = Logger.getLogger(AgentInstrumentationConfig.class.getName()); + + private static final InstrumentationConfig DEFAULT = new EmptyInstrumentationConfig(); + + // lazy initialized, so that javaagent can set it + private static volatile InstrumentationConfig instance = DEFAULT; + + /** + * Sets the instrumentation configuration singleton. This method is only supposed to be called + * once, during the agent initialization, just before {@link AgentInstrumentationConfig#get()} is + * used for the first time. + * + *

This method is internal and is hence not for public use. Its API is unstable and can change + * at any time. + */ + public static void internalInitializeConfig(InstrumentationConfig config) { + if (instance != DEFAULT) { + logger.warning("InstrumentationConfig#instance was already set earlier"); + return; + } + instance = requireNonNull(config); + } + + /** Returns the global instrumentation configuration. */ + public static InstrumentationConfig get() { + return instance; + } +} diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ConfiguredResourceAttributesHolder.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ConfiguredResourceAttributesHolder.java index 77f2e7ac16fb..ea7c51ff436f 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ConfiguredResourceAttributesHolder.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ConfiguredResourceAttributesHolder.java @@ -28,7 +28,7 @@ public static Map getResourceAttributes() { public static void initialize(Attributes resourceAttribute) { List mdcResourceAttributes = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getList( "otel.instrumentation.common.mdc.resource-attributes", Collections.emptyList()); for (String key : mdcResourceAttributes) { diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/DeprecatedConfigProperties.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/DeprecatedConfigProperties.java index 002bf787c99c..2709a6ab0ea2 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/DeprecatedConfigProperties.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/DeprecatedConfigProperties.java @@ -8,6 +8,7 @@ import static java.util.Collections.emptyList; import static java.util.logging.Level.WARNING; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import java.util.List; import java.util.logging.Logger; diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EmptyInstrumentationConfig.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EmptyInstrumentationConfig.java index ede916b3b6ad..303931c5b674 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EmptyInstrumentationConfig.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/EmptyInstrumentationConfig.java @@ -5,12 +5,13 @@ package io.opentelemetry.javaagent.bootstrap.internal; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import java.time.Duration; import java.util.List; import java.util.Map; import javax.annotation.Nullable; -final class EmptyInstrumentationConfig extends InstrumentationConfig { +final class EmptyInstrumentationConfig implements InstrumentationConfig { @Nullable @Override diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ExperimentalConfig.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ExperimentalConfig.java index fe3779ab2550..736229de4ecb 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ExperimentalConfig.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/ExperimentalConfig.java @@ -7,6 +7,7 @@ import static java.util.Collections.emptyList; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import java.util.List; /** @@ -16,7 +17,7 @@ public final class ExperimentalConfig { private static final ExperimentalConfig instance = - new ExperimentalConfig(InstrumentationConfig.get()); + new ExperimentalConfig(AgentInstrumentationConfig.get()); private final InstrumentationConfig config; private final List messagingHeaders; diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/JavaagentHttpClientInstrumenters.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/JavaagentHttpClientInstrumenters.java new file mode 100644 index 000000000000..e7331c550fff --- /dev/null +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/bootstrap/internal/JavaagentHttpClientInstrumenters.java @@ -0,0 +1,64 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.bootstrap.internal; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.context.propagation.TextMapSetter; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; +import java.util.function.Consumer; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class JavaagentHttpClientInstrumenters { + + private JavaagentHttpClientInstrumenters() {} + + public static Instrumenter create( + String instrumentationName, + HttpClientAttributesGetter httpAttributesGetter) { + return create(instrumentationName, httpAttributesGetter, null); + } + + public static Instrumenter create( + String instrumentationName, + HttpClientAttributesGetter httpAttributesGetter, + TextMapSetter headerSetter) { + return create(instrumentationName, httpAttributesGetter, headerSetter, b -> {}); + } + + public static Instrumenter create( + DefaultHttpClientInstrumenterBuilder builder) { + return create(builder, customizer -> {}); + } + + public static Instrumenter create( + String instrumentationName, + HttpClientAttributesGetter httpAttributesGetter, + TextMapSetter headerSetter, + Consumer> instrumenterBuilderConsumer) { + DefaultHttpClientInstrumenterBuilder defaultHttpClientTelemetryBuilder = + new DefaultHttpClientInstrumenterBuilder<>( + instrumentationName, GlobalOpenTelemetry.get(), httpAttributesGetter); + if (headerSetter != null) { + defaultHttpClientTelemetryBuilder.setHeaderSetter(headerSetter); + } + return create(defaultHttpClientTelemetryBuilder, instrumenterBuilderConsumer); + } + + private static Instrumenter create( + DefaultHttpClientInstrumenterBuilder builder, + Consumer> builderCustomizer) { + return builder + .configure(AgentCommonConfig.get()) + .setBuilderCustomizer(builderCustomizer) + .build(); + } +} diff --git a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/InstrumentationModule.java b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/InstrumentationModule.java index 9d8bb78b8200..7f404090b679 100644 --- a/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/InstrumentationModule.java +++ b/javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/InstrumentationModule.java @@ -49,6 +49,10 @@ public abstract class InstrumentationModule implements Ordered { * InstrumentationModule} must have a default constructor (for SPI), so they have to pass the * instrumentation names to the super class constructor. * + *

When enabling or disabling the instrumentation module configuration property that + * corresponds to the main instrumentation name is considered first, after that additional + * instrumentation names are considered in the order they are listed here. + * *

The instrumentation names should follow several rules: * *

    diff --git a/javaagent-internal-logging-simple/build.gradle.kts b/javaagent-internal-logging-simple/build.gradle.kts index 125653c86421..b87f59ec43cf 100644 --- a/javaagent-internal-logging-simple/build.gradle.kts +++ b/javaagent-internal-logging-simple/build.gradle.kts @@ -3,8 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id("otel.java-conventions") id("otel.publish-conventions") - - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") } group = "io.opentelemetry.javaagent" diff --git a/javaagent-tooling/build.gradle.kts b/javaagent-tooling/build.gradle.kts index 850f4382fe17..1f318ac0f203 100644 --- a/javaagent-tooling/build.gradle.kts +++ b/javaagent-tooling/build.gradle.kts @@ -13,6 +13,7 @@ dependencies { implementation(project(":javaagent-extension-api")) implementation(project(":javaagent-tooling:javaagent-tooling-java9")) implementation(project(":instrumentation-api")) + implementation(project(":instrumentation-api-incubator")) implementation(project(":instrumentation-annotations-support")) implementation(project(":muzzle")) implementation(project(":sdk-autoconfigure-support")) @@ -42,6 +43,7 @@ dependencies { implementation("io.opentelemetry.contrib:opentelemetry-aws-resources") implementation("io.opentelemetry.contrib:opentelemetry-gcp-resources") + implementation("io.opentelemetry.contrib:opentelemetry-baggage-processor") api("net.bytebuddy:byte-buddy-dep") implementation("org.ow2.asm:asm-tree") diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java index 19d06f834f2e..54c6938c96d9 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java @@ -26,8 +26,8 @@ import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizer; import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizerHolder; import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseMutator; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.bootstrap.internal.ConfiguredResourceAttributesHolder; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; import io.opentelemetry.javaagent.extension.AgentListener; import io.opentelemetry.javaagent.extension.ignore.IgnoredTypesConfigurer; import io.opentelemetry.javaagent.tooling.asyncannotationsupport.WeakRefAsyncOperationEndStrategies; @@ -122,7 +122,7 @@ private static void installBytebuddyAgent( installOpenTelemetrySdk(extensionClassLoader); ConfigProperties sdkConfig = AutoConfigureUtil.getConfig(autoConfiguredSdk); - InstrumentationConfig.internalInitializeConfig(new ConfigPropertiesBridge(sdkConfig)); + AgentInstrumentationConfig.internalInitializeConfig(new ConfigPropertiesBridge(sdkConfig)); copyNecessaryConfigToSystemProperties(sdkConfig); setBootstrapPackages(sdkConfig, extensionClassLoader); diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/AgentConfig.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/AgentConfig.java index 3077b56536c0..66ac96401612 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/AgentConfig.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/AgentConfig.java @@ -11,20 +11,14 @@ public final class AgentConfig { public static boolean isInstrumentationEnabled( ConfigProperties config, Iterable instrumentationNames, boolean defaultEnabled) { - // If default is enabled, we want to enable individually, - // if default is disabled, we want to disable individually. - boolean anyEnabled = defaultEnabled; for (String name : instrumentationNames) { String propertyName = "otel.instrumentation." + name + ".enabled"; - boolean enabled = config.getBoolean(propertyName, defaultEnabled); - - if (defaultEnabled) { - anyEnabled &= enabled; - } else { - anyEnabled |= enabled; + Boolean enabled = config.getBoolean(propertyName); + if (enabled != null) { + return enabled; } } - return anyEnabled; + return defaultEnabled; } public static boolean isDebugModeEnabled(ConfigProperties config) { diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigPropertiesBridge.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigPropertiesBridge.java index c690921de4a8..de6b3baca6b3 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigPropertiesBridge.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigPropertiesBridge.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.tooling.config; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import java.time.Duration; @@ -13,7 +13,7 @@ import java.util.Map; import javax.annotation.Nullable; -public final class ConfigPropertiesBridge extends InstrumentationConfig { +public final class ConfigPropertiesBridge implements InstrumentationConfig { private final ConfigProperties configProperties; diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/field/FieldBackedImplementationInstaller.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/field/FieldBackedImplementationInstaller.java index 3a2f065769fe..5c1e69063fd3 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/field/FieldBackedImplementationInstaller.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/field/FieldBackedImplementationInstaller.java @@ -14,7 +14,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder; import io.opentelemetry.javaagent.bootstrap.VirtualFieldDetector; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import io.opentelemetry.javaagent.tooling.HelperInjector; import io.opentelemetry.javaagent.tooling.TransformSafeLogger; import io.opentelemetry.javaagent.tooling.instrumentation.InstrumentationModuleInstaller; @@ -64,7 +64,7 @@ final class FieldBackedImplementationInstaller implements VirtualFieldImplementa TransformSafeLogger.getLogger(FieldBackedImplementationInstaller.class); private static final boolean FIELD_INJECTION_ENABLED = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.javaagent.experimental.field-injection.enabled", true); private final Class instrumenterClass; diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/GlobalIgnoredTypesConfigurer.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/GlobalIgnoredTypesConfigurer.java index 12a178a5c7ce..9abe23ce5f50 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/GlobalIgnoredTypesConfigurer.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/GlobalIgnoredTypesConfigurer.java @@ -125,6 +125,7 @@ private static void configureIgnoredClassLoaders(IgnoredTypesBuilder builder) { .ignoreClassLoader("org.openjdk.nashorn.internal.runtime.ScriptLoader") .ignoreClassLoader("org.codehaus.janino.ByteArrayClassLoader") .ignoreClassLoader("org.eclipse.persistence.internal.jaxb.JaxbClassLoader") + .ignoreClassLoader("com.alibaba.fastjson.util.ASMClassLoader") .ignoreClassLoader(AgentClassLoader.class.getName()) .ignoreClassLoader(ExtensionClassLoader.class.getName()) .ignoreClassLoader(InstrumentationModuleClassLoader.class.getName()); diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/AdviceSignatureEraser.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/AdviceSignatureEraser.java new file mode 100644 index 000000000000..429b93d11e1e --- /dev/null +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/AdviceSignatureEraser.java @@ -0,0 +1,106 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.instrumentation.indy; + +import io.opentelemetry.javaagent.extension.instrumentation.internal.AsmApi; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.tree.ClassNode; + +/** + * This transformer is a workaround to make the life of instrumentation developers easier. + * + *

    When inserting the instrumentation and calling the advice enter/exit methods, we insert an + * invokedynamic instruction to perform this method call. This instruction has a {@link + * java.lang.invoke.MethodType} associated, which normally corresponds to the method type of the + * called advice. This can however lead to problems, when the advice method signature contains types + * which are not visible to the instrumented class. + * + *

    To prevent this, we instead associate the invokedynamic instruction with a type where all + * class reference are replaced with references to {@link Object}. To lookup the correct advice + * method, we pass the original type as string argument to the invokedynamic bootstrapping method. + * + *

    Because bytebuddy currently doesn't support this customization, we perform the type erasure on + * the .class via ASM before bytebuddy parses the advice. In addition, we insert an annotation to + * preserve the original descriptor of the method. + */ +// TODO: replace this workaround when buddy natively supports altering the MethodType for +// invokedynamic advices +class AdviceSignatureEraser { + + private static final Pattern TYPE_REFERENCE_PATTERN = Pattern.compile("L[^;]+;"); + + public static final String ORIGNINAL_DESCRIPTOR_ANNOTATION_TYPE = + "L" + OriginalDescriptor.class.getName().replace('.', '/') + ";"; + + private AdviceSignatureEraser() {} + + static byte[] transform(byte[] bytes) { + ClassReader cr = new ClassReader(bytes); + ClassWriter cw = new ClassWriter(cr, 0); + ClassNode classNode = new ClassNode(); + cr.accept(classNode, 0); + + Set methodsToTransform = listAdviceMethods(classNode); + if (methodsToTransform.isEmpty()) { + return bytes; + } + + ClassVisitor cv = + new ClassVisitor(AsmApi.VERSION, cw) { + @Override + public MethodVisitor visitMethod( + int access, String name, String descriptor, String signature, String[] exceptions) { + if (methodsToTransform.contains(name + descriptor)) { + String erased = eraseTypes(descriptor); + MethodVisitor visitor = super.visitMethod(access, name, erased, null, exceptions); + AnnotationVisitor av = + visitor.visitAnnotation(ORIGNINAL_DESCRIPTOR_ANNOTATION_TYPE, false); + av.visit("value", descriptor); + av.visitEnd(); + return visitor; + } else { + return super.visitMethod(access, name, descriptor, signature, exceptions); + } + } + }; + classNode.accept(cv); + return cw.toByteArray(); + } + + private static String eraseTypes(String descriptor) { + Matcher matcher = TYPE_REFERENCE_PATTERN.matcher(descriptor); + StringBuffer result = new StringBuffer(); + while (matcher.find()) { + String reference = matcher.group(); + if (reference.startsWith("Ljava/")) { + // do not erase java.* references + matcher.appendReplacement(result, reference); + } else { + matcher.appendReplacement(result, "Ljava/lang/Object;"); + } + } + matcher.appendTail(result); + return result.toString(); + } + + private static Set listAdviceMethods(ClassNode classNode) { + return classNode.methods.stream() + .filter( + mn -> + AdviceTransformer.hasAnnotation(mn, AdviceTransformer.ADVICE_ON_METHOD_ENTER) + || AdviceTransformer.hasAnnotation(mn, AdviceTransformer.ADVICE_ON_METHOD_EXIT)) + .map(mn -> mn.name + mn.desc) + .collect(Collectors.toSet()); + } +} diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/AdviceTransformer.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/AdviceTransformer.java index e71ba5b7874d..ac1f46a99e3a 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/AdviceTransformer.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/AdviceTransformer.java @@ -50,6 +50,10 @@ static byte[] transform(byte[] bytes) { return cw.toByteArray(); } + // Advices already using Advice.AssignReturned are assumed to be already compatible + // Those won't be transformed except for setting inline to false + boolean justDelegateAdvice = usesAssignReturned(classNode); + // sort enter advice method before exit advice classNode.methods.sort( Comparator.comparingInt( @@ -74,8 +78,12 @@ public MethodVisitor visitMethod( @Override public void visitEnd() { super.visitEnd(); - - instrument(context, this, classVisitor); + if (justDelegateAdvice) { + applyAdviceDelegation( + context, this, classVisitor, exceptions.toArray(new String[0])); + } else { + instrument(context, this, classVisitor); + } } }; } @@ -225,13 +233,37 @@ private static List getLocals(MethodNode source) { return result; } - private static final Type ADVICE_ON_METHOD_ENTER = Type.getType(Advice.OnMethodEnter.class); + static final Type ADVICE_ON_METHOD_ENTER = Type.getType(Advice.OnMethodEnter.class); + private static final Type ADVICE_ASSIGN_RETURNED_TO_RETURNED = + Type.getType(Advice.AssignReturned.ToReturned.class); + private static final Type ADVICE_ASSIGN_RETURNED_TO_ARGUMENTS = + Type.getType(Advice.AssignReturned.ToArguments.class); + private static final Type ADVICE_ASSIGN_RETURNED_TO_FIELDS = + Type.getType(Advice.AssignReturned.ToFields.class); + private static final Type ADVICE_ASSIGN_RETURNED_TO_ALL_ARGUMENTS = + Type.getType(Advice.AssignReturned.ToAllArguments.class); + + private static boolean usesAssignReturned(MethodNode source) { + return hasAnnotation(source, ADVICE_ASSIGN_RETURNED_TO_RETURNED) + || hasAnnotation(source, ADVICE_ASSIGN_RETURNED_TO_ARGUMENTS) + || hasAnnotation(source, ADVICE_ASSIGN_RETURNED_TO_FIELDS) + || hasAnnotation(source, ADVICE_ASSIGN_RETURNED_TO_ALL_ARGUMENTS); + } + + private static boolean usesAssignReturned(ClassNode classNode) { + for (MethodNode mn : classNode.methods) { + if (usesAssignReturned(mn)) { + return true; + } + } + return false; + } private static boolean isEnterAdvice(MethodNode source) { return hasAnnotation(source, ADVICE_ON_METHOD_ENTER); } - private static final Type ADVICE_ON_METHOD_EXIT = Type.getType(Advice.OnMethodExit.class); + static final Type ADVICE_ON_METHOD_EXIT = Type.getType(Advice.OnMethodExit.class); private static boolean isExitAdvice(MethodNode source) { return hasAnnotation(source, ADVICE_ON_METHOD_EXIT); @@ -250,7 +282,7 @@ private static AnnotationNode getAnnotationNode(MethodNode source, Type type) { return null; } - private static boolean hasAnnotation(MethodNode source, Type type) { + static boolean hasAnnotation(MethodNode source, Type type) { return getAnnotationNode(source, type) != null; } @@ -656,6 +688,14 @@ private static void instrument( } } + applyAdviceDelegation(context, methodNode, classVisitor, exceptionsArray); + } + + private static void applyAdviceDelegation( + TransformationContext context, + MethodNode methodNode, + ClassVisitor classVisitor, + String[] exceptionsArray) { MethodVisitor mv = classVisitor.visitMethod( methodNode.access, diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/IndyBootstrap.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/IndyBootstrap.java index 9e23725cf8d3..3ec6d531138d 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/IndyBootstrap.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/IndyBootstrap.java @@ -20,6 +20,8 @@ import java.util.logging.Logger; import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.annotation.AnnotationDescription; +import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.utility.JavaConstant; /** @@ -131,7 +133,12 @@ private static ConstantCallSite internalBootstrap( case BOOTSTRAP_KIND_ADVICE: // See the getAdviceBootstrapArguments method for the argument definitions return bootstrapAdvice( - lookup, adviceMethodName, adviceMethodType, (String) args[1], (String) args[2]); + lookup, + adviceMethodName, + adviceMethodType, + (String) args[1], + (String) args[2], + (String) args[3]); case BOOTSTRAP_KIND_PROXY: // See getProxyFactory for the argument definitions return bootstrapProxyMethod( @@ -153,8 +160,9 @@ private static ConstantCallSite internalBootstrap( private static ConstantCallSite bootstrapAdvice( MethodHandles.Lookup lookup, String adviceMethodName, - MethodType adviceMethodType, + MethodType invokedynamicMethodType, String moduleClassName, + String adviceMethodDescriptor, String adviceClassName) throws NoSuchMethodException, IllegalAccessException, ClassNotFoundException { CallDepth callDepth = CallDepth.forClass(IndyBootstrap.class); @@ -177,10 +185,14 @@ private static ConstantCallSite bootstrapAdvice( // Advices are not inlined. They are loaded as normal classes by the // InstrumentationModuleClassloader and invoked via a method call from the instrumented method Class adviceClass = instrumentationClassloader.loadClass(adviceClassName); + MethodType actualAdviceMethodType = + MethodType.fromMethodDescriptorString(adviceMethodDescriptor, instrumentationClassloader); + MethodHandle methodHandle = instrumentationClassloader .getLookup() - .findStatic(adviceClass, adviceMethodName, adviceMethodType); + .findStatic(adviceClass, adviceMethodName, actualAdviceMethodType) + .asType(invokedynamicMethodType); return new ConstantCallSite(methodHandle); } finally { callDepth.decrementAndGet(); @@ -195,9 +207,19 @@ static Advice.BootstrapArgumentResolver.Factory getAdviceBootstrapArguments( Arrays.asList( JavaConstant.Simple.ofLoaded(BOOTSTRAP_KIND_ADVICE), JavaConstant.Simple.ofLoaded(moduleName), + JavaConstant.Simple.ofLoaded(getOriginalSignature(adviceMethod)), JavaConstant.Simple.ofLoaded(adviceMethod.getDeclaringType().getName())); } + private static String getOriginalSignature(MethodDescription.InDefinedShape adviceMethod) { + for (AnnotationDescription an : adviceMethod.getDeclaredAnnotations()) { + if (OriginalDescriptor.class.getName().equals(an.getAnnotationType().getName())) { + return (String) an.getValue("value").resolve(); + } + } + throw new IllegalStateException("OriginalSignature annotation is not present!"); + } + private static ConstantCallSite bootstrapProxyMethod( MethodHandles.Lookup lookup, String proxyMethodName, diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/IndyTypeTransformerImpl.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/IndyTypeTransformerImpl.java index 2c51be92aac6..e78ab79236fd 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/IndyTypeTransformerImpl.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/IndyTypeTransformerImpl.java @@ -101,9 +101,11 @@ public byte[] resolve() { if (result != null) { dump(name, result); InstrumentationModuleClassLoader.bytecodeOverride.put(name.replace('/', '.'), result); - return result; + } else { + result = bytes; } - return bytes; + result = AdviceSignatureEraser.transform(result); + return result; } } diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/OriginalDescriptor.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/OriginalDescriptor.java new file mode 100644 index 000000000000..2104696965fc --- /dev/null +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/instrumentation/indy/OriginalDescriptor.java @@ -0,0 +1,10 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.instrumentation.indy; + +public @interface OriginalDescriptor { + String value(); +} diff --git a/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/config/AgentConfigTest.java b/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/config/AgentConfigTest.java index e4b36be6c51a..ab428499269d 100644 --- a/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/config/AgentConfigTest.java +++ b/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/config/AgentConfigTest.java @@ -25,16 +25,14 @@ class AgentConfigTest { @ArgumentsSource(InstrumentationEnabledParams.class) void testIsInstrumentationEnabled( @SuppressWarnings("unused") String description, - boolean firstEnabled, - boolean secondEnabled, + Boolean firstEnabled, + Boolean secondEnabled, boolean defaultEnabled, boolean expected) { ConfigProperties config = mock(ConfigProperties.class); - when(config.getBoolean("otel.instrumentation.first.enabled", defaultEnabled)) - .thenReturn(firstEnabled); - when(config.getBoolean("otel.instrumentation.second.enabled", defaultEnabled)) - .thenReturn(secondEnabled); + when(config.getBoolean("otel.instrumentation.first.enabled")).thenReturn(firstEnabled); + when(config.getBoolean("otel.instrumentation.second.enabled")).thenReturn(secondEnabled); assertEquals( expected, @@ -49,13 +47,41 @@ public Stream provideArguments(ExtensionContext context) { return Stream.of( Arguments.of( "enabled by default, both instrumentations are off", false, false, true, false), - Arguments.of("enabled by default, one instrumentation is on", true, false, true, false), + Arguments.of("enabled by default, first instrumentation is on", true, null, true, true), + Arguments.of("enabled by default, second instrumentation is on", null, true, true, true), Arguments.of("enabled by default, both instrumentations are on", true, true, true, true), + Arguments.of( + "enabled by default, first instrumentation is off, second is on", + false, + true, + true, + false), + Arguments.of( + "enabled by default, first instrumentation is on, second is off", + true, + false, + true, + true), + Arguments.of("enabled by default", null, null, true, true), Arguments.of( "disabled by default, both instrumentations are off", false, false, false, false), - Arguments.of("disabled by default, one instrumentation is on", true, false, false, true), + Arguments.of("disabled by default, first instrumentation is on", true, null, false, true), + Arguments.of( + "disabled by default, second instrumentation is on", null, true, false, true), + Arguments.of("disabled by default, both instrumentation are on", true, true, false, true), + Arguments.of( + "disabled by default, first instrumentation is off, second is on", + false, + true, + false, + false), Arguments.of( - "disabled by default, both instrumentation are on", true, true, false, true)); + "disabled by default, first instrumentation is on, second is off", + true, + false, + false, + true), + Arguments.of("disabled by default", null, null, false, false)); } } } diff --git a/javaagent/build.gradle.kts b/javaagent/build.gradle.kts index 89df36ddc9d6..ef7a6369eac0 100644 --- a/javaagent/build.gradle.kts +++ b/javaagent/build.gradle.kts @@ -2,7 +2,9 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.github.jk1.license.filter.LicenseBundleNormalizer import com.github.jk1.license.render.InventoryMarkdownReportRenderer import org.spdx.sbom.gradle.SpdxSbomTask +import java.nio.file.Files import java.util.UUID +import java.util.regex.Pattern plugins { id("com.github.jk1.dependency-license-report") @@ -240,11 +242,29 @@ tasks { delete(rootProject.file("licenses")) } + val removeLicenseDate by registering { + // removing the license report date makes it idempotent + doLast { + val filePath = rootDir.toPath().resolve("licenses").resolve("licenses.md") + if (Files.exists(filePath)) { + val datePattern = Pattern.compile("^_[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} .*_$") + val lines = Files.readAllLines(filePath) + // 4th line contains the timestamp of when the license report was generated, replace it with + // an empty line + if (lines.size > 3 && datePattern.matcher(lines[3]).matches()) { + lines[3] = "" + Files.write(filePath, lines) + } + } + } + } + val generateLicenseReportEnabled = gradle.startParameter.taskNames.any { it.equals("generateLicenseReport") } named("generateLicenseReport").configure { dependsOn(cleanLicenses) finalizedBy(":spotlessApply") + finalizedBy(removeLicenseDate) // disable licence report generation unless this task is explicitly run // the files produced by this task are used by other tasks without declaring them as dependency // which gradle considers an error diff --git a/licenses/byte-buddy-dep-1.14.17.jar/META-INF/LICENSE b/licenses/byte-buddy-dep-1.14.18.jar/META-INF/LICENSE similarity index 100% rename from licenses/byte-buddy-dep-1.14.17.jar/META-INF/LICENSE rename to licenses/byte-buddy-dep-1.14.18.jar/META-INF/LICENSE diff --git a/licenses/byte-buddy-dep-1.14.17.jar/META-INF/NOTICE b/licenses/byte-buddy-dep-1.14.18.jar/META-INF/NOTICE similarity index 100% rename from licenses/byte-buddy-dep-1.14.17.jar/META-INF/NOTICE rename to licenses/byte-buddy-dep-1.14.18.jar/META-INF/NOTICE diff --git a/licenses/jackson-annotations-2.17.1.jar/META-INF/LICENSE b/licenses/jackson-annotations-2.17.2.jar/META-INF/LICENSE similarity index 100% rename from licenses/jackson-annotations-2.17.1.jar/META-INF/LICENSE rename to licenses/jackson-annotations-2.17.2.jar/META-INF/LICENSE diff --git a/licenses/jackson-annotations-2.17.1.jar/META-INF/NOTICE b/licenses/jackson-annotations-2.17.2.jar/META-INF/NOTICE similarity index 100% rename from licenses/jackson-annotations-2.17.1.jar/META-INF/NOTICE rename to licenses/jackson-annotations-2.17.2.jar/META-INF/NOTICE diff --git a/licenses/jackson-core-2.17.1.jar/META-INF/LICENSE b/licenses/jackson-core-2.17.2.jar/META-INF/LICENSE similarity index 100% rename from licenses/jackson-core-2.17.1.jar/META-INF/LICENSE rename to licenses/jackson-core-2.17.2.jar/META-INF/LICENSE diff --git a/licenses/jackson-core-2.17.1.jar/META-INF/NOTICE b/licenses/jackson-core-2.17.2.jar/META-INF/NOTICE similarity index 100% rename from licenses/jackson-core-2.17.1.jar/META-INF/NOTICE rename to licenses/jackson-core-2.17.2.jar/META-INF/NOTICE diff --git a/licenses/jackson-databind-2.17.1.jar/META-INF/LICENSE b/licenses/jackson-databind-2.17.2.jar/META-INF/LICENSE similarity index 100% rename from licenses/jackson-databind-2.17.1.jar/META-INF/LICENSE rename to licenses/jackson-databind-2.17.2.jar/META-INF/LICENSE diff --git a/licenses/jackson-databind-2.17.1.jar/META-INF/NOTICE b/licenses/jackson-databind-2.17.2.jar/META-INF/NOTICE similarity index 100% rename from licenses/jackson-databind-2.17.1.jar/META-INF/NOTICE rename to licenses/jackson-databind-2.17.2.jar/META-INF/NOTICE diff --git a/licenses/jackson-dataformat-yaml-2.17.1.jar/META-INF/LICENSE b/licenses/jackson-dataformat-yaml-2.17.2.jar/META-INF/LICENSE similarity index 100% rename from licenses/jackson-dataformat-yaml-2.17.1.jar/META-INF/LICENSE rename to licenses/jackson-dataformat-yaml-2.17.2.jar/META-INF/LICENSE diff --git a/licenses/jackson-dataformat-yaml-2.17.1.jar/META-INF/NOTICE b/licenses/jackson-dataformat-yaml-2.17.2.jar/META-INF/NOTICE similarity index 100% rename from licenses/jackson-dataformat-yaml-2.17.1.jar/META-INF/NOTICE rename to licenses/jackson-dataformat-yaml-2.17.2.jar/META-INF/NOTICE diff --git a/licenses/licenses.md b/licenses/licenses.md index beb0de09419b..fe413be6f62e 100644 --- a/licenses/licenses.md +++ b/licenses/licenses.md @@ -1,7 +1,7 @@ # javaagent ## Dependency License Report -_2024-06-07 12:54:43 UTC_ + ## Apache License, Version 2.0 **1** **Group:** `com.blogspot.mydailyjava` **Name:** `weak-lock-free` **Version:** `0.18` @@ -9,35 +9,35 @@ _2024-06-07 12:54:43 UTC_ > - **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.17.1` +**2** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-annotations` **Version:** `2.17.2` > - **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.17.1.jar/META-INF/LICENSE](jackson-annotations-2.17.1.jar/META-INF/LICENSE) - - [jackson-annotations-2.17.1.jar/META-INF/NOTICE](jackson-annotations-2.17.1.jar/META-INF/NOTICE) +> - **Embedded license files**: [jackson-annotations-2.17.2.jar/META-INF/LICENSE](jackson-annotations-2.17.2.jar/META-INF/LICENSE) + - [jackson-annotations-2.17.2.jar/META-INF/NOTICE](jackson-annotations-2.17.2.jar/META-INF/NOTICE) -**3** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-core` **Version:** `2.17.1` +**3** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-core` **Version:** `2.17.2` > - **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.17.1.jar/META-INF/LICENSE](jackson-core-2.17.1.jar/META-INF/LICENSE) - - [jackson-core-2.17.1.jar/META-INF/NOTICE](jackson-core-2.17.1.jar/META-INF/NOTICE) +> - **Embedded license files**: [jackson-core-2.17.2.jar/META-INF/LICENSE](jackson-core-2.17.2.jar/META-INF/LICENSE) + - [jackson-core-2.17.2.jar/META-INF/NOTICE](jackson-core-2.17.2.jar/META-INF/NOTICE) -**4** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-databind` **Version:** `2.17.1` +**4** **Group:** `com.fasterxml.jackson.core` **Name:** `jackson-databind` **Version:** `2.17.2` > - **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.17.1.jar/META-INF/LICENSE](jackson-databind-2.17.1.jar/META-INF/LICENSE) - - [jackson-databind-2.17.1.jar/META-INF/NOTICE](jackson-databind-2.17.1.jar/META-INF/NOTICE) +> - **Embedded license files**: [jackson-databind-2.17.2.jar/META-INF/LICENSE](jackson-databind-2.17.2.jar/META-INF/LICENSE) + - [jackson-databind-2.17.2.jar/META-INF/NOTICE](jackson-databind-2.17.2.jar/META-INF/NOTICE) -**5** **Group:** `com.fasterxml.jackson.dataformat` **Name:** `jackson-dataformat-yaml` **Version:** `2.17.1` +**5** **Group:** `com.fasterxml.jackson.dataformat` **Name:** `jackson-dataformat-yaml` **Version:** `2.17.2` > - **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.17.1.jar/META-INF/LICENSE](jackson-dataformat-yaml-2.17.1.jar/META-INF/LICENSE) - - [jackson-dataformat-yaml-2.17.1.jar/META-INF/NOTICE](jackson-dataformat-yaml-2.17.1.jar/META-INF/NOTICE) +> - **Embedded license files**: [jackson-dataformat-yaml-2.17.2.jar/META-INF/LICENSE](jackson-dataformat-yaml-2.17.2.jar/META-INF/LICENSE) + - [jackson-dataformat-yaml-2.17.2.jar/META-INF/NOTICE](jackson-dataformat-yaml-2.17.2.jar/META-INF/NOTICE) -**6** **Group:** `com.google.cloud.opentelemetry` **Name:** `detector-resources-support` **Version:** `0.29.0` +**6** **Group:** `com.google.cloud.opentelemetry` **Name:** `detector-resources-support` **Version:** `0.31.0` > - **POM Project URL**: [https://github.com/GoogleCloudPlatform/opentelemetry-operations-java](https://github.com/GoogleCloudPlatform/opentelemetry-operations-java) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) @@ -59,264 +59,268 @@ _2024-06-07 12:54:43 UTC_ > - **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) -**11** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api` **Version:** `1.39.0` +**11** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api` **Version:** `1.40.0` > - **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-api-incubator` **Version:** `1.39.0-alpha` +**12** **Group:** `io.opentelemetry` **Name:** `opentelemetry-api-incubator` **Version:** `1.40.0-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) -**13** **Group:** `io.opentelemetry` **Name:** `opentelemetry-context` **Version:** `1.39.0` +**13** **Group:** `io.opentelemetry` **Name:** `opentelemetry-context` **Version:** `1.40.0` > - **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) -**14** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-common` **Version:** `1.39.0` +**14** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-common` **Version:** `1.40.0` > - **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.39.0` +**15** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-logging` **Version:** `1.40.0` > - **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.39.0` +**16** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-logging-otlp` **Version:** `1.40.0` > - **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.39.0` +**17** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-otlp` **Version:** `1.40.0` > - **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.39.0` +**18** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-otlp-common` **Version:** `1.40.0` > - **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.39.0-alpha` +**19** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-prometheus` **Version:** `1.40.0-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.39.0` +**20** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-sender-okhttp` **Version:** `1.40.0` > - **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.39.0` +**21** **Group:** `io.opentelemetry` **Name:** `opentelemetry-exporter-zipkin` **Version:** `1.40.0` > - **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-kotlin` **Version:** `1.39.0` +**22** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-kotlin` **Version:** `1.40.0` > - **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) -**23** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-trace-propagators` **Version:** `1.39.0` +**23** **Group:** `io.opentelemetry` **Name:** `opentelemetry-extension-trace-propagators` **Version:** `1.40.0` > - **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-sdk` **Version:** `1.39.0` +**24** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk` **Version:** `1.40.0` > - **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-common` **Version:** `1.39.0` +**25** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-common` **Version:** `1.40.0` > - **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-extension-autoconfigure` **Version:** `1.39.0` +**26** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure` **Version:** `1.40.0` > - **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-spi` **Version:** `1.39.0` +**27** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-autoconfigure-spi` **Version:** `1.40.0` > - **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-incubator` **Version:** `1.39.0-alpha` +**28** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-incubator` **Version:** `1.40.0-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) -**29** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-jaeger-remote-sampler` **Version:** `1.39.0` +**29** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-extension-jaeger-remote-sampler` **Version:** `1.40.0` > - **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-logs` **Version:** `1.39.0` +**30** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-logs` **Version:** `1.40.0` > - **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-metrics` **Version:** `1.39.0` +**31** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-metrics` **Version:** `1.40.0` > - **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-trace` **Version:** `1.39.0` +**32** **Group:** `io.opentelemetry` **Name:** `opentelemetry-sdk-trace` **Version:** `1.40.0` > - **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.contrib` **Name:** `opentelemetry-aws-resources` **Version:** `1.36.0-alpha` +**33** **Group:** `io.opentelemetry.contrib` **Name:** `opentelemetry-aws-resources` **Version:** `1.37.0-alpha` +> - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java-contrib](https://github.com/open-telemetry/opentelemetry-java-contrib) +> - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) + +**34** **Group:** `io.opentelemetry.contrib` **Name:** `opentelemetry-aws-xray-propagator` **Version:** `1.37.0-alpha` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java-contrib](https://github.com/open-telemetry/opentelemetry-java-contrib) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**34** **Group:** `io.opentelemetry.contrib` **Name:** `opentelemetry-aws-xray-propagator` **Version:** `1.36.0-alpha` +**35** **Group:** `io.opentelemetry.contrib` **Name:** `opentelemetry-baggage-processor` **Version:** `1.37.0-alpha` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java-contrib](https://github.com/open-telemetry/opentelemetry-java-contrib) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**35** **Group:** `io.opentelemetry.contrib` **Name:** `opentelemetry-gcp-resources` **Version:** `1.36.0-alpha` +**36** **Group:** `io.opentelemetry.contrib` **Name:** `opentelemetry-gcp-resources` **Version:** `1.37.0-alpha` > - **POM Project URL**: [https://github.com/open-telemetry/opentelemetry-java-contrib](https://github.com/open-telemetry/opentelemetry-java-contrib) > - **POM License**: Apache License, Version 2.0 - [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) -**36** **Group:** `io.opentelemetry.semconv` **Name:** `opentelemetry-semconv` **Version:** `1.25.0-alpha` +**37** **Group:** `io.opentelemetry.semconv` **Name:** `opentelemetry-semconv` **Version:** `1.25.0-alpha` > - **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) -**37** **Group:** `io.opentelemetry.semconv` **Name:** `opentelemetry-semconv-incubating` **Version:** `1.25.0-alpha` +**38** **Group:** `io.opentelemetry.semconv` **Name:** `opentelemetry-semconv-incubating` **Version:** `1.25.0-alpha` > - **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) -**38** **Group:** `io.prometheus` **Name:** `prometheus-metrics-config` **Version:** `1.3.1` +**39** **Group:** `io.prometheus` **Name:** `prometheus-metrics-config` **Version:** `1.3.1` > - **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-exporter-common` **Version:** `1.3.1` +**40** **Group:** `io.prometheus` **Name:** `prometheus-metrics-exporter-common` **Version:** `1.3.1` > - **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-exporter-httpserver` **Version:** `1.3.1` +**41** **Group:** `io.prometheus` **Name:** `prometheus-metrics-exporter-httpserver` **Version:** `1.3.1` > - **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-exposition-formats` **Version:** `1.3.1` +**42** **Group:** `io.prometheus` **Name:** `prometheus-metrics-exposition-formats` **Version:** `1.3.1` > - **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) -**42** **Group:** `io.prometheus` **Name:** `prometheus-metrics-model` **Version:** `1.3.1` +**43** **Group:** `io.prometheus` **Name:** `prometheus-metrics-model` **Version:** `1.3.1` > - **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) -**43** **Group:** `io.prometheus` **Name:** `prometheus-metrics-shaded-protobuf` **Version:** `1.3.1` +**44** **Group:** `io.prometheus` **Name:** `prometheus-metrics-shaded-protobuf` **Version:** `1.3.1` > - **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:** `io.zipkin.reporter2` **Name:** `zipkin-reporter` **Version:** `3.4.0` +**45** **Group:** `io.zipkin.reporter2` **Name:** `zipkin-reporter` **Version:** `3.4.0` > - **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-3.4.0.jar/META-INF/LICENSE](zipkin-reporter-3.4.0.jar/META-INF/LICENSE) -**45** **Group:** `io.zipkin.reporter2` **Name:** `zipkin-sender-okhttp3` **Version:** `3.4.0` +**46** **Group:** `io.zipkin.reporter2` **Name:** `zipkin-sender-okhttp3` **Version:** `3.4.0` > - **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-3.4.0.jar/META-INF/LICENSE](zipkin-sender-okhttp3-3.4.0.jar/META-INF/LICENSE) -**46** **Group:** `io.zipkin.zipkin2` **Name:** `zipkin` **Version:** `2.27.1` +**47** **Group:** `io.zipkin.zipkin2` **Name:** `zipkin` **Version:** `2.27.1` > - **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.27.1.jar/META-INF/LICENSE](zipkin-2.27.1.jar/META-INF/LICENSE) -**47** **Group:** `net.bytebuddy` **Name:** `byte-buddy-dep` **Version:** `1.14.17` +**48** **Group:** `net.bytebuddy` **Name:** `byte-buddy-dep` **Version:** `1.14.18` > - **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.17.jar/META-INF/LICENSE](byte-buddy-dep-1.14.17.jar/META-INF/LICENSE) - - [byte-buddy-dep-1.14.17.jar/META-INF/NOTICE](byte-buddy-dep-1.14.17.jar/META-INF/NOTICE) +> - **Embedded license files**: [byte-buddy-dep-1.14.18.jar/META-INF/LICENSE](byte-buddy-dep-1.14.18.jar/META-INF/LICENSE) + - [byte-buddy-dep-1.14.18.jar/META-INF/NOTICE](byte-buddy-dep-1.14.18.jar/META-INF/NOTICE) -**48** **Group:** `org.jetbrains` **Name:** `annotations` **Version:** `13.0` +**49** **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) -**49** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib` **Version:** `2.0.0` +**50** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib` **Version:** `2.0.0` > - **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) -**50** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib-jdk7` **Version:** `2.0.0` +**51** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib-jdk7` **Version:** `2.0.0` > - **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) -**51** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib-jdk8` **Version:** `2.0.0` +**52** **Group:** `org.jetbrains.kotlin` **Name:** `kotlin-stdlib-jdk8` **Version:** `2.0.0` > - **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) -**52** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.7` +**53** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.7` > - **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) -**53** **Group:** `org.ow2.asm` **Name:** `asm-analysis` **Version:** `9.7` +**54** **Group:** `org.ow2.asm` **Name:** `asm-analysis` **Version:** `9.7` > - **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-commons` **Version:** `9.7` +**55** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.7` > - **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-tree` **Version:** `9.7` +**56** **Group:** `org.ow2.asm` **Name:** `asm-tree` **Version:** `9.7` > - **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-util` **Version:** `9.7` +**57** **Group:** `org.ow2.asm` **Name:** `asm-util` **Version:** `9.7` > - **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.snakeyaml` **Name:** `snakeyaml-engine` **Version:** `2.7` +**58** **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) -**58** **Group:** `org.yaml` **Name:** `snakeyaml` **Version:** `2.2` +**59** **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 -**59** **Group:** `org.slf4j` **Name:** `slf4j-api` **Version:** `2.0.13` +**60** **Group:** `org.slf4j` **Name:** `slf4j-api` **Version:** `2.0.16` > - **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.13.jar/META-INF/LICENSE.txt](slf4j-api-2.0.13.jar/META-INF/LICENSE.txt) +> - **Embedded license files**: [slf4j-api-2.0.16.jar/META-INF/LICENSE.txt](slf4j-api-2.0.16.jar/META-INF/LICENSE.txt) -**60** **Group:** `org.slf4j` **Name:** `slf4j-simple` **Version:** `2.0.13` +**61** **Group:** `org.slf4j` **Name:** `slf4j-simple` **Version:** `2.0.16` > - **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.13.jar/META-INF/LICENSE.txt](slf4j-simple-2.0.13.jar/META-INF/LICENSE.txt) +> - **Embedded license files**: [slf4j-simple-2.0.16.jar/META-INF/LICENSE.txt](slf4j-simple-2.0.16.jar/META-INF/LICENSE.txt) ## The 3-Clause BSD License -**61** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.7` +**62** **Group:** `org.ow2.asm` **Name:** `asm` **Version:** `9.7` > - **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) -**62** **Group:** `org.ow2.asm` **Name:** `asm-analysis` **Version:** `9.7` +**63** **Group:** `org.ow2.asm` **Name:** `asm-analysis` **Version:** `9.7` > - **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) -**63** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.7` +**64** **Group:** `org.ow2.asm` **Name:** `asm-commons` **Version:** `9.7` > - **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) -**64** **Group:** `org.ow2.asm` **Name:** `asm-tree` **Version:** `9.7` +**65** **Group:** `org.ow2.asm` **Name:** `asm-tree` **Version:** `9.7` > - **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) -**65** **Group:** `org.ow2.asm` **Name:** `asm-util` **Version:** `9.7` +**66** **Group:** `org.ow2.asm` **Name:** `asm-util` **Version:** `9.7` > - **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/) diff --git a/licenses/slf4j-api-2.0.13.jar/META-INF/LICENSE.txt b/licenses/slf4j-api-2.0.16.jar/META-INF/LICENSE.txt similarity index 100% rename from licenses/slf4j-api-2.0.13.jar/META-INF/LICENSE.txt rename to licenses/slf4j-api-2.0.16.jar/META-INF/LICENSE.txt diff --git a/licenses/slf4j-simple-2.0.13.jar/META-INF/LICENSE.txt b/licenses/slf4j-simple-2.0.16.jar/META-INF/LICENSE.txt similarity index 100% rename from licenses/slf4j-simple-2.0.13.jar/META-INF/LICENSE.txt rename to licenses/slf4j-simple-2.0.16.jar/META-INF/LICENSE.txt diff --git a/muzzle/build.gradle.kts b/muzzle/build.gradle.kts index bd25aeff7ed8..5e8f5ff9b9f6 100644 --- a/muzzle/build.gradle.kts +++ b/muzzle/build.gradle.kts @@ -18,6 +18,7 @@ dependencies { implementation(project(":javaagent-bootstrap")) implementation(project(":instrumentation-api")) + implementation(project(":instrumentation-api-incubator")) implementation(project(":javaagent-extension-api")) // Used by byte-buddy but not brought in as a transitive dependency. diff --git a/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/AgentCachingPoolStrategy.java b/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/AgentCachingPoolStrategy.java index afc19d21511b..a9385f8bd45c 100644 --- a/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/AgentCachingPoolStrategy.java +++ b/muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/AgentCachingPoolStrategy.java @@ -9,7 +9,7 @@ import io.opentelemetry.instrumentation.api.internal.cache.Cache; import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder; import io.opentelemetry.javaagent.bootstrap.VirtualFieldAccessorMarker; -import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig; +import io.opentelemetry.javaagent.bootstrap.internal.AgentInstrumentationConfig; import java.lang.instrument.Instrumentation; import java.lang.ref.WeakReference; import java.lang.reflect.Method; @@ -53,7 +53,7 @@ public class AgentCachingPoolStrategy implements AgentBuilder.PoolStrategy { // others to avoid creation of synthetic accessors private static final boolean REFLECTION_ENABLED = - InstrumentationConfig.get() + AgentInstrumentationConfig.get() .getBoolean("otel.instrumentation.internal-reflection.enabled", true); private static final Method findLoadedClassMethod = getFindLoadedClassMethod(); diff --git a/opentelemetry-api-shaded-for-instrumenting/build.gradle.kts b/opentelemetry-api-shaded-for-instrumenting/build.gradle.kts index 47292515b076..1f188a09a255 100644 --- a/opentelemetry-api-shaded-for-instrumenting/build.gradle.kts +++ b/opentelemetry-api-shaded-for-instrumenting/build.gradle.kts @@ -1,8 +1,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/opentelemetry-ext-annotations-shaded-for-instrumenting/build.gradle.kts b/opentelemetry-ext-annotations-shaded-for-instrumenting/build.gradle.kts index d0c92d3611ba..a95aca5f8e1b 100644 --- a/opentelemetry-ext-annotations-shaded-for-instrumenting/build.gradle.kts +++ b/opentelemetry-ext-annotations-shaded-for-instrumenting/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/opentelemetry-instrumentation-annotations-shaded-for-instrumenting/build.gradle.kts b/opentelemetry-instrumentation-annotations-shaded-for-instrumenting/build.gradle.kts index 3dc29118754b..177ebb817e6d 100644 --- a/opentelemetry-instrumentation-annotations-shaded-for-instrumenting/build.gradle.kts +++ b/opentelemetry-instrumentation-annotations-shaded-for-instrumenting/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/opentelemetry-instrumentation-api-shaded-for-instrumenting/build.gradle.kts b/opentelemetry-instrumentation-api-shaded-for-instrumenting/build.gradle.kts index 64450dad1ae3..5d44310162f7 100644 --- a/opentelemetry-instrumentation-api-shaded-for-instrumenting/build.gradle.kts +++ b/opentelemetry-instrumentation-api-shaded-for-instrumenting/build.gradle.kts @@ -1,6 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/settings.gradle.kts b/settings.gradle.kts index 3410fb87758d..e728bee40217 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,7 +4,7 @@ pluginManagement { id("com.google.cloud.tools.jib") version "3.4.3" id("com.gradle.plugin-publish") version "1.2.1" id("io.github.gradle-nexus.publish-plugin") version "2.0.0" - id("org.jetbrains.kotlin.jvm") version "2.0.0" + id("org.jetbrains.kotlin.jvm") version "2.0.10" 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.10.2" @@ -12,8 +12,8 @@ pluginManagement { } plugins { - id("com.gradle.develocity") version "3.17.5" - id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.1" + id("com.gradle.develocity") version "3.17.6" + id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.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 @@ -145,6 +145,7 @@ include(":testing-common:library-for-integration-tests") // smoke tests include(":smoke-tests") +include(":smoke-tests:images:early-jdk8") include(":smoke-tests:images:fake-backend") include(":smoke-tests:images:grpc") include(":smoke-tests:images:play") @@ -222,6 +223,7 @@ include(":instrumentation:cassandra:cassandra-4.4:library") include(":instrumentation:cassandra:cassandra-4.4:testing") include(":instrumentation:cassandra:cassandra-4-common:testing") include(":instrumentation:cdi-testing") +include(":instrumentation:clickhouse-client-0.5:javaagent") include(":instrumentation:couchbase:couchbase-2.0:javaagent") include(":instrumentation:couchbase:couchbase-2.6:javaagent") include(":instrumentation:couchbase:couchbase-2-common:javaagent") @@ -302,6 +304,7 @@ include(":instrumentation:java-http-client:library") include(":instrumentation:java-http-client:testing") include(":instrumentation:java-util-logging:javaagent") include(":instrumentation:java-util-logging:shaded-stub-for-instrumenting") +include(":instrumentation:javalin-5.0:javaagent") include(":instrumentation:jaxrs:jaxrs-1.0:javaagent") include(":instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-annotations:javaagent") include(":instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-arquillian-testing") @@ -357,6 +360,9 @@ include(":instrumentation:jetty:jetty-common:javaagent") include(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:javaagent") include(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:library") include(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:testing") +include(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:javaagent") +include(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:library") +include(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:testing") include(":instrumentation:jms:jms-1.1:javaagent") include(":instrumentation:jms:jms-3.0:javaagent") include(":instrumentation:jms:jms-common:bootstrap") @@ -545,7 +551,6 @@ include(":instrumentation:spark-2.3:javaagent") include(":instrumentation:spring:spring-batch-3.0:javaagent") include(":instrumentation:spring:spring-boot-actuator-autoconfigure-2.0:javaagent") include(":instrumentation:spring:spring-boot-autoconfigure") -include(":instrumentation:spring:spring-boot-autoconfigure-3") include(":instrumentation:spring:spring-boot-resources:javaagent") include(":instrumentation:spring:spring-boot-resources:javaagent-unit-tests") include(":instrumentation:spring:spring-cloud-gateway:spring-cloud-gateway-2.0:javaagent") diff --git a/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts b/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts index 7483b76355d2..9fe628dd698b 100644 --- a/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts +++ b/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { implementation("org.apache.commons:commons-dbcp2") implementation("org.springframework.kafka:spring-kafka") implementation("org.springframework.boot:spring-boot-starter-data-mongodb") + implementation("org.springframework.boot:spring-boot-starter-aop") implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)) implementation(project(":smoke-tests-otel-starter:spring-boot-common")) diff --git a/smoke-tests-otel-starter/spring-boot-3.2/build.gradle.kts b/smoke-tests-otel-starter/spring-boot-3.2/build.gradle.kts index 502de91d64af..8b125966863b 100644 --- a/smoke-tests-otel-starter/spring-boot-3.2/build.gradle.kts +++ b/smoke-tests-otel-starter/spring-boot-3.2/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { implementation("org.apache.commons:commons-dbcp2") implementation("org.springframework.kafka:spring-kafka") implementation("org.springframework.boot:spring-boot-starter-data-mongodb") + implementation("org.springframework.boot:spring-boot-starter-aop") implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)) implementation(project(":smoke-tests-otel-starter:spring-boot-common")) diff --git a/smoke-tests-otel-starter/spring-boot-3.2/src/test/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-3.2/src/test/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java index 2fac92b2d1cf..f01bafb6e22e 100644 --- a/smoke-tests-otel-starter/spring-boot-3.2/src/test/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-3.2/src/test/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java @@ -10,7 +10,6 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.sdk.testing.assertj.TraceAssert; import io.opentelemetry.semconv.HttpAttributes; -import io.opentelemetry.semconv.UrlAttributes; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -52,14 +51,8 @@ void restClient() { private static void assertClient(TraceAssert traceAssert) { traceAssert.hasSpansSatisfyingExactly( - nestedClientSpan -> - nestedClientSpan - .hasKind(SpanKind.CLIENT) - .hasAttributesSatisfying( - a -> assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/ping")), - nestedServerSpan -> - nestedServerSpan - .hasKind(SpanKind.SERVER) - .hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping")); + span -> HttpSpanDataAssert.create(span).assertClientGetRequest("/ping"), + span -> span.hasKind(SpanKind.SERVER).hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"), + span -> withSpanAssert(span)); } } diff --git a/smoke-tests-otel-starter/spring-boot-3/build.gradle.kts b/smoke-tests-otel-starter/spring-boot-3/build.gradle.kts index a9e7e556e4f8..78e01e6685e1 100644 --- a/smoke-tests-otel-starter/spring-boot-3/build.gradle.kts +++ b/smoke-tests-otel-starter/spring-boot-3/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { implementation("org.apache.commons:commons-dbcp2") implementation("org.springframework.kafka:spring-kafka") implementation("org.springframework.boot:spring-boot-starter-data-mongodb") + implementation("org.springframework.boot:spring-boot-starter-aop") implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)) implementation(project(":smoke-tests-otel-starter:spring-boot-common")) diff --git a/smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/RuntimeHints.java b/smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/RuntimeHints.java index ab181ee823d5..85da65c58417 100644 --- a/smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/RuntimeHints.java +++ b/smoke-tests-otel-starter/spring-boot-3/src/main/java/io/opentelemetry/spring/smoketest/RuntimeHints.java @@ -24,8 +24,6 @@ public void registerHints( .registerType( TypeReference.of( "org.springframework.data.mongodb.core.aggregation.AggregationOperation"), - hint -> { - hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS); - }); + hint -> hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)); } } diff --git a/smoke-tests-otel-starter/spring-boot-common/build.gradle.kts b/smoke-tests-otel-starter/spring-boot-common/build.gradle.kts index e32d7771828e..1e4df320a25f 100644 --- a/smoke-tests-otel-starter/spring-boot-common/build.gradle.kts +++ b/smoke-tests-otel-starter/spring-boot-common/build.gradle.kts @@ -19,6 +19,7 @@ dependencies { compileOnly("org.testcontainers:junit-jupiter") compileOnly("org.testcontainers:kafka") compileOnly("org.testcontainers:mongodb") + compileOnly("org.springframework.boot:spring-boot-starter-aop") api(project(":smoke-tests-otel-starter:spring-smoke-testing")) diff --git a/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractJvmKafkaSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractJvmKafkaSpringStarterSmokeTest.java index 8be2b86e9539..73a801d96365 100644 --- a/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractJvmKafkaSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractJvmKafkaSpringStarterSmokeTest.java @@ -7,7 +7,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; -import io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka.KafkaInstrumentationAutoConfiguration; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.kafka.KafkaInstrumentationAutoConfiguration; import java.time.Duration; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -30,7 +30,7 @@ public class AbstractJvmKafkaSpringStarterSmokeTest extends AbstractKafkaSpringS @BeforeAll static void setUpKafka() { kafka = - new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:6.2.10")) + new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.7.0")) .withEnv("KAFKA_HEAP_OPTS", "-Xmx256m") .waitingFor(Wait.forLogMessage(".*started \\(kafka.server.KafkaServer\\).*", 1)) .withStartupTimeout(Duration.ofMinutes(1)); diff --git a/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractJvmMongodbSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractJvmMongodbSpringStarterSmokeTest.java index ac213a4b4669..5915f8fca138 100644 --- a/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractJvmMongodbSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractJvmMongodbSpringStarterSmokeTest.java @@ -8,7 +8,7 @@ import com.mongodb.client.MongoClient; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; -import io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.mongo.MongoClientInstrumentationAutoConfiguration; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.mongo.MongoClientInstrumentationAutoConfiguration; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; diff --git a/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractOtelSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractOtelSpringStarterSmokeTest.java index 9760907a126b..4e802dd3bccb 100644 --- a/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractOtelSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractOtelSpringStarterSmokeTest.java @@ -5,6 +5,8 @@ package io.opentelemetry.spring.smoketest; +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.opentelemetry.api.common.AttributeKey; @@ -19,13 +21,15 @@ import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions; +import io.opentelemetry.semconv.ClientAttributes; import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.ServerAttributes; import io.opentelemetry.semconv.UrlAttributes; import io.opentelemetry.semconv.incubating.CodeIncubatingAttributes; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import io.opentelemetry.semconv.incubating.ServiceIncubatingAttributes; import java.util.Collections; +import java.util.List; import org.assertj.core.api.AbstractCharSequenceAssert; import org.assertj.core.api.AbstractIterableAssert; import org.junit.jupiter.api.MethodOrderer; @@ -140,10 +144,16 @@ void shouldSendTelemetry() { clientSpan .hasKind(SpanKind.CLIENT) .hasAttributesSatisfying( - a -> assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/ping")), + satisfies( + UrlAttributes.URL_FULL, + stringAssert -> stringAssert.endsWith("/ping")), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + satisfies( + ServerAttributes.SERVER_PORT, + integerAssert -> integerAssert.isNotZero())), serverSpan -> - serverSpan - .hasKind(SpanKind.SERVER) + HttpSpanDataAssert.create(serverSpan) + .assertServerGetRequest("/ping") .hasResourceSatisfying( r -> r.hasAttribute( @@ -151,12 +161,19 @@ void shouldSendTelemetry() { .hasAttribute( AttributeKey.stringKey("attributeFromYaml"), "true") .hasAttribute( - OpenTelemetryAssertions.satisfies( + satisfies( ServiceIncubatingAttributes.SERVICE_INSTANCE_ID, AbstractCharSequenceAssert::isNotBlank))) - .hasAttribute(HttpAttributes.HTTP_REQUEST_METHOD, "GET") - .hasAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L) - .hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"))); + .hasAttributesSatisfying( + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L), + equalTo(HttpAttributes.HTTP_ROUTE, "/ping"), + equalTo(ServerAttributes.SERVER_ADDRESS, "localhost"), + equalTo(ClientAttributes.CLIENT_ADDRESS, "127.0.0.1"), + satisfies( + ServerAttributes.SERVER_PORT, + integerAssert -> integerAssert.isNotZero())), + span -> withSpanAssert(span))); // Metric testing.waitAndAssertMetrics( @@ -165,15 +182,21 @@ void shouldSendTelemetry() { AbstractIterableAssert::isNotEmpty); // Log - LogRecordData firstLog = testing.getExportedLogRecords().get(0); - assertThat(firstLog.getBody().asString()) - .as("Should instrument logs") - .startsWith("Starting ") - .contains(this.getClass().getSimpleName()); - assertThat(firstLog.getAttributes().asMap()) - .as("Should capture code attributes") - .containsEntry( - CodeIncubatingAttributes.CODE_NAMESPACE, "org.springframework.boot.StartupInfoLogger"); + List exportedLogRecords = testing.getExportedLogRecords(); + assertThat(exportedLogRecords).as("No log record exported.").isNotEmpty(); + if (System.getProperty("org.graalvm.nativeimage.imagecode") == null) { + // log records differ in native image mode due to different startup timing + LogRecordData firstLog = exportedLogRecords.get(0); + assertThat(firstLog.getBody().asString()) + .as("Should instrument logs") + .startsWith("Starting ") + .contains(this.getClass().getSimpleName()); + assertThat(firstLog.getAttributes().asMap()) + .as("Should capture code attributes") + .containsEntry( + CodeIncubatingAttributes.CODE_NAMESPACE, + "org.springframework.boot.StartupInfoLogger"); + } } @Test @@ -209,14 +232,9 @@ void restTemplate() { testing.waitAndAssertTraces( traceAssert -> traceAssert.hasSpansSatisfyingExactly( - nestedClientSpan -> - nestedClientSpan - .hasKind(SpanKind.CLIENT) - .hasAttributesSatisfying( - a -> assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/ping")), - nestedServerSpan -> - nestedServerSpan - .hasKind(SpanKind.SERVER) - .hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"))); + span -> HttpSpanDataAssert.create(span).assertClientGetRequest("/ping"), + span -> + span.hasKind(SpanKind.SERVER).hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"), + span -> withSpanAssert(span))); } } diff --git a/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestController.java b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestController.java index 891666797bf6..7d02c29d5fc1 100644 --- a/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestController.java +++ b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTestController.java @@ -20,15 +20,19 @@ public class OtelSpringStarterSmokeTestController { public static final String TEST_HISTOGRAM = "histogram-test-otel-spring-starter"; public static final String METER_SCOPE_NAME = "scope"; private final LongHistogram histogram; + private final SpringComponent component; - public OtelSpringStarterSmokeTestController(OpenTelemetry openTelemetry) { + public OtelSpringStarterSmokeTestController( + OpenTelemetry openTelemetry, SpringComponent springComponent) { Meter meter = openTelemetry.getMeter(METER_SCOPE_NAME); histogram = meter.histogramBuilder(TEST_HISTOGRAM).ofLongs().build(); + this.component = springComponent; } @GetMapping(PING) public String ping() { histogram.record(10); + component.withSpanMethod("from-controller"); return "pong"; } } diff --git a/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/SpringComponent.java b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/SpringComponent.java new file mode 100644 index 000000000000..072b39393b01 --- /dev/null +++ b/smoke-tests-otel-starter/spring-boot-common/src/main/java/io/opentelemetry/spring/smoketest/SpringComponent.java @@ -0,0 +1,18 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.spring.smoketest; + +import io.opentelemetry.instrumentation.annotations.SpanAttribute; +import io.opentelemetry.instrumentation.annotations.WithSpan; +import org.springframework.stereotype.Component; + +@Component +public class SpringComponent { + + @SuppressWarnings("MethodCanBeStatic") + @WithSpan + public void withSpanMethod(@SpanAttribute String paramName) {} +} diff --git a/smoke-tests-otel-starter/spring-boot-common/src/main/resources/META-INF/native-image/reflect-config.json b/smoke-tests-otel-starter/spring-boot-common/src/main/resources/META-INF/native-image/reflect-config.json index ce3d6a3b14ad..ab4757f6961c 100644 --- a/smoke-tests-otel-starter/spring-boot-common/src/main/resources/META-INF/native-image/reflect-config.json +++ b/smoke-tests-otel-starter/spring-boot-common/src/main/resources/META-INF/native-image/reflect-config.json @@ -544,5 +544,705 @@ "typeReachable": "com.zaxxer.hikari.util.Sequence$Factory" }, "name": "java.util.concurrent.atomic.LongAdder" + }, + { + "name": "org.apache.kafka.clients.consumer.CooperativeStickyAssignor", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.ConsumerPartitionAssignor" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.clients.consumer.RangeAssignor", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.ConsumerPartitionAssignor" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.clients.consumer.RoundRobinAssignor", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.ConsumerPartitionAssignor" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.clients.consumer.StickyAssignor", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.ConsumerPartitionAssignor" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.clients.producer.RoundRobinPartitioner", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.metrics.JmxReporter", + "condition": { + "typeReachable": "org.apache.kafka.common.utils.Utils" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.security.authenticator.AbstractLogin$DefaultLoginCallbackHandler", + "condition": { + "typeReachable": "org.apache.kafka.common.security.authenticator.LoginManager" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.security.authenticator.DefaultLogin", + "condition": { + "typeReachable": "org.apache.kafka.common.security.authenticator.LoginManager" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.security.authenticator.SaslClientCallbackHandler", + "condition": { + "typeReachable": "org.apache.kafka.common.network.SaslChannelBuilder" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.security.plain.PlainLoginModule", + "condition": { + "typeReachable": "org.apache.kafka.common.security.authenticator.AbstractLogin" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.BooleanDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.BooleanSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.ByteArrayDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.ByteArraySerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.ByteBufferDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.ByteBufferSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.BytesDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.BytesSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.DoubleDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.DoubleSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.FloatDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.FloatSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.IntegerDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.IntegerSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.ListDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.ListSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.LongDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.LongSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$BooleanSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListDeserializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$BooleanSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$ByteArraySerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$ByteBufferSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$BytesSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$DoubleSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$FloatSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$IntegerSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$LongSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$ShortSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$StringSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$UUIDSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.Serdes$VoidSerde", + "condition": { + "typeReachable": "org.apache.kafka.common.serialization.ListSerializer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.ShortDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.ShortSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.StringDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.StringSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.UUIDDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.UUIDSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.VoidDeserializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.consumer.KafkaConsumer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.serialization.VoidSerializer", + "condition": { + "typeReachable": "org.apache.kafka.clients.producer.KafkaProducer" + }, + "methods": [ + { + "name": "", + "parameterTypes": [ + + ] + } + ] + }, + { + "name": "org.apache.kafka.common.utils.AppInfoParser$AppInfo", + "queryAllPublicConstructors": true, + "condition": { + "typeReachable": "org.apache.kafka.common.utils.AppInfoParser" + } + }, + { + "name": "org.apache.kafka.common.utils.AppInfoParser$AppInfoMBean", + "queryAllPublicMethods": true, + "condition": { + "typeReachable": "org.apache.kafka.common.utils.AppInfoParser" + } } ] diff --git a/smoke-tests-otel-starter/spring-boot-common/src/main/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-common/src/main/resources/application.yaml index 62816a2e1d4d..1995223b3841 100644 --- a/smoke-tests-otel-starter/spring-boot-common/src/main/resources/application.yaml +++ b/smoke-tests-otel-starter/spring-boot-common/src/main/resources/application.yaml @@ -8,6 +8,11 @@ otel: logback-appender: experimental: capture-code-attributes: true + http: + client: + emit-experimental-telemetry: true + server: + emit-experimental-telemetry: true propagators: - b3 resource: @@ -16,6 +21,7 @@ otel: spring: kafka: + bootstrap-servers: localhost:9094 consumer: auto-offset-reset: earliest listener: diff --git a/smoke-tests-otel-starter/spring-boot-reactive-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractOtelReactiveSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-reactive-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractOtelReactiveSpringStarterSmokeTest.java index 7bc32e819fcc..8de8f4fc0ac5 100644 --- a/smoke-tests-otel-starter/spring-boot-reactive-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractOtelReactiveSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-reactive-common/src/main/java/io/opentelemetry/spring/smoketest/AbstractOtelReactiveSpringStarterSmokeTest.java @@ -8,8 +8,6 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.semconv.HttpAttributes; -import io.opentelemetry.semconv.UrlAttributes; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -52,17 +50,8 @@ void webClientAndWebFluxAndR2dbc() { trace.hasSpansSatisfyingExactly(span -> span.hasName("CREATE TABLE testdb.player")), trace -> trace.hasSpansSatisfyingExactly( - span -> - span.hasKind(SpanKind.CLIENT) - .hasName("GET") - .hasAttributesSatisfying( - a -> assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/webflux")), - span -> - span.hasKind(SpanKind.SERVER) - .hasName("GET /webflux") - .hasAttribute(HttpAttributes.HTTP_REQUEST_METHOD, "GET") - .hasAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L) - .hasAttribute(HttpAttributes.HTTP_ROUTE, "/webflux"), + span -> HttpSpanDataAssert.create(span).assertClientGetRequest("/webflux"), + span -> HttpSpanDataAssert.create(span).assertServerGetRequest("/webflux"), span -> span.hasKind(SpanKind.CLIENT) .satisfies( diff --git a/smoke-tests-otel-starter/spring-boot-reactive-common/src/main/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-reactive-common/src/main/resources/application.yaml index f0568098a28b..26b301f52d79 100644 --- a/smoke-tests-otel-starter/spring-boot-reactive-common/src/main/resources/application.yaml +++ b/smoke-tests-otel-starter/spring-boot-reactive-common/src/main/resources/application.yaml @@ -3,6 +3,11 @@ otel: common: db-statement-sanitizer: enabled: false + http: + client: + emit-experimental-telemetry: true + server: + emit-experimental-telemetry: true spring: r2dbc: diff --git a/smoke-tests-otel-starter/spring-smoke-testing/build.gradle.kts b/smoke-tests-otel-starter/spring-smoke-testing/build.gradle.kts index cc34ef0d91bb..6b2eae7f32ab 100644 --- a/smoke-tests-otel-starter/spring-smoke-testing/build.gradle.kts +++ b/smoke-tests-otel-starter/spring-smoke-testing/build.gradle.kts @@ -13,7 +13,6 @@ dependencies { compileOnly("org.springframework.boot:spring-boot-starter") compileOnly("org.springframework.boot:spring-boot-starter-test") api(project(":testing-common")) - api(project(":instrumentation:spring:spring-boot-autoconfigure")) api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi") } diff --git a/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/AbstractSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/AbstractSpringStarterSmokeTest.java index e7269737d6c7..7ca5cab29615 100644 --- a/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/AbstractSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/AbstractSpringStarterSmokeTest.java @@ -8,6 +8,10 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; +import java.util.Arrays; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -19,6 +23,11 @@ @ExtendWith(OutputCaptureExtension.class) public abstract class AbstractSpringStarterSmokeTest { + private static final List IGNORED_WARNINGS = + Arrays.asList( + "Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider", + "The architecture 'amd64' for image"); + @Autowired protected OpenTelemetry openTelemetry; protected SpringSmokeTestRunner testing; @@ -47,12 +56,16 @@ void checkSpringLogs(CapturedOutput output) { // only look for WARN and ERROR log level, e.g. [Test worker] WARN .satisfies( s -> { - if (!s.toString() - .contains( - "Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider") - && !s.toString().contains("The architecture 'amd64' for image")) { - assertThat(s).doesNotContain("] WARN").doesNotContain("] ERROR"); + for (String line : s.toString().split("\n")) { + if (IGNORED_WARNINGS.stream().noneMatch(line::contains)) { + assertThat(line).doesNotContain("] WARN").doesNotContain("] ERROR"); + } } }); } + + static SpanDataAssert withSpanAssert(SpanDataAssert span) { + return span.hasName("SpringComponent.withSpanMethod") + .hasAttribute(AttributeKey.stringKey("paramName"), "from-controller"); + } } diff --git a/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/HttpSpanDataAssert.java b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/HttpSpanDataAssert.java new file mode 100644 index 000000000000..4f6018d46167 --- /dev/null +++ b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/HttpSpanDataAssert.java @@ -0,0 +1,62 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.spring.smoketest; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.sdk.testing.assertj.ResourceAssert; +import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; +import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.UrlAttributes; +import io.opentelemetry.semconv.incubating.HttpIncubatingAttributes; +import java.util.function.Consumer; +import org.assertj.core.api.AbstractLongAssert; + +public final class HttpSpanDataAssert { + + private final SpanDataAssert span; + + private HttpSpanDataAssert(SpanDataAssert span) { + this.span = span; + } + + public static HttpSpanDataAssert create(SpanDataAssert serverSpan) { + return new HttpSpanDataAssert(serverSpan); + } + + @CanIgnoreReturnValue + public HttpSpanDataAssert assertClientGetRequest(String path) { + span.hasKind(SpanKind.CLIENT) + .hasAttributesSatisfying( + satisfies(UrlAttributes.URL_FULL, a -> a.endsWith(path)), + // this attribute is set by the experimental http instrumentation + satisfies( + HttpIncubatingAttributes.HTTP_RESPONSE_BODY_SIZE, + AbstractLongAssert::isNotNegative)); + return this; + } + + @CanIgnoreReturnValue + public HttpSpanDataAssert assertServerGetRequest(String route) { + span.hasKind(SpanKind.SERVER) + .hasAttributesSatisfying( + equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"), + equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L), + equalTo(HttpAttributes.HTTP_ROUTE, route), + // this attribute is set by the experimental http instrumentation + satisfies( + HttpIncubatingAttributes.HTTP_RESPONSE_BODY_SIZE, + AbstractLongAssert::isNotNegative)); + return this; + } + + public SpanDataAssert hasResourceSatisfying(Consumer resource) { + return span.hasResourceSatisfying(resource); + } +} diff --git a/smoke-tests/build.gradle.kts b/smoke-tests/build.gradle.kts index 83420e2cf074..2004e1e85640 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.6" +val dockerJavaVersion = "3.4.0" 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.64.0")) + implementation(platform("io.grpc:grpc-bom:1.66.0")) 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.3") + implementation("com.google.protobuf:protobuf-java-util:3.25.4") implementation("io.grpc:grpc-netty-shaded") implementation("io.grpc:grpc-protobuf") implementation("io.grpc:grpc-stub") diff --git a/smoke-tests/images/early-jdk8/Dockerfile b/smoke-tests/images/early-jdk8/Dockerfile new file mode 100644 index 000000000000..0476bce8d9ec --- /dev/null +++ b/smoke-tests/images/early-jdk8/Dockerfile @@ -0,0 +1,16 @@ +# https://github.com/zulu-openjdk/zulu-openjdk/blob/master/ubuntu/8u412-8.78/Dockerfile +FROM ubuntu:noble + +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8' + +RUN apt-get -qq update && \ + apt-get -qq -y --no-install-recommends install software-properties-common locales curl tzdata unzip && \ + echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && \ + locale-gen en_US.UTF-8 && \ + curl -sLO https://cdn.azul.com/zulu/bin/zulu1.8.0_31-8.5.0.1-x86lx64.zip && \ + unzip zulu1.8.0_31-8.5.0.1-x86lx64.zip -d /opt && \ + apt-get -qq -y purge --auto-remove software-properties-common curl unzip && \ + rm zulu1.8.0_31-8.5.0.1-x86lx64.zip + +ENV JAVA_HOME=/opt/zulu1.8.0_31-8.5.0.1-x86lx64 +ENV PATH="${PATH}:/opt/zulu1.8.0_31-8.5.0.1-x86lx64/bin" diff --git a/smoke-tests/images/early-jdk8/build.gradle.kts b/smoke-tests/images/early-jdk8/build.gradle.kts new file mode 100644 index 000000000000..d583cd6f53fd --- /dev/null +++ b/smoke-tests/images/early-jdk8/build.gradle.kts @@ -0,0 +1,35 @@ +import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage +import com.bmuschko.gradle.docker.tasks.image.DockerPushImage +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +plugins { + id("com.bmuschko.docker-remote-api") +} + +val extraTag = findProperty("extraTag") + ?: DateTimeFormatter.ofPattern("yyyyMMdd.HHmmSS").format(LocalDateTime.now()) + +tasks { + val dockerWorkingDir = layout.buildDirectory.dir("docker") + + val imagePrepare by registering(Copy::class) { + into(dockerWorkingDir) + from("Dockerfile") + } + + val imageBuild by registering(DockerBuildImage::class) { + dependsOn(imagePrepare) + inputDir.set(dockerWorkingDir) + + images.add("ghcr.io/open-telemetry/opentelemetry-java-instrumentation/smoke-test-zulu-openjdk-8u31:$extraTag") + dockerFile.set(dockerWorkingDir.get().file("Dockerfile")) + } + + val dockerPush by registering(DockerPushImage::class) { + group = "publishing" + description = "Push all Docker images" + dependsOn(imageBuild) + images.add("ghcr.io/open-telemetry/opentelemetry-java-instrumentation/smoke-test-zulu-openjdk-8u31:$extraTag") + } +} diff --git a/smoke-tests/images/fake-backend/build.gradle.kts b/smoke-tests/images/fake-backend/build.gradle.kts index 246b11bca742..040a51daf41f 100644 --- a/smoke-tests/images/fake-backend/build.gradle.kts +++ b/smoke-tests/images/fake-backend/build.gradle.kts @@ -5,14 +5,13 @@ import java.time.format.DateTimeFormatter plugins { id("otel.java-conventions") - id("com.bmuschko.docker-remote-api") - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") id("com.google.cloud.tools.jib") } dependencies { - implementation("com.linecorp.armeria:armeria-grpc:1.29.0") + implementation("com.linecorp.armeria:armeria-grpc:1.30.0") 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 55b79f1b0e56..381e5d0d647c 100644 --- a/smoke-tests/images/grpc/build.gradle.kts +++ b/smoke-tests/images/grpc/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } dependencies { - implementation(platform("io.grpc:grpc-bom:1.64.0")) + implementation(platform("io.grpc:grpc-bom:1.66.0")) 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.23.1")) diff --git a/smoke-tests/images/quarkus/build.gradle.kts b/smoke-tests/images/quarkus/build.gradle.kts index 52f64ecdf3b8..1951fad7a751 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.11.2" + id("io.quarkus") version "3.13.2" } dependencies { - implementation(enforcedPlatform("io.quarkus:quarkus-bom:3.11.2")) + implementation(enforcedPlatform("io.quarkus:quarkus-bom:3.13.2")) implementation("io.quarkus:quarkus-resteasy") } diff --git a/smoke-tests/src/test/groovy/io/opentelemetry/smoketest/CrashEarlyJdk8Test.groovy b/smoke-tests/src/test/groovy/io/opentelemetry/smoketest/CrashEarlyJdk8Test.groovy index e1aefc5b128d..c6f79a2fea6d 100644 --- a/smoke-tests/src/test/groovy/io/opentelemetry/smoketest/CrashEarlyJdk8Test.groovy +++ b/smoke-tests/src/test/groovy/io/opentelemetry/smoketest/CrashEarlyJdk8Test.groovy @@ -13,7 +13,6 @@ import org.testcontainers.containers.output.Slf4jLogConsumer import org.testcontainers.containers.wait.strategy.Wait import org.testcontainers.utility.DockerImageName import org.testcontainers.utility.MountableFile -import spock.lang.Ignore import spock.lang.IgnoreIf import spock.lang.Specification @@ -25,12 +24,6 @@ import static io.opentelemetry.smoketest.TestContainerManager.useWindowsContaine // java.lang.invoke.CallSite // This test verifies that such jvm does not crash with opentelemetry agent @IgnoreIf({ useWindowsContainers() }) -// com.github.dockerjava.api.exception.DockerClientException: Could not pull image: [DEPRECATION NOTICE] -// Docker Image Format v1 and Docker Image manifest version 2, schema 1 support is disabled by default -// and will be removed in an upcoming release. Suggest the author of docker.io/azul/zulu-openjdk:8u31 -// to upgrade the image to the OCI Format or Docker Image manifest v2, schema 2. More information -// at https://docs.docker.com/go/deprecated-image-specs/ -@Ignore class CrashEarlyJdk8Test extends Specification { private static final Logger logger = LoggerFactory.getLogger(CrashEarlyJdk8Test) @@ -40,7 +33,7 @@ class CrashEarlyJdk8Test extends Specification { def "test crash on early jdk8"() { setup: GenericContainer target = - new GenericContainer<>(DockerImageName.parse("azul/zulu-openjdk:8u31")) + new GenericContainer<>(DockerImageName.parse("ghcr.io/open-telemetry/opentelemetry-java-instrumentation/smoke-test-zulu-openjdk-8u31:20240709.9848833570")) .withStartupTimeout(Duration.ofMinutes(5)) .withLogConsumer(new Slf4jLogConsumer(logger)) .withCopyFileToContainer( diff --git a/testing-common/integration-tests/src/main/java/io/opentelemetry/javaagent/IndyInstrumentationTestModule.java b/testing-common/integration-tests/src/main/java/io/opentelemetry/javaagent/IndyInstrumentationTestModule.java index 82a0dc29fbd5..1206f0056825 100644 --- a/testing-common/integration-tests/src/main/java/io/opentelemetry/javaagent/IndyInstrumentationTestModule.java +++ b/testing-common/integration-tests/src/main/java/io/opentelemetry/javaagent/IndyInstrumentationTestModule.java @@ -84,13 +84,15 @@ public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod(named("exceptionPlease"), prefix + "$ThrowExceptionAdvice"); transformer.applyAdviceToMethod( named("noExceptionPlease"), prefix + "$SuppressExceptionAdvice"); + transformer.applyAdviceToMethod( + named("instrumentWithErasedTypes"), prefix + "$SignatureErasureAdvice"); } @SuppressWarnings({"unused"}) public static class AssignFieldViaReturnAdvice { @Advice.OnMethodEnter(inline = false) - @Advice.AssignReturned.ToFields(@ToField(value = "privateField")) + @Advice.AssignReturned.ToFields(@ToField(value = "privateField", typing = DYNAMIC)) public static String onEnter(@Advice.Argument(0) String toAssign) { return toAssign; } @@ -110,7 +112,7 @@ public static Object[] onEnter(@Advice.Argument(0) String toAssign) { public static class AssignArgumentViaReturnAdvice { @Advice.OnMethodEnter(inline = false) - @Advice.AssignReturned.ToArguments(@ToArgument(0)) + @Advice.AssignReturned.ToArguments(@ToArgument(value = 0, typing = DYNAMIC)) public static String onEnter(@Advice.Argument(1) String toAssign) { return toAssign; } @@ -130,7 +132,7 @@ public static Object[] onEnter(@Advice.Argument(1) String toAssign) { public static class AssignReturnViaReturnAdvice { @Advice.OnMethodExit(inline = false) - @Advice.AssignReturned.ToReturned + @Advice.AssignReturned.ToReturned(typing = DYNAMIC) public static String onExit(@Advice.Argument(0) String toAssign) { return toAssign; } @@ -150,7 +152,7 @@ public static Object[] onExit(@Advice.Argument(0) String toAssign) { public static class GetHelperClassAdvice { @Advice.OnMethodExit(inline = false) - @Advice.AssignReturned.ToReturned + @Advice.AssignReturned.ToReturned(typing = DYNAMIC) public static Class onExit(@Advice.Argument(0) boolean localHelper) { if (localHelper) { return LocalHelper.class; @@ -175,7 +177,7 @@ public static void onMethodEnter() { throw new RuntimeException("This exception should be suppressed"); } - @Advice.AssignReturned.ToReturned + @Advice.AssignReturned.ToReturned(typing = DYNAMIC) @Advice.OnMethodExit( suppress = Throwable.class, onThrowable = Throwable.class, @@ -184,6 +186,23 @@ public static void onMethodExit(@Advice.Thrown Throwable throwable) { throw new RuntimeException("This exception should be suppressed"); } } + + @SuppressWarnings({"unused", "ThrowSpecificExceptions"}) + public static class SignatureErasureAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) + public static LocalHelper onMethodEnter() { + return new LocalHelper(); + } + + @Advice.AssignReturned.ToReturned(typing = DYNAMIC) + @Advice.OnMethodExit( + suppress = Throwable.class, + onThrowable = Throwable.class, + inline = false) + public static LocalHelper onMethodExit(@Advice.Enter LocalHelper enterVal) { + return enterVal; + } + } } public static class GlobalHelper {} diff --git a/testing-common/integration-tests/src/test/java/indy/IndyInstrumentationTest.java b/testing-common/integration-tests/src/test/java/indy/IndyInstrumentationTest.java index 4973641b331e..ad39c24e57ea 100644 --- a/testing-common/integration-tests/src/test/java/indy/IndyInstrumentationTest.java +++ b/testing-common/integration-tests/src/test/java/indy/IndyInstrumentationTest.java @@ -60,6 +60,10 @@ private Class getHelperClass(boolean local) { return null; } + private Object instrumentWithErasedTypes() { + return "replace_me"; + } + @AfterEach public void reset() { privateField = null; @@ -112,6 +116,12 @@ void testThrowExceptionIntoUserCode() { assertThatThrownBy(this::exceptionPlease).isInstanceOf(RuntimeException.class); } + @Test + void testAdviceSignatureReferenceInternalHelper() { + Object result = instrumentWithErasedTypes(); + assertThat(result.getClass().getName()).contains("LocalHelper"); + } + @Test void testHelperClassLoading() { Class localHelper = getHelperClass(true); diff --git a/testing-common/src/main/groovy/io/opentelemetry/instrumentation/test/base/HttpServerTest.groovy b/testing-common/src/main/groovy/io/opentelemetry/instrumentation/test/base/HttpServerTest.groovy index fdade11a389d..54bcba8bbc26 100644 --- a/testing-common/src/main/groovy/io/opentelemetry/instrumentation/test/base/HttpServerTest.groovy +++ b/testing-common/src/main/groovy/io/opentelemetry/instrumentation/test/base/HttpServerTest.groovy @@ -173,10 +173,6 @@ abstract class HttpServerTest extends InstrumentationSpecification imple return true } - String getMetricsInstrumentationName() { - null - } - /** A list of additional HTTP server span attributes extracted by the instrumentation per URI. */ Set> httpAttributes(ServerEndpoint endpoint) { [ @@ -237,9 +233,6 @@ abstract class HttpServerTest extends InstrumentationSpecification imple options.sockPeerAddr = { endpoint -> HttpServerTest.this.sockPeerAddr(endpoint) } - options.metricsInstrumentationName = { - HttpServerTest.this.getMetricsInstrumentationName() - } options.responseCodeOnNonStandardHttpMethod = getResponseCodeOnNonStandardHttpMethod() options.testRedirect = testRedirect() diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java index 3246bad915f7..74c9e6c67af2 100644 --- a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java @@ -353,12 +353,8 @@ void httpServerMetrics() { spanData -> assertServerSpan(assertThat(spanData), method, SUCCESS, SUCCESS.status)); }); - String metricsInstrumentationName = options.metricsInstrumentationName.get(); - if (metricsInstrumentationName == null) { - metricsInstrumentationName = instrumentationName.get(); - } testing.waitAndAssertMetrics( - metricsInstrumentationName, + instrumentationName.get(), "http.server.request.duration", metrics -> metrics.anySatisfy( diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpServerTestOptions.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpServerTestOptions.java index ad0700b83359..970184967589 100644 --- a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpServerTestOptions.java +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpServerTestOptions.java @@ -19,7 +19,6 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; -import java.util.function.Supplier; import javax.annotation.Nullable; public final class HttpServerTestOptions { @@ -42,7 +41,6 @@ public final class HttpServerTestOptions { Function sockPeerAddr = unused -> "127.0.0.1"; String contextPath = ""; Throwable expectedException = new Exception(EXCEPTION.body); - Supplier metricsInstrumentationName = () -> null; // we're calling /success in the test, and most servers respond with 200 anyway int responseCodeOnNonStandardHttpMethod = ServerEndpoint.SUCCESS.status; @@ -108,13 +106,6 @@ public HttpServerTestOptions setExpectedException(Throwable expectedException) { return this; } - @CanIgnoreReturnValue - public HttpServerTestOptions setMetricsInstrumentationName( - Supplier metricsInstrumentationName) { - this.metricsInstrumentationName = metricsInstrumentationName; - return this; - } - @CanIgnoreReturnValue public HttpServerTestOptions setResponseCodeOnNonStandardHttpMethod( int responseCodeOnNonStandardHttpMethod) { diff --git a/testing/agent-exporter/build.gradle.kts b/testing/agent-exporter/build.gradle.kts index 063a7d3a01dc..f42ab5055727 100644 --- a/testing/agent-exporter/build.gradle.kts +++ b/testing/agent-exporter/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") id("otel.java-conventions") } diff --git a/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingCustomizer.java b/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingCustomizer.java index 3c4d7aef6923..058ad0e38d6d 100644 --- a/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingCustomizer.java +++ b/testing/agent-exporter/src/main/java/io/opentelemetry/javaagent/testing/exporter/AgentTestingCustomizer.java @@ -35,14 +35,34 @@ static void reset() { @Override public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) { autoConfigurationCustomizer.addTracerProviderCustomizer( - (tracerProvider, config) -> tracerProvider.addSpanProcessor(spanProcessor)); + (tracerProvider, config) -> { + // span processor is responsible for exporting spans, not adding it disables exporting of + // the spans + if (config.getBoolean("testing.exporter.enabled", true)) { + return tracerProvider.addSpanProcessor(spanProcessor); + } + return tracerProvider; + }); autoConfigurationCustomizer.addMeterProviderCustomizer( - (meterProvider, config) -> meterProvider.registerMetricReader(metricReader)); + (meterProvider, config) -> { + // metric reader is responsible for exporting metrics, not adding it disables exporting of + // the metrics + if (config.getBoolean("testing.exporter.enabled", true)) { + return meterProvider.registerMetricReader(metricReader); + } + return meterProvider; + }); autoConfigurationCustomizer.addLoggerProviderCustomizer( - (logProvider, config) -> - logProvider.addLogRecordProcessor( - SimpleLogRecordProcessor.create(AgentTestingExporterFactory.logExporter))); + (logProvider, config) -> { + // log record processor is responsible for exporting logs, not adding it disables + // exporting of the logs + if (config.getBoolean("testing.exporter.enabled", true)) { + return logProvider.addLogRecordProcessor( + SimpleLogRecordProcessor.create(AgentTestingExporterFactory.logExporter)); + } + return logProvider; + }); } } diff --git a/testing/armeria-shaded-for-testing/build.gradle.kts b/testing/armeria-shaded-for-testing/build.gradle.kts index 8a41ac6616ad..50a806548ad1 100644 --- a/testing/armeria-shaded-for-testing/build.gradle.kts +++ b/testing/armeria-shaded-for-testing/build.gradle.kts @@ -1,11 +1,10 @@ plugins { - id("com.github.johnrengelman.shadow") - + id("com.gradleup.shadow") id("otel.java-conventions") } dependencies { - implementation("com.linecorp.armeria:armeria-junit5:1.29.0") + implementation("com.linecorp.armeria:armeria-junit5:1.30.0") } tasks { diff --git a/version.gradle.kts b/version.gradle.kts index 74ba053e5a5a..50f3cd2a28d4 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -1,5 +1,5 @@ -val stableVersion = "2.5.0-SNAPSHOT" -val alphaVersion = "2.5.0-alpha-SNAPSHOT" +val stableVersion = "2.7.0-SNAPSHOT" +val alphaVersion = "2.7.0-alpha-SNAPSHOT" allprojects { if (findProperty("otel.stable") != "true") {